Get Service Container from Entity in Symfony 2.1 (Doctrine)

Get service container from entity in symfony 2.1 (Doctrine)

An entity is a data model and should only hold data (and not have any dependencies on services). If you want to modify your model in case of a certain event (PrePersist in your case) you should look into making a Doctrine listener for that. You can inject the container when defining the listener:

services:
my.listener:
class: Acme\SearchBundle\Listener\YourListener
arguments: [@your_service_dependency_or_the_container_here]
tags:
- { name: doctrine.event_listener, event: prePersist }

Injectiong or accessing service container within an entity object

@Ahmend is correct in that you should not inject the container into entities. In your case you might do something like:

// Controller
$order = ...find($orderId);
$currency = $this->getContainer()->getParameter('currency');
$price = $order->calculatePrice($currency);

So currency is passed as a method parameter.

I fully understand that this is a difficult concept especially if one is used to active records and plenty of globals. But in the end it will make sense and produce better code.

However, just so you don't get stuck, I will reveal onto you the secret of accessing the container from anywhere. Turns out that the app kernel is a global variable. So:

class Orders
{
public function getCurrency()
{
global $kernel;
$container = $kernel->getContainer();
return $container->getParameter('currency');
}

Get symfony parameter inside doctrine entity for lifecyclecallback

like @Cerad said, I solved it by defining the path as php class constant. That is even better style because the path should only be changed in very special cases and shouldn't be a parameter therefore.

Put a symfony container inside a repository or an entity is a good or bad practice?

There are some example of how to create Entity managers (or repository), relevant is as described in FOSUserBundle where doctrine Entity manager has been injected as object manager inside the Dependency injection.

    if ('custom' !== $config['db_driver']) {
if (isset(self::$doctrineDrivers[$config['db_driver']])) {
$loader->load('doctrine.xml');
$container->setAlias('fos_user.doctrine_registry', new Alias(self::$doctrineDrivers[$config['db_driver']]['registry'], false));
} else {
$loader->load(sprintf('%s.xml', $config['db_driver']));
}
$container->setParameter($this->getAlias().'.backend_type_'.$config['db_driver'], true);
}
if (isset(self::$doctrineDrivers[$config['db_driver']])) {
$definition = $container->getDefinition('fos_user.object_manager');
$definition->setFactory(array(new Reference('fos_user.doctrine_registry'), 'getManager'));
}

In this case there are UserManager instead of repository that have the same role.

In this example all services has been initialized and injected directly inside the dependency injection

It is more powerful to call (private) services directly inside the bundle construction / or "compilation" (the dependency injection) instead of colling container inside services

Creating a symfony service that can access doctrine

I believe that most people starting from scratch would use ORM, I didn't because I had existing PHP code working with PDO SQL. Here is an example showing how to access Doctrine DB connection:

In [YourBundle]\Resources\config\services.yml

services:

#dependency injection services
pdo_connection:
class: [YourBundle]\DependencyInjection\PDOManagement\PdoConnection
arguments: ["@doctrine.dbal.default_connection"]

Then in [YourBundle]\DependencyInjection\PDOManagement\PdoConnection.php

<?php
namespace [YourBundle]\DependencyInjection\PDOManagement;

use Doctrine\DBAL;

class PdoConnection {

protected $db;

public function __construct($dbalConnection){
$this->db = $dbalConnection;
}

}
?>

this->db of class PdoConnection will have access to the DB connection after constructor.

I let you figure out how to use it according to your need.

How to use my Entities and Entity Managers in Symfony 2 Console Command?

I think you should not retrieve the container in the constructor directly. Instead, retrieve it in the configure method or in the execute method. In my case, I get my entity manager just at the start of the execute method like this and everything is working fine (tested with Symfony 2.1).

protected function execute(InputInterface $input, OutputInterface $output)
{
$entityManager = $this->getContainer()->get('doctrine')->getEntityManager();

// Code here
}

I think that the instantiation of the application object is not done yet when you are calling getContainer in your constructor which result in this error. The error comes from the getContainer method tyring to do:

$this->container = $this->getApplication()->getKernel()->getContainer();

Since getApplication is not an object yet, you get the a error saying or are calling a method getKernel on a non-object.

Update: In newer version of Symfony, getEntityManager has been deprecated (and could have been removed altogether by now). Use $entityManager = $this->getContainer()->get('doctrine')->getManager(); instead. Thanks to Chausser for pointing it.

Update 2: In Symfony 4, auto-wiring can be used to reduce amount of code needed.

Create a __constructor with a EntityManagerInterface variable. This variable will be accessible in the rest of your commands. This follows the auto-wiring Dependency Injection scheme.

class UserCommand extends ContainerAwareCommand { 
private $em;

public function __construct(?string $name = null, EntityManagerInterface $em) {
parent::__construct($name);

$this->em = $em;
}

protected function configure() {
**name, desc, help code here**
}

protected function execute(InputInterface $input, OutputInterface $output) {
$this->em->getRepository('App:Table')->findAll();
}
}

Credits to @profm2 for providing the comment and the code sample.

Symfony2: Get Service Inside Entity

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...



Related Topics



Leave a reply



Submit