PHP致命错误:在(...)第36行调用未定义的方法stdClass :: num_rows()

时间:2013-02-17 12:06:32

标签: php codeigniter activerecord login-control

这是我的第一个问题。我是PHP和CI的新手,但我想学习:)

首先是我的模特:

  

类Login_model扩展了MY_Model {

protected $table   = 'users';
protected $primary = 'user_id';

function __construct()
{

    parent::__construct();
}

public function validate()
{
    // Récupère le POST du login
    $user_mail = $this->input->post('user_mail');
    $password  = sha1($this->input->post('user_mail') . $this->input->post('password'));

    //Execution de la requete

    $query = $this->users_m->get(array('user_mail' => $user_mail));
    // Verification qu'il existe un enregistrement
    var_dump($query);
    if($query->num_rows() == 1)
    {
        // If there is a user, then create session data
        $row = $query->row();
        $data = array(
                'userid' => $row->userid,
                'fname' => $row->fname,
                'lname' => $row->lname,
                'username' => $row->username,
                'validated' => true
                );
            $this->session->set_userdata($data);
            return true;
            //      }
            // Si le login ne se valide pas
            // return false.
            return false;
        }
    }
}

此模型扩展了My_model MY_MODEL.PHP

<?php

if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
 * MY_Model
 */
class MY_Model extends CI_Model
{

  /**
   * Connexion à la BDD
   * 
   * @var object 
   */
  protected $link;

  /**
   * Groupe de connexion BDD
   * 
   * @var string 
   */
  protected $db_group = 'default';

  /**
   * Table de la BDD
   * 
   * @var string
   */
  protected $table = '';

  /**
   * Clé(s) primaire(s)
   * 
   * @var string/array
   */
  protected $primary = 'id';

  /**
   * Déclanche une exception
   * 
   * @var boolean
   */
  private $_throw_exception = TRUE;

  /**
   * Constructeur
   */
  public function __construct()
  {
    parent::__construct();

    if ($this->table != '')
    {
      $this->_set_link();
    }
  }

  /**
   * Connexion à la BDD
   */
  private function _set_link()
  {
    $this->link = $this->load->database($this->db_group, TRUE);
  }

  /**
   * Active la gestion des exceptions
   */
  public function enable_exception()
  {
    $this->_throw_exception = TRUE;
  }

  /**
   * Desactive la gestion des exceptions
   */
  public function disable_exception()
  {
    $this->_throw_exception = FALSE;
  }

  /**
   * Récupère un enregistrement unique
   * 
   * @param array $where
   * @return boolean
   * @throws Exception
   */
  public function get($where = array())
  {
    if (is_array($where) && $where)
    {
      foreach ($where as $key => $value)
      {
        $this->link->where($key, $value);
      }
    }

    $query = $this->link->get($this->table);

    /* Traitement de la requete */
    $data = FALSE;

    if (is_object($query))
    {
      if ($query->num_rows() == 1)
      {
        $result = $query->result();
        $data = $result[0];
      }
      else if ($this->_throw_exception)
      {
        throw new Exception($query->num_rows(), 11);
      }
    }
    else
    {
      throw new Exception($this->link->_error_number() . ":" . $this->link->_error_message(), 10);
    }
    return $data;
  }

  /**
   * Liste des enregistrements de la table
   * 
   * @param array $orders
   * @return array
   */
  public function get_all($where = array(), $orders = array(), $limit = NULL, $offset = NULL)
  {
    /* Conditions */
    if (is_array($where) && $where)
    {
      foreach ($where as $key => $value)
      {
        $this->link->where($key, $value);
      }
    }

    /* Tris */
    if (is_array($orders) && $orders)
    {
      foreach ($orders as $order)
      {
        $this->link->order_by("$this->table.$order");
      }
    }
    else if ($orders)
    {
      $this->link->order_by("$this->table.$orders");
    }
    else if (is_array($this->primary))
    {
      foreach ($this->primary as $order)
      {
        $this->link->order_by("$this->table.$order");
      }
    }
    else
    {
      $this->link->order_by("$this->table.$this->primary");
    }

    /* Requete */
    $query = $this->link->get($this->table, $limit, $offset);

    /* Traitement de la requete */
    $data = array();

    if (is_object($query))
    {
      if ($query->num_rows() > 0)
      {
        $data = $query->result();
      }
    }
    else if ($this->_throw_exception)
    {
      throw new Exception($this->link->_error_number() . ":" . $this->link->_error_message(), 10);
    }

    /* Retour */
    return $data;
  }

  /**
   * Nombre d'enregistrements de la table
   * 
   * @return integer
   */
  public function count($where = array())
  {
    if (is_array($where) && $where)
    {
      foreach ($where as $key => $value)
      {
        $this->link->where($key, $value);
      }
    }

    $this->link->from($this->table);

    return $this->link->count_all_results();
  }

  /**
   * Insertion dans la BDD
   * 
   * @param array $data
   * @return boolean
   * @throws Exception
   */
  public function insert($data = array())
  {
    $insert = FALSE;
    if ($this->link->insert($this->table, $data))
    {
      if (is_array($this->primary))
      {
        $insert = TRUE;
      }
      else if (isset($data[$this->primary]))
      {
        $insert = $data[$this->primary];
      }
      else
      {
        $insert = $this->link->insert_id();
      }
    }
    else if ($this->_throw_exception)
    {
      throw new Exception($this->link->_error_number() . ":" . $this->link->_error_message(), 20);
    }
    return $insert;
  }

  /**
   * Insertion de masse dans une base de donnée
   * 
   * @param array $data
   * @return boolean
   * @throws Exception
   */
  public function insert_batch($data)
  {
    $insert = FALSE;

    if ($this->link->insert_batch($this->table, $data))
    {
      $insert = TRUE;
    }
    else if ($this->_throw_exception)
    {
      throw new Exception($this->link->_error_number() . ":" . $this->link->_error_message(), 20);
    }

    return $insert;
  }

  /**
   * Mise à jour d'enregistrements de la BDD
   * 
   * @param array $data
   * @param array $where
   * @return boolean
   * @throws ExceptionModel
   */
  public function update($data = array(), $where = array())
  {
    $update = FALSE;

    if (is_array($where) && $where)
    {
      foreach ($where as $key => $value)
      {
        $this->link->where($key, $value);
      }
    }

    if ($this->link->update($this->table, $data))
    {
      $update = TRUE;
    }
    else if ($this->_throw_exception)
    {
      throw new Exception($this->link->_error_number() . ":" . $this->link->_error_message(), 30);
    }

    return $update;
  }

  /**
   * Suppression d'enregistrements de la BDD
   * 
   * @param array $where
   * @return boolean
   * @throws Exception
   */
  public function delete($where = array())
  {
    $delete = FALSE;

    if (is_array($where) && $where)
    {
      foreach ($where as $key => $value)
      {
        $this->link->where($key, $value);
      }
    }

    if ($this->link->delete($this->table))
    {
      $delete = TRUE;
    }
    else if ($this->_throw_exception)
    {
      throw new Exception($this->link->_error_number() . ":" . $this->link->_error_message(), 40);
    }

    return $delete;
  }

}

/* End of file MY_Model.php */
/* Location: ./application/core/MY_Model.php */

我有我的控制器:Accueil(将是默认路线)

方法login()调用view login.php

ACCUEIL.PHP:

    <?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class Accueil extends MY_Controller
{

    public function __construct()
    {
        parent::__construct();
        $this->load->model('users_model', 'users_m');
        $this->load->library('form_validation');
        $this->load->helper(array('form', 'url'));
        $this->load->library('template');
    }

    public function index($msg = NULL) //msg en cas d'erreur , NULL si pas d'erreur
    {
        $data['msg'] = $msg;
        $this->load->view('/login', $data);
    }

    public function login()
    {
        // Chargement du model de login
        $this->load->model('login_model');
        // Validation que l'user puisse se connecter
        $result = $this->login_model->validate();
        // Verification du résultat
        if (!$result)
        {
            // Pas de validation on renvoit vers l'index
            $msg = '<font color=red>Nom d\'utilisateur ou mot de passe incorrect(s).</font><br />';
            $this->index($msg);
        }
        else
        {
            // Si validation ok,
            // On l'envoit vers la partie "protégée"
            redirect('home');
        }
    }

}

最后视图:LOGIN.PHP

    <!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>connexion</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="">
        <meta name="author" content="kliklipse">

        <!-- Le styles -->
        <link rel="stylesheet" href="<?php echo css_url('bootstrap.min'); ?>">
        <style>
            body {
                padding-top: 40px;
                padding-bottom: 40px;
                background-color: #f5f5f5;
            }

            .form-signin {
                max-width: 300px;
                padding: 19px 29px 29px;
                margin: 0 auto 20px;
                background-color: #fff;
                border: 1px solid #e5e5e5;
                -webkit-border-radius: 5px;
                -moz-border-radius: 5px;
                border-radius: 5px;
                -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
                -moz-box-shadow: 0 1px 2px rgba(0,0,0,.05);
                box-shadow: 0 1px 2px rgba(0,0,0,.05);
            }
            .form-signin .form-signin-heading,
            .form-signin .checkbox {
                margin-bottom: 10px;
            }
            .form-signin input[type="text"],
            .form-signin input[type="password"] {
                font-size: 16px;
                height: auto;
                margin-bottom: 15px;
                padding: 7px 9px;
            }

        </style>
        <link rel="stylesheet" href="<?php echo css_url('bootstrap-responsive.min'); ?>"> 
        <link rel="stylesheet" href="<?php echo css_url('main'); ?>">  


        <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
        <!--[if lt IE 9]>
          <script src="../assets/js/html5shiv.js"></script>
        <![endif]-->

        <!-- Fav and touch icons -->
        <link rel="apple-touch-icon-precomposed" sizes="144x144" href="../assets/ico/apple-touch-icon-144-precomposed.png">
        <link rel="apple-touch-icon-precomposed" sizes="114x114" href="../assets/ico/apple-touch-icon-114-precomposed.png">
        <link rel="apple-touch-icon-precomposed" sizes="72x72" href="../assets/ico/apple-touch-icon-72-precomposed.png">
        <link rel="apple-touch-icon-precomposed" href="../assets/ico/apple-touch-icon-57-precomposed.png">
        <link rel="shortcut icon" href="../assets/ico/favicon.png">
    </head>

    <body>

        <div class="container">



            <form class="form-signin" action="<?php echo base_url();?>accueil/login" method="post" name="process">
                <h2 class="form-signin-heading">Identifiez vous</h2>
                <br />
                <?php if(! is_null($msg)) echo $msg;?> 
                <input type="text" name="user_mail" id="user_mail" class="input-block-level" placeholder="Adresse Email">
                <input type="password" name="password" id="password" class="input-block-level" placeholder="Mot de passe">
                <label class="checkbox">
                    <input type="checkbox" value="remember-me"> Se souvenir de moi
                </label>
                <button class="btn btn-large btn-primary" type="submit">Se connecter</button>
            </form>

        </div> <!-- /container -->

        <div id="footer">
            <div class="container-narrow">
                <p>&copy; Kliklipse 2013 <a href="<?php echo base_url(); ?>">Gestion des utilisateur & groupes</a></p>
            </div>
        </div>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>

        <script src="<?php echo js_url('bootstrap.min'); ?>"></script>
        <script src="<?php echo js_url('sorttable'); ?>"></script>
        <script>var base_url = <?php echo base_url(); ?></script>

        <!-- {elapsed_time} seconds-->
    </body>
</html>

我得到了num_rows()的错误,它是一个未定义的方法......只是不知道为什么..

如果有任何问题,请问我(抱歉我的英文^^)

6 个答案:

答案 0 :(得分:1)

num_rows()仅用于CI的数据库对象资源(不是结果)。这$query = $this->users_m->get(array('user_mail' => $user_mail));看起来并不像。

尝试这样的事情:

$query = $this->db->get_where('table_name', array('user_mail' => $user_mail));

然后您可以使用$query->num_rows();

答案 1 :(得分:0)

根据您的问题,哪个num_rows()的调用导致了错误,这一点并不清楚。但我将假设它来自您的登录模型,即var_dump($query);

之后的行

在您的My_model get功能中,您有以下内容:

if (is_object($query))
{
  if ($query->num_rows() == 1)
  {
    $result = $query->result();
    $data = $result[0];             <<<<<< NOTE THIS
  }
  else if ($this->_throw_exception)
  {
    throw new Exception($query->num_rows(), 11);
  }
}

,您从$data返回get

此时$data是一个$CI_result对象,它没有num_rows()方法可用,这是查询类中的方法。

CI results docs

如果要在My_model中检入num行,则无需在登录模型中执行此操作。您现在可以直接调用这些方法,因为您已经完成了检查。

答案 2 :(得分:0)

我发现错误在哪里。

if ($query->num_rows() == 1) 

不是正确的语法

if ($query->num_rows == 1) 

是正确的。 $ query-&gt; num_rows值为“1”

最后我选择的解决方案是:

我的user_model.php(用于与用户进行数据库操作)

class Users_model extends MY_Model
{

    protected $table   = 'users';
    protected $primary = 'user_id';

    public function liste()
    {

        $this->link->select('user_id');
        $this->link->select('user_name');
        $this->link->select('user_mail');
        $this->link->select("GROUP_CONCAT(group_name ORDER BY group_name SEPARATOR '<br />') AS user_groups", FALSE);

        $this->link->join('groups_users', 'users_user_id=user_id', 'left');
        $this->link->join('groups', 'group_id=groups_group_id', 'left');

        $this->link->group_by('user_id');

        return parent::get_all(array(), array('user_name ASC'));
    }

    public function validate($mail, $password)
    {
        $pass_hashed = sha1($mail . $password);
        return parent::get(array('user_mail'     => $mail, 'user_password' => $pass_hashed));
    }

}
/* End of file users_model.php */

/* Location: ./application/models/users_model.php */

验证方法更简单,我不做任何控制。只是Db操作。

现在我的控制器accueil.php

<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class Accueil extends MY_Controller
{

    public function __construct()
    {
        parent::__construct();
        $this->load->model('users_model', 'users_m');        // Chargement model
        $this->load->library('form_validation');             // Librairie validation
        $this->load->helper(array('form', 'url'));           // helpers
        $this->load->library('template');                   // Librairie template
    }

    public function index($msg = NULL) //msg en cas d'erreur , NULL si pas d'erreur
    {
        $data['msg'] = $msg;
        $this->load->view('login', $data);
    }

public function login()
    {

        try
        {
            $user = $this->users_m->validate($this->input->post('user_mail'), $this->input->post('password'));

            $this->session->set_userdata(array(
                'user_id'   => $user->user_id,
                'user_mail' => $user->user_mail,
                'validated' => TRUE
            ));

            redirect('users');
        }
        catch (Exception $e)
        {
            // Pas de validation on renvoit vers l'index avec un message d'erreur
            $msg = '<font color=red>Nom d\'utilisateur ou mot de passe incorrect(s).</font><br />';
            $this->index($msg);
        }
    }

}

/* End of file accueil.php */
/* Location: ./application/controllers/accueil.php */

我的观点仍然相同,没有变化。

我想我这次更正确地编写了代码。

使用控件分隔数据库操作。

随意发表评论。

答案 3 :(得分:0)

如果缺少以下语句,有时会发生这种情况 (即,url helper尚未手动或自动加载) $this->load->helper('url');

答案 4 :(得分:0)

替换

num_row() 

由此:

if(!empty($Variable))
...............

答案 5 :(得分:0)

如果解决使用太难:

$count($query);

代替

$query->num_rows();

:/