I saw this post (The difference between an Eloquent Model and a Model?) but it doesn't explicitly answer the question for me.
I may not be using the right terminology here...
I understand Eloquent to be "...an ActiveRecord implementation for working with your database..." as it says in the documentation. But is what is not clear to me is difference between these eloquent models, and models as one refers to them in the MVC sense.
Does it sound logical if I was to say that in a particular laravel application
there will be many models, some of which are Eloquent models, and some of which are models in the MVC sense.
Eloquent models are quite lean and pure classes, allowing interaction with the database layer.
MVC models, by comparison may contain all sorts of business rules & logic
Both types are easily created by php artisan make:model although with an Eloquent model one might want to create the migration at the same time.
All models are stored in the same place, unless otherwise organised. It's not as if there is some externally visible location or naming convention to indicate that this is an Eloquent Model, or a MVC model.
...is that about right?
There are only models. Some of them have extended functionality by using the Object-relational mapping methodology - Eloquent ( one of many ).You can read more about ORM here:
https://en.wikipedia.org/wiki/Object-relational_mapping
They are everything but not lean and pure. They are far blown and use a lot of unnecessary data to create relations between database object in the form of easy to read / use syntax. Example firstModel->secondModel->thirdModel->somethingSilly();
MVC Models can contain everything as Controller but they answer to convention so you should probably read more extensively about MVC and the logic behind it.
Pretty much that's the purpose of Artisan. To make everything more simple and easy to use.
Yep.
If you need a bit more information I can provide you with answers and url in the comment below.
Related
I'm building an application in CakePHP 3. It uses a number of legacy databases which are not built in the Cake conventions.
I do not want to use any of the ORM features Cake provides, as it's more tedious to set up all the relations than just write "Raw SQL". We are also not going to make any changes to the database structures, so the ORM is a non-starter. So I'm going to write raw SQL queries for everything.
However, I'm not sure where this code would be put. I've read https://book.cakephp.org/3.0/en/orm/database-basics.html#running-select-statements but it doesn't say where you actually put that code.
I don't want to put my queries in a controller ideally since that defeats the purpose of MVC.
All I really need is one Model where I can put all my queries in different functions and reference them in my Controller(s).
In Cake 2.x it was easy to just create a model under app/Model/ then load it (loadModel) where needed in controller(s). But with the new Cake 3.x Table and Entity spaces, I'm not sure how this fits in?
I've also read up on Modelless Forms but don't think they're right either. For example the initial page of the application shows a list of chemicals which is just a SELECT statement - it doesn't involve forms or user input at all at this stage.
Obviously there will also be situations where I need to pass data from a Controller to the Model, e.g. queries based on user input.
As mentioned in the comments, I would suggest to not ditch the ORM, it has so many benefits, you'll most probably regret it in the long run.
Setting up the tables shouldn't be a big deal, you could bake everything, and do the refactoring with for example an IDE that does the dirty work of renaming references and filenames, and then set up the rules and associations manually, which might be a little tedious, but overally pretty simple, as there shouldn't really be much more to configure with respect to the database schema, than the foreign keys, and possibly the association property names (which might require updating possible entities #property annotations too) - maybe here and there also conditions and stuff, but oh well.
That being said, for the sake of completeness, you can always create any logic you want, anywhere you want. CakePHP is just PHP, so you could simply create a class somewhere in say the Model namespace (which is a natural fit for model related logic), and use it like any other class wherever needed.
// src/Model/SomeModelRelatedClass.php
namespace App\Model;
class SomeModelRelatedClass
{
public function queryTheDatabase()
{
// ...
}
}
$inst = new \App\Model\SomeModelRelatedClass();
$results = $inst->queryTheDatabase();
See also
Cookbook > Database Access & ORM > Associations - Linking Tables Together > BelongsTo Associations
I've been using laravel (php mvc framework) for a few weeks now. Currently I am creating a model for every single non-pivot table. Even tables as simple as:
id (unsigned int (PK)) | usertype (varchar(20))
1 | guest
2 | member
3 | Moderator
Because it makes it easier to relate my other models to them using the eloquent ORM.
I was wondering if its normal to create models for such simple tables for the sake of utilizing an ORM or if there is a better approach?
Currently my application is functioning using models for these tables, but I still want to make sure I am picking up good coding conventions while I'm learning.
Thanks in advance.
Here comes the long answer: YES!
I don't know when or why model became a synonym to entity, but this leads to confusion.
According to MVC inventor, Trygve Reenskaug, in the original MVC article:
DEFINITION
A Model is an active representation of an abstraction in the form of data in a computing system
[...]
The models are represented in the computer as acollection of data together with the methods necessary to process these data.
So, many people nowadays define (incorrectly) models as data representation, or the data storage or something else, but this is wrong.
Model deals with your application logic and this INCLUDES data abstraction, data storage, data processing, etc.
I use to call my data abstractions an Entity instead of model. My application model layer is called Service or Application Model. My storage layer is called just Storage and so on... All of this togheter is what we can call Model
That being clarified, now we can go on...
You said:
Because it makes it easier to relate my other models to them using the eloquent ORM.
That's enough!
Nothing keeps you away from using plan txt files as storage, but if your data relate to others, then you should look for a database.
Eloquent is an ORM (Object-Relational Mapping) and so, it relies on a database behind it. If you use txt files, how would do to recover users by their user type?
I'm not used to frameworks, but most of them generate entities automatically, you just need to declare them...
If some entity has no business logic and you just need to store it, so you don't need a "full model" for it. And that's what you're doing.
Hope I convinced you...
I've got a question regarding a conflict / conundrum I've run into with my application.
I want to make some common "stuff" available to all of my models and controllers, such as data from a cache, or session information, as well as the methods of my PDO wrapper.
Currently each individual feature controller and feature model extends a base controller and base model, which in turn extend a single object that does all of that common stuff.
A controller will get called by a router/dispatcher, and the controller will then call on a model to get some data. The problem with this is it means the main Object gets constructed twice: once when the feature controller is called, and again when the feature controller calls the feature model.
See the diagram below:
Obviously I'm doing something wrong, so I was wondering if there's some kind of best practice solution to this issue.
What I dont want is to have to pass the stuff the object loads, through the controller, to the model. That means any time I have to add a new common element to Object, I have to pass it through to the Model.
It's far simpler and easier for $this->cache or $this->db or $this->session to always be universally available in both controllers and models (as well as future helpers and misc classes).
How would I go about solving this issue?
Thanks :)
I think you are going in a wrong path about solving this issue.
If you are building an MVC application, you should separate concerns, thats why we use MVC. To separate Models, Controllers and Views.
You should define what do you need Model to do, what will Controller do, and use View only for presentation logic.
In proper MVC, Model is a layer that deals with business logic, database access, validation etc. So Model is not a one class. And you can use many models in one controller. And Controller is just... connection between Models and Views. Models should be fat, and Controllers should be light.
The way you are doing this is in my opinion wrong, since you can do the same stuff in both model and controller and that is not what MVC is for. Controller should not do any logic, thats why we use Models, controller only tells models what to do, and based on their reaction we tell other Models to do something else, or render View with success or error message or with posts from database etc.
The way you can do this is to once you have invoked appropriate controller, use it to get models you need. And again, model is composed of lots of classes, so your model folder can be fat. From Controller you should have only methods to access models so that models can do some actions, and report back to Controller what they did. And based on that returned value you do some more actions or call View to render.
So you should not have one object that can be extended by both models and controllers.
Your model folder can look like this:
Models
- Entities
- Forms
- Validators
- Services
...
And then you call any of them in your controller to do some action, and report back.
If you really need to have the same functionality in both controllers and models then this didnt answer your question, but I think its wrong to do it like you started.
Hope this helps you, interesting question Il try to help some more if I can.
I get a feeling, that the root of your problems is bad architecture.
The main thing you have to understand about MVC and MVC-inspired design patterns is that the pattern is made from two layers: presentation later and model layer. Those layers should not share common functionality. Controllers (as well as views and templates) are part of presentation layer.
When you have variables like $this->cache, $this->db or $this->session in the controller, it means that you have a severe leak of abstraction. These are storage structures, which should be hidden fairly deep in the model layer. If your controller is interaction with them directly, you do not have a controller.
Next problem is your base class (the one you call Object for some reason .. while objects kinda are instances of a class). It seems to be responsible for quite a lot, especially the instantiation of different abstraction for interaction with storage. If you controller needs a PDO instance (for some exceptionally bizarre reason), then it should be injected in the constructor. Same goes for cache and session management.
And then there is that small thing that model is not an object or a class. It is a layer. And just like presentation layer it is composed from different kinds of structures. Usually the recommendation is to have:
structures that deal with logical entities, which is usually what domain objects are for
one or more types of storage abstractions: data mapper, repository, unit of work, dao and/or some similar structures.
something, that controls the interaction between the above mentioned structures so that they do not leak in the presentation layer, commonly referred as services
And yes, you are correct assuming that using controller to pass along structures is a bad practice. It violates LoD. Instead you should be providing your controller with a factory, that instantiates your model layer structures and provides them with necessary dependencies .. this post might help.
my two cents on the subject .. for a more precise advice you would have to show some code
Shouldn't models just describe data that will be passed from a controller to a view? Doesn't that make models unnecessary in weakly typed languages? In PHP, they are doing DB work in models, but isn't that wrong? As I see it, models are just unnecessary in weakly typed languages...
There are some misconceptions about the term model. Microsoft's MVC3 framework has the concept of a view-model, which is simply the data you use to render your views. This isn't however what the M stands for exactly in MVC. The model includes your business entities. We have thin controllers and fat models, but very thin view models. Our controllers make calls to services that perform business logic, and the controllers never do this logic themselves. We then translate our business entities (our data models) and convert them into a lightweight view model, which can be used for rendering a view.
So to answer your question
Shouldn't model just describe data that will be passed from controller to view?
Then perhaps what you are really asking is aren't view-models unnecessary? I'm not sure why you think this. View model + view makes the result. In PHP it can be helpful to define a class with easily accessible properties on it. This is just sensible for clarifying your expectations and prevents you from calling methods with hideously long sets or arguments. In JavaScript there is no need to define a view model as such, you just push the properties onto a new object and pass it along with your view to your view rendering logic. This is more a reflection of the OO pattern these languages use and not the fact that they are weakly typed.
If you are asking if model is unnecessary, then you have missed the purpose of the MVC architecture. A big part of MVC is that you separate your concerns. Why apply any architecture to your code? I am sure you can find a better explanation of the motivation behind MVC than I can give you.
A model is a useful conceptual tool, even if it's not strictly necessary in PHP to separate it from the DB code e.g. you can have a data object associated with each table that encapsulates some business logic, or define a set of business entities that aggregate the data across tables into domain-specific objects that the controllers can then use, or just have one monster DB object that has all the access functions and returns the entities. This has definite advantages over having DB code directly in use by the controllers:
If you are defining complex data structures that run across DB tables, you don't want to do that in controller code due to the risk of duplication - far better to have a single definition that enforces consistency across the system. Although this can introduce dependencies, having one function/object that defines that data makes it easy to find out where the data is used so you can fix things.
Third party maintenance is far easier if there's one place to go to where all the data structure definitions are found.
It makes unit testing easier if you can swap out the whole model or parts of it and replace it with mock object(s) that will provide test data
It makes controllers lighter and therefore more readable and maintainable
So you could argue that it's not necessary, but it helps a lot.
I've always seen models as a tool to provide data. That means that your controller doesn't ever have to worry about the data source, and if you want to switch from using a database to XML files then you only have to swap out your model.
So long as you have some data provider abstraction. Some Models will do low level validation (tightly coupled to the storage engine - null checks etc) but the controller "should" do all of the business logic/validation.
I personally have a thin struct like class that is mapped to each table (all implementing IDataStruct). This struct, or a collection thereof, is the only thing that moves between the DomainObject and the DataProvider. I can then enforce via my interface what datastruct I should be receiving. This is not a silver bullet but I have found it to work well (Makes things like caching and unit testing quite easy)
I hope this hasn't confused the issue.
I'm working on a large project at the moment and am just wondering which is best practice, to model entities and sets of entities seperately or in one class?
Currently I am implementing two classes for each entity (for example an 'author' and 'authors' class) where the plural class contains methods like 'fetch authors' (using Zend_Db_Table_Abstract for plural and Zend_Db_Table_Row_Abstract for singular).
However I realised that I've often seen methods like 'fetch/list' functions in a single entity's object, which seems quite neat in terms of the fact that I won't have to have as many files.
I know there are no hard-and-fast rules for data modelling but before I continue too far I'd be interested in learning what the general consensus on best-practice for this is (along with supporting arguments of course!).
Answers [opinions] gratefully received!
Rob Ganly
Personally, I prefer a model called Person to actually represent a single person and a model like PersonCollection to represent a collection of persons. In neither case, would I have methods for fetch/get on these objects. Rather, I would put those methods on a PersonRepository or a PersonMapper class.
That's really my biggest area of discomfort with ActiveRecord as a pattern for modeling. By having methods like find() and save(), it opens the door to methods like getPersonByName(), getPersonsWithMinimumAge(), etc. These methods are great, nothing wrong with them, but I think that semantically, they work better on a mapper or a repository class. Let the Model actually model, leave persistence and retrieval to mappers and repositories.
So, to more directly address your question, I see potentially three classes per "entity type":
Person - actually models a person
PersonCollection - extends some Abstract Collection class, each item of class Person
PersonMapper - persistence and retrieval of Person objects and PersonCollections
Controllers would use the mapper to persist and retrieve models and collections.
It's probably no surprise that I'm drawn to Doctrine2. The EntityManager there functions as a single point of contact for persistence and retrieval. I can then create repositories and services that use the EntityManager for custom functionality. And I can then layer on action helpers or factories or dependency injection containers to make it easy to get/create those repositories and services.
But I know that the standard ActiveRecord approach is quite common, well-understood, and very mainstream. You can get good results using it and can find many developers who immediately understand it and can work well with it.
As in most things, YMMV.