这已经困扰了我很长一段时间了。
控制器,就我而言,是我进行验证,模型调用和数据显示的地方。在模型上,只有一个目的,就是我进行SQL查询的地方。
但是什么是模型的最佳方法。我是否必须使用不同的条件/方法制作许多功能,或者我必须在单个功能中完成所有功能,专用于数据库中的单个表。以下面的代码为例:
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
优点:灵活的 缺点:比第一种方法更慢(?)
两者之间更理想的是什么?或者还有其他更理想的方式吗?
答案 0 :(得分:1)
我更喜欢让每个表都拥有自己的模型,使用不同的方法,就像在“多个模型”中一样。这样,它更易于维护,更容易接近和理解代码。第二个是虽然它更难以接近,但它可能在所有情况下都没用。
我一直在使用Codeigniter MVC&amp; HMVC超过2年。第一个是我到目前为止的选择,它帮助我检查和维护我的代码,也有助于我将来的更新/代码。
答案 1 :(得分:1)
您可以尝试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;
}
通过这种方法,您必须为表创建每个模型并通过控制器访问数据
答案 2 :(得分:1)
我更喜欢一个通用模型,我可以使用它执行所有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
,并且可以在所有控制器中使用其所有通用功能。因此,这种方法避免了冗余模型函数来获取,插入和更新数据,并且通过为每个表定义不同的模型来节省我们。
答案 3 :(得分:1)
大多数情况下,多个函数更容易调试,理解和维护。
也就是说,你可以使你的多方法模型代码重复性降低很多。
考虑以下。 (__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();
}
}
然而,&#34;灵活&#34;方法在某些情况下可能有用。
&#34;单身&#34;之间的速度差异vs&#34;灵活&#34;是微不足道的,不是考虑因素。需要考虑的是&#34;灵活的&#34;当你试图回应更多&#34;条件时,你会很快变得笨拙。
有些东西会使写作变得更加灵活&#34;模型方法更容易 - 更容易编写,理解,调试和维护。而不是手动构建查询字符串并将其传递给$this->db->query()
使用Query Builder。它专为需要有条件地构建查询语句的情况而设计。
你的&#34;灵活的&#34; getsword()
的版本至少有一个限制,即您不能选择不属于WHERE子句的列。
在这里使用Query Builder是一种可以实现灵活方法的方法,该方法为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);
}
并在致电or_where()
之前询问where()
的使用情况。查询生成器足够聪明,可以知道是否已添加任何其他WHERE并且不会放置&#34; OR&#34;在&#34; WHERE&#34;前面如果不需要的话。
让我们看看一些用法示例。
$this->sword_model->getsword();
生成查询语句
SELECT * FROM sword_tb ORDER BY sword_name
$this->sword_model->getsword('model, sword_name, cost', array('model' => 'Broad'));
产生
SELECT model,sword_name,cost FROM sword_tb WHERE model = Broad ORDER BY sword_name
$this->sword_model->getsword(NULL, array('model' => 'Broad', 'cost <' => 100));
SELECT * FROM sword_tb WHERE model = Broad AND cost&lt; 100 ORDER BY sword_name
$this->sword_model->getsword('model, sword_name, cost',
array('model' => 'Broad, Samurai', 'sword_name' => 'Excalibur'), 'or');
SELECT model,sword_name,cost FROM sword_tb WHERE model = Broad OR model = Samurai OR sword_name = Excalibur ORDER BY sword_name
$this->sword_model->getsword(NULL,
array('model' => 'Broad, Samurai', 'sword_name' => ['Excalibur', 'Fred']), 'or');
SELECT * FROM sword_tb WHERE model = Broad OR model = Samurai OR sword_name = Excalibur OR sword_name = Fred ORDER BY sword_name
注意:我从生成的查询字符串中删除了后台抽象,因为在这里它看起来很奇怪。请放心,一切都妥善逃脱。
如果您担心速度,我会对上述情况进行基准测试。构建查询语句所需的最长时间为0.0007秒。要构建所有五个查询,总共需要0.0022秒 - 平均每个0.00044。
注意,现在是构建语句的时候了。检索数据的时间不包括在内,因为......好吧......我没有数据。