Access Symfony2 service layer in Doctrine entity? - php

I'm sure the title is pretty descriptive, but for a more in depth question: How does one access Symfony2's service layer for use in Doctrine's lifecycle callbacks? I plan on utilizing these callbacks to register an entity in my search index (which is managed by another service) every time it is created/updated/deleted.
There are a couple of things that come to mind, though, so I might as well ask them as well...
Is this illegal, bad practice, or just plain terrible? Is there another solution to hooking logic involving services into the entity's lifecycle or should I decouple them altogether?
I dig any advice and am down to try new things.

Check out this cookbook entry.

Related

Is a repository or service provider required?

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.

SoftDelete, Relations and the SonataORMAdminBundle

Im using SonataAdminBundle - more specificly the SonataORMAdminBundle with Doctrine - to do some of my administration. So far this turned out to be a really useful Bundle, however a senseful deletion of entities is somewhat tricky.
Consider a Tour entity has a Truck and a Trailer entity, but when a Truck is being discarded it should no longer appear in the overall Admin Application. Nevertheless, there might still exists legacy Tour entities with a relation to this Truck.
So it is unclear how to tackle this problem when a user might edit such a legacy Tour in the admin, is the entity selection gone?
I've taken a look at the SoftDelete Extension Bundles, but it seems to come with a lot of work for adjusting all the specific cases.
Is there a simple approach at the Bundle Level or in Doctrine in General tackle those kind of problems?
The way this behavior is implemented when needed in the Sonata suite is through a new boolean field in the entity: 'enabled'. We then add a filter on it to display it or not, and never actually delete the object in the usage. Soft-deletion being a client-specific operation (you might have dedicated business rules along with it), we didn't implement it natively in the Sonata suite. Your implementation should depend on your needs in this case.
We however integrated the EntityAuditBundle from Simplethings (https://github.com/simplethings/EntityAudit) in the SonataDoctrineORMAdminBundle: each entity which has an Admin class is audited automatically. This allows to track each edit done on the audited entities. (Not necessarily what you're looking for but might be interesting nonetheless).
Finally, as you mentioned, SoftDelete might do the trick for you. But you might rather have your own event listeners (using preRemove for instance) and implement your solution your own way.
If you think your solution might be worth integration in the SonataDoctrineORMAdminBundle, feel free to create an issue on github, and we'll discuss it.

How do I architect my classes for easier unit testing?

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

Symfony 2 architecture in the case of a model class (Services,Dependencie injection)

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.

ServiceLocator and the Open/Closed Principle

I'd like to:
Make commonly required services visible to all classes that need them,
with a minimum of boilerplate, and
without sacrificing testability!
It's a small project and I think DI might be overkill, but maybe I'm wrong? Anyhow, I have been focusing on the ServiceLocator pattern as described by Martin Fowler
In a client class' constructor, I have something like this:
this->db = Locator::getDb();
this->log = Locator::getLogger();
Then the rest of the class' methods access the service through those member attributes, e.g.:
this->fooModel = new fooModel(this->db);
fooItem1234 = this->fooModel->findById(1234);
However I would also like this level of visibility for "model" objects (like fooModel above) because they are accessed from several different places and there is no need to have more than one instance.
So my initial thought was to extend Locator to have a ::getFooModel() but now it seems I'm violating the Open/Closed Principle, since I'll have to modify Locator every time I introduce a new model class.
To satisfy OCP, I could use the Dynamic Service Locator (also described on Fowler's page) however I'm not totally sold on this for the same reasons as him, i.e. it's not explicit enough.
Another solution would be to just make all my models' methods static. So:
fooItem1234 = FooModel::findById(1234);
I like this because it's zero boilerplate. I can just create a new model class and start calling it from anywhere with a single line. But now the model depends on Locator to find its DB connection and I'm not sure how I feel about that. For one, if I ever needed to have two fooModels open on separate database connections, it would be a mess and/or impossible. That said, I don't actually need to do that currently so this option seems a little tempting.
Finally, there's DI. But like I said above I think it might be too much for this little project.
Conclusion: I'm a little stuck here and would appreciate some advice from the gurus of StackOverflow!
Why do you think that DI is overkill for your project? DI patterns such as Constructor Injection is way simpler and cleaner than Service Locator (which I consider an anti-pattern).
I consider Service Locator to be an anti-pattern since it is totally opaque to the user of the API which dependencies need to be in place; thus, one could easily invoke methods on your objects in a context where the Service Locator would throw, and the API gives you absolutely no clue that this is the case.
You don't need a DI Container to use DI. If just have a simple project, you can use what is known as Poor Man's DI where you wire up dependencies manually.
... and there is no need to have more than one instance.
You're mixing apples and oranges. The fact that you only need one instance of a class for an application, is not the same thing as it being a good idea to make that instance globally available. With DI you don't change the cardinality - there is still just one instance. What you change is the scope of variables that address said instance. There's a difference.

Categories