我正在使用CodeIgniter构建一个php Web应用程序,我正在尝试使用良好的OO实践 - 其中似乎有许多思想流派。我特意有一个类的传记_model来与MySQL表进行交互。此数据模型具有一些表示表中列的类属性,但它在表中还有一些属性不,例如$image_url
。类构造函数接受一个可选的记录ID参数,该参数然后从表中获取该记录,并通过调用get_biography()
方法设置所有对象属性,包括不在表中的$image_url
属性。这样我就可以在控制器中实例化一个新的biology_model对象,并准备好所有有用的属性:$bio = new biography_model($id);
但是,当我们从表中返回多行记录集时,最好的方法是什么?对于每条记录,我还需要设置$image_url
。我可以在控制器中执行此操作,方法是查询表中的记录列表,然后将每个id传递给新的tradition_model($ id)对象。但后来我会遇到这样一种情况:控制器直接查询绕过模型的数据库。
相反,我选择从biology_model中返回一个tradition_model对象数组。
实施例:
class Biography_model extends Model
{
/**
* This model manages biography information in the 'biography_content' table.
* If a biography ID is passed in when instantiating a new object,
* then all class properties are set.
*/
protected $id;
protected $person_name;
protected $title;
protected $image_file_name;
protected $image_url;
protected $biography_text;
protected $active;
/**
* Constructor
*
* If an id is supplied when instantiating a new object, then
* all class variables are set for the record.
*/
public function __construct($person_id = NULL)
{
parent::Model();
if(isset($person_id))
{
$this->set_property('id',$person_id);
$this->get_biography();
}
}
/**
* Sets supplied property with supplied value.
*/
public function set_property($property, $value)
{
// Set image path if $value is the file name
if($property == 'image_file_name')
{
$this->set_property('image_url',$this->get_bio_img_url($value));
}
$this->$property = $value;
}
/**
* Gets requested property value.
*/
public function get_property($property)
{
return $this->$property;
}
/**
* Returns the biography thumbnail image URL
*/
public function get_bio_img_url($image_name)
{
return $this->config->item('parent_url').'assets/img/biography/'.$image_name;
}
/**
* Get one or more biography entries
*/
public function get_biography()
{
// If the ID is set then set model properties.
if($this->get_property('id'))
{
$this->db->where('id',$this->get_property('id'));
$query = $this->db->get('biography_content');
if($query->num_rows() == 1)
{
foreach($query->row() as $key => $value)
{
$this->set_property($key, $value);
}
}
}
// Otherwise return result set of all biographies
else
{
// Get the list of record ID's
$this->db->select('id');
$query = $this->db->get('biography_content');
if ($query->num_rows() > 0)
{
// New array to return result set
$biography_list = array();
// For each record, return a new biography_model object
foreach($query->result() as $value)
{
$biography_list[] = new biography_model($value->id);
}
}
return $biography_list;
}
}
}
// End of Biography_model Class
有效。但这是一种合理的方法吗?还有其他更受欢迎的方法吗?我敏锐地意识到我两次查询数据库,但我不确定是否有更好的方法来处理这个问题。欢迎所有建议!
谢谢,狼
答案 0 :(得分:2)
使用数组表示一组记录是一种非常有效的方法。
但是属性image_url
直接取决于另一个属性的值,因此将其存储为单独的字段没有意义。只需动态计算,在您的情况下,您必须使用get_property
方法进行计算。
另一方面,模型真的要负责处理URL吗?我不这么认为。模型外部应该有一个方法来获取Biography_model
对象,并根据其image_file_name
生成图像的URL。如果您已经有一些路由模块负责将控制器映射到URL,则此代码可能应该落在那里。
答案 1 :(得分:2)
通常情况下,一个职位的职能更好。你的get_biography()函数有2:得到一本传记并获得所有的传记。考虑将它们分成两个函数。此外,不需要多个数据库访问。
public function get_biography($id=null)
{
$this->db->where('id', $this->get_property($id))
$query = $this->db->get('biography_content');
foreach($query->row() as $key => $value)
{
$this->set_property($key, $value);
}
}
public function get_biographies()
{
$biography_list = array();
// don't limit this query to just id's - get everything
$query = $this->db->get('biography_content');
// For each record, return a new biography_model object
foreach($query->result() as $row)
{
$model = new biography_model();
// set the properties you already have straight onto the new model
// instead of querying again with just the id
foreach($row as $key => $value)
{
$model->set_property($key, $value);
}
$biography_list[] = $model;
}
return $biography_list;
}
此外,您可能希望利用php的__get
和__set
魔术方法:
public function __get($property)
{
if(!isset($this->$property))
return null;
return $this->$property;
}
public function __set($property, $value)
{
if(!property_exists($this, $property))
return;
if($property == 'image_file_name')
{
$this->image_url = $this->get_bio_img_url($value);
}
else
$this->$property = $value;
}
这样您就可以获得模型上的属性:$bio->title
而不是$bio->get_property('title')
,同时提供一个可以在以后引入新逻辑的位置。