[英]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.