Now I have an model User which represents an user in the application. And I use an UserRepository with methods like getById($id) and getAll().
An user can post reviews. If I want to show the 5 or 10 or maybe 20 last reviews of an user it's most logical to ask the user I think. So I would have a method $user->getLastReviews(5).
But what's the best way to implement this? Give each user an instance of the ReviewRepository (with a method $reviewRepository->getByUser(User $user) for example)? Or are there better ways?
I think it's fine to have models contain and use instances of other models, so your way is fine, to have User model contain an instance of the Review model, and let that Review model handle the logic of getting said reviews.
Also, you could add a method to the UserRepository to handle it like so:
class UserRepository extends Model{
$review = new reviewRepository();
function getReviews($numOfReviews){
return $this->review->getReviews($user_id);
}
Another option would be to create a repository method where you passed in both variables. Something like $reviewRepository->getLastReviewsByUser(5, $user).
Usually this is a job for the ORM. Almost every framework uses one implementation (ie. Doctrine for PHP/Symfony or Hibernate for Java) but naturally you can implement your own ORM (ORM are often implemented using introspection).
Once you have an ORM library you define relations between Models in a "setup phase" (in your case you'll have "user has many reviews"). Then you'll use the ORM methods which knows how to deal with those ones (often relations are mutual ie. "review belongs to user"). The concept is that this setup phase will discharge you from dealing with issues like the one you pointed.
My suggestion is to use one of the already existing ORM implementations which already supplies facilities for getter and setter methods of related Models. In the other case, you have to write specialized getters and setters by yourself for every Model.
Related
I use Eloquent to implement my models. It has a lot of methods that makes working with models much easier. However, in some cases I have to implement functionality that is accessing the database, but doesn't return an Eloquent model.
For example, imagine a common User model. Eloquent helps me a lot in CRUD operations for the User model, but what if I have to implement a method that returns some statistics about users (ex. how many total users, how many active users, etc.).
Where should I implement this functionality? In the Eloquent model, as a public static function, (e.g. User::getStats()), or should have a different class for this.
It seems a little bit unnatural to have these methods on a Eloquent model, because they are not Eloquent related.
It's really up to you, but it's a good idea to decide on a convention and stick to it.
My rule of thumb is this:
if it's related to a single item that is normally represented by an Eloquent model, do it as a public static method on that model. For example, in my current project, I have a Contract model. I needed a method that would generate a contract ID string (for compatibility with legacy systems) for new contracts. This is related to a single item (a contract) but for technical reasons needed to be generated separately from the Eloquent model (ie. it was based on a separate database with a different connection). So I created a public static method: public static function generateContractIdentifier($id, $salesRep). If you're using a repository for access to your database, you could put it there.
If it's more general (ie. not tied to an instance of the Eloquent model), I put it into a separate library. For example, in the same application I have a queue for processing items for printing (an industrial process). The application has a dashboard and I needed to show the current queue status for management. For this I created a ProcessStatus library and implemented a method: public function getStatus() which runs a query and provides the results as an array for display in a view. This is not related to any particular item in the queue, so I put it in a separate library.
As always, it depends on your project and what role the user plays in it.
But basically, no, I don't think the logic for building reports belongs on the user model. While it may be related to the user, regarding the SOLID-principle the User class should only have one responsibility, which in this case is to handle the User entity.
This contains getting and setting properties on an instance, in a simple project it's probably also fine to define some scopes on the model, e.g. to select only active users, like User::getActive();
But as your project grows, you should consider using more specific classes.
For instance, you could abstract the Eloquent functionality into a User-Repository. So now you have a handler for operations on the entitiy itself, like
$userRepo->getAll();
$userRepo->getActive();
$userRepo->getInactive();
and a handler for a User instance:
$user->getName();
$user->setStatus();
Creating reports and statistics is yet a completely different topic. So you could have something like a UserReportBuilder oder UserStatisticsService:
$userStats->getMostActive();
$userStats->getRegistrationsPerDay();
A simple example:
// UserRepository:
class UserRepository
{
protected $model = $model;
public function __construct($model)
{
// you pass in an instance of the actual Eloquent model
// so you have the whole power of eloquent in here
$this->model = $model;
}
public function getActive()
{
// this returns a collection of models
return $this->model->where('status', 'active')->get();
}
}
$userRepo = new UserRepo(new User);
And that's pretty much it. You can still work with Eloquent, but you have separated the functionality in parts with a clewar responsibility. So your UserStats class would only be resposible for building user statistics:
class UserStats
{
// You could pass in the Repository through the constructor
// or just use the Eloquent model directly
public function getRegistrationsPerDay()
{
return User::groupBy('day')->get(
[
DB::raw('DATE(created_at) as day'),
DB::raw('count(*) as registration_count')
]
);
}
}
The User instance or the UserStats-builder do not need to know how to fetch all users, and the User instance or the UserRepository do not need to know how to calculate registrations per day, so it makes sense to split that functionality into separate, independent parts that do exactly one thing.
I think you get the idea and I hope it makes sense. Maybe you should make yourself more familiar with the SOLID-principles and try to keep them in mind when you get stuck on problems like that.
Just really what the title says, does anybody have a decent explanation on how to use models properly in laravel 4? I'm fine with using the pre-existing User model. But I read somewhere that queries and such should be done in a model of your own.
So what I have is basically a form where you can make a status update (like facebook) and it stores it in a database but the query is run through the controller.
I want it to be done through a model.
Any information on this would be great! Thanks in advance
It's a broad question and right place to learn about how to use model in Laravel-4 is the laravel site itself, but anyways.
Actually, model is the the place where you should keep the business logic in any MVC framework, it could be database related or anything else that is the heart of the application and controller and View are just two parts of the application whose responsibility is only communicate to the model, fetch data and present it to the user but all the data processing should be done in the model and controller should be kept slim and view is only a mechanism to present the user a UI.
So, if you want to have a User model in your application (laravel-4) then you may extend it from Eloquent like
class User extends Eloquent{
// code goes here
}
and then call it's methods from the controller, like
$user = User::get(1);
then passing it to the view like
return View::make('viewname', $user);
That's it. But, if you think, where the find method come from then, it's because, you have extended the Eloquent model and in that model all the necessary methods (find e.t.c) are available and your User model inherited the behavior of Eloquent model, so you can use all the methods from User and it's not necessary to a single method in your User model unless you need to write some special methods for that User model, like relationship functions and so. well, the perfect place to seek help or to know the basic about it is the Laravel site, try to understand it from there and if you fail or just stuck anywhere then come here to ask with specific problem. Also, check Basic Database Usage and Query Builder.
BTW, you may check this post for a detailed answer on model of MVC.
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.
I'm seriously confused about the concept of the 'Model' in MVC. Most frameworks that exist today put the Model between the Controller and the database, and the Model almost acts like a database abstraction layer. The concept of 'Fat Model Skinny Controller' is lost as the Controller starts doing more and more logic.
In DDD, there is also the concept of a Domain Entity, which has a unique identity to it. As I understand it, a user is a good example of an Entity (unique userid, for instance). The Entity has a life-cycle -- it's values can change throughout the course of the action -- and then it's saved or discarded.
The Entity I describe above is what I thought Model was supposed to be in MVC? How off-base am I?
To clutter things more, you throw in other patterns, such as the Repository pattern (maybe putting a Service in there). It's pretty clear how the Repository would interact with an Entity -- how does it with a Model?
Controllers can have multiple Models, which makes it seem like a Model is less a "database table" than it is a unique Entity.
UPDATE: In this post the Model is described as something with knowledge, and it can be singular or a collection of objects. So it's sound more like an Entity and a Model are more or less the same. The Model is an all encompassing term, where an Entity is more specific. A Value Object would be a Model as well. At least in terms of MVC. Maybe???
So, in very rough terms, which is better?
No "Model" really ...
class MyController {
public function index() {
$repo = new PostRepository();
$posts = $repo->findAllByDateRange('within 30 days');
foreach($posts as $post) {
echo $post->Author;
}
}
}
Or this, which has a Model as the DAO?
class MyController {
public function index() {
$model = new PostModel();
// maybe this returns a PostRepository?
$posts = $model->findAllByDateRange('within 30 days');
while($posts->getNext()) {
echo $posts->Post->Author;
}
}
}
Both those examples didn't even do what I was describing above. I'm clearly lost. Any input?
Entity
Entity means an object that is a single item that the business logic works with, more specifically those which have an identity of some sort.
Thus, many people refer to ORM-mapped objects as entities.
Some refer to as "entity" to a class an instance of which represents a single row in a database.
Some other people prefer to call only those of these classes as "entity" which also contain business rules, validation, and general behaviour, and they call the others as "data transfer objects".
Model
A Model is something that is not directly related to the UI (=View) and control flow (=Controller) of an application, but rather about the way how data access and the main data abstraction of the application works.
Basically, anything can be a model that fits the above.
MVC
You can use entities as your models in MVC. They mean two different things, but the same classes can be called both.
Examples
A Customer class is very much an entity (usually), and you also use it as part of data access in your app. It is both an entity and a model in this case.
A Repository class may be part of the Model, but it is clearly not an entity.
If there is a class that you use in the middle of your business logic layer but don't expose to the rest of the application, it may be an entity, but it is clearly not a Model from the perspective of the MVC app.
Your example
As for your code examples, I would prefer the first one.
A Model is a class that is used as a means of data abstaction of an application, not a class which has a name suffixed with "Model". Many people consider the latter bloatware.
You can pretty much consider your Repository class as part of your model, even if its name isn't suffixed with "Model".
I would add to that the fact that it is also easier to work with the first one, and for other people who later may have to understand your code, it is easier to understand.
All answers are a heavy mashup of different things and simply wrong.
A model in DDD is much like a model in the real world:
A simplification and abstraction of something.
No less and no more.
It has nothing to do with data nor objects or anything else.
It's simply the concept of a domain part. And in also every complex domain
there is always more than one model, e.g. Trading, Invoicing, Logistics.
An entity is not a "model with identity" but simply an object with identity.
A repository is not just a 1st level cache but a part of the domain too.
It is giving an illusion of in-memory objects and responsible for fetching
Aggregates (not entities!) from anywhere and saving them
i.e. maintaining the life cycle of objects.
The "model" in your application is the bit which holds your data. The "entity" in domain-driven design is, if I remember correctly, a model with an identity. That is to say, an entity is a model which usually corresponds directly to a "physical" element in a database or file. I believe DDD defines two types of models, one being the entity, the other being the value, which is just a model without and identity.
The Repository pattern is just a type of indexed collection of models/entities. So for instance if your code wants order #13, it will first ask the repository for it, and if it can't get it from there, it will go and fetch it from wherever. It's basically a level 1 cache if you will. There is no difference in how it acts with a model, and how it acts with an entity, but since the idea of a repository is to be able to fetch models using their IDs, in terms of DDD, only entities would be allowed into the repository.
A simple solution using service and collection:
<?php
class MyController {
public function index() {
$postService = ServiceContainer::get('Post');
$postCollection = $postService->findAllByDateRange('within 30 days');
while($postCollection->getNext()) {
echo $postCollection->current()->getAuthor();
}
}
}
EDIT:
The model(class) is the simple representation of the entity scheme. The model(object) is a single entity. The service operates on models and provides concrete data to the controllers. No controller has any model. The models stand alone.
On the other "side", mappers map the models into persistance layers (e.g: databases, 3rd party backends, etc).
while this is specifically about Ruby on Rails, the same principles and information still apply since the discussion is around MVC and DDD.
http://blog.scottbellware.com/2010/06/no-domain-driven-design-in-rails.html
What are some of the ways you have implemented models in the Zend Framework?
I have seen the basic class User extends Zend_Db_Table_Abstract and then putting calls to that in your controllers:
$foo = new User;
$foo->fetchAll()
but what about more sophisticated uses? The Quickstart section of the documentation offers such an example but I still feel like I'm not getting a "best use" example for models in Zend Framework. Any interesting implementations out there?
EDIT: I should clarify (in response to CMS's comment)... I know about doing more complicated selects. I was interested in overall approaches to the Model concept and concrete examples of how others have implemented them (basically, the stuff the manual leaves out and the stuff that basic how-to's gloss over)
I worked for Zend and did quite a bit of work on the Zend_Db_Table component.
Zend Framework doesn't give a lot of guidance on the concept of a "Model" with respect to the Domain Model pattern. There's no base class for a Model because the Model encapsulates some part of business logic specific to your application. I wrote a blog about this subject in more detail.
Persistence to a database should be an internal implementation detail of a Model. The Model typically uses one or more Table. It's a common but improper object-oriented design to consider a Model as an extension of a Table. In other words, we should say Model HAS-A Table -- not Model IS-A Table.
This is an example of IS-A:
class MyModel extends Zend_Db_Table_Abstract
{
}
This is an example of HAS-A:
class MyModel // extends nothing
{
protected $some_table;
}
In a real domain model, you would use $some_table in the methods of MyModel.
You can also read Martin Fowler's take on the Domain Model design pattern, and his description of the Anemic Domain Model antipattern, which is how many developers unfortunately approach OO programming.
I personally subclass both Zend_Db_Table_Abstract and Zend_Db_Table_Row_Abstract. The main difference between my code and yours is that explicitly treat the subclass of Zend_Db_Table_Abstract as a "table" and Zend_Db_Table_Row_Abstract as "row". Very rarely do I see direct calls to select objects, SQL, or the built in ZF database methods in my controllers. I try to hide the logic of requesting specific records to calls for behind Zend_Db_Table_Abstract like so:
class Users extends Zend_Db_Table_Abstract {
protected $_name = 'users';
protected $_rowClass = 'User'; // <== THIS IS REALLY HELPFUL
public function getById($id) {
// RETURNS ONE INSTANCE OF 'User'
}
public function getActiveUsers() {
// RETURNS MULTIPLE 'User' OBJECTS
}
}
class User extends Zend_Db_Table_Row_Abstract {
public function setPassword() {
// SET THE PASSWORD FOR A SINGLE ROW
}
}
/* CONTROLLER */
public function setPasswordAction() {
/* GET YOUR PARAMS */
$users = new Users();
$user = $users->getById($id);
$user->setPassword($password);
$user->save();
}
There are numerous ways to approach this. Don't think this is the only one, but I try to follow the intent of the ZF's design. (Here are more of my thoughts and links on the subject.) This approach does get a little class heavy, but I feel it keeps the controllers focused on handling input and coordinating with the view; leaving the model to do the application specific work.
Don't ever use Zend_Db_Table as your model. It just gets you into trouble. Either you write your own model classes which use Zend_Db_Table to talk to your database or you can read my blog post here for a hack that allows you to somewhat combine the "Model" class and Zend_Db_Table.
The main thing to not is that when you use Zend_Db_Table directly in your controllers you end up doing the same things in multiple places. If you have to make a change to some of that logic, you have to make a change in multiple places. Not good. My first professional project was done like this because I was the one in the company who had to learn how to use ZF and it's a total mess now.
I also tend to write helper functions into my classes for sophisticated fetches. Somthing like $table->doNameFetchAll() or $table->doOrderFetchAll().
I've been doing some research on Models for ZF and came across an interesting series of articles by Matthew Weier O'Phinney which are well worth checking out:
Using Zend_Form in your Models
Applying ACLs to Models
Model Infrastructure
It's not "production code" and a lot is left to the imagination, but it's a good read and has helped me quite a bit.
A model has nothing to do with the database. What if I am fetching data from an RSS feed or a SOAP service or reading files from the FS?
I put all these kinds of things in models. In that case, my model class might not extend anything. I'm about to write a model that uses methods of other models.
Skip ZF for the models part, there are much better solutions. The "M" in ZF's "MVC" is pretty much absent. Reading their docs they don't really mention models at all -- which is a good thing, it means you can use just about anything you want without writing lots of adapter code.
Take a look at Doctrine for models instead. It is quickly becoming the de-facto ORM for PHP.
You can do more complicated queries, check the Advanced usage section in the Zend_Db_Table manual page.
$select = $table->select();
$select->from($table,
array('COUNT(reported_by) as `count`', 'reported_by'))
->where('bug_status = ?', 'NEW')
->group('reported_by');
you can extend the Zend_Db_Table_Abstract class and add some useful methods to it. for example you can add a changePassword() method to your user class and manipulate it's data. or you can change the default __toString() method of your class, so you'll have a customized __toString() method that, let's say returns the whole contact information of the user (name, address, phone number) in a well formatted string. in your constructor you could populate your data into properties of your object. then use them like:
public function __toString() {
$data = $this->_name . ', ' . $this->_adderss . ', call: ' . $this->_phone;
return $data;
}
your model extends the Zend_Db_Table_Abstract just to ease the process of accessing its data, but the functionality you could have on that data is all up on your creativity and need.
I recommend you the book "php|architect's guide to programming with zend framework" by Cal Evans. the book is very informative and easy to read. chapters 4 and 6 are going to be useful for this matter.
A database entity is not the only kind of model component. As such, it doesn't really make sense to speak of models (in plural) - Your application has one model, which contains a multitude of components. Some of these components could be table gateways (And thus extend from Zend_Db), while others would not.
I recommend that you get hold of the book Domain Driven Design by Eric Evans, which does an excellent job of explaining how to construct an object model.
I use Propel 1.3 instead of Zend_Db_Table.
It's tricky to setup, but awesome.
It can examine your database and auto-generate all your models.
It actually generates 2 levels and 2 types of model.
Examples for 'user' table:
Level 1: BaseModel & BasePeer: these get overwritten every time you regenerate your ORM. i.e. BaseUser.php & BaseUserPeer.php
Level 2: StubModel & StubPeer: these don't get overwritten. They're the ones you customize. i.e. User.php & UserPeer.php
Type 1: Model - for basic CRUD operations, not queries i.e. User.php
Type 2: Peer -- for queries. These are static objects. i.e. UserPeer.php
So to create a user:
$derek = new User();
$derek->setFirstName('Derek');
$derek->save();
To find all dereks:
$c = new Criteria();
$c->add(UserPeer::FIRST_NAME, 'Derek');
$dereks = UserPeer::doSelect($c);
http://zfsite.andreinikolov.com/2008/08/zend_db_table-time-overhead-about-25-percents/
Bit of a catch 22, Zend_Table is nice in principle, but generates some performance overheads (without caching)...