如何在Codeigniter中实现存储库模式?

时间:2012-02-17 09:27:06

标签: php model-view-controller codeigniter repository-pattern

当我在ASP.NET MVC中编程时,有一个称为Repository的简洁模式。我想在Codeigniter中实现它,但我不知道如何。这就是我真正想要的:

$mock_repository = new MockRepository();
$mock_repository->add(new Item(‘title1′, ‘description1′, 1));
$mock_repository->add(new Item(‘title2′, ‘description2′, 2));
$mock_repository->add(new Item(‘title3′, ‘description3′, 1));
$controller = new Item_controller($mock_repository);
$items = $controller->get_items_by_user_id(1);
$this->_assert_equals(count($items), 2);

我正在使用TOAST进行单元测试。那么如何在测试中实例化控制器呢?测试当然是另一个控制器本身。

3 个答案:

答案 0 :(得分:2)

据我所知,要像在​​C#中一样创建一个通用存储库模式,你需要PHP 5.6所拥有的两件事:

  1. 实际方法重载。
  2. PHP中的通用接口或通用抽象类。
  3. 点击C#中的通用存储库模式here for more

    然而你仍然可以借助魔术方法 __ call 在PHP中创建伪方法重载,我们可以输入更多的代码模式的通用部分。

    注意:在Codeigniter 3.0中创建此模式之前,您需要在数据库中创建一个表,并为文件夹应用程序/库创建自动加载器。

    首先 我们需要在application / libraries文件夹中创建 Interface

    sendQuestion() -> askQuestion() -> getQuestion()

    Seconde 我们需要创建抽象类,实现接口并扩展 CI_Model 能够使用数据库图书馆:

    <?php
    
    interface IRepository
    {
        public function getById($id);
        public function select($columns);
        public function delete($id);
    }
    

    第三次 测试存储库。在应用程序/模型中创建一个新模型,并扩展Base_repository,设置表名和重载保存方法,为此模型创建实体:

    <?php
    
    abstract class Base_repository extends CI_Model implements IRepository
    {
        /**
         * This must be valid table name in the Database.
         *
         * @var string $table Name of the table.
         */
        protected $table;
    
        public function __construct()
        {
            parent::__construct();
        }
    
        /**
         * Pseudo method overloading.
         * It's called when method is not declared in the abstract class.
         *
         * @param string $name      Name of the method
         * @param mixed  $arguments Arguments of the method
         */
        public function __call($name, $arguments)
        {
            switch ($name)
            {
                case 'save':
                    if ($arguments[0]->id > 0)
                    {
                        $this->update($arguments[0]);
                    }
                    else
                    {
                        $this->insert($arguments[0]);
                    }
                break;
            }
        }
    
        /**
         * Get row with id.
         *
         * @param  integer $id
         * @return mixed
         */
        public function getById($id)
        {
            return $this->db->get_where($this->table, ['id' => $id])->row_array();
        }
    
        /**
         * Select columns.
         *
         * @param  array $columns
         * @return mixed
         */
        public function select($columns = ['*'])
        {
            $this->db->select($columns);
            return $this->db->get($this->table)->result();
        }
    
        /**
         * Insert data.
         *
         * @param  object $item
         * @return void
         */
        private function insert($item)
        {
            unset($item->id);
            $this->db->insert($this->table, $item);
        }
    
        /**
         * Update data.
         *
         * @param  object $item
         * @return void
         */
        private function update($item)
        {
            $this->db->where('id =', $item->id);
            unset($item->id);
            $this->db->update($this->table, $item);
        }
    
        /**
         * Delete data.
         *
         * @param  integer $id
         * @return void
         */
        public function delete($id)
        {
            $this->db->delete($this->table, ['id' => $id]);
        }
    
    }
    

    在控制器中尝试一下。加载模型并尝试获取,插入等...

    创建真实模型的过程与此相同。如果您需要添加更多对每个模型都相同的方法,如果您只需要为特定模型创建方法,则在抽象类中添加它们。仅在此模型中添加它。

    我不推荐Codeigniter freamwork 。以下是PHP CLICK的一些模式!

答案 1 :(得分:0)

您必须完全劫持系统文件才能从另一个控制器加载控制器。这是不可能做到的,可以解决。

答案 2 :(得分:0)

可以用HMVC完成。

$result = Modules::run('controller/get_items_by_user_id', $params);

$this->_assert_equals($result, $expected);