Я строю крошечную структуру MVC для обучения / экспериментирования и небольших проектов. Мне нужно было выяснить основы внутренних компонентов Модели, так как полная структура MVC и ORM переполняют всего несколько запросов к базе данных.
Class Model { }
Использование пустого класса, где я должен был бы вызвать new PDO
объект new PDO
для вызовов базы данных?
Что вызовет запрос, как внутри модели?
Кроме того, где я могу найти ресурс для начинающих / книжный ресурс для MVC (с большим количеством примеров кода)? Я слышал много терминов, таких как бизнес-логика и логика базы данных. Я помню, где-то читал, что вы должны отделить бизнес-логику и логику базы данных. Я могу понять концепцию несколько, мне просто интересно, как это выглядит или что они означают в самом коде. Я смущен тем, что логика бизнес-логики и логика базы данных должны быть разделены, но все еще находиться внутри модели.
В основном я ищу примеры кода / логики в качестве ответов, кроме, может быть, последнего абзаца.
Предупреждение:
Информация на этих постах крайне устарела . Он представляет мое понимание шаблона MVC, как это было более двух лет назад. Он будет обновляться, когда я подхожу к нему. Вероятно, в этом месяце (2013.09).Черт возьми! (2017,11).
Сама Model
не должна содержать SQL. Когда-либо. Он предназначен только для бизнес-логики домена.
Подход, который я бы рекомендовал, состоит в том, чтобы отделить обязанности, которые не являются строго «бизнес-логикой», на два других других набора конструктов: объекты домена и карты данных .
Например, если вы делаете блог, то модель не будет Post. Вместо этого, скорее всего, модель будет Blog, и эта модель будет иметь дело с несколькими Domain Objects
: несколько экземпляров сообщений Post, Comment, User и, возможно, других объектов.
В вашей модели объекты домена не должны знать, как хранить себя в базе данных. Или даже осознавать существование какой- либо формы хранения. Это ответственность Data Mappers
. Все, что вам нужно сделать в Модели, – вызвать $mapper->store( $comment );
, И диспетчер данных должен знать, как хранить один конкретный тип объектов домена, и выигрывать, какая таблица помещает информацию (обычно хранение одного домена фактически влияет на несколько таблиц).
(только соответствующие фрагменты из файлов):
_
в примере, protected
из /application/bootstrap.php
/* --- snip --- */ $connection = new PDO( 'sqlite::memory:' ); $model_factory = new ModelFactory( $connection ); $controller = new SomeController( $request , $model_factory ); /* --- snip --- */ $controller->{$action}(); /* --- snip --- */
из /framework/classes/ModelFactory.php
/* --- snip --- */ class ModelFactory implements ModelBuilderInterface { /* --- snip --- */ protected function _prepare() { if ( $this->_object_factory === null ) { $this->_object_factory = new DomainObjectFactory; } if ( $this->_mapper_factory === null ) { $this->_mapper_factory = new DataMapperFactory( $this->_connection ); } } public function build( $name ) { $this->_prepare(); return new {$name}( $this->_object_mapper , $this->_data_mapper ); } /* --- snip --- */ }
файл /application/controllers/SomeController.php
/* --- snip --- */ public function get_foobar() { $factory = $this->_model_factory; $view = $this->_view; $foo = $factory->build( 'FooModel' ); $bar = $factory->build( 'BarModel' ); $bar->set_language( $this->_request->get('lang') ); $view->bind( 'ergo' , $foo ); /* --- snip --- */ } /* --- snip --- */
файл /application/models/FooModel.php
/* --- snip --- */ public function find_something( $param , $filter ) { $something = $this->_object_factory('FooBar'); $mapper = $this->_mapper_factory('FooMapper'); $something->set_type( $param ); $mapper->use_filter( $filter )->fetch( $something ); return $something; } /* --- snip --- */
Надеюсь, это поможет вам понять разницу между логикой БД и бизнес-логикой (и на самом деле, логикой представления тоже)
Модель никогда не должна расширять базу данных или ORM, потому что модель не является их подмножеством. Расширяя класс, вы объявляете, что имеет все характеристики суперкласса, но с небольшими исключениями.
class Duck extends Bird{} class ForestDuck extends Duck{} // this is ok class Table extends Database{} class Person extends Table{} // this is kinda stupid and a bit insulting
Помимо очевидных логических проблем, если ваша модель тесно связана с базой данных, она делает код чрезвычайно трудным для тестирования (речь идет об тестировании устройств (видео) ).
Я лично считаю, что ОРМ бесполезны и в большом проекте – даже вредны. Проблема связана с тем, что ORM пытаются объединить два совершенно разных способа решения проблем: ООП и SQL.
Если вы начинаете проект с ORM, тогда, после короткой кривой обучения, вы можете быстро писать простые запросы. Но к тому времени, когда вы начнете сталкиваться с ограничениями и проблемами ORM, вы уже полностью инвестировали в использование ORM (возможно, даже новые люди были наняты, которые были действительно хороши в выбранном вами, но были втянуты в простой SQL). Вы попадаете в ситуацию, когда каждый новый вопрос, связанный с БД, занимает все больше времени для решения. И если вы используете ORM на основе шаблона ActiveRecord, то проблемы напрямую влияют на ваши модели.
Дядя Боб называет этот «технический долг».
слабо связан с субъектом
По моему опыту различные структуры интерпретируют MVC несколько свободно и обычно с некоторыми отклонениями. Однако они обычно соглашаются, что MVC делится следующим образом:
Я много использую Symfony и могу дать вам пару небольших примеров. Имейте в виду, что они чрезвычайно упрощены. :п
class MyUnitTable extends Doctrine_Table { // .. various other pieces of code added by Symfony ... // public function getForAccount( Account $_account ) { $q = $this ->createQuery('e') ->leftJoin('e.User u') ->leftJoin('u.Profile p') ->leftJoin('p.Account a') ->where('a.accountid = ?', $_account->getAccountid()); return $q->execute(); } } class myUnitActions extends sfActions { public function executeIndex(sfWebRequest $request) { $this->units = Doctrine_Core::getTable('MyUnit')->getForAccount($foo); } }
<div id="my-unit-list-container"> <ul> <?php foreach( $units as $unit ): ?> <li><?php echo $unit->getName(); ?></li> <?php endforeach; ?> </ul> </div>
Контроллер – это место, где обрабатывается запрос. Он проанализирует запрос и выяснит, какое действие (например, myUnitActions :: executeIndex () сверху) в модели, которая должна быть вызвана.
Я уверен, что вы можете видеть, что происходит в коде выше (много удобностей добавляется ORM). У вас есть диспетчер, отправляющий запрос модели, модель, работающая с вашей проблемной областью, и фактическое извлечение данных из базы данных и, наконец, представление, отображающее данные.
Это имеет много преимуществ для вас как разработчика, поскольку это позволяет, среди прочего, упростить и повысить надежность тестирования.
Превосходный читаемый для вас будет 21-й день с руководством Jobeet от людей, стоящих за Symfony. Это хорошая работа.
Вы также должны взглянуть на код как для Symfony, так и для Zend . Они оба превосходны. Также взгляните на пару ORM, таких как Doctrine и Propel .
Также см. Статью Википедии о MVC .
Вы могли бы взглянуть на подход модели карты данных, на который ссылается руководство по модели системы Zend
Затем у вас есть модель, содержащая свойства, и у нее есть сопоставитель, который выполняет фактическое взаимодействие с базой данных для заполнения модели.
Очевидно, что вы не хотите создавать новое соединение каждый раз при создании новой модели, поэтому вы хотите инициализировать объект PDO отдельно. (Я когда-то сталкивался с внутренней структурой MVC, когда модель расширила свой класс базы данных. Как вы можете себе представить, это было не быстро …)
Может, что-то подобное вам нужно?
abstract class Model { protected $db = NULL; public function __construct (PDO $db) { $this -> db = $db; } }
Пример использования
class Article extends Model { public $props = array (); private function getPage ($id) { $q = $this -> db -> prepare ('select * from pages where pageId = :pageId'); $q -> execute (array ('pageId' => $id)); $ret = $res -> fetchAll (); return ($this -> props = $ret); } } $db = new PDO ('dsn goes here'); $page = new Article ($db); $page -> getPage (1234);
Что касается поиска примеров? Попробуйте googling для «php mvc» и посмотрите на статьи, которые появляются