2

私は CodeIgniter を使用して php Web アプリケーションを構築しています。また、適切な OO プラクティスを使用しようとしていますが、これには多くの流派があるようです。特に、MySQL テーブルとやり取りするためのクラス biography_model があります。このデータ モデルには、テーブル内の列を表すいくつかのクラス プロパティがありますが、 などのテーブルにないプロパティもいくつかあります$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

できます。しかし、それは合理的なアプローチですか?他にもっと受け入れられている方法はありますか?データベースに 2 回クエリを実行していることはよくわかっていますが、これを処理するより良い方法がわかりませんでした。すべての提案を歓迎します!

ありがとう、ウルフ

4

2 に答える 2

2

通常、関数には1つのジョブがある方がよいでしょう。get_biography()関数には2があります。1つの伝記を取得し、すべての伝記を取得します。それらを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;
}

__getまた、phpと__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 に答える
2

一連のレコードを表すために配列を使用することは、完全に有効なアプローチです。

ただし、プロパティimage_urlは別のプロパティの値に直接依存するため、別のフィールドとして保存する意味はありません。その場で計算するだけです。あなたの場合は、get_propertyメソッドでそれを行う必要があります。

一方、モデルは本当に URL の処理を​​担当する必要があるのでしょうか? 私はそうは思わない。Biography_modelオブジェクトを取得し、その .xml に基づいて画像の URL を生成するモデルの外部にメソッドが必要image_file_nameです。コントローラーを URL にマッピングするルーティング モジュールが既にある場合、このコードはおそらくそこに到達するはずです。

于 2010-09-19T22:16:57.893 に答える