27

I'm learning Symfony2 (and OOP) and want to create a service that's available throughout my app. This service takes a value foo, checks it against a database table, and returns a value bar.

I have a little class

namespace Acme\TestBundle\Toolbox;

class StringToolbox
{
    public function lookupSomething($foo)
   {

        $conn = $this->get('database_connection');
        $sql = "SELECT bar FROM bar_list WHERE foo = :foo";
        $stmt = $conn->prepare($sql);
        $stmt->bindValue("foo", $foo);
        $stmt->execute();


        return $bar;
    }


}

My settings are:

services:
    toolbox:
       class:        Acme\TestBundle\Toolbox
        arguments:   [@database_connection]

But it throws an error saying that the get() method is undefined. I'm stuck-- how can I use DBAL in the service? Thanks!

user1578653
  • 4,888
  • 16
  • 46
  • 74
Acyra
  • 15,864
  • 15
  • 46
  • 53

2 Answers2

40

First off you should add a constructor to your class and pass in the @doctrine.dbal.%connection_name%_connection service

namespace Acme\TestBundle\Toolbox;
use Doctrine\DBAL\Connection;

class StringToolbox
{
    /**
    *
    * @var Connection
    */
    private $connection;

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

    public function lookupSomething($foo)
    {

    $sql = "SELECT bar FROM bar_list WHERE foo = :foo";
    $stmt = $this->connection->prepare($sql);
    $stmt->bindValue("foo", $foo);
    $stmt->execute();


    return $bar;
    }


}

Your service configuration should now look like this:

parameters:
 my_service_connection: default

services:
 toolbox:
   class:        Acme\TestBundle\Toolbox\StringToolbox
    arguments:   [@doctrine.dbal.%my_service_connection%_connection]

What you are saying with this configuration is "make me a service named toolbox that will receive the doctrine.dbal.default_connection service as the first constructor argument"

There are other injection methods besides Constructor injection and you should read the http://symfony.com/doc/current/book/service_container.html documentation to get a grasp of all possibilities (Setter injection, Factory injection, etc) and to better understand how Dependency Injection works

catalin.costache
  • 3,123
  • 1
  • 25
  • 15
  • This helps a lot! The Symfony docs are great but they assume full OOP knowledge, and I have some gaps. Thanks! – Acyra Aug 04 '11 at 15:02
  • For some reason this no longer works, I have to pass a different argument: arguments: [@database_connection] – Acyra Jan 16 '13 at 16:35
  • 6
    The `@doctrine.dbal.connection` service is an abstract. Try to use `@doctrine.dbal.%connection_name%_connection` where the `%connection_name%` placeholder the name of the connection that you want to inject. – Igor Timoshenko Feb 01 '13 at 17:34
  • @IgorTimoshenko, Thank you for your answer. If we use `@doctrine.dbal.%connection_name%_connection` approach, then how do we pass the `%connection_name%` for the desired connection out of 10 possible connections? – Nis Jun 23 '14 at 05:53
  • @Nis %connection_name% is a parameter that you can set it your parameters.ini, parameters.yml or in the `parameters:` section of an yaml config file. It will automatically be interpolated by the DI container. See my example above – catalin.costache Jun 23 '14 at 08:57
  • @catalin.costache Thank you very very much for your quick response. I have one doubt though. I am using this method because I have few DB to connect to. `clientA` & `clientG` & `clientX` to name few. I can define the variable in parameters.yml file saying `my_service_connection: clientA`. However, on runtime, when i instantiate my service, from my service how does it know / how can I let it know that I want to connect to either `clientA` or `clientX` or `clientG`. – Nis Jun 23 '14 at 10:59
  • @Nis you can always inject the `@doctrine` service which is an http://www.doctrine-project.org/api/common/2.4/class-Doctrine.Common.Persistence.AbstractManagerRegistry.html child. Take a look at: https://github.com/doctrine/DoctrineBundle/blob/master/Resources/config/dbal.xml – catalin.costache Jun 23 '14 at 11:13
11

@doctrine.dbal.connection not working, As Igor says, @doctrine.dbal.connection is an abstract, use @doctrine.dbal.default_connection if you only have one db connection, or @doctrine.dbal.%connection_name%_connection where the %connection_name% placeholder the name of the connection that you want to inject.

Your service configuration should now look like this:

services:
 toolbox:
   class:        Acme\TestBundle\Toolbox\StringToolbox
    arguments:   [@doctrine.dbal.default_connection]
Steely Wing
  • 16,239
  • 8
  • 58
  • 54
  • Thank you for your answer. If we use `@doctrine.dbal.%connection_name%_connection` approach, then how do we pass the `%connection_name%` for the desired connection? – Nis Jun 23 '14 at 05:30