I was trying to setup a UserModel Class and very unhappy with the separation of database and Models.
For example I want to check if Username already exists or generate a new User. But all these actions require a database connection, which is only available in a controller. Of course i can always inject the DB Object, but it just feels wrong. What is the right way to handle these things?
You can use the UniqueEntity validator, the docs are here
http://symfony.com/doc/current/reference/constraints/UniqueEntity.html
About the db connection, you can easily inject specific repositories or the entity manager itself in your services where needed.
Related
the background for this is that we have an existing site which is going to be somewhat linked with the new one, so it would make a lot of sense to use the same user base.
So, we want to use the same user database. The way I tried is not working, adding two databases and providing the same Entity. This is also a different Symfony project, I could do it on the same one but it's more convenient to separate it because it might be running on different servers later on.
How can I make my user provider fetch the users from another MySQL database the easiest or best reliable way?
Have you looked at the documentation for using multiple entity managers?
http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html
You can set up configuration for multiple database connections and define which connection to use by default based on the bundle.
Alternatively you can explicitly choose which connection to use with
$this->get('doctrine')->getManager('<your custom manager name>');
If you're using a user provider specified in your security.yml (the approach used here) you can inject the userRepository for your alternate connection in the service definition.
your.definition.of.user.provider:
class: YourBundle\Entity\UserProvider
arguments:
- #=service('doctrine').getRepository('YourBundle:User', '<alternate manager name goes here>')
I am trying to create simple database abstraction layer. I read a lot of articles about Active Record and Table Data Gateway and right now I am very confused.
I think that I understand some theory (small) about them but not how exactly to implement them. I have choosed to implement Data Table Gateway. I will try to explain what I did and if you give me some advices I will be glad. I am not sure why (for example in ZF2) every time I have to use Table Data Gateway like DI in the models.
In my case my AbstractModel just get DbAdapter in the constrictor by IoC container but I am not sure that this is ok.
Ok I will describe my situation.
I have following classes:
DbAdapter -> it creates db connection (using PDO)
IoC (Inversion of Control Container)
AbstractModel -> in constructor I get DbAdapter using IoC. This means that it hold only one instance of DbAdapter. In this class I also have CRUD methods.
Another classes represent the tables in db. For example class User extends AbstractModel and has method getTable which return the name of the table. Another sql queries will be in this classes which represent the tables. These classes have access to DbAdapter.
Is it ok this scheme and how can I improve it?
I'm a bit confused on how to perform insert and update statements using MVC.
Is it ok to create an instance of an object in your controller and pass it to your service to save it or do you pass data to your service and handle everything else in there?
Insert
In my controller something like:
$userservice->insert("myname","mypassword");
In my UserService:
function insert($username,$password){
$user = ORM::for_table('user')->create();
$user->username= $username;
$user->password= $password;
$user->save();
}
Update
In my controller something like:
$userservice->update("myname","mypassword",1);
In my UserService:
function insert($username,$password,$id){
$user = ORM::for_table('user')->find($id);
$user->username= $username;
$user->password= $password;
$user->save();
}
Is this good practice?
Because I see a lot of these answers where for example a user is being created in the controller and passed to a repository to save it:
Proper Repository Pattern Design in PHP?
But I don't like the idea of creating a user in the controller...
Controllers belongs to application layer and controlls only activity. In your example the activities are Create- and Update for an existing or for a new User. These operations belongs to the Domain Layer, which contains services. Thus services encapsulate the domain as a gatekeeper and provides operations for resolving domain like a facade.
Is it ok to create an instance of an object in your controller and pass it to your service to save it or do you pass data to your service and handle everything else in there?
The service should provide a method to pass a ValueObject. ValueObjects are better to encapsulate lot of data (Property values for User). Inside the service, the ValueObject should be delegated to Filter and Validator. If validation didn't fail the ValueObject will be delegated to a DataMapper. The DataMapper will map the properties of ValueObject to a data-model for the UserRepository (ORM). Repositories often need another model of data, e.g. Objects versus storage mediums based on RDBMS like MySQL.
This approach should be strict to seperate the concerns between layers to improve maintainabilty and interchangeabilty. Services should be thin and acts as a delegator to Domain Objects (Filter, Validator, etc.), for example see Service Layer Pattern.
So, where should be a value object created?
I would prefer that the service provides a method for this: getEntityPrototype() by using the prototype pattern.
Be careful with naming. ValueObject is an object which have no identity. Entity is an object with identity (here id of User). For an existing User you will have have a method like getUserById($id), which should return an UserEntity. If User does not exist for given id, it should return a NullObject. To create a new User getEntityPrototype() will return an UserEntity which have no identity yet, so you will call it ValueObject or better Prototype of Entity. After setting properties (e.g. by a FormObject) and persisting this object is a real entity. In a Factory for this service you can set the EntityPrototype.
What you should think about in this case is if the classes have only one responsibility.
Controller decides about the flow of the action. If there's a need for registering a user then it registers him, but it should not define how to do it, but ask a service to complete this task and get the result.
On the other hand you should have some kind of UserManager which updates, creates and fetches users - is this single responsibility? Kinda, yes - it's managing them in a broad sense.
There's a slight problem you have with your methods' names though. You should have registerUser not insert since it's way easier to tell what it actually does.
You should Pass Data to Model. MVC is all about dividing tasks Controller - Handles Application Flow, Model - Contains all the business login Database etc and View - here you decide how to show. Basically the UI part is stored here
So the Controller should send data to Model and model decides what to do with the data. The advantage of coding this way is that in future if you want to change something in the code you know where to look, or if you ask a designer to redesign your website you only have to give him the VIEW part of code . If the designer does something that caused an error , correcting that wont take that much time. If you follow MVC properly Adding,Updating or Maintaining functionality wont be a problem
So I've been studying the role of the repository pattern as a means of decoupling the persistence layer from my models in an MVC framework. Prior to this, I might have my UserModel calling active record methods directly in order to store/retrieve domain objects.
Here's a sketch of what I'm thinking in regards to the call stack in a request that should create a new User:
Here are my questions:
Is this a correct implementation of the repository pattern?
I understand that the controller should take the user's information from the request and pass it into the model. How does that usually happen? Should the controller create a User object and then pass that into the model? I sure as heck don't wanna just pass in an array of values into the model--nor do I want to pass in 15 arguments to the model method that creates a user.
In order for this pattern to really work, it looks like to me I would need to have a domain object that is just a simple data structure with no behavior and then if I'm using an ORM, I would have an ORM object which will describe how the object is persisted. Initially I resisted this because it feels like duplicate code, but if I'm really separating persistence from the business logic, this would be needed right? For example, what if I went with an in-memory store? I would no longer use the ORM object.
Am I thinking correctly here? Is this acceptable. Please help me connect the dots in my head.
1. Is this a correct implementation of the repository pattern?
I'm not sure where you been doing that research, but you have got it wrong.
Repositories as for separating the domain objects from data mappers.
There no such thing as "models". Model in MVC design pattern is one of the to main layers: presentation layer and model layer.
And the repository pattern is incompatible with active record (anti)pattern, which combines domain and storage logic in single instance, thus causing a major SRP violation.
To use a real world example for, when and how to use a repository here is an example:
You are creating some document management tool, where said documents can come from several sources (for example: local SQL database, SOAP service and cache). In this situation you create a repository, which deals with the "routing" of storage. It is the part of application, that decides which data mapper to use for storing/retrieving each document.
The goal of repository is to separate the domain logic from the interaction with storage. For the system, that was described above, a repository would also let add new data sources, without need to rewrite large amounts of code (if any). You could just add another type of mapper for the document.
2. Should the controller create a User object and then pass that into the model?
To begin with, controller itself should not create anything. Instead your controller should use a factory for acquiring instance of the object that you need. This factory can be provided to the controller through constructor or some other method. This is called: Dependency Injection (to learn more about it, watch this lecture).
Also, as noted above, model is a layer, not any specific class or object. The responsibility of controller is to alter the state of model layer (by passing data to it). You could interact with domain objects and mappers (or repositories) directly in the controller, but it would mean leaking some of the business logic in the controller. It is recommended to instead use services, which then manipulates said domain objects and storage related structures.
As for the issue with 10+ parameter, that you would require for creation of new user account, let's assume you have action with following footprint:
public function postUser( Request $request )
{
....
}
If the action gets called with specific Request instance, you have two options how to deal with large amount of parameters:
Wrap the instance in a decorator, which would let you call a single method for forming the data from request in a specific array. Then you pass this array to the service(s).
Form the array inside the controller's action and pass it, where th data is required.
The former solution is more suited for large scale applications, where such formation of data would be required repeatedly though-out the code. But in a small/medium projects the second option is the common-sense approach.
Thing is, the job of the controller is to take the user's input, and distribute it to the model layer and current view. And formation of such array fits right-in with this mandate.
3. (..) main object that is just a simple data structure with no behavior and then (..)
No. Domain object is not "simple data". It is where most of the domain business logic resides in the application.
And forget about magical ORMs. First step for implementing a repository is to separate the domain and storage logic. Domain object handles the validation and business rules, mapper deals with persistence and data integrity (small example here).
Another thing that you must realize is that repositories for web application do not really interact with in-memory persistence (apart from cache). Instead your repository would be juggling mappers for different data sources.
Should the controller create a User object and then pass that into the model?
I'm not sure what you mean by "pass that into the model" -- the User object is the model. "Controller" and "model" represent different layers in the design, they are not specific objects, and there shouldn't be a separate UserModel object as you mentioned.
The repository interface itself is generally considered part of the model, though the domain objects shouldn't be saving themselves -- this should be done in the controller.
Your controller's job would then be to interpret the request and create a User object, then use the repository to save the user:
$user = new User(...); // based on Request
$repository->save($user);
it looks like to me I would need to have a domain object that is just a simple data structure with no behavior
This is not true, you can and should encapsulate behaviour in your domain objects. As for how persistence is actually implemented, a good ORM should take care of most of the details and you shouldn't have to create additional classes by hand.
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...