hope some of you can give me a hand with this.
Im working in a project using Codeigniter 2 and Doctrine 2, everything is working ok but I have some "sanity" issues i would like to fix.
The main problem I have right now is with persisting the entities.
In a normal MVC the persistance should be in the Model, but now that I only have Entities and Repositories and i dont have the so called "Models", I'm putting all of this code in the controller making them huge and intimidating :(
I've read on some places that the best approach for this is to have a "Service" layer between the Controller and the Entities, but I haven't found a good way to do this in Codeigniter due to is hard classic MVC pattern.
So im asking for some advice in how to aproach this.
Any of you guys is having the same problems?
I found a solution for my problem, hope it works for some of you.
I'm using Joel's Verhagen integration of Codeigniter 2 and Doctrine 2, you can read his article for more detail "http://www.joelverhagen.com/blog/2011/05/setting-up-codeigniter-2-with-doctrine-2-the-right-way/"
In simple words what I'm doing is using Codeigniter's Models as a Service layer.
This was the cleanest approach that i could find, mainly because all the "wiring" is already done by Codeigniter, so I didn't have to make anything else :D.
I had to make some modifications to the folder structure of Joel's implementation, that way i can use CI's models and still using his Doctrine code.
So I moved everything from inside the folder "models" to a new folder called "entities" (I know it might not be the best name, but it works :P).
Then I changed all the references to the new folder and checked that everything worked.
That's it, now i have my "service layer" workign and my code is a lot more cleaner.
If some of you need help with this, please feel free to ask me.
Was in the same boat a while back. Ended up not using Doctrine's ORM, but basically you're right - you need a "service layer" for anything that isn't directly modeled via Doctrine's entities and repositories.
The way I do this creating a namespaced folder in /application/ for my project code. I then used Doctrine Common's class loader to recognize that folder as the namespace. For example /application/Acme/Authentication.php contains:
namespace Acme;
class Authentication {
//Do Doctrine queries in various methods here
}
Doctrine's class loader uses SPL (spl_autoload_register or something) internally. What that means is that you can fully use PHP 5.3 namespaces. You then have all the fun trials and tribulations of dependency injection for accessing the doctrine dbal inside this service layer. Your controllers will then use this "service layer" directly. Like I said, in my case I decided not to use Doctrine's ORM - so I'm using CodeIgniters ActiveRecord database classes inside my "service layer". Rather than using $this->CI =& get_instance() ... I'm providing the database access into the constructors using a DI container.
For example in my auth/login controller action I may have
function login() {
$user = $_POST['u'];
$pass = $_POST['p'];
$auth = new Acme\Authentication($this->db); //or use a DI container
$user = $auth->authenticate($user, $pass);
....
}
Related
I have some issues regarding the zf2 to zf3 migration of my application. I've gone through the migration guides and started the migration process as describe there.
According to the migration guide, there is no serviceLocator available into controllers anymore. And I used to use it within each and every controller action to inject the config variable array (located in module.config.php), Doctrine MongoDB DocumentManager and the Doctrine EntityManager into the Models where they are needed. Now I'm getting so many deprecated warnings messages as below;
PHP Deprecated: Usage of
Zend\ServiceManager\ServiceManager::getServiceLocator is deprecated
since v3.0.0; please use the container passed to the factory instead
in
/var/www/html/LeapX/vendor/zendframework/zend-servicemanager/src/ServiceManager.php
on line 169
Since I need to access config variables and inject the Doctrine DocumentManager and Doctrine EntityManager into my Models, I had to call $this->getServiceLocator() within my controllers. Let me know how to fix this issue. Is there any possibility to directly inject these dependencies into my Model classes? Should I need to use factories for Models?
And the other question is when it comes to factories regarding the controllers, Should I need to create individual factory for each and every controller of my application? There are quite a lot of number of controllers spread within few Modules in the application. If I add dedicated factory for each and every controller there will be double the number. Let me know the best way to do this.
From what i have read myself, it is no longer possible to call getServiceLocator() from controllers, they removed it since it promotes antipattern.
Here's a blog post from Matthew himself on this issue:
https://mwop.net/blog/2016-04-26-on-locators.html
Another explanation from the guy himself here (shorter, might be easier to digest):
https://github.com/zendframework/zend-mvc/issues/89
I am currently also in the process of trying to migrate a ZF2 (2.4.10) project to ZF3 and face the same issue.
I personally agree with the recommendation to explicitly define dependencies of your classes and controllers instead of (over)using getServiceLocator() method, though depending on your code, refactoring lots of code for this purpose might seem to be a PITA.
Alternatively, this can probably help (though, i can't say for sure since i haven't tried this myself):
http://circlical.com/blog/2016/3/9/preparing-for-zend-f
I cannot to understand this example:
// inside a bootstrap somewhere
$di = new Zend\Di\Di();
$di->instanceManager()->setParameters('MyLibrary\DbAdapter', array(
'username' => $config->username,
'password' => $config->password
));
// inside each controller
$movieLister = $di->get('MyMovieApp\MovieLister');
foreach ($movieLister as $movie) {
// iterate and display $movie
}
How another part of source code ("inside each controller") knows about $di variable?
Is it not completed example? Can anyone show how I can to use DI container in my controllers?
Tutorial page: http://framework.zend.com/manual/2.0/en/modules/zend.di.quick-start.html
Examples in Zend Framework 2 tutorials describe how to use particular component outside of whole framework environment to let you understand better its features.
One of basic ideas of Zend's developers was always to create a package of independent libraries (with only some dependencies between them when needed) to let you choose which part of framework you want to use. For example you could take DI class and use it in some other framework. It would work fine. When they say
inside controller
they mean
not necessarily our controller you any others too
Please note that ZendSkeletonApplication is just an example of use for ZF2, but it doesn't actually belongs to the framework itself.
So the way that you will get Di object in any place depends on your application architecture. If you think in context of using whole ZF2, then you probably won't create Di object on your own at all. Di will be used by ServiceLocator which will let you manage your services (objects, factories etc.).
I think you should read this one to get a perceptive for a future research :
http://zend-framework-community.634137.n4.nabble.com/Services-Instances-Dependencies-in-ZF2-td4584632.html
You also should check out :
https://github.com/zendframework/ZendSkeletonApplication
Roughly speaking , ServiceManager in Zend/Mvc/Application does lots of Di work.
The example is missing the indication on how to configure the controller to have MyMovieApp\MovieLister injected into it, rather than invoking Zend\Di\Di::get(); the latter assumes that the DIC itself has been injected into the controller, which is indeed an anti pattern.
To be honest, that's actually a downside of the current default implementation of ZF2 mvc controllers, which have the ServiceManager (which has superseded Di mainly for performance reasons) injected into them. This issue has been discussed extensively and it will very likely be dealt with in ZF3.
For the time being, just use the ServiceManager, ignore the fact that it is injected into controllers, and use constructor injection inside concrete service factories. That is the best acknowledged way to do IoC in ZF2 at the moment, it's solid and by no means a bad practice.
How do I use a component that I created in cakePHP inside one of my model classes? Is this possible?
If so, please let me know how I can do so
It is possible but pretty bad practice in a MVC framework. You should re-think and re-organize your code if you think you need to use the component in a model because something is cleary wrong then.
A component is thought to share code between controllers, only between controllers.
Components in CakePHP 1.3
Components in CakePHP 2.x
Components in CakePHP 3.x
To share re-usable code between models it would be a behavior. For a view it would be a helper.
If you have some really generic code it should be a lib or put it in the Utility folder / namespace or create a new namespace. Check the existing classes there to get an idea what to put in there.
No code was provided so it is not possible to give any real recommendation on how to refactor it. However the way you want to use the existing code won't work in the MVC context, so time to rethink your approach of whatever you try to do.
It is possible to use a component inside a model (but I cannot comment if this is a recommended or a best-practice).
Inspired from original source, an example to use a component called ‘Geocoder’ in a model:
App::import('Component','GeoCoder');
$gc = new GeoCoderComponent(new ComponentCollection);
Then you can use $gc to call the functions of the component.
--
P.S.: I do not want to encourage bad programming practices, but sometimes the pressure of deadlines (in real world projects) may force a developer to make such decisions.
#AD7six
// Use anywhere
AuthComponent::user('id')
// From inside a controller
$this->Auth->user('id');
From the cake PHP documentation they provide AuthComponent::user('id') so that it can be used in places other than a controller.
Maybe I need a bigger hint, but why shouldn't my model be able to access ACL information ?
After reading a trillion vague tutorials on Dependency Injection Containers, I feel as though I'm still not fully getting the point.
When it comes to things that are application specific (like models, controllers, etc), how should I manage the auto-injection of dependencies?
I happen to have a LARGE website, with maybe 30-40 different types of models...do I really create a single application dependency manager to handle each of these different types?
I have had people tell me that DIC's are not meant for domain stuff, but more for framework stuff, and I have also heard the opposite.
Which is "right"?
BONUS QUESTION:
If DIC's aren't applicable for domain layer objects (like models), how do you pass dependencies to the domain layer objects?
Maybe not exactly what you are looking for but here is an example usage of Dependency Injection Container (DIC)
Let's say I have a Database class and a Cache class. I need to be able to access my database and my Cache class inside of my other classes (models, controllers, etc).
This is a situation where a DIC would come in handy, I can simply store my Database and Cache class inside the DIC class and pass that DIC class into any other class that needs access to the objects that it holds
It's not very clear what the question is, but I'll try.
When it comes to things that are application specific (like models,
controllers, etc), how should I manage the auto-injection of
dependencies?
Do you use a DIC? Did you write one, or do you use a library?
Maybe a library would help, I am the author of PHP-DI so I'm biased, but the library helps me auto-inject dependencies.
For example I can write:
class UserController
{
private $formFactory;
public function __construct(FormFactory $formFactory) {
$this->formFactory = $formFactory;
}
public function createForm($type, $data, $options) {
// $this->formFactory->...
}
}
In that situation, the DIC can detect what dependencies your controller want, and autoinject them. That makes life easier.
I happen to have a LARGE website, with maybe 30-40 different types of
models...do I really create a single application dependency manager to
handle each of these different types?
Why would you need that? I don't understand the need, maybe you need to explain a bit more what's the problem.
I have had people tell me that DIC's are not meant for domain stuff,
but more for framework stuff, and I have also heard the opposite.
Which is "right"?
IMO there's no difference between "domain stuff" and "framework stuff". The only thing that is hard though, is having a DIC injecting stuff in an entity, because that's not a "singleton" (not in the Singleton Pattern way): these objects are not "managed" by the DIC, you can create instances manually everywhere in your code. Example:
$user = new User();
If the User class needs a service, then everywhere in your code you have to do:
$user = new User($service);
On the contrary, you never need to create a service manually (you never need to call "new"), so you can let the container create the instance and inject everything.
I'm not very happy with my answer as it's a bit vague, but I have trouble identifying really what's your problem. Maybe you should give code examples, or at least explain a bit more.
PS: I have struggled to understand DI and what is a DIC too, don't settle for a "I think I get it a bit more now, though not totally", I did the same and it took me months to finally understand.
If it helps, read the introduction text at http://mnapoli.github.io/PHP-DI/ and maybe also: http://mnapoli.fr/controllers-as-services/ (not directly related, but it can help)
I've a question related to Doctrine 2 and Zend Framework.
If you use Zend Framework without Doctrine by default you place business logic in the models. But as Doctrine 2 does have Entities where should the business logic be placed?
I first had created models where the entity manager did calls to the Entities. But when I wanted to write unit tests for my models without database calls. I needed to move the entity manager to the controllers. But I'm getting business logic in my controllers which is not good.
The code below shows a part of an controller action:
$customerAddress = $this->_model->save($values, $id);
$this->_em->persist($customerAddress);
// Update default billing address
$defaultBilling = $this->_model->saveDefaultBilling($values, $customerAddress);
if ($defaultBilling != FALSE) {
$this->_em->persist($defaultBilling);
}
// Update default shipping address
$defaultShipping = $this->_model->saveDefaultShipping($values, $customerAddress);
if ($defaultShipping != FALSE) {
$this->_em->persist($defaultShipping);
}
$this->_em->flush();
Can somebody say what's the best practice for this issue? Thx
I'm not sure there is an agreed upon best practice, but I see a lot of talk regarding Service Layers when discussing Doctrine or Zend Framework.
When I started my app with Doctrine, I tried to build as much functionality into my Entity objects as I could, but quickly realized that's almost impossible without injecting the Entity Manager, which totally breaks the idea of plain, non-persistence-aware objects that makes Doctrine 2 so nice.
If you're coming from an Active Record world, it's easy to think of your 'model' as single object that corresponds to a database table and that controllers have to talk to these objects. This is usually okay for very simple CRUD applications. But because of Doctrine's approach, doing it that way is weird and frustrating.
Instead, think of the different layers in your application. Doctrine is a layer that sits on top of the database, your Entities sit on top of Doctrine, and your Service Layer should sit on top of your Entities. That whole package is your M in MVC, and it comprises both data persistence and business logic.
I would suggest you check out this presentation on the topic.
UPDATE
I originally missed the part where you mentioned you had separate model objects making calls to the Entities. I think that would be an acceptable pattern to use. If you want to write tests without making database calls, you're probably going to want to to use a mock of the Entity Manager -- it's a dependency no matter which layer you put it in.
Here is the github skeleton project I used, it did the doctrine 2 initialisation with Zend Franework 1.11.2 in the bootstrap, nice and clean, using model for entities & model repository for business logic. Unit tests & ant build script too for you TDD developers out there.
https://github.com/eddiejaoude/Zend-Framework--Doctrine-ORM--PHPUnit--Ant--Jenkins-CI--TDD-