Now, I am writing a php project with doctrine. But at service class, I need inject a EntityManager. How to do it? I have searched some answer, but They use a framework.
If donot use any php framework, How to write a service class and inject EntityManager?
Thanks a lots.
You just need to write a class that obtains an EntityManager object, as per:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/configuration.html#obtaining-an-entitymanager
class EntityManagerService
{
public static function getEntityManager() {
// return EntityManager object as per documentation.
}
}
$em = EntityManagerService::getEntityManager();
I hope this helps!
Related
I'm trying to access the EasyCorp\Bundle\EasyAdminBundle\Dto\PaginatorDtoin my Crud Controller :
public function __construct(
private EntityManagerInterface $manager,
private EntityRepository $entityRepository,
private PaginatorDto $paginatorDto,
) {
}
But I've got this error => Cannot autowire service "App\Controller\Activity\ActivityCrudController": argument "$paginatorDto" of method "__construct()" references class "EasyCorp\Bundle\EasyAdminBundle\Dto\PaginatorDto" but no such service exists. and I don't understand why and How to fix it :(
Any idea ?
I'm not an expert of that bundle so take my answer with a pinch of salt but looking at bundle's code I've noticed PaginatorDto not to be a service (as the name suggests).
As that DTO is not a service (and it's ok it is not), you can't autowire it nor make it a service "locally" (eg.: in your application).
So, in order to retrieve the DTO object, inject AdminContextProvider (that is a service as you can notice here) instead and use it to get the DTO
$adminContext->getCrud()->getPaginator();
Your crud controller should extend AbstractCrudController which give you access to the current admin context.
So if you want to use it in one of your crud controller method you should be able to access the paginator with:
$paginator = $this->getContext()->getCrud()->getPaginator();
If you want to do the same outside your crud controller, let's say in another service. You need to inject the AdminContextProvider to first get the AdminContext and do it the same way.
private ?AdminContext $siteRepository;
public function __construct(AdminContextProvider $adminContextProvider)
{
$this->adminContext = $adminContextProvider->getContext();
}
I read in the documentation how to use a controller as a service. But I am not sure what would be the purpose of it. Why not then simply use a service (a class define as a service)?
If anyone could give me some good examples of transforming a controller in a service that would be great.
The classical Symfony controller uses a Service Locater pattern to pull in it's dependencies:
class PersonController
{
public function showAction()
{
$personRepository =
$this->getDoctrine()->getEntityManager()->getRepository('Entity\Person');
$person = $personRepository->find(1);
return new JsonResponse($person);
Getting the person repository requires the action to have quite a bit of knowledge about how to locate things. Somewhat magical in fact . The controller is tied directly to doctrine and the framework infrastructure.
It also makes the action hard to test. You have to make a container then define the necessary services before running the action.
Contrast that with a controller defined as a service with it's dependencies injected:
class PersonController
{
protected $personRepository;
public function __construct($personRepository)
{
$this->personRepository = $personRepository;
}
public function showAction()
{
$person = $this->personRepository->find(1);
The action no longer needs know about how to locate the repository. It's just there. For testing, just need to make a repository and inject it. Clean and simple.
Read books From Apprentice To Artisan and Implementing Laravel by Chris Fidao and now i don't know how to correctly work with Models in Repositories.
In Implementing laravel book author is working with models in this way:
Example #1
<?php
use MyApp\Interfaces\UserInterface;
use Illuminate\Database\Eloquent\Model;
class UserRepository implements UserInterface
{
protected $user;
public function __construct(Model $user)
{
$this->user = $user;
}
public function find($userId)
{
return $this->user->find($userId);
}
}
But that can by done in other way, not injecting Model as a dependency, like this:
Example #2
Built example using tutorial http://culttt.com/2013/07/08/creating-flexible-controllers-in-laravel-4-using-repositories/
<?php
use MyApp\Interfaces\UserInterface;
use MyApp\Models\User\User;
class UserRepository implements UserInterface
{
public function find($userId)
{
return User::with('profile')->find($userId);
}
}
Why in first example Model is injected, why not use directly Model like in example two?
Which way is correct and why ?
Also which way will be more testable with integrated to laravel UnitTest package ?
The example 2 is bad because it's coupling your repository to a particular implementation of the User model.
Every time you use your repository it'll need to instantiate Univemba\Models\User\User. The whole idea of Dependency Injection is to inject (send) in to your object whatever dependencies it has. If your object needs a Model to work with you can send it a Laravel Eloquent Model, but any of your co-workers could also need to send to it a Doctrine Model. But if you couple your class to Eloquent, this isn't possible.
So in the first example, there is no instantiation happening on your code and it's not using a concrete class directly as in the second:
return User::with('profile')->find($userId);
It is receiving an implementation in the process of its instantiation:
public function __construct(Model $user)
{
$this->user = $user;
}
There are better ways to do that, because it is still expecting a concrete class while it should be expecting an implementation of an interface
public function __construct(ModelInterface $user)
{
$this->user = $user;
}
In this case you just need to pass to your object something that implements ModelInterface, which could be
Univemba\Models\EloquentModel
Or
Univemba\Models\DoctrineModel
Because both would be implementing
Univemba\Models\ModelInterface
I think if a Repository is intended to be the Eloquent implementation of a RepositoryInterface it isn't a bad idea to use the EloquentModel directly.
Is there any way to call service inside entity
I need entity Manager inside entity so I can able to get custom result with repository functions.
I am thinking about inject ContainerInterface inside my entity like this.
use Symfony\Component\DependencyInjection\ContainerInterface;
class MyEntity
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function getEntityManager(){
return $this->container->get('doctrine')->getEntityManager();
}
}
But I think this is not right way to do that and it take more code I mean I have to do this for all entity where I need entity Manager
Is there any good solution ?
I don't know if you can but you shouldn't do it anyway. The entities are meant to be really simple...
need entity Manager inside entity so i can able to get custom result with repository functions
What do you want to do exactly, there must be a different solution...
As already mentioned, dependency injection is definitely the wrong way to go.
Use either Custom Entity Repositories (http://symfony.com/doc/2.0/book/doctrine.html#custom-repository-classes) for more complex queries or use a specific service where you can implement your custom result if more complexity is needed (http://symfony.com/doc/2.0/book/service_container.html#referencing-injecting-services)
I'm looking for a good example of how to correctly implement Service Layer with Zend Framework and Doctrine2
I've seen some implementations but all of them have access to the EM from the controller when instantiating the service, and I think that might be wrong or not?
Exmaple:
http://cobbweb.me/2010/11/integrate-doctrine-2-zend-framework-application/
Also I got to this project but not really sure how to implement it:
Thanks
Use a helper to act like a factory for the services:
You need to create an Action Helper and inject the EntityManager on it when you register the instance in the Front Controller.
This Action Helper receives as parameter in the direct() method the name of the service class that the factory should create.
Inside this method you should try to instantiate the service class requested, and return it (or throw an exception if the same is not found).
Let your service classes receive as parameter in the constructor the EntityManager and inject it during the construction on the factory.
The rest should already be clear to you. In your controller you only need to use something like:
SomeController extends Zend_Controller_Action {
//...
public function someAction ()
{
$myService = $this->_helper->service( 'MyService' );
$myService->doSomething();
}
}