Лучший вариант для вызова функциональности модели в контроллере PHP - PullRequest
4 голосов
/ 13 марта 2012

Я создаю пользовательский MVC-фреймворк с использованием PHP. Моя проблема, когда я хочу получить доступ к любому классу модели через класс контроллера. Один из способов, с помощью которых я видел это, - это шаблон проектирования реестра с использованием магических методов, таких как get и set, хотя PHP get и set считаются некоторыми плохой практикой. Я читал о внедрении зависимостей, выполняемых через контейнер, но я не могу видеть, как это работает эффективно, так как контейнер должен вызывать модели или содержать модели, которые бы опровергли цель MVC и создали огромный суперкласс. Синглтон считается плохой практикой. Есть ли какие-либо решения или улучшения методов, которые я упомянул. Это может быть только мое понимание, и знание PHP нуждается в улучшении.

В настоящее время у меня есть это: router.php (загружает контроллер через переменную GET

 <?php

class router {



function __construct() {

    if (file_exists("controller/".$_GET['url']."Controller.php"))  {


       function __autoload($controller) {

           $controlinclude = "controller/".$controller.".php";
            include $controlinclude;

      }
       $control = $_GET['url']."Controller";
        new $control();


    }
    else    {

        // throw exception
    }

}

}
?>

Надежда, которая имеет смысл

Ответы [ 2 ]

5 голосов
/ 13 марта 2012

Прежде всего ... Не ставьте автозагрузочный скрипт в механизм маршрутизации. Вы смешиваете обязанности. Вам лучше создать отдельный класс для этого на основе spl_autoload_register.

Neeext .. не ставить сложные операции над конструктором. Это делает ваш код несколько непроверенным. Может быть, вы должны быть что-то вроде:

// you might want to replace $_GET with $_SERVER['QUERY_STRING'] later
$router = new Router( $_GET['url'] );

// where 'default' is the name of fallback controller
$controller_class = $router->get_controller( 'default' );
$method_name = $router->get_action( 'index' );

$model_factory = new ModelFactory( new PDO( ... ) );
$controller = new {$controller_class}( $model_factory );
$controller->{$method_name}();

Кроме того, вы должны изучить пространства имен php . Нет смысла заканчивать класс с ...Controller, просто чтобы знать, где будет находиться класс.

Хорошо ... вернемся к модели.

Существует довольно распространенное заблуждение о моделях в сообществе веб-разработчиков (я обвиняю RoR в этом беспорядке). Модель в MVC - это не класс , а прикладной уровень, который содержит множество экземпляров. Большинство экземпляров принадлежат к одному из двух типов классов. Со следующими обязанностями:

  • Доменная логика :

    Имеет дело со всеми вычислениями, расчетами и всеми специфическими для домена деталями. Объекты в этой группе не знают, где и как на самом деле хранятся данные. Они только манипулируют информацией.

  • Доступ к данным

    Обычно состоит из объектов, которые соответствуют шаблону DataMapper (не путайте с ORM с тем же именем .. ничего общего). Отвечает за хранение данных из доменных объектов и их получение. Может быть в базе данных .. не может. Вот где будут ваши SQL-запросы.

В ситуации полуреального мира () это может выглядеть примерно так (связано с кодом выше):

class SomeController
{
   // ... snip ...
   protected $model_factory = null;
   // ... snip ...

   public function __construct( ModelFactory $factory )
   {
       $this->model_factory = $factory;
   }
   // ... snip ...

   public function action_foobar()
   {
      $user = $this->model_factory->build_object( 'User' );
      $mapper = $this->model_factory->build_mapper( 'User' );

      $user->set_id(42);
      $mapper->fetch($user);

      if ( $user->hasWarning()  )
      {
          $user->set_status( 'locked' );
      }

      $mapper->store( $user );
   }

   // ... snip ...
}

Как видите, нет указаний на то, как были сохранены данные. Не имеет значения, была ли учетная запись новой или уже существующей.

Некоторые материалы, которые вам могут пригодиться

Видео

Книга:

1 голос
/ 13 марта 2012

Отличным контейнером для инъекций зависимости является «прыщ», который некоторые могут считать сервисным локатором. Он использует замыкания php 5.3 для создания класса, который используется для создания всех объектов вашего проекта с помощью отложенной загрузки. Так, например, вы можете создать замыкание, содержащее код для инициализации данного объекта. Затем вы будете использовать метод get() контейнера DI, который, в свою очередь, вызовет замыкание для создания объекта. Или просто передам вам объект, если он уже создан.

// simplified dic class
class dic {

    protected $closures = array();
    protected $classes = array();

    public function addResource($name, Closure $initialization_closure) {
        $this->closures[$name] = $initialization_closure;
    }

    public function get($name) {
        if (isset($this->classes[$name]) === false) {
           $this->classes[$name] = $this->closures[$name]();
        }
        return $this->classes[$name];
    }
}

//setup
$dic = new dic();
$dic->addResource('user', function() {
   return new UserClass($some_args);
});
$dic->addResource('userContainer', function() use ($dic) {
   return new UserContainerClass($dic->get('user'));
});

// usage
$userContainer = $dic->get('userContainer');

Это позволяет вам сохранять гибкость возможности изменять, как и какие объекты создаются в вашем проекте, изменяя только очень небольшое количество кода.

...