1

I’m trying to create an authentication system in php with the Slim3 framework along with the Twig template system, and for the database I’m using MySQL with PDO. I’m also trying to implement it using a model view controller design pattern. However I’m having difficulty understanding how to use an MVC structure for a web application. I’ve looked at a plethora of explanations on the web and there doesn’t seem to be a clear cut answer. A lot of people say to to use a php framework such as Laravel, Symfony or CodeIgniter as they apparently employ an MVC like structure. However I would much rather keep things simple and to write the code manually rather than using a framework.

Currently there are two interpretations of MVC that I see. The first one being depicted in this diagram:

enter image description here

The other interpretation I’ve seen is this: (which is taken from this YouTube video)

enter image description here

I have done my research. Questions and answers such as this and this have been helpful. But I’m still not sure how I might structure my own applications, specifically indentifying and understanding the model aspect of MVC. I’ll now explain the register process of my authentication app. So you have an idea how my code is works.

Firstly I have an SQLQueries class that simply puts a series of SQL statements into functions. I then have a SQLWrapper class that has functions that can for example store a new users details inside the database. This class also calls functions from the SQLQueries class. I also have a ValidateSanitize class that has functions that cleans user input as well as checking if user input is valid in the form. These three classes I think are part of the model aspect of MVC but I'm not sure. I see a lot of other tutorials using a ‘User Model class’ but I can’t find the need for one in my application.

My views are simply Twig templates that display html, such as the homepage, register, login etc. I then have controllers. I intend to have multiple controllers that do different things. For now I’ve only implemented the AuthController which is responsible for Registering and Signing a user in.

So the first thing the AuthController does is to display the register form in a function called getRegisterForm. Once the user has submitted the form the postRegisterForm function takes that user input and assigns it to tainted variables.

public function postRegisterForm($request, $response)  
{
   $arr_tainted_params = $request->getParsedBody(); 

   $tainted_email = $arr_tainted_params['email'];  it a variable
   $tainted_username = $arr_tainted_params['username'];
   $tainted_password = $arr_tainted_params['password'];
   $tainted_password_confirm = $arr_tainted_params['password_confirm'];

Next all of the three previous classes as well as the database details are instantiated so their functions can be used in the AuthController:

$sanitizer_validator = $this->container->ValidateSanitize;
$sql_wrapper = $this->container->SQLWrapper;
$sql_queries = $this->container->SQLQueries;
$db_handle = $this->container->get('dbase');

The tainted user details are then cleaned with the sanitize_input function. The cleaned user details are then fed into the validate functions to make sure they don’t trigger any validation violations. The password is also hashed here:

$cleaned_email = $sanitizer_validator->sanitize_input($tainted_email, FILTER_SANITIZE_EMAIL); 
$cleaned_username = $sanitizer_validator->sanitize_input($tainted_username, FILTER_SANITIZE_STRING);
$cleaned_password = $sanitizer_validator->sanitize_input($tainted_password, FILTER_SANITIZE_STRING);
$cleaned_password_confirm = $sanitizer_validator->sanitize_input($tainted_password_confirm, FILTER_SANITIZE_STRING);

$hashed_cleaned_password = password_hash($cleaned_password, PASSWORD_DEFAULT); 

$sanitizer_validator->check_email_exists($cleaned_email);
$sanitizer_validator->validate_email($cleaned_email);
$sanitizer_validator->validate_username($cleaned_username);
$sanitizer_validator->validate_password($cleaned_password);
$sanitizer_validator→validate_password_confirm($cleaned_password_confirm);

Finally there is an if statement that checks to see if all validation error messages are empty. If they are we provide the SQLWrapper class with the database details as well as a SQLQueries class object. We then insert the users details into the database by calling the SQLWrapper classes store-details function. Finally we direct the user to the login page, so the user can sign into their newly registered account.

if ($sanitizer_validator->get_validate_messages('email_error') == ' ' && $sanitizer_validator->get_validate_messages('username_error') == ' '
    && $sanitizer_validator->get_validate_messages('password_error') == ' ' && $sanitizer_validator->check_passwords_match($cleaned_password, $cleaned_password_confirm ) == true
    && $sanitizer_validator->check_email_exists($cleaned_email) == false)
{   

    $sql_wrapper->set_db_handle($db_handle); 
    $sql_wrapper->set_sql_queries($sql_queries); 

     $sql_wrapper->store_details($cleaned_email, $cleaned_username, $hashed_cleaned_password);
     return $response→withRedirect($this→container→router→pathFor('login'));

}

However if any of the validate error messages are not blank, then we call the SanitiseValidate display_validate_messages which simply sets the messages into a session to be displayed on the register twig template. We then redirect back to the register page so the user can see the validation error messages.

else
  {
      $sanitizer_validator->display_validate_messages();
      return $response->withRedirect($this->container->router->pathFor('register'));
  }
}

So based on this structure of a user registering an account. Does this adhere to a clean simple MVC structure or do some changes need to be made? Do any of my classes take the role of a model? Any suggestions and tips regarding my structure will be appreciated.

The full application can be seen on my GitHub if that would be helpful. Note that this version is slightly older than the sample code I used in this question.

SneakyShrike
  • 723
  • 1
  • 10
  • 31
  • 1
    I think you're missing the point of @tereško's answer here: https://stackoverflow.com/questions/5863870/how-should-a-model-be-structured-in-mvc/5864000. Read over it carefully and pay particular attention to the "What a model is" section. You have domain logic all over your controller and, worse, you have SQL/mapping logic riddled throughout the procedure. Also, the files in your Model folder are classes per se, but they don't adhere the best to OOP principles – jeremy Jan 14 '19 at 14:40
  • Possible duplicate of [How should a model be structured in MVC?](https://stackoverflow.com/questions/5863870/how-should-a-model-be-structured-in-mvc) – jeremy Jan 14 '19 at 14:41
  • @jeremy Thats the problem I don't know what should go where in my application. Despite reading that answer I still don't really understand which is why I'm asking. You say I have domain logic all over the place. I havn't a clue what that means. An answer telling me how to structure it properly is what I'm after. And it's not a duplicate. – SneakyShrike Jan 14 '19 at 15:01
  • @jeremy I'm also not sure what you mean by a Model folder. Do you mean the src folder? – SneakyShrike Jan 14 '19 at 15:06
  • I did mean that folder, sorry. – jeremy Jan 14 '19 at 15:11
  • If it's not a duplicate, then the Q is too opinion-based. But in my opinion, @tereško's answer indicates the model layer should be divided between: data mappers, domain objects, and services (primarily). Then, "communication between model layer and other parts of MVC should happen through Services." His answer also sums up what domain logic ("business logic") is. – jeremy Jan 14 '19 at 15:14
  • @jeremy I'm sure the guys answer is correct, but the problem I'm having is applying that to my code. It's all right talking about these concepts if you understand them but I don't unfortunately. I only have a vague idea what he's talking about. My question is more about applying these concepts to my own code. You seem to have identified the issues with my structure which is great, but I need assistance on how i might improve it. I have done a lot of research on the matter but I'm still struggling with the idea. – SneakyShrike Jan 14 '19 at 16:53

2 Answers2

7

Indeed, there are multiple approaches regarding how the MVC pattern should be applied in web applications. This multitude of variants is the result of the simple fact, that the original MVC pattern - developed for desktop applications (by Trygve Reenskaug, in 1979) - can not be applied as is to the web applications. Here is a little description. But, from this set of approaches, you can choose one which best complies with your requirements. Maybe you'll try more of them before you'll make your mind. Though, at some point, you'll know which one fits to your vision.

In the following diagrams I tried to present my chosen approach on the web MVC workflow - mainly inspired by Robert Martin's presentation Keynote: Architecture the Lost Years (licensed under a Creative Commons Attribution ShareAlike 3.0).


  • Diagram: Web MVC (general)
  • Diagram: Web MVC (detail 1)
  • Diagram: Web MVC (detail 2)

In general, you could think of a web MVC application as composed of the following parts:

  1. Domain model (e.g. model, e.g. model layer);
  2. Service layer (optional);
  3. Delivery mechanism;
  4. Other components (like own libraries, etc).

1) The domain model should consist of the following components:

  • Entities (e.g. domain objects) and value objects. They model the business rules in terms of properties and behavior and, being application-independent, can be used by multiple (types of) applications.
  • (Data) mappers and, optional, repositories. These components are responsible with the persistence logic.
  • External services. They are used to perform different tasks involving the use of external/own libraries (like sending emails, parsing documents, etc).

Further, the domain model could be split into two parts:

a) Domain model abstraction. This would be the only space of the model layer accessed by the components of the delivery mechanism, or by the services of the service layer - if one is implemented:

  • Entities and value objects;
  • (Data) mapper abstractions and, optional, repository abstractions;
  • Abstractions of external services.

    Note: By abstractions I mean interfaces and abstract classes.

b) Domain model implementation. This space would be the one in which the implementations of the different domain model abstractions (see a) would reside. The dependency injection container (as part of the delivery mechanism) will be responsible with passing instances of these concrete classes as dependencies - as constructor arguments, for example - to the other components of the application (like controllers, views, services, etc).

2) Service layer (optional): Technically, the components of the delivery mechanism could directly interact with the elements of the domain model. Though such interactions involve (a lot of) operations, specific only to the model, not to the delivery mechanism. Therefore, a good choice is to defer the execution of these operations to service classes (e.g. services), as part of the so-called service layer. The delivery mechanism components will then use only these services to access the domain model components.

Note: The service layer can, actually, be seen as part of the model layer. In my diagrams bellow I preferred to display it as a layer residing outside the model. But, in the file system example, I put the corresponding folder in the domain space.

3) The delivery mechanism sums up the constructs used to assure the interaction between the user and the model layer's components. By user I don't mean a person, but an interface with which a person can interact - like a browser, a console (e.g. CLI), a desktop GUI, etc.

  • Web server: parses the user request through a single point of entry (index.php).

  • Dependency injection container: provides the proper dependencies to the different components of the application.

  • HTTP message (e.g. HTTP request and HTTP response) abstraction (see PSR-7: HTTP message interfaces).

  • Router: matches the request components (HTTP method and URI path) against the components of each route (HTTP method and pattern) in a predefined list of routes and returns the matched route, if found.

  • Front controller: matches the user request against a route and dispatches it to a certain controller and/or view action.

  • Controllers. They write (e.g. perform create, update and delete operations) to the model layer and (should) expect no results. This can happen by directly interacting with the components defined in the domain model, or, preferably, by only interacting with the service classes.

  • Views. They should be classes, not template files. They can receive a template engine as dependency. They only fetch data (e.g. perform read operations) from the model layer. Either by directly interacting with the components defined in the domain model, or, preferably, by only interacting with the service classes. Also, they decide which result (like a string), or template file content, will be displayed to the user. A view action should always return a HTTP response object (maybe as defined by the PSR-7 specification), whose body will be before-hand updated with the mentioned result or template file content.

  • Template files. Should be kept as simple as possible. The whole presentation logic should happen only in the view instances. So, the template files should contain only variables (be they pure PHP ones, or presented with the used template engine syntax) and, maybe, some simple conditional statements, or loops.

  • Response emitter: reads the body of the HTTP response instance returned by the view and prints it.

4) Other components. As wished. For example some libraries developed by your own. Like an implementation of the PSR-7 abstraction.


How I chose to dispatch the user request:

As you see in the diagrams above, the front controller dispatches the user request not only to a controller action (in order to update the domain model), but also to a view action (in order to read and display the updated state/data from the model layer). Kind of a splitted dispatch. This can be relatively easy achieved by assigning the controller action and the view action to each route (like bellow), and telling the front controller to call them successively:

<?php

use MyApp\UI\Web\Application\View;
use MyApp\UI\Web\Application\Controller;

// Note: $this specifies a RouteCollection to which the route is added. 
$this->post('/upload', [
    'controller' => [Controller\Upload::class, 'uploadFiles'],
    'view' => [View\Upload::class, 'uploadFiles'],
]);

This approach gives flexibility in regard to the user request dispatch. For example, the name of the view action can be different from the name of the controller action. Or, in order to only fetch model layer data, you don't need to dispatch the user request to a controller, but only to a view. Therefore you don't need to assign a controller action in the route at all:

<?php

use MyApp\UI\Web\Application\View;

$this->get('/upload', [View\Upload::class, 'listFiles']);

File system structure example:

enter image description here

myapp/domain: folder containing the domain model classes and the services. This directory could be brought into the "myapp/web/src" folder, but it shouldn't, because the model layer and the service layer are not part of the delivery mechanism.

domain folder

myapp/web: folder containing the delivery mechanism classes. Its name depicts the type of application - can be a web app, a cli app, etc.

web folder

myapp/web/src:

web-src folder


Resources:

*) Sandro Mancuso : An introduction to interaction-driven design

*) The ones listed in an older answer of mine.

*) The tutorials presented by Alejandro Gervasio:

*) The example on the Slim 3 page: Action-Domain-Responder with Slim.

PajuranCodes
  • 303
  • 3
  • 12
  • 43
  • I apprieate the answer, but to be honest I'm even more confused then when I started. I'm going to have to investigate this deeply because this is the most complicated thing I've ever seen. Maybe reading those resources will enlighten me a bit more. Thanks. – SneakyShrike Jan 16 '19 at 16:27
  • Hey I have a question about the difference between the domain model abstraction and domain model implementation. In Alejandro Gervasio's examples would this correspond to his interfaces being the domain model abstration, and the actual implementation of those interfaces being the domain model implementation? I may have a few more questions as i'm slowly starting to understand this. Thanks again. – SneakyShrike Jan 23 '19 at 12:11
  • @GR412 Yes, you could imagine his interfaces as part of a _domain model abstraction_ space. And their implementations as part of a _domain model implementation_ space. Note that the name _domain model abstraction_ is just a choice of mine. By choosing it, I wanted to emphasize the fact that the delivery mechanism should "communicate" with the model layer only through the constructs of this space. – PajuranCodes Jan 25 '19 at 01:36
  • @GR412 Though, evidently, my space _domain model abstraction_ contains not only abstractions (e.g. interfaces and abstract classes) - of data mappers, repositories and external services, but also implementations (e.g. concrete classes) - of entities. You could though define abstractions for the entities in the space _domain model abstraction_ too, if you wish. And bring their implementations in a _domain model implementation_ space. – PajuranCodes Jan 25 '19 at 01:39
  • Thanks, i'll have another read. The whole thing is slowly making sense to me. And i'll be sure to ask in the chatroom if there are more questions. – SneakyShrike Jan 25 '19 at 15:24
  • Hi there, sorry I havn't responded in a while. I've just been really busy this past month. I noticed the chat room is closed due to inactivity. But I'd just like to thank you for your latest response in regard to using slim 3 with an MVC view. When I have more time i'll be sure to read through it. I think I have enough information for now to start understanding MVC now. – SneakyShrike Mar 13 '19 at 10:05
  • @GR412 You are welcome. Yes, in principle you have the basic infos to start your own mvc project or a Slim 3 project. A new chat room can be opened anytime. So, if you have further questions necessitating the chat, just write a comment here. Good luck! – PajuranCodes Mar 14 '19 at 01:22
  • @dakis your file system schema is interesting, I'm new in PHP and in using MVC. I reach here because I wanted to implement my web project without using any framework, with the purpose of understand whats behind everything. Do you have any simple project (e.g. in Git) that shows which basic php files go in which folder? e.g. where are placed the htaccess or the php.ini or how is implemented DI and router, etc., it would be great a very small project with neither logic at all nor a real persistence layer, just returning strings simulating returning from DB, etc... just to get the whole idea. – Esteban Sep 20 '19 at 16:05
  • @ESt3b4n Hi. Thanks. I don't have any github project online. But I will think about writing a small web app for you, following the above scheme. I'll let you know in the next 2 weeks. – PajuranCodes Sep 20 '19 at 21:21
  • @dakis Hi. I have many questions about MVC using PHP, as I am reading a lot (many authors say there is confussion and even some frameworks do some conceptual mistakes). A 1st question is about Services: I think Services should have all the business logic, e.g. the last step for "confirming" a transaction of an online shopping (many steps during the process holding data in session), would call a single method "processOrder" of the "ShoppingService" (it'd call diferent Mappers for insert/updating in tables like Orders,OrderDetail,Customer,Stock,etc). I use SpringFramework in Java (uses Services) – Esteban Sep 23 '19 at 22:10
  • 1
    @ESt3b4n More correctly: _"Services have business logic too"_... The entities are defined not only by their properties, but also by their **behavior** (business logic). And, because they are unchangeable, their business rules are not specific to a particular application. That's why they can be shared between applications. The services have business logic too. Though, in comparison, their business rules are specific to a particular application. – PajuranCodes Sep 24 '19 at 01:37
  • @ESt3b4n For more details regarding services: [How should a model be structured in MVC?](https://stackoverflow.com/questions/5863870/how-should-a-model-be-structured-in-mvc/5864000#5864000), [Keynote: Architecture the Lost Years](http://confreaks.tv/videos/rubymidwest2011-keynote-architecture-the-lost-years) (with _services_ = _interactors_ = _use cases_), [GeeCON 2014: Sandro Mancuso - Crafted Design](https://vimeo.com/101106002) (with _domain services_, plus _use cases_ as application services), – PajuranCodes Sep 24 '19 at 01:38
  • @ESt3b4n [Sandro Mancuso : An introduction to interaction-driven design](https://vimeo.com/107963074) (with _domain services_, plus _actions_ as application services). Should the _services_ be split into _domain services_ and _application services_? It makes sense. Though it's up to you. – PajuranCodes Sep 24 '19 at 02:11
  • Hello @dakis.. where would you put the classes related to accesing Soap WebServices (using soapClient for instance)? – Esteban Nov 11 '21 at 17:51
  • Hi, @Esteban. First of all, **I am sorry for not coming back to you in _"the next 2 weeks"_, as promised**! Unfortunately, I completely forgot this and I still didn't put any MVC-based project online. In regard of SOAP, I would most probably see it as an interface similar to PDO. PDO transfers data to/from databases. Similarly, SOAP is used to access informations from a remote location. – PajuranCodes Nov 21 '21 at 12:56
  • Technically, with the help of a _dependency injection container_, I would create an instance of PDO and pass it to all the [data mappers](https://www.martinfowler.com/eaaCatalog/dataMapper.html) that would need it. By creating an additional layer of [repositories](https://www.martinfowler.com/eaaCatalog/repository.html), which would use these data mappers as dependencies, I would completely hide the (type of the) data source from the user of the domain (e.g. a [service](https://www.martinfowler.com/eaaCatalog/serviceLayer.html), or, maybe, directly a controller/view). – PajuranCodes Nov 21 '21 at 12:57
  • In other words, for the user of the domain, a repository is just a **collection of objects** of a certain type, which can be accessed in a **collection-like** matter (_"find/get/remove/update/store/exists/count/etc the book in the book collection"_). Nothing of it reveals anything about any database source. – PajuranCodes Nov 21 '21 at 12:58
  • Similarly to the use of PDO, I would create an instance of [SoapClient](https://www.php.net/manual/en/class.soapclient.php) and pass it to all the data mappers that would need it. And my repositories would use these data mappers as required. – PajuranCodes Nov 21 '21 at 12:59
  • (1/2) Hi @dakis, well I did the following. The file system structure of my project is the following, the parent root folder is , under this are the following folders: the backend , and the frontend apps: , , (collection of rest apis), . The are used by the others frontend apps, as it holds the logic of the whole system. Aditionally under the parent root folder is the folder. Under the folder are the Vendor folder and my own common function classes. – Esteban Dec 08 '21 at 18:24
  • (2/2) And under this folder I placed the SoapClients of some specific webservices. These clients are used by others . I thought similar as java webapps, as they have a lib folder which holds third party jars and my own company jars (that holds common logic for many webapps). By the way, I dont use any framework like zend, codeigniter, dependency injection container, etc... and I use all with OOP aproach, so my common function classes under holds just static functions (methods). Hope for my next projects to start using some framework like codeigniter. – Esteban Dec 08 '21 at 18:36
  • @Esteban Hi. I'd add the following: *) The folder should reside outside any . It should contain self made libraries, interfaces to external libraries AND the code of your own framework (if you decide to develop one). The external libraries reside in "vendor", for example (which, by the way, shouldn't reside in , but in . – PajuranCodes Dec 09 '21 at 22:01
  • @Esteban *) You shouldn't use static methods at all! *) I, personally, recommend only the use of Symfony and Laminas (ex-Zend), as frameworks. I really like how Slim is developed too, though they still have some things to change. *) I strongly recommend the use of a DI. – PajuranCodes Dec 09 '21 at 22:08
  • @dakis Yes, the folder should reside outside of any , so it should be under the folder. I think the folder should be inside the folder as it contains "common projects" like phpmailer, phpoffice, monolog etc which are common and invoked by all these Core System Apps, as long as the maintenance of these applications ensure that they all maintain the same versions of these common projects. – Esteban Dec 10 '21 at 16:27
  • In regard to static methods, I was reading some Helper classes Symfony uses, e.g. [String Helper Class](https://symfony.com/doc/current/components/string.html#methods-to-create-string-objects) references to use static methods.. I think it is ok for OOP paradigm. – Esteban Dec 10 '21 at 16:30
  • @Esteban In regard to : I wouldn't put all _vendor_ libraries in a folder usable by all apps. Each app is unique, so it MUST have the liberty to juggle with any version it wishes, for a given library. So, app 1 should be able to work with monolog 1, whereas app 2 should work with version 24 of the monolog library, if wished. – PajuranCodes Dec 10 '21 at 20:56
  • @Esteban In regard of statics: [The Clean Code Talks - "Global State and Singletons"](https://www.youtube.com/watch?v=-FRm3VPhseI)... and so on. What do you think, are such helper classes (like [String Helper Class](https://symfony.com/doc/current/components/string.html#methods-to-create-string-objects)) necessary? The alternative would be...? – PajuranCodes Dec 10 '21 at 21:20
  • @dakis the **myapp/domain** folder should contain **Infrastructure** folder (containing Mail, Parser, Persistence folders) ? I would think of the domain folder as containing just the **domain/business/core logic** of the application. It seems to me that those folders related to Infrastructure could be like part of your own library (that may be used from different applications) just like Utility classes or kind of more technical classes that are independent or unaware of the business that is running. Of course, from your business code you may use some of those classes. – Esteban Jan 07 '22 at 19:06
  • @Esteban Hi. Here is my point of view: Remember that, from the whole components of `myapp/web` and `myapp/domain`, only the _entities_ (and the _value objects_) are application-independent and, therefore, can/should be reused by multiple apps. By _entities_ I means that domain classes containing properties **AND** behavior, e.g. _business logic_. All other components should remain specific to each application. – PajuranCodes Jan 13 '22 at 20:33
  • @Esteban Also, imagine that you would, by your own, develop a little library with classes to fetch some records from a database. It would consist of GENERAL (e.g. NOT SPECIFIC) code, shareable by each of your apps, right? It would therefore contain code like this: _"Fetch for me from the **given** db and tables(s) the **given** set of records (like 'all', or just 'the first 27'), ordered by the **given** columns, in the **given** sort order, etc"_. This library would then reside in a folder of yours (named maybe _"my-libs"_), along with other own libraries. – PajuranCodes Jan 13 '22 at 20:34
  • @Esteban Well, this folder (_"my-libs"_) would **NOT** be a subfolder of any of your _"myapp-x"_ folders, but a completely separate folder! Moreover, imagine that you would want to develop a web framework, to be used by any applications of yours and of others. Well its code would reside in a folder named _"my-framework"_ (for example), completely separated from both the folder _"my-libs"_ and _"myapp-x"_. For example, if you'd develop an application using [middlewares](https://www.php-fig.org/psr/psr-15/), you would put in the folder _"my-framework"_ classes – PajuranCodes Jan 13 '22 at 20:34
  • @Esteban like `Framework\Routing\RouteDispatcher` and `Framework\Routing\RouteInvoker` and `Framework\ErrorHandling\ErrorHandler` and `Framework\Authorization\Authorization` (all of them being middlewares on top of your MVC-based application). Let me try to answer to your actual question. What kind of classes are eligible for the folder _"myapp/domain/Infrastructure"_ - having in mind also the three previous comments? Well, classes like `MyApp\Domain\Infrastructure\Repository\User\UserCollection`, `MyApp\Domain\Infrastructure\Mapper\User\UserMapper` (interface) – PajuranCodes Jan 13 '22 at 20:34
  • @Esteban and `MyApp\Domain\Infrastructure\Mapper\User\PdoUserMapper` (implementing the `[...]\UserMapper` interface) (see [data mapper](https://www.martinfowler.com/eaaCatalog/dataMapper.html) and [repository](https://www.martinfowler.com/eaaCatalog/repository.html)). Now, you see, for example, each data mapper class is specific to the database structure that you are using (table names, column names, etc) for your application. So, for example, the data mapper `MyApp\Domain\Infrastructure\Mapper\User\PdoUserMapper` would have a – PajuranCodes Jan 13 '22 at 20:35
  • @Esteban method `public function fetchAllUsers(): array { $sql = 'SELECT * FROM users'; [...] }`, or/and a method `public function userExists(User $user): bool { $sql = 'SELECT COUNT(*) as cnt FROM users WHERE username = :username'; [...] }`. As you can see, the classes contain references to the infrastructure of a certain database, SPECIFICALLY used by the application. That's why I, too, consider that the folder named _"Infrastructure"_ should reside in the folder _"myapp/domain"_, along with the folder _"Model"_. – PajuranCodes Jan 13 '22 at 20:35
  • (1/3) @dakis Yes, _entities_ are part of the domain's component as they hold the business logic. Is it application independent? I think it is relative depending of what is an application for you and/or how is the size of your system. For instance consider this structure: **mydomain/domain**, **mydomain/webapp01**, **mydomain/webapp02**, **mydomain/webapp03**, etc., being **mydomain** an specific business area in your enterprise (see it just as a folder container to group projects or web applications related to that business area), ... – Esteban Jan 14 '22 at 23:54
  • (2/3) @dakis ... **webappXX** different kind of web applications as an online shopping web site, or an administration webapp (backend), or a group of rest api endpoints, or simply a single web page for a specific url, etc. All these web apps call the domain as they share common logic for querying database for example. In this case, domain is application-independent. – Esteban Jan 14 '22 at 23:56
  • (3/3) @dakis But in the case of the common structure (generated by almost all frameworks): **myapp/domain**, **myapp/webapp** (or myapp/controller, myapp/model, myapp/view) in this case the domain only serves for that specific "myapp" (actually webapp). In laminas they mention "modules" concept but I'm not sure if each module can be seen as independent webapplications, anyway, each module contain Controller, Model (domain) and View folder, so these components are **tied couppled** (model is not application independent) and it happens for each specific module. – Esteban Jan 15 '22 at 00:04
  • So what do you think about these **2 scenarios**, where the domain can be application-independent and in other scenario is tied coupled? Let´s discuss first about this topic (lets leave domain/Infrastructure for the next one). Related to the 1st scenario, I found usefull this [link](https://ambujsoni.medium.com/share-laravel-eloquent-models-between-multiple-applications-179d8f31078c) in conjunction with this other [link](https://stackoverflow.com/a/29995226/2551281), so I know how to develop and architecture that scenario with good practices using composer for reusing the model layer (domain). – Esteban Jan 15 '22 at 00:12
  • @Esteban Imho, the modules-based applications are not a reliable solution if you want to share code between applications. Also, I read the first link of yours. As far as I know, the so-called _"models"_ in Laravel are part of the Eloquent ORM. And I'm one of those people who think that ORMs are a bad idea. As for sharing domain components between applications: just because, momentarily, only one application uses the components of a domain layer, it doesn't mean that these components can't be relocated and used by other future applications, if needed. – PajuranCodes Jan 16 '22 at 14:15
  • @Esteban And yes, sharing code between applications should be done using Composer, similar to the description provided in your first link. P.S: What other ideas I find bad: static methods, [Active Record](https://www.martinfowler.com/eaaCatalog/activeRecord.html), [service locator](http://misko.hevery.com/2008/07/18/breaking-the-law-of-demeter-is-like-looking-for-a-needle-in-the-haystack/), modeling an application after the structure of a database (e.g. considering the database the central point of an application), – PajuranCodes Jan 16 '22 at 14:16
  • @Esteban PDO wrappers (e.g. custom classes extending the PDO class in order to add some additional, but not really useful, capabilities), [singleton pattern](https://en.wikipedia.org/wiki/Singleton_pattern). – PajuranCodes Jan 16 '22 at 14:16
0

There is a course where you get walked through making MVC with slim 3. Ill link it here : https://codecourse.com/courses/slim-3-authentication . Hope this helped, its a really easy to follow course and you learn alot.

Toni
  • 3
  • 1