Php 使用CodeIgniter的活动记录和“where sha1”返回第一行条目的SQL Select查询

Php 使用CodeIgniter的活动记录和“where sha1”返回第一行条目的SQL Select查询,php,mysql,codeigniter,activerecord,sha1,Php,Mysql,Codeigniter,Activerecord,Sha1,我在完全干净的CodeIgniter 2.0.2安装上重复了这个问题 以下代码被添加到默认的“欢迎”控制器中,我创建了一个“test_模型”来演示错误 可以假定/更改配置/自动加载/数据库: -基本url的正确定义 -自动加载数据库库 -日志记录设置为4所有消息 -数据库连接参数 这是我添加到controllers/welcome.php的内容: function test_me() { $this->load->model('test_model'); # dat

我在完全干净的CodeIgniter 2.0.2安装上重复了这个问题

以下代码被添加到默认的“欢迎”控制器中,我创建了一个“test_模型”来演示错误

可以假定/更改配置/自动加载/数据库: -基本url的正确定义 -自动加载数据库库 -日志记录设置为4所有消息 -数据库连接参数

这是我添加到controllers/welcome.php的内容:

function test_me()
{
    $this->load->model('test_model');

    # data for sql query
    $where = array(
        'email'     => $this->input->post('email'),
        'password'  => sha1($this->input->post('password'), true);
    );

    log_message('info', '----email: '.$where['email']);
    log_message('info', '----password: '.$where['password']);

    # exec query
    $query = $this->test_model->get_user($where);

    log_message('info', '----query->num_rows() ='.$query->num_rows());

    if($query->num_rows() > 0) 
    {
        $row = $query->row();

        log_message('info', '----query->row()->email = '.$row->email);

        print $row->email;
    }
    else
        print "worked correctly.";  # returned ZERO rows

}
这是models/test_model.php:

class Test_model extends CI_Model {

var $_user_table = 'users';     # user table name

// ------------------------------------------------------------------------

/**
 * Constructor
 *
 * @access  public
 */
public function __construct()
{
    log_message('INFO', 'User model initialized');

    parent::__construct();
}

/**
 * Get_user
 * 
 * Retrieves user data from the database
 *
 * @access  public
 * @param   array   sql select query data
 * @param   int     default return limits to 1 user
 * @param   int     offset  
 * @return  mixed   sql query result
 */
public function get_user($data, $limit = 1, $offset = 0)
{
    foreach($data as $where)
        log_message('INFO', 'Getting user data from db where: '.$where);


    # refer this as QUERY1

    $query = $this->db->query('SELECT * 
                   FROM `users` 
                   WHERE `email` = \''.$data['email'].'\' 
                   AND `password` = \''.$data['password'].'\' 
                   LIMIT 1
                   OFFSET 0
                  ');

    # refer this as QUERY2

    #$query = $this->db->get_where($this->_user_table, $data, $limit, $offset);

    log_message('info', 'get last sql query: '.$this->db->last_query());

    return $query;
}
}
在QUERY1中,这只是使用直接SQL和传递给QUERY2的所有参数。不同之处在于QUERY2利用了CodeIgniter的活动记录

现在,这是运行上述程序生成的日志:

信息-2011-07-19 23:34:01->--电子邮件: 信息-2011-07-19 23:34:01->--密码:9 信息-2011-07-19 23:34:01->从数据库获取用户数据,其中:

INFO-2011-07-19 23:34:01->从数据库获取用户数据where:

INFO-2011-07-19 23:34:01->获取最后一个sql查询:从用户中选择*,其中email=和password='u2189^kK2Uï•'u216;'限制1偏移量0

信息-2011-07-19 23:34:01->--查询->行数=0

调试-2011-07-19 23:34:01->最终输出发送到浏览器 调试-2011-07-1923:34:01->总执行时间:0.0923

浏览器的输出为:工作正常

这就是当我注释掉QUERY1并运行QUERY2 CI的AR时发生的情况:

信息-2011-07-19 23:40:05->--电子邮件:

信息-2011-07-19 23:40:05->--密码:kK2U࠯֠Я؇

信息-2011-07-19 23:40:05->从数据库获取用户数据,其中: 信息-2011-07-19 23:40:05->从数据库获取用户数据࠯֠Я؇

INFO-2011-07-19 23:40:05->获取最后一个sql查询:从电子邮件=0、密码=kK\r2U的用户中选择*࠯֠Я؇限制1

信息-2011-07-19 23:40:05->--查询->行数=1

信息-2011-07-19 23:40:05->--查询->行->电子邮件=myemail@gmail.com

调试-2011-07-19 23:40:05->最终输出发送到浏览器 调试-2011-07-19 23:40:05->总执行时间:0.0965

脚本的输出是myemail@gmail.com 这是表中的第一行,它始终返回表中的第一行。如果我不使用LIMIT=1默认值,num_rows实际上等于表中的行数

现在,背景,我使用这显然是一个表单脚本检查,但表单不一定总是填写的。我使用javascript进行检查,但在这种情况下,浏览器无法启用javascript,或者如果用户试图提交空白字段。数据库没有有效的空白条目,不应返回任何行。因为我将sha1散列存储为原始二进制数据20,所以使用了sha1,true。奇怪的是,这会在CI中的活动记录中产生某种错误,而不是返回一个错误,或者返回零行,就像它在表中返回任何一行一样

我是否做错了什么,或者这是一个bug,还是不是使用活动记录的预期方式?因为我希望保留在查询中接受where子句数组的方法

谢谢

更新- 感谢下面的用户评论将我推向了这个方向。看来我搞错了sha1和这件事有任何关系实际上。。。如果本例中没有post数据,$this->input->post返回'False',因此,数组中'email'的值为'False'

所以现在我实际上在讨论一个不同的问题,我可能会重新发布,这就是为什么where email='false'返回整个表

更新-
事实上,我以前从未见过这种情况,因为它从未发生过。。。在QUERY1 sql中,它工作正常。在带有ActiveRecords的QUERY2中,它不存在。所以还是有区别。

你只需检查$this->input->post'password'和email,看看其中是否有空白。如果为空,则将页面重定向回原处。否则,执行代码。我已经这样做了,这样我就可以继续做其他事情,但这忽略了一点,即ActiveRecords生成SQL查询的方式存在差异。即使它正确地清理了输入,它也不应该返回表中的每一行,对吗?我认为这是一个类型问题,而不是活动记录问题。条件语句email=和email=0的sql查询将根据表结构中的电子邮件类型产生不同的行为。下面是structureid int11 No None None AUTO_INCREMENT email varchar50 latin1_swedish_ci Yes NULL password binary20 Yes NULL首名varchar50拉丁语1瑞典语ci是NULL姓varchar50拉丁语1瑞典语ci是NULL
verified Tinyint1我建议您在stackoverflow中针对电子邮件=或电子邮件=0的两个类似查询的不同行为提出另一个问题。这与ActiveRecord无关。ActiveRecord刚刚根据您的输入生成了查询,在本例中,您为$data['email']提供了NULL。