Alex Zhulin Alex Zhulin - 5 months ago 37
PHP Question

Php Symfony 3.1 exception by using Doctrine DBAL

I'm trying to use Doctrine DBAL in my Symfony web project.

What I've done:

Config.yml

# Doctrine Configuration
doctrine:
dbal:
driver: pdo_pgsql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8


parameters.yml

parameters:
database_host: 127.0.0.1
database_port: 5432
database_name: my_project_db
database_user: postgres
database_password: my_password


My controller for company profile

/**
* @Route("/profile/{userId}/{sessionKey}", name="profile")
*/

public function profileAction($userId=null, $sessionKey=null)
{
$securityController = new SecurityController();
$securityController->userId = $userId;
$securityController->sessionKey = $sessionKey;
if ($securityController->sessionKeyIsValid())
{
return new Response('Profile');
}
else
{
return $this->redirectToRoute('login');
}
}


And my securityController where I'm trying to connect to my Postresql

class SecurityController extends Controller
{
public $userId;
public $sessionKey;

public function sessionKeyIsValid()
{
$conn = $this->get('database_connection');
//$conn->fetchAll('select * from main.users;');
return false;
}
}


Exception (
Error: Call to a member function get() on null
) appears on this string of code
$conn = $this->get('database_connection');

What I'm doing wrong? It seems that I followed step by step as is it advised in Symfony cookBook http://symfony.com/doc/current/cookbook/doctrine/dbal.html

Answer

In a Symfony project, you never instantiate yourself a controller. If you want to separate your logic from your controller, create a service and inject what you need as a dependency.

Your service for instance may look like this :

namespace AppBundle\Service;

use Doctrine\DBAL\Connection;

class SecurityService 
{
    protected $db;
    public $userId;
    public $sessionKey;

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

    public function sessionKeyIsValid()
    {
        // $this->db->fetchAll('select * from main.users;');
    }
}

And you declare it in your services.yml like this :

services:
    app_security:
       class:        AppBundle\Service\SecurityService
       arguments:   [ "@database_connection" ]

Then, in any controller, you have access to a shared instance of SecurityService :

public function profileAction($userId=null, $sessionKey=null)
{
    $security = $this->get('app_security');

    // ...
}

I must warn you however that accessing directly to the database layer is probably not the correct way. You should read the Databases and Doctrine section from the documentation first.