簡體   English   中英

CodeIgniter-最佳模型方法

[英]CodeIgniter - Best Model Approach

這已經困擾了我好一段時間了。

在我看來,控制器是我進行驗證,模型調用和數據顯示的地方。 在模型上,只有一個目的,就是我進行SQL查詢的地方。

但是在Model上最好的方法是什么。 我是否必須使用不同的條件/方法來創建許多函數,還是必須在單個函數中完成所有這些工作,這些函數專用於數據庫中的單個表。 以下面的代碼為例:

多種功能:

class Sword_model extends CI_Model {

    public function __construct()
    {
        $this->load->database();
        $this->load->library('session');
        $this->load->helper('url_helper');
    }

    public function getsword($swordid = NULL)
    {
        if($swordid === NULL){
            $query = $this->db->query("SELECT * FROM sword_tb");
            return $query->result_array();
        }

        $query = $this->db->query("SELECT * FROM sword_tb WHERE sword_id = ?", array($swordid));
        return $query->row_array();
    }

    public function getstrongswords($strong = NULL)
    {

        if($strong === NULL){
            return false;
        }

        $query = $this->db->query("SELECT * FROM sword_tb WHERE strong = ?", array($strong));
        return $query->result_array();

    }

    /*** AND MORE SUCCEEDING FUNCTIONS BELOW FOR DIFFERENT COLUMNS/CONDITIONS ***/
}

優點:這是直通且易於理解的(而且我認為速度更快)
缺點:您必須手動創建用於不同條件/列的函數


單一功能:

class Sword_model extends CI_Model {

    public function __construct()
    {
        $this->load->database();
        $this->load->library('session');
        $this->load->helper('url_helper');
    }

    public function getsword($column = NULL, $value = NULL, $condition = 'AND')
    {

        $query = 'SELECT * FROM sword_tb';
        $count = count($column);
        for($x = 0; $x < $count; $x++){
            if($x > 0){
                $query .= ' '.$condition;
            } else {
                $query .= ' WHERE (';
            }
            $query .= ' '.$column[$x].' = ?';
        }
        $query .= ' ORDER BY sword_name';

        $query = $this->db->query($query, $value);
        return $query->result_array();

    }

}

使用這種單一函數方法,可以通過將數組作為參數放置來調用此函數,如下所示:

$this->Sword_model->getsword(array('sword', 'strong'), array(3, 1), 'OR');

查詢將如下所示:

SELECT * FROM sword WHERE (sword = ? OR strong = ?) ORDER BY sword_name

如果將其留為空白,查詢將如下所示:

SELECT * FROM sword ORDER BY sword_name

優點:靈活
缺點:比第一種方法慢(?)

兩者之間更理想的是什么? 還是還有其他更理想的方法?

我更喜歡讓每個表都有自己的模型,就像在“多個模型”中所做的那樣,使用不同的首選方法。 這樣,它更易於維護,更易於理解和理解代碼。 第二個問題是,雖然很難解決,但可能並非在所有情況下都有用。

我已經使用Codeigniter MVC和HMVC超過2年了。 到目前為止,第一個選擇是我的選擇,它可以幫助我檢查和維護代碼,還可以幫助我將來進行更新/代碼。

您可以嘗試ORM(對象關系映射)

Datamapper是一個ORM庫,旨在將您的數據庫表映射為易於使用的對象。

成功安裝Datamapper之后

如果您有一個稱為users的表

使用名稱user創建模型

<?php

class User extends DataMapper {

    function __construct($id = NULL)
    {
        parent::__construct($id);
    }
}

在您的控制器中,您可以通過以下方式簡單地訪問數據:

    $u = new user(); // Singular of model name is required
    $u->get();

    foreach ($u as $user => $value) 
    {
        echo $user->name;
    }

通過這種方法,您必須為表創建每個模型並通過控制器訪問數據

我更喜歡一個通用模型,通過該模型我可以執行所有mysql查詢(不是那么復雜,否則,如果需要太多復雜的查詢,則需要編寫查詢字符串並在少數情況下使它執行。)可以通過傳遞數據數組和表名來從控制器調用模型的通用函數,其余部分將由模型管理。 這是我使用的通用模型:

<?php

/*
  All user module related databse functions
  Author : Himanshu Upadhyay (himanshuvarun@gmail.com)
 */

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

class User_Model extends MY_Model {

    public function __construct() {
        parent::__construct();
    }

    public function get_rows($filters = array(), $table = TBL_USER) {
        return parent::get_rows($filters, $table);
    }

    public function get_columns($table = TBL_USER) {
        return parent::get_columns($table);
    }

    public function update_table($data, $where, $table = TBL_USER, $set = '') {
        return parent::update_table($data, $where, $table, $set = '');
    }

    public function get_count($filters = array(), $table = TBL_USER) {
        return parent::get_count($filters, $table);
    }

    public function insert($data, $table = TBL_USER) {
        return parent::insert($data, $table);
    }

    public function delete($where, $table = TBL_USER) {
        return parent::delete($where, $table);
    }
/* End of file user_model.php */
/* Location: ./application/models/user_model.php */
?>

在您的控制器中,您可以像這樣調用模型函數:

$user_data['first_name'] = 'ABC';
$user_data['last_name'] = 'XYZ';
$this->user_model->insert($user_data, 'tbl_users');  // This is calling `insert` function of user model with first array argument with the data with column names as keys of the array and 2nd argument is the table name.

結論:因此,通過這種方法,您可以在所有控制器中加載user_model ,並且可以在所有控制器中使用其所有通用功能。 因此,這種方法避免了多余的模型函數來獲取,插入和更新數據,並且通過為每個表定義不同的模型來節省了我們。

大多數時候,多個功能更易於調試,理解和維護。

也就是說,您可以使多方法模型代碼的重復性降低很多。 考慮以下。 __construct()未顯示,因為您沒問題。)

class Sword_model extends CI_Model
{
    protected $get_all_sql = 'SELECT * FROM sword_tb';
    protected $get_where_sql = "SELECT * FROM sword_tb WHERE sword_id = ?";

    public function getsword($swordid = NULL)
    {
        $sql = isset($swordid) ? $this->get_where_sql : $this->get_all_sql;
        $bind = isset($swordid) ? $swordid : FALSE;
        return $this->do_Query($sql, $bind);
    }

    public function getstrongswords($strong = NULL)
    {
        if(isset($strong))
        {
            return $this->do_Query($this->get_where_sql, $strong);
        }
        //Returning an empty array means the controller can skip doing a conditional 
        //check for a model return === FALSE.
        //foreach() won't choke on an empty array, but it will choke if passed FALSE
        return array();
    }

    protected function do_Query($sql, $binds = FALSE)
    {
        $query = $this->db->query($sql, $binds);
        return $query->result_array();
    }
}

但是,在某些情況下,“靈活”的方法可能會有用。

“單人”與“靈活”之間的速度差異可以忽略不計,而不是一個考慮因素。 需要考慮的是,當您嘗試應對更多“條件”時,“靈活”很快變得笨拙。

有一些東西會使編寫“靈活的”模型方法更容易-易於編寫,理解,調試和維護。 使用查詢生成器,而不是手動構造查詢字符串並將其傳遞給$this->db->query() 它專為需要有條件地構建查詢語句的情況而設計。

getsword() “靈活”版本至少有一個限制,那就是您不能選擇不屬於WHERE子句的列。

在這里使用查詢生成器是一種可以實現為AND WHERE和OR WHERE子句構建查詢的靈活方法的方法。 希望該方法之前的DocBlock能夠提供一些見解。

class Sword_model extends CI_Model
{
    protected $get_all_sql = 'SELECT * FROM sword_tb';
    protected $get_where_sql = "SELECT * FROM sword_tb WHERE sword_id = ?";

    /**
     * 
     * @param mixed $columns The columns to retrieve. Can be either a string 
     * e.g. 'title, content, date',
     * or it can be an array e.g. array('title', 'content', 'date') 
     * 
     * @param array $where If provided, must be an associative array where 
     * the key => value is 'field_name' => value_to_match, e.g. 
     * array('title' => "Kill Bill") 
     * $where requires a different structure when the $condition argument is 
     * "OR". In this case the value part should provide multiple values. 
     * These values can be provided either in an array 
     * or a comma separated string list. For instance:
     *    As an array, $where = array('field_name' => array('val1', 'val2'));

     *    As a string, $where = array('field_name' => 'val1, val2'));
     * 
     * @param string $condition For this example can be either 'AND' (default) or 'OR'
     */
    public function getsword($columns = NULL, $where = NULL, $condition = 'AND')
    {
        if(!empty($columns)) //No $columns means SELECT *
        {
            $this->db->select($columns);
        }

        $condition = strtoupper($condition); //Don't assume
        if(!empty($where))
        {
            if($condition === 'OR')
            {
                foreach($where as $key => $values)
                {
                    if(is_string($values))
                    {
                        $values = explode(', ', $values);
                    }
                    if(is_array($values))
                    {
                        foreach($values as $matching)
                        {
                            $match = [$key => $matching];
                            $this->db->or_where($match);
                        }
                    }
                    else
                    {
                        $this->db->or_where($key, $values);
                    }
                }
            }
            else
            {
                $this->db->where($where);
            }
        }

        return $this->db
          ->order_by('sword_name')
          ->get("sword_tb")
          ->result_array();
    }

}

您可能會看一下街區

                        foreach($values as $matching)
                        {
                            $match = [$key => $matching];
                            $this->db->or_where($match);
                        }

並在調用where()之前or_where()的使用。 查詢生成器足夠聰明,可以知道是否添加了其他任何WHERE,並且如果不需要,也不會在“ WHERE”前放置“ OR”。

讓我們看一些用法示例。

$this->sword_model->getsword();

產生查詢語句

SELECT * FROM sword_tb排序方式

$this->sword_model->getsword('model, sword_name, cost', array('model' => 'Broad'));

產生

SELECT模型,sword_name,成本FROMwords_tb WHERE模型=廣泛ORDER BY sword_name

$this->sword_model->getsword(NULL, array('model' => 'Broad', 'cost <' => 100));

SELECT * FROM sword_tb哪里模型=廣泛AND成本<100 ORDER BY劍名

$this->sword_model->getsword('model, sword_name, cost',
      array('model' => 'Broad, Samurai', 'sword_name' => 'Excalibur'), 'or');

SELECT模型,sword_name,成本FROMwords_tb WHERE模型=廣義OR模型=武士OR sword_name = Excalibur ORDER BY sword_name

$this->sword_model->getsword(NULL,
      array('model' => 'Broad, Samurai', 'sword_name' => ['Excalibur', 'Fred']), 'or');

選擇* FROM sword_tb,其中模型=寬泛OR模型=武士OR劍名=神劍OR劍名=弗雷德·ORDER BY劍名

注意:我從生成的查詢字符串中刪除了back-tic,因為在這里看起來很奇怪。 放心,一切都已妥當。

如果您擔心速度,我會以上述為基准。 建立查詢語句所需的最長時間為0.0007秒。 要構建所有五個查詢,總共需要0.0022秒-每個平均0.00044秒。

注意,現在是構建語句的時候了。 檢索數據的時間不包括在內,因為……我沒有數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM