What good is a repository pattern when you have an ORM?
Example. Suppose i have the following (fictional) tables:
Table: users
pk_user_id
fk_userrole_id
username
Table: userroles
fk_userrole_id
role
Now with an orm i could simply put this in a model file:
$user = ORM::load('users', $id);
Now $user is already my object, which could easily be lazy loaded:
(would be even nicer if things are automatically singular/pluralized)
foreach ( $user->userroles()->role as $role )
{
echo $role;
}
Now with the Repository pattern i'd had to create a repository for the Users and one for the Roles. The repository also needs all kinds of functions to retrieve data for me and to store it. Plus it needs to work with Entity models. So i have to create all of those too.
To me that looks like alot of stuff do... When i could simply get the data like i described above with an ORM. And i could store it just as easy:
ORM::store($user);
In this case it would not only store the user object to the database, but also any changes i made to the 'Roles' object aswell. So no need for any extra work like you need with the repository pattern...
So my question basically is, why would i want to use a repository pattern with an ORM? I've seen tutorials where to use that pattern (like with Doctrine). But it really just doesn't make any sense to me... Anyone any explanation for its use in combination with an ORM..??
The ORM is an implementation detail of the Repository. The ORM just makes it easy to access the db tables in an OOP friendly way. That's it.
The repository abstract persistence access, whatever storage it is. That is its purpose. The fact that you're using a db or xml files or an ORM doesn't matter. The Repository allows the rest of the application to ignore persistence details. This way, you can easily test the app via mocking or stubbing and you can change storages if it's needed. Today you might use MySql, tomorrow you'll want to use NoSql or Cloud Storage. Do that with an ORM!
Repositories deal with Domain/Business objects (from the app point of view), an ORM handles db objects. A business objects IS NOT a db object, first has behaviour, the second is a glorified DTO, it only holds data.
Edit
You might say that both repository and ORM abstract access to data, however the devil is in the details. The repository abstract the access to all storage concerns, while the ORM abstract access to a specific RDBMS
In a nutshell, Repository and ORM's have DIFFERENT purposes and as I've said above, the ORM is always an implementation detail of the repo.
You can also check this post about more details about the repository pattern.
ORM and repository pattern...depends on setup.
If you use your ORM entities as the domain layer, then please use no repositories.
If you have a separate domain model and you need to map from that model to ORM entities and so perform a save, then repositories are what you need.
More details you find here (but must be logged to linked-in). Also to understand the difference, check out the definition of the repository pattern.
Most people use classes that they call repositories, but aren't repositories at all, just query classes - this is how/where you should place your queries if you decided to go with the #1 option (see answer above). In this case make sure not to expose DbContext or ISession from that query class, nor to expose CUD-methods from there - remember, Query class!
The #2 option is a tough one. If you do a real repository, all the inputs and outputs on the repository interface will contain clear domain classes (and no database related object). It's forbidden to expose ORM mapped classes or ORM architecture related objects from there. There will be a Save method also. These repositories might also contain queries, but unlike query classes, these repos will do more - they will take your domain aggregate (collection and tree of entities) and save them to DB by mapping those classes to ORM classes and perform a save on ORM. This style (#2) does not needs to use ORM, the repository pattern was primarly made for ADO.NET (any kind of data access).
Anyhow these 2 options are the 2 extremes we can do. A lot of people use repositories with ORM, but they just add an extra layer of code without real function, the only real function there is the query class like behaviour.
Also I'd be careful when someone talks about UnitOfWork, especially with ORM. Almost every sample on the internet is a fail in terms of architecture. If you need UoW, why not use TransactionScope (just make sure you got a wrapper which uses other than Serializable transaction by default). In 99,9% you won't need to manage 2 sets of independent changes in data (so 2 sets of OuW), so TransactionScope will be a fine choce in .NET - for PHP i'd look for some open-session-view implementations...
Related
there is a Repositories layer in my laravel project. I am a freshman about laravel. I can not fully understand the advantages of this layer. My colleagues tell me that it is purpose to lower the coupling of the codes. Obviously, it is true. But I also look forward to your comments.
Using repositories, we can create complicated query and isolated it behind a readable method name. The coupled used, when using eloquent, we must put the record name in eloquent query, but using repositories, we can hide the record name and put in the other place. So that is give some security reason too. Also we can use for grouped some entities for authoritative users. Repository allows abstraction from data provide engine.
This article can help you.
I am building a Laravel 5.3 app that pulls data from a number of potential sources. It's a fallback system with 3 sources:
Database
If not found, source 1
If not found, source 2
All 3 sources are quite simple and will be accessed in the same way, by using the following 2 methods:
function get($id)
function query($type, $string)
I'm aware there is various terminology around the different ways to implement this, but I'm unsure after reading the docs what the cleanest approach is. Should each data source be implemented as a Repository? A ServiceProvider wrapped in a container? I find the docs thorough but also lacking in overall/high level explanations, so any pointers are appreciated.
The Repository Pattern is the following:
Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects. Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.
With that in mind, you can say that Eloquent itself is a much larger implementation of the Repository Pattern, but a Repository nonetheless. Since it's an ActiveRecord implementation, there isn't any real separation between the Repository and Storage mechanisms.
On to your question specifically, Laravel won't really cover the Repository Pattern itself in much the same way it doesn't cover Service classes or Singletons: It's not Laravel's responsibility to teach you these patterns, it's just giving you the means to organize these patterns more easily if you choose to implement them.
All that said, I would agree with you that each data source implement its own RepositoryInterface. From there, you can register your own ServiceProvider that in turn instantiates a custom Service Class whose purpose is to return the appropriate Repository.
If determining the appropriate Repository is light in logic, and is dependent only on the Controller responsible for the alternate data source, you can likely use Contextual Binding and skip the Service Class altogether.
Either way, there's a few ways to skin this cat, but you're on the right track.
Edit: As an aside, if you want to strictly go "by the book" on this, you would probably want to separate out different Storage classes that connect to each data store separately, which you can then query as appropriate. Then your Repository - which is likely housing the same type of data collection regardless of its storage origins - can be responsible for the returned results.
Otherwise, if you want to stick with Eloquent as much as possible, you can look into multiple data connections to house each of your data sets.
I'm working in a project in Symfony 3.0.1 that use five databases with DBAL as data access layer. I always worked in Symfony with ORM and I always used the next MVC model:
Data access:
CONTROLLER -> REPOSITORY (the queries goes here) -> ENTITY
Display results:
CONTROLLER -> render($view,$params) -> VIEW
This model allow short and simple controllers, but now I'm using DBAL so I can't use repositories.
The question is:
How can I achieve a similar model by using DBAL? In others words, Where should I put the queries?
Should I use services instead of repositories?
Note: I only use the select statement in that databases.
Thanks in advance!
You don't need an ORM in order to use entities.
Likewise, you do not need Doctrine to be able to build repositories once a repository is a implementation of design pattern:
Repository
Mediates between the domain and data mapping layers using a
collection-like interface for accessing domain objects.
Read more
Even though you can't use Doctrine ORM you still can to design POPO classes against an abstract model class or/and model interface.
You could inject DBAL Connection object for each model/entity via construct or setter method. After creating repo classes is easy. Returning collection objects, hydrating items or using raw arrays is up to you.
Edit #1
I have added a real worl exemple I have used in the past (few years ago), look:
https://github.com/felipsmartins/misc-and-code-snippets/tree/master/php/model-exemple/src/AppBundle/Model
Edit #2
Regarding services, it would much better if there is specialized and well defined models (as opposed to Anemic Models) working together inside a service which coordinates the whole transaction, in this case it would be what we know by Unit of Work (see Unit of Work Pattern)
What are the advantages of Repositories in Laravel? It seems to be abstracting the Model layer from the business logic of the application. Although it really just seems to make the whole request life cycle just that much more complicated for little gain.
Can someone shed light on the advantage of Laravel repositories?
Edit
After now using repositories for some time I would add the following:
Repositories enforce single responsibility
Repositories should only return one collection of entities
Although separate from dependancy injection the concepts are brothers
Storage abstraction for the actual storage implementation (e.g. MySQL)
Easier testing
Repositories, like in the provided tutorial, aren't necessary a Laravel concept. Rather, they're a form of IoC injection that is possible with Laravel. Any object that might similarly be injected doesn't mean it's a repository. See the video for a good example from Taylor Otwell, which happens to use a "repository" as well: http://vimeo.com/53029232.
In this example, the repository abstracts where the data came from that is passed to the controller. As long as the data passed implements the specified interface, the controller can "blissfully" make use of the interface's defined methods without worry about where the data initially came from. This allows switching the initial source of the data without breaking your controller. You could pull the data from a file, a database, an outside API, a mock object, or just some arbitrary array. Basically, the controller doesn't need to gather the data represented by the repository. It can just receive and use.
In addition to the other answers here, it's worth pointing out that repositories used when used in Laravel can add an extra level of expressiveness. Take for example the following:
$users = User::whereHas("role", function($q) {
$q->where('name', 'moderator');
}, '<', 1)->get();
The code is difficult to read and awkward to look at. It can be encapsulated in a repository method, and demonstrate much clearer code intent:
$users = $userRepository->getUsersWhoAreNotModerators();
This is also achievable using eloquent 'query scopes' but I think using a repository is superior, as is adheres much better to the single responsibility principal, and is doable regardless of whether you are using Eloquent.
Repositories help to keep your controller clean and make reusable code. Functions in repositories can be accessed in one or more controllers, repositories, etc.
Also, all your backend related logic (like fetching data from database or external calls) can be added in repositories to make the logical separation.
One of the main uses of repositories is to create different binding (using interfaces to define your functions and with the help of the app, bind different implementations of the function as per need). For example, two separate repositories (implementing the parent repository/interface) handling database and files for backend data.
The main reason you use repository pattern is to be able to easily change your data source. For example, in my experience the most common change is adding a caching layer, because the repository implements an interface all you need to do is build the new object implementing the same interface with the new methods handling cache and change the binding.
In my experience the repository in Laravel benefits are these:
The most important thing by using repositories is that you can change your ORM any time and for any reason that you prefer. for example, you want to migrate from MySQL eloquent to some other SQLite ORM.
Helps you to keep your controllers clean and readable.
Helps you to reuse your methods in a repository for any other controllers.
You can add BaseRepository to your repositories list, which involves all base methods like all(), get(), findOrFail(), firstOrFail(), paginate(), create(), ... and use them in other repositories.
Using Interfaces for repositories and binding them that also can be used as services in Laravel.
Looking through several tutorials and books regarding data access in Zend Framework, it seems as if most people do data access within their models (Active Record Pattern) or even controllers. I strongly disagree with that. Therefore I want to have a Data Access Layer (DAL) so that my domain layer remains portable by not having any "ZF stuff" in it. I have searched around but have not really found exactly what I wanted. Heads up: I am new to ZF.
DAL structure
So, the first problem is where to place the Data Access Layer. While it could certainly be placed within the library folder and adding a namespace to the autoloader, that does not seem logical as it is specific to my application (so the applications folder is suitable). I am using a modular structure. I am thinking of using the below structure:
/application/modules/default/dal/
However, I am not sure how include this folder so that I can access the classes within the controllers (without using includes/requires). If anyone knows how to accomplish this, that would be super! Any other ideas are of course also welcome.
The idea is to have my controllers interact with the Data Access Objects (DAO). Then the DAOs use models that can then be returned to the controllers. By doing this, I can leave my models intact.
Implementation
In other languages, I have previously implemented DAOs per model, e.g. DAL_User. This resulted in an awful lot of DAO classes. Is there a smarter way to do this (using a single class does not seem easy with foreign keys)?
I would also appreciate suggestions on how to implement my DAO classes in ZF. I have not spent an awful lot of time reading about all of the components available for database interaction, so any ideas are very welcome. I suspect that there is something smarter than standard PDO available (which probably uses PDO internally, though). Name drops would be sufficient.
Sorry for the many questions. I just need a push in the right direction.
Well, the first thing you have to take into account when dealing with the Data Access Layer, is that this layer also have sub-layers, it's unusual to find folders called "dal" in modern frameworks (I'm taking as basis both Zend Framework and Symfony).
Second, about ActiveRecord, you must be aware that by default Zend Frameworks doesn't implement it. Most of the tutorials take the easiest path to teach new concepts. With simple examples, the amount of business logic is minimal, so instead of adding another layer of complexity (mapping between database and model's objects) they compose the domain layer (model) with two basic patterns: Table Data Gateway and Row Data Gateway. Which is enough information for a beginner to start.
After analyzing it, you will see some similarity between ActiveRecord
and Row Data Gateway patterns. The main difference is that
ActiveRecord objects (persistable entities) carries business logic and
Row Data Gateway only represents a row in the database. If you add
business logic on a object representing a database row, then it will
become an ActiveRecord object.
Additionally, following the Zend Framework Quick Start, on the domain model section, you will realize that there's a third component, which uses the Data Mapper Pattern.
So, if the main purpose of your DAL is to map data between business objects (model) and your storage, the responsibility of this task is delegated to the Data Mappers as follows:
class Application_Model_GuestbookMapper
{
public function save(Application_Model_Guestbook $guestbook);
public function find($id);
public function fetchAll();
}
Those methods will interact with the Database Abstraction Layer and populate the domain objects with the data. Something along this lines:
public function find($id, Application_Model_Guestbook $guestbook)
{
$result = $this->getDbTable()->find($id);
if (0 == count($result)) {
return;
}
$row = $result->current();
$guestbook->setId($row->id)
->setEmail($row->email)
->setComment($row->comment)
->setCreated($row->created);
}
As you can see, the Data Mappers interacts with a Zend_Db_Table instance, which uses the Table Data Gateway Pattern. On the other hand, the $this->getDbTable->find() returns instances of the Zend_Db_Table_Row, which implements the Row Data Gateway Pattern (it's an object representing a database row).
Tip: The domain object itself, the guestbook
entity, was not created by the find() method on the DataMapper,
instead, the idea is that object creation is a task of factories
and you must inject the dependency in order to achieve the so called
Dependency Inversion Principle (DIP) (part of the SOLID principles). But that's
another subject, out of the scope of the question. I suggest you
to access the following link http://youtu.be/RlfLCWKxHJ0
The mapping stuff begins here:
$guestbook->setId($row->id)
->setEmail($row->email)
->setComment($row->comment)
->setCreated($row->created);
So far, I think I have answered your main question, your structure will be as following:
application/models/DbTable/Guestbook.php
application/models/Guestbook.php
application/models/GuestbookMapper.php
So, as in the ZF Quick Start:
class GuestbookController extends Zend_Controller_Action
{
public function indexAction()
{
$guestbook = new Application_Model_GuestbookMapper();
$this->view->entries = $guestbook->fetchAll();
}
}
Maybe you want to have a separated folder for the data mappers. Just change:
application/models/GuestbookMapper.php
to
application/models/DataMapper/GuestbookMapper.php
The class name will be
class Application_Model_DataMapper_GuestbookMapper
I've seen that you want to separate your domain model objects into modules. It's possible too, all you need is to follow the ZF's directory and namespace guidelines for modules.
Final tip: I've spent a lot of time coding my own data mappers for
finally realize that it's nightmare to maintain the object mapping when
your application grows with a lot of correlated entities. (i.e Account
objects that contain references to users objects, users that contain
roles, and so on) It's not so easy to write the mapping stuff at this
point. So I strongly recommend you, if you really want a true
object-relational mapper, to first study how legacy frameworks perform
such tasks and perhaps use it.
So, take some spare time with Doctrine 2, which is the
one of the best so far (IMO) using the DataMapper pattern.
That's it. You still can use your /dal directory for storing the DataMappers, just register the namespace, so that the auto loader can find it.
In my opinion you should have a gateway abstraction (not just Database access) per model. A DAO is not enough. What if you need to get the data from the cloud at some point? This is quickly coming a reality. If you abstract your gateway logic into something generic and then implement it using a database you can have the best of both worlds.
The implementation of a specific gateway interface could use a generic data mapper if you so chose. I work for a small company and have always just created my implementation using PDO. This lets me be close enough to the database to deal with any interesting bits of SQL I might need but am able to support a very abstracted interface.
I have not used the Zend Framework at all. I do not know if they have data-mapper tools that could help you implement the gateway interfaces.