2

我正在使用 CodeIgniter 构建一个 php Web 应用程序,并且我正在尝试使用良好的 OO 实践——其中似乎有很多思想流派。我特别有一个类 biography_model 来与 MySQL 表交互。这个数据模型有一些类属性表示表中的列,但它也有一些表中没有的属性,例如$image_url. 类构造函数接受一个可选的记录 ID 参数,然后从表中获取该记录并通过调用该get_biography()方法设置所有对象属性,包括$image_url不在表中的属性。这样我就可以在控制器中实例化一个新的 biography_model 对象,并准备好所有有用的属性:$bio = new biography_model($id);

但是,当我们从表中返回记录的多行结果集时,最好的方法是什么?对于每条记录,我还需要设置$image_url. 我可以在控制器中执行此操作,方法是查询表中的记录列表,然后将每个 id 传递给新的 biography_model($id) 对象。但是后来我会遇到控制器绕过模型直接查询数据库的情况。

相反,我选择从 biography_model 中返​​回一个 biography_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

有用。但这是一个合理的方法吗?还有其他更受欢迎的方法吗?我敏锐地意识到我正在查询数据库两次,但我不确定有更好的方法来处理这个问题。欢迎所有建议!

谢谢,狼

4

2 回答 2

2

使用数组来表示一组记录是一种完全有效的方法。

但是该属性image_url直接依赖于另一个属性的值,因此将其存储为单独的字段是没有意义的。只需即时计算,在您的情况下,您必须在get_property方法中执行此操作。

另一方面,模型真的应该负责处理 URL 吗?我不这么认为。模型之外应该有一个方法可以获取Biography_model对象并根据其生成图像的 URL image_file_name。如果您已经有一些路由模块负责将控制器映射到 URL,那么这段代码可能应该在那里。

于 2010-09-19T22:16:57.893 回答
2

通常功能最好有一份工作。您的 get_biography() 函数有 2:获取一本传记并获取所有传记。考虑将它们分成 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')同时提供一个可以稍后引入新逻辑的地方。

于 2010-09-19T22:38:20.127 回答