I'm currently just starting on porting a large Yii2 application to Laravel and I'm considering using repositories to solve my current problem of messy controllers and bloated models.
I've looked at a ton of examples of repositories but most them only cover simple CRUD. For example in my current app a User can created in multiple places and must be created with like 5 related records in other tables, for example a User must be added to Groups and must have Permission records created based on their role.
Currently almost all of my models have a custom Create function that can reused anywhere. Here is a very basic Yii2 example of what I'm talking about.
Example User creation in User model:
public static function create(array $attributes, array $group_ids)
{
$user = new User;
$user->attributes = $attributes;
$user->save();
$role = $user->role;
foreach ($role->rolePermissions as $role_permission) {
UserPermission::create($user->id, $role_permission);
}
foreach ($group_ids as $group_id) {
GroupUser::create($user->id, $group_id)
}
if ($role->admin_mode) {
// send welcome email
}
return $user;
}
Is it good practice to simply inject the UserPermission and GroupUser Repositories into my UserRepository in this case? How do you handle saving related records in Repositories?
Does anyone have any more advanced examples of using Repositories with related models?
You need to understand that in Repository pattern, repository is not the place to store your business logic, that's why they are simple, doing CRUD only.
For what you need here is a business logic layer on top of the repositories. What I did to my recent projects is that I create a Services folder in my app root, and create all sort of services in it with my main business logic in it, like $userService->createUser(..), and in it will have checks on different roles, groups, emitting events, send emails.
So a typical calls could look like this:
calls UsersController->createUser
calls UserService->createUser
verifications, checks, throws errors
calls UserRepository->create
calls GroupUserRepository->create
emit UserCreated event
(disjointed: event listeners)
dedicated listeners listened UserCreated event
calls UserService->sendWelcomeEmail
send welcome emails
So services is almost identical to your fat models, but they are standalone php classes that understand your business logic, use whatever database it knows, and process requests and return results. It does not depend on anything to instantiate one, and so can be included by anyone to use it. They also can be instantiated as singleton or instances depending on your need.
Side note
I've wasted too much time on creating repositories when I could have just use Eloquent. They are not identical, but I could not foresee my project to change underlying DBMS so I would usually just use eloquent directly in my services layer.
I'll admit, I haven't unit tested much... but I'd like to. With that being said, I have a very complex registration process that I'd like to optimize for easier unit testing. I'm looking for a way to structure my classes so that I can test them more easily in the future. All of this logic is contained within an MVC framework, so you can assume the controller is the root where everything gets instantiated from.
To simplify, what I'm essentially asking is how to setup a system where you can manage any number of third party modules with CRUD updates. These third party modules are all RESTful API driven and response data is stored in local copies. Something like the deletion of a user account would need to trigger the deletion of all associated modules (which I refer to as providers). These providers may have a dependency on another provider, so the order of deletions/creations is important. I'm interested in which design patterns I should specifically be using to support my application.
Registration spans several classes and stores data in several db tables. Here's the order of the different providers and methods (they aren't statics, just written that way for brevity):
Provider::create('external::create-user') initiates registration at a particular step of a particular provider. The double colon syntax in the first param indicates the class should trigger creation on providerClass::providerMethod. I had made a general assumption that Provider would be an interface with the methods create(), update(), delete() that all other providers would implement it. How this gets instantiated is likely something you need to help me with.
$user = Provider_External::createUser() creates a user on an external API, returns success, and user gets stored in my database.
$customer = Provider_Gapps_Customer::create($user) creates a customer on a third party API, returns success, and stores locally.
$subscription = Provider_Gapps_Subscription::create($customer) creates a subscription associated to the previously created customer on the third party API, returns success, and stores locally.
Provider_Gapps_Verification::get($customer, $subscription) retrieves a row from an external API. This information gets stored locally. Another call is made which I'm skipping to keep things concise.
Provider_Gapps_Verification::verify($customer, $subscription) performs an external API verification process. The result of which gets stored locally.
This is a really dumbed down sample as the actual code relies upon at least 6 external API calls and over 10 local database rows created during registration. It doesn't make sense to use dependency injection at the constructor level because I might need to instantiate 6 classes in the controller without knowing if I even need them all. What I'm looking to accomplish would be something like Provider::create('external') where I simply specify the starting step to kick off registration.
The Crux of the Problem
So as you can see, this is just one sample of a registration process. I'm building a system where I could have several hundred service providers (external API modules) that I need to sign up for, update, delete, etc. Each of these providers gets related back to a user account.
I would like to build this system in a manner where I can specify an order of operations (steps) when triggering the creation of a new provider. Put another way, allow me to specify which provider/method combination gets triggered next in the chain of events since creation can span so many steps. Currently, I have this chain of events occurring via the subject/observer pattern. I'm looking to potentially move this code to a database table, provider_steps, where I list each step as well as it's following success_step and failure_step (for rollbacks and deletes). The table would look as follows:
# the id of the parent provider row
provider_id int(11) unsigned primary key,
# the short, slug name of the step for using in codebase
step_name varchar(60),
# the name of the method correlating to the step
method_name varchar(120),
# the steps that get triggered on success of this step
# can be comma delimited; multiple steps could be triggered in parallel
triggers_success varchar(255),
# the steps that get triggered on failure of this step
# can be comma delimited; multiple steps could be triggered in parallel
triggers_failure varchar(255),
created_at datetime,
updated_at datetime,
index ('provider_id', 'step_name')
There's so many decisions to make here... I know I should favor composition over inheritance and create some interfaces. I also know I'm likely going to need factories. Lastly, I have a lot of domain model shit going on here... so I likely need business domain classes. I'm just not sure how to mesh them all together without creating an utter mess in my pursuit of the holy grail.
Also, where would be the best place for the db queries to take place?
I have a model for each database table already, but I'm interested in knowing where and how to instantiate the particular model methods.
Things I've Been Reading...
Design Patterns
The Strategy Pattern
Composition over Inheritance
The Factory method pattern
The Abstract factory pattern
The Builder pattern
The Chain-of-responsibility pattern
You're already working with the pub/sub pattern, which seems appropriate. Given nothing but your comments above, I'd be considering an ordered list as a priority mechanism.
But it still doesn't smell right that each subscriber is concerned with the order of operations of its dependents for triggering success/failure. Dependencies usually seem like they belong in a tree, not a list. If you stored them in a tree (using the composite pattern) then the built-in recursion would be able to clean up each dependency by cleaning up its dependents first. That way you're no longer worried about prioritizing in which order the cleanup happens - the tree handles that automatically.
And you can use a tree for storing pub/sub subscribers almost as easily as you can use a list.
Using a test-driven development approach could get you what you need, and would ensure your entire application is not only fully testable, but completely covered by tests that prove it does what you want. I'd start by describing exactly what you need to do to meet one single requirement.
One thing you know you want to do is add a provider, so a TestAddProvider() test seems appropriate. Note that it should be pretty simple at this point, and have nothing to do with a composite pattern. Once that's working, you know that a provider has a dependent. Create a TestAddProviderWithDependent() test, and see how that goes. Again, it shouldn't be complex. Next, you'd likely want to TestAddProviderWithTwoDependents(), and that's where the list would get implemented. Once that's working, you know you want the Provider to also be a Dependent, so a new test would prove the inheritance model worked. From there, you'd add enough tests to convince yourself that various combinations of adding providers and dependents worked, and tests for exception conditions, etc. Just from the tests and requirements, you'd quickly arrive at a composite pattern that meets your needs. At this point I'd actually crack open my copy of GoF to ensure I understood the consequences of choosing the composite pattern, and to make sure I didn't add an inappropriate wart.
Another known requirement is to delete providers, so create a TestDeleteProvider() test, and implement the DeleteProvider() method. You won't be far away from having the provider delete its dependents, too, so the next step might be creating a TestDeleteProviderWithADependent() test. The recursion of the composite pattern should be evident at this point, and you should only need a few more tests to convince yourself that deeply nested providers, empty leafs, wide nodes, etc., all will properly clean themselves up.
I would assume that there's a requirement for your providers to actually provide their services. Time to test calling the providers (using mock providers for testing), and adding tests that ensure they can find their dependencies. Again, the recursion of the composite pattern should help build the list of dependencies or whatever you need to call the correct providers correctly.
You might find that providers have to be called in a specific order. At this point you might need to add prioritization to the lists at each node within the composite tree. Or maybe you have to build an entirely different structure (such as a linked list) to call them in the right order. Use the tests and approach it slowly. You might still have people concerned that you delete dependents in a particular externally prescribed order. At this point you can use your tests to prove to the doubters that you will always delete them safely, even if not in the order they were thinking.
If you've been doing it right, all your previous tests should continue to pass.
Then come the tricky questions. What if you have two providers that share a common dependency? If you delete one provider, should it delete all of its dependencies even though a different provider needs one of them? Add a test, and implement your rule. I figure I'd handle it through reference counting, but maybe you want a copy of the provider for the second instance, so you never have to worry about sharing children, and you keep things simpler that way. Or maybe it's never a problem in your domain. Another tricky question is if your providers can have circular dependencies. How do you ensure you don't end up in a self-referential loop? Write tests and figure it out.
After you've got this whole structure figured out, only then would you start thinking about the data you would use to describe this hierarchy.
That's the approach I'd consider. It may not be right for you, but that's for you to decide.
Unit Testing
With unit testing, we only want to test the code that makes up the individual unit of source code, typically a class method or function in PHP (Unit Testing Overview). Which indicates that we don't want to actually test the external API in Unit Testing, we only want to test the code we are writing locally. If you do want to test entire workflows, you are likely wanting to perform integration testing (Integration Testing Overview), which is a different beast.
As you specifically asked about designing for Unit Testing, lets assume you actually mean Unit Testing as opposed to Integration Testing and submit that there are two reasonable ways to go about designing your Provider classes.
Stub Out
The practice of replacing an object with a test double that (optionally) returns configured return values is refered to as stubbing. You can use a stub to "replace a real component on which the SUT depends so that the test has a control point for the indirect inputs of the SUT. This allows the test to force the SUT down paths it might not otherwise execute". Reference & Examples
Mock Objects
The practice of replacing an object with a test double that verifies expectations, for instance asserting that a method has been called, is referred to as mocking.
You can use a mock object "as an observation point that is used to verify the indirect outputs of the SUT as it is exercised. Typically, the mock object also includes the functionality of a test stub in that it must return values to the SUT if it hasn't already failed the tests but the emphasis is on the verification of the indirect outputs. Therefore, a mock object is lot more than just a test stub plus assertions; it is used a fundamentally different way".
Reference & Examples
Our Advice
Design your class to both all both Stubbing and Mocking. The PHP Unit Manual has an excellent example of Stubbing and Mocking Web Service. While this doesn't help you out of the box, it demonstrates how you would go about implementing the same for the Restful API you are consuming.
Where is the best place for the db queries to take place?
We suggest you use an ORM and not solve this yourself. You can easily Google PHP ORM's and make your own decision based off your own needs; our advice is to use Doctrine because we use Doctrine and it suits our needs well and over the past few years, we have come to appreciate how well the Doctrine developers know the domain, simply put, they do it better than we could do it ourselves so we are happy to let them do it for us.
If you don't really grasp why you should use an ORM, see Why should you use an ORM? and then Google the same question. If you still feel like you can roll your own ORM or otherwise handle the Database Access yourself better than the guys dedicated to it, we would expect you to already know the answer to the question. If you feel you have a pressing need to handle it yourself, we suggest you look at the source code for a number a of ORM's (See Doctrine on Github) and find the solution that best fits your scenario.
Thanks for asking a fun question, I appreciate it.
Every single dependency relationship within your class hierarchy must be accessible from outside world (shouldn't be highly coupled). For instance, if you are instantiating class A within class B, class B must have setter/getter methods implemented for class A instance holder in class B.
http://en.wikipedia.org/wiki/Dependency_injection
The furthermost problem I can see with your code - and this hinders you from testing it actually - is making use of static class method calls:
Provider::create('external::create-user')
$user = Provider_External::createUser()
$customer = Provider_Gapps_Customer::create($user)
$subscription = Provider_Gapps_Subscription::create($customer)
...
It's epidemic in your code - even if you "only" outlined them as static for "brevity". Such attitiude is not brevity it's counter-productive for testable code. Avoid these at all cost incl. when asking a question about Unit-Testing, this is known bad practice and it is known that such code is hard to test.
After you've converted all static calls into object method invocations and used Dependency Injection instead of static global state to pass the objects along, you can just do unit-testing with PHPUnit incl. making use of stub and mock objects collaborating in your (simple) tests.
So here is a TODO:
Refactor static method calls into object method invocations.
Use Dependency Injection to pass objects along.
And you very much improved your code. If you argue that you can not do that, do not waste your time with unit-testing, waste it with maintaining your application, ship it fast, let it make some money, and burn it if it's not profitable any longer. But don't waste your programming life with unit-testing static global state - it's just stupid to do.
Think about layering your application with defined roles and responsibilities for each layer. You may like to take inspiration from Apache-Axis' message flow subsystem. The core idea is to create a chain of handlers through which the request flows until it is processed. Such a design facilitates plugable components which may be bundled together to create higher order functions.
Further you may like to read about Functors/Function Objects, particularly Closure, Predicate, Transformer and Supplier to create your participating components. Hope that helps.
Have you looked at the state design pattern? http://en.wikipedia.org/wiki/State_pattern
You could make all your steps as different states in state machine and it would look like graph. You could store this graph in your database table/xml, also every provider can have his own graph which represents order in which execution should happen.
So when you get into certain state you may trigger event/events (save user, get user). I dont know your application specific, but events can be res-used by other providers.
If it fails on some of the steps then different graph path is executed.
If you will correctly abstract it you could have loosely coupled system which follows orders given by graph and executes events based on state.
Then later if you need add some other provider you only need to create graph and/or some new events.
Here is some example: https://github.com/Metabor/Statemachine
I am fairly new to Domain Driven Design (DDD), but what I understand of it is that you speak to the application service, which is the entry to your "model". The service can talk to a repository which uses sources (files, databases, etc) to get data. The repository returns an entity.
That is the global idea what I get of it. The service knows the repository but not the entity etc.
Now I have the following issue.
I have an entity user, which is something like the following (is just an example)
<?php
class User
{
protected $name;
protected $city_id;
public function getCity()
{
// return $city_entity;
}
}
The getCity() function returns the city entity. I wish for this function to use lazy loading so injecting the CityEntity when you use the user repository is not really lazy loading.
I came with two solutions to the problem. But I feel that both are against the DDD principals.
First solution I came up with is to inject the city repository in the user entity, which has disadvantages: if you need more repositories you have to load them all in the entity. It looks like answer but it just looks like a wrapper for the repository to me. So why not just inject the repository then?
Second solution, you give the entity a service locator. The disadvantage of this is you don't know any more which repositories are needed unless you read the code.
So now, the question is, what is the best way to give the flexibility of lazy loading while keeping the DDD principals intact?
One of main point in DDD is that your domain model should only express the ubiquitous language of the bounded context to handle the business rules.
Thus, in DDD entities, lazy loading is an anti-pattern. There are some reasons for that:
if an aggregate holds only the data that it requires to ensure business invariants, it needs them all and they are few, thus eager loading works better.
if you lazy load data, your clients have to handle much more exceptional paths that those relevant in business terms
you can use shared identifiers to cope with references between aggregates
it's cheap to use dedicated queries for projective purposes (often called read-model)
IMHO, you should never use DDD entities as a data access technique: use DTOs for that.
For further info you could take a look at Effective Aggregate Design by Vaughn Vernon.
We are having trouble in deciding where to put the ->flush() call in a Symfony2 application. Let's see if you can "inspire" us, please.
Our application is very big. It currently has about 30 bundles. We have 2 separate developer teams: one does frontend (controllers + twigs) and another does core (database + services + model, etc).
Frontend is one project (has its own bundles, which do not have any doctrine models nor logic nor services, but have twigs, public images and css and controllers), and lives in one repository.
Core is another project (has its own bundles, which offer services, model objects, etc, has doctrine objects in their inside and have no controllers nor twigs), and lives in another repo.
The goal of this approach is that our product is delivered with DIFFERENT FRONTENDS (Core+Frontend1 for the web, Core+Frontend2 for the mobiles, Core+Frontend3 for the support-team with a special web to admin the normal users). So all "logic" is "in the core" and either one or other frontend project is consuming the same services, so an improvement in the Core, improves all the deploys without having to re-test every piece of frontend.
So... we are trying that the controllers NEVER access the doctrine objects, but acces a "modelling layer", so if ever the persistance layer changes, the controllers and twigs (ie: all the frontend) remains without a single change so we only have to re-test the core but not the frontend.
We are trying to make a MODEL in such a way that all access to DB in "encapsulated" so the controllers do NOT access the doctrine but to "services" that in turn use doctrine. Suppose we treat the objects "cars" and "people", then a controller can access a "cars_manager" service or a "people_manager" service from which to do ALL necessary operations (create objects, retrieve them, etc).
Where would you put the flush call?
Example (in pseudo-code, to make it simpler to read):
controller AjaxJsonAddDriverToCar( $CarId, $DriverId )
{
try
{
$Cars = getService( "core.cars_manager" );
$Car = $Cars->getCarById( $CarId );
$Car->addDriver( $DriverId );
$Result = JSON_OK;
}
catch
{
$Result = JSON_FAIL;
}
return $Result;
}
Provided that the controller does NOT know how the core is implemented... it should NOT get the doctrine and perform a ->flush() on it.
Inspiration is welcome.
Thanks.
To avoid calling flush from the controller, I suggest encapsulating all the code that updates the database for a particular controller action into a service method which calls flush() at the end, in which case flush() won't be called if the service method throws an exception.
In the example you have given this can be accomplished by replacing:
$Cars = getService( "core.cars_manager" );
$Car = $Cars->getCarById( $CarId );
$Car->addDriver( $DriverId );
$Result = JSON_OK;
with:
$Cars = getService( "core.cars_manager" );
$Cars->addDriverToCar($CarId, $DriverId);
$Result = JSON_OK;
and CarsManager::addDriverToCar would be something like:
$Car = $this->getCarById( $CarId );
$Car->addDriver( $DriverId );
$this->getEntityManager()->flush();
However, this is a fairly simplistic example as it only updates a single Entity and the beauty of flush is that it saves changes to all the entities you have added/removed/updated, constituting the completion of a unit of work.
The approach you described mentions managers which are entity specific. Whilst there is no reason that the manager for a complex entity can't have methods that create/update/remove multiple entities of various types it is worth considering the responsibilities of your manager classes. It may be helpful to have a manager for each entity type that handles simple Find and CRUD type operations for that entity and then an additional layer of managers between the entity managers and the controllers that handle the processing for a particular feature or set of features.
My first thought was some kind of active record, where you would tell the car to save itself. As Car is only boilerplate code, it could be ok that it knows about the database implementation and accesses some services.
My second thought was that the cars manager should know about the saving, so it would be something very similar to the entity manager and you woudl tell him flush and he flushes. You would basically abstract the entity manager and make him a bit easier to use (as there is no repository which one uses directly).
My third thought was wtf. I understand that you want to seperate the frontend from the backend. I don't understand why the frontend cannot operate on models but needs to operate on boilerplate code. The funny thing is: If the models change, so do your layers in between. If you don't want to change the layer, you could also not change the model (it's the same either way). E.g. you want to remove a field from the database: Remvoe the annotation and ignore it. No harm done. If you rename it, you can always have the old getter and setter in place, operating on the new name. And so on.
Of course I don't see the whole picture, but you may want to think this through again ;)
And here is another thought: Maybe you want to just tell the abstraction layer if the whole thing was a success or failure and he does everything what needs to be done (flushing the database, writing logs, sending emails and so on). If you can narrow your use cases down to success and failure and the service knows what to do, then this might be the easiest solution.
Recently i moved to Symfony 2 and i have a litte question.
Let's say i have the following Model:
"catalog" which contains "catalogs". The model gets its data from files but also needs a database connection to verify things.
In the Zend framework or other past projects i loaded the dependencies by a static object which forms a kind of "registry".
As i understand, Symfony 2 uses their service pattern (dependencie injection) instead. But how does this apply to my case.
Must i create a service for every model class i use to auto inject all dependencies? Or is it perfectly valid when i create a instance from my object myself and set for example the database connection in my constructor?
To create a service for every class which needs dependencies, seems a little bit overkill to me.
You can certainly create classes and inject dependencies the old-fashion way but take the time to learn the details of creating services. I think you will find:
Adding a new service is trivial. Copy/paste a few lines of configuration, adjust the class, id and maybe some parameters and you are done. Takes much less time than creating the actual class.
Very soon you will progress from just injecting a database connection to injecting other services as well as perhaps some parameters. Do you really want to have to remember to do all that stuff each time you need to new an object?
Using service id's can divorce your controllers from the exact location/name of a class. The first time you need to do some refactoring and maybe move some services into their own bundle or perhaps swap out a service with another you will be glad that you won't need to hunt down all your code and make changes.
S2 is not really focused on "Models". Instead, think in terms of a service named CatalogManager which wraps access to assorted catalog functionality.