Я создаю пользовательскую структуру MVC с помощью PHP. Моя проблема в том, когда я хочу получить доступ к любому классу модели через класс контроллера. Один из способов, который я видел, это сделать через шаблон дизайна реестра, используя магические методы, такие как get и set, хотя PHP get и set считаются плохой практикой для некоторых. Я прочитал об инъекции зависимостей, выполненной через контейнер, но я не вижу, чтобы это работало эффективно, поскольку контейнер должен был бы вызвать модели, или он должен был содержать модели, которые могли бы победить цель MVC и создать массивный суперкласс. Синглтон считается плохой практикой. Есть ли какие-либо решения или улучшения методов, о которых я упомянул. Это может быть просто мое понимание, и знание PHP нуждается в улучшении.
В настоящее время у меня есть это: router.php (загружает controllor через GET varible
<?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 } } } ?>
Надеюсь, что это делает
Прежде всего … Не ставьте автозагрузку в механизм маршрутизации. Вы смешиваете обязанности. Вам будет лучше создать отдельный класс для этого на основе spl_autoload_register
.
Neeext .. do no сложность операций над конструктором. Это заставляет вас кодировать несколько непроверяемых. Может быть, вы должны быть чем-то вроде:
// 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-запросы.
В ситуации полу реального мира () он может выглядеть примерно так (относящийся к коду abowe):
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 ... }
Как вы видите, нет никаких указаний на то, как данные были сохранены. Даже не имеет значения, была ли учетная запись пользователя новой или уже существует.
Некоторые материалы, которые могут вам пригодиться
Видео
Книги:
Большой контейнер для инъекций зависимостей – это «прыщ», который некоторыми из них может считаться локатором обслуживания. Он использует закрытие 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');
Это позволяет сохранять гибкость в том, что вы можете изменить способ создания и создания объектов во всем своем проекте, только изменяя очень малый объем кода.