|
Disclaimer: The following is a description of what I understand mvc-like patterns in the context of php-based Web Applications. All the external links that is used in the content is there to explain terms and concepts, and not to imply my Own credibility on the subject.
The first thing that I must clear up are: The model is a layer. Second:there is a difference between classical MVC and "We use" in web development. Here's a bit of a older answer I wrote, which briefly describes how they is different. What's a model is not:The model is no a class or any single object. It is a very common mistake to make (I do too, though the original answer was written if I began to learn otherwise ), because most frameworks perpetuate this misconception. Neither is it a object-relational Mapping technique (ORM) nor an abstraction of database tables. Anyone who tells you otherwise are most likely trying to ' sell ' another brand-new ORM or a whole framework. What's a model is:In proper MVC adaptation, the M contains all the domain business logic and the Model Layer is mostly mad E from three types of structures:
Domain Objects
A domain object is a logical container of purely domain information; It usually represents a logical entity in the problem domain space. Commonly referred to as business logic.
This would is where you define do to validate data before sending a invoice, or to compute the total cost of an order. At the same time, Domain Objects is completely unaware of Storage-neither from where (SQL database, R EST API, text file, etc.) Nor even if they get saved or retrieved.
Data mappers These objects is only responsible for the storage. If you store information in a database, this would is where the SQL lives. Or maybe you the XML file to store data, and your data mappers is parsing from and to XML files.
Services You can think of them as ' higher level Domain Objects ', but instead of business logic, Services is responsible F or interaction between Domain Objects and mappers. These structures end up creating a ' public ' interface for interacting with the domain business logic. You can avoid them, but at the penalty of leaking some domain logic into Controllers. There is a related answer to this subject in the ACL implementation question-it might be useful.
How to interact with a model?
Prerequisites: Watch Lectures "Global State and singletons" and "Don't Look for things!" from the clean Code talk S.
The communication between the model layer and other parts of the MVC triad should happen only through Services. The clear separation has a few additional benefits:
- It helps to enforce the single responsibility principle (SRP)
- Provides additional ' wiggle ' in case the logic changes
- Keeps the controller as simple as possible
- Gives a clear blueprint, if you ever need an external API
The easiest-sure, both View and Controller instances (for that incoming request) has AC Cess to the same version of the Model Layer would is to provide them both with the same ServiceFactory instance. I would do it like this: /* * Closure for providing lazy initialization of DB connection */$dbhProvider = function () {$instance = new \pdo (' Mys Ql:host=localhost;dbname=******;charset=utf-8 ', ' **username** ', ' **password** '); $instance->setattribute (Pdo::attr_errmode, pdo::errmode_exception); $instance->setattribute (Pdo::attr_emulate_prepares, false); return $instance;};/ * * Creates basic structures, which'll be a used for * interaction with model layer */$serviceFactory = new Servicefacto Ry (New Datamapperfactory ($dbhProvider), new domainobjectfactory); $serviceFactory->setdefaultnamespace (' appli Cation\\service '),/* * Initializes the routing mechanism */$configuration = Json_decode (file_get_contents (__dir__). '/config/routes.json '), true); $router = new Router (new Routebuilder); $router->import ($configuration);/* * Gets the Part of URI after the "?" Symbol */$uri = isset ($_server[' Request_uri '))? $_server[' Request_uri ': '/'; */* initializes theRequest abstraction and * Apply routing pattens to that instance */$request = new request ($uri); $router->route ($reques t);/* * Initialization of View */$class = ' \\Application\\View\\ '. $request->getresourcename (); $view = new $class ($serviceFactory); $view->setdefaulttemplatelocation (__dir__. '/templates ');/* * Initialization of Controller */$class = ' \\Application\\Controller\\ '. $request->getresourcename (); $controller = new $class ($serviceFactory, $view);/* * Execute the necessary command on the Controller */$command = $request->getcommand (); $controller->{$command} ($request);/* * Produces the response * * echo $view->render ();
This would to initialize a not-too-complicated MVC application (notice that there are no caching nor authentication/au Thorization included). As can see, the $serviceFactory object is shared between both the View object and Controller object, and keeps Track of initialized services. Also, you might notice, the anonymous $dbhProvider function was passed only DataMapperFactory to the instance, which would being creating all The Data mappers within any given service. With this given code, the Controller instance would the state of the Model Layer, and the Vie W instance (as per Model2 MVC) would request data from the Model Layer. How to build the model?Since There is not a single "model" class (as explained above), and you really does not "build the model". Instead you start from making Services, which is able to perform certain methods. And then implement Domain Objects and mappers. An example of a service method:This might is a simplified authentication method in a recognition service (something that ascertains a user's identity). But you should not think of this example as directly related to the one above, because as part of the Authenticat Ion process, it should happen right after $serviceFactory the is created (the check-if-logged-in part) and while the authenticate() method Woul D is called from within the controller. And the authentication would closely interact with (but is separate from) the authorization service. namespace Service;class Recognitions{ // -- snip -- /* This is an EXAMPLE, not a production-level code. Do not copy-paste! */ public function authenticate( $username, $password ) { $account = $this->domainObjectFactory->build(‘User‘); $mapper = $this->dataMapperFactory->build(‘User‘); $account->setUsername( $username ); $mapper->fetch( $account ); if ( $account->matchPassword($password) ) { $state = $this->dataMapperFactory->build(‘Cookie‘); } else { $state = $this->dataMapperFactory->build(‘Session‘); } $state->store($account); } // -- snip --}
As you can see, at this level of abstraction, there are no indication of where the data was fetched from. It might is a database, but it also might is just a mock object for testing purposes. P.s. This would also are the part where caching is introduced. For example, as an additional Mapper. Some Additional Comments:
Database Tables and model While sometimes there is a direct 1:1:1 relationship between a database table, Domain Object, and Mapper , in larger projects it might is less common than you expect:
Information used by a single Domain Object might is mapped from different tables, while the object itself have no Persistence in the database. Example: If you is generating a monthly report. This would collect information from different of tables, but there was no magical MonthlyReport table in the database.
A single Mapper can affect multiple tables. Example: When is storing data from User the object, this Domain object could contain collection of Other domain objects- Group instances. If you alter them User and store the, the Data Mapper 'll has to update and/or insert entries in multiple tabl Es.
Data from a single Domain Object was stored in more than one table. Example: in large systems (THINK:A medium-sized social network), it might is pragmatic to store user Authenticat Ion data and often-accessed data separately from larger chunks of content, which is rarely required. In this case you might still has a single User class, but the information it contains would depend of whether full Detai LS were fetched.
-
A view is not a template view instances in MVC (if you aren't using the MVP Variat Ion of the pattern) is responsible for the presentational logic. This means, each View would usually juggle at least a few templates. It acquires data from the Model Layer and then, based on the received information, chooses a template and sets VA Lues. One of the benefits you gain from this is re-usability. If you create a ListView class, then, with well-written code, you can have the same class handing the present Ation of User-list and comments below an article. Because They both has the same presentation logic. You just switch templates. You can use the either native PHP templates or use some Third-party templating engine. There also might be some third-party libraries, which is able to fully replace View instances.
-
What's the old version of the answer? The only major change was that, which is called Model in the old version, is actually a Service . The rest of the "library analogy" keeps up pretty well. The only flaw that I see are that would are a really strange library, because it would return you information from T He book, but don't let you touch the book itself, because otherwise the abstraction would start to "leak". I might has to think of a more fitting analogy.
What is the relationship between View and Controller instances? The MVC structure is composed of both layers:presentation and model. The main structures in the Presentation layer is views and controller. When you were dealing with websites this use MVC design pattern, the best-of-the-to has 1:1 relation between views and con Trollers. Each view represents a whole page in your website and it have a dedicated controller to handle all the incoming requests fo R that particular view. For example, to represent a opened article, you would has \Application\Controller\Document and \Application\View\Document . This would contain all the main functionality for presentation layer, when it comes to dealing with articles (of cours E You might has some XHRcomponents (that is not directly related to articles).
|