在MVC模型视图控制器设计中,您可以将模型单独工作并包含商务逻辑,从数据库中提取信息。
我在实施一个好模型的设计上非常挣扎。我知道需要从数据库中下载哪些信息,我只是不知道实现它的最佳方法。我认为该模型是程序API,我用像
这样的问题超载自己我的API /模型变得非常臃肿,为每个功能提供单独的功能和查询(只是轻微调整/更改)
例如
$cart->getShoppingCart()
$cart->getShoppingCartSortByTitle()
$cart->getShoppingCartGroupByItemType()
我觉得这使得模型非常臃肿且非常紧密,创造了大量重复的代码。拥有这种模型可能会更好;
更好的主意
$cart->getItems('title, price')->order_by('title');
'title, price'
是您可以选择的mySQL字段,显然是由getItems()
函数验证的。这样,它不仅限于返回某些字段。
答案 0 :(得分:1)
使用对象关系映射(ORM)...
尝试Doctrine ORM项目。
另一种解决方案是CodeIgniter,它拥有最好的活动记录库。非常有帮助。
如果您仍然决定编写自己的类,请使用PHP5的method chaining。语法会更漂亮......
答案 1 :(得分:0)
Code Igniter framework数据库管理允许您在数据库上执行此类请求,限制复制/粘贴代码。
请参阅其文档中的Active Records module
我认为他们的模型非常好。
答案 2 :(得分:0)
“更好的主意”绝对是一个更好的主意。您可以考虑查看Django implements this的方式,因为这是在那里使用的方法。 Django是用Python编写的,它确实使一些事情变得更容易,但你也应该能够在PHP中使用那里的概念(只是有点不那么整洁)。总而言之,创建查询会创建一个查询对象,该对象具有order_by等方法。应用这些方法将改变查询的状态,只有在实际执行查询时才需要生成SQL并在数据库上执行它。
如果您坚持使用前者,您可以考虑使用动态名称的“魔术方法”,就像许多现有框架一样。例如,
getShoppingCart_groupby
getShoppingCart_orderby
你将拥有一个带有动态参数列表的'catch-all'方法,该列表读取被调用函数的名称,并在有效时执行所需的行为(如果有效则抛出标准的'找不到方法'错误它不是)。这与你现在正在做的基本相同,但它会整理代码并整理你的模型。你需要PHP5,而且你正在寻找the __call magic method。
Julien在他的回答中提到了Code igniter - 编写好的模型非常困难,所以通常你最好使用现有的框架。 (但尝试很有趣!)
答案 3 :(得分:0)
首先,请确保您自问的所有“问题”都涉及您的应用程序现在实际需要的功能。我在设计新项目时遇到的最大问题之一是投机设计。只添加你需要的东西。为您添加的内容编写单元测试。当您到达需要额外功能的位置时,如有必要,请重构为更好的设计。
如果您确实需要预先提供所有功能,我仍然建议使用重构方法。实现一些您可以看到相似或有助于“膨胀”的功能。当你完成后,退后一步,看看你是否可以重构更优雅的东西或者在不同的对象和/或方法之间更均匀地分配责任的东西。然后继续。各种“模式”和“重构”书籍将在这里为您提供很多帮助。
答案 4 :(得分:0)
首先,你应该考虑的是:
如果我选择*只是因为调用函数可能需要删除任何信息,那么性能会受到多大影响?
这取决于您网站的负载。大多数时候(如果你没有拉大blob和文本)*没问题,但是当资源稀缺时,你必须指定列。所以你可以节省一些IO时间。
我觉得这使得模型非常臃肿且非常紧密,创造了大量重复的代码。使用这种模型可能会更好;
也许试试这个:
首先,对于复杂的查询,我使用我很久以前为MySQL做的这个类。它帮助了很多人。
class sqlAssembler
{
private $data = array();
var $S = array();
var $F = array();
var $W = array();
var $G = array();
var $H = array();
var $O = array();
var $L = array();
//Clause abbreviations
var $clauselist = array
(
'S' => 'SELECT',
'F' => 'FROM',
'W' => 'WHERE',
'G' => 'GROUP BY',
'H' => 'HAVING',
'O' => 'ORDER BY',
'L' => 'LIMIT'
);
//Default clause separators
var $clausesep = array
(
'S' => ',',
'F' => ',',
'W' => ' AND ',
'G' => ',',
'H' => ' AND ',
'O' => ',',
'L' => ''
);
function gen()
{
$tmp = '';
foreach ( $this->clauselist as $area => $clause )
{
if ( count($this->{$area}) )
{
$tmp .= ($clause != 'S' ? ' ' : '') . $clause . ' ';
for ($i=0; $i < count($this->{$area}); $i++)
{
//echo $area = (string)$area;
$tmp .= $this->{$area}[$i];
} //for
} //if
} //foreach
return $tmp;
} //function
function genSection($area, $showsection = 0)
{
$tmp = '';
if ( count($this->{$area}) )
{
for ($i=0; $i < count($this->{$area}); $i++)
{
$tmp .= $this->{$area}[$i];
} //for
} //if
return $tmp;
} //function
function clear()
{
foreach ($this as $area => $v)
{
//We only care about uppercase variables... do not declare any else variable with ALL UPPERCASE since it will be purged
if (ctype_upper($area))
{
if ($area == 'L')
$this->$area = '';
else
$this->$area = array();
} //if
} //foreach
} //function
public function add($area, $str, $criteria = 1, $sep = '#')
{
if ($criteria)
{
if ($sep == '#')
$sep = $this->clausesep[$area];
//Postgres' OFFSET should be set like: $str = '25 OFFSET 0'
//Not very neat I know, but fuck it
if ($area == 'L')
{
$this->{$area} = array();
} //if
//$ref = $this->$area;
$this->{$area}[] = (count($this->$area) ? $sep : '').$str;
return count($this->$area)-1;
} //if
} //function
public function del($area,$index)
{
if ( isset($this->{$area}[$index]) )
unset($this->{$area}[$index]);
else
trigger_error("Index nr. {$index} not found in {$area}!",E_USER_ERROR);
} //function
//-*-* MAGIC CHAIN FUNCTIONS
public function S($str,$criteria = 1,$sep = '#')
{
$this->add(__FUNCTION__,$str,$criteria,$sep);
return $this;
} //function
public function F($str,$criteria = 1,$sep = '#')
{
$this->add(__FUNCTION__,$str,$criteria,$sep);
return $this;
} //function
public function W($str,$criteria = 1,$sep = '#')
{
$this->add(__FUNCTION__,$str,$criteria,$sep);
return $this;
} //function
public function G($str,$criteria = 1,$sep = '#')
{
$this->add(__FUNCTION__,$str,$criteria,$sep);
return $this;
} //function
public function H($str,$criteria = 1,$sep = '#')
{
$this->add(__FUNCTION__,$str,$criteria,$sep);
return $this;
} //function
public function O($str,$criteria = 1,$sep = '#')
{
$this->add(__FUNCTION__,$str,$criteria,$sep);
return $this;
} //function
public function L($str,$criteria = 1,$sep = '#')
{
$this->add(__FUNCTION__,$str,$criteria,$sep);
return $this;
} //function
} //_sql
也许试试这个:
function getShoppingCart($d)
{
$xx = new sqlAssembler();
$xx->S('*')->
F('items')->
//Notice, that we specified a criteria... if $d['id_item'] exists it will be joined to the WHERE clause, if not it will be left out
W("(id_item > '{$d[id_item]}')",$d['id_item'])->
//Same here
O("dt DESC",$d['date'])
$sql = echo $xx->gen();
//id_item = 11, date = 2009-11-12
//$sql = "SELECT * FROM items WHERE (id_item > '11') ORDER BY dt DESC";
//id_item = null, date = null
//$sql = "SELECT * FROM items";
$data = sqlArray($sql);
//... handle data
}
答案 5 :(得分:0)