Integrating Doctrine into your Slim 3 project

In this post we will explain how to setup Doctrine 2 in your Slim 3 project. Integrating Doctrine can be a bit of a pain but reading this article should get you around the major hurdles

Firstly you will need the all-mighty doctrine

composer install doctrine/orm

Now on to the hard-parts.

  1. Getting the Doctrine CLI tool setup
  2. Getting up the XML Mapping location (or you can use annotations if you want... but I hate annotations)

Okay, you will need to create a cli-config.php file in the root of your directory.

It's contents should be something like:

<?php
use Doctrine\ORM\Tools\Console\ConsoleRunner;

// cli-config.php
require_once __DIR__."/config/bootstrap.php";


return ConsoleRunner::createHelperSet($entityManager);

In my /config/bootstrap.php file you will find

<?php
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Space\Persistence\User;

include __DIR__ . "/../vendor/autoload.php";

//Doctrine Config

// database configuration parameters
$conn = array(
    'driver' => 'pdo_sqlite',
    'path' => __DIR__ . '/../db/db.sqlite',
);

$paths = array(__DIR__."/xml");
$config = Setup::createXMLMetadataConfiguration($paths, true);
$entityManager = EntityManager::create($conn, $config);

The gotcha's here are the path to the db.sqlite and the xml directory.

So far so good... nothing to cray-cray, 1 and 2 are checked off. Refactoring the Doctrine into a bootstrap file makes writing phpunit tests very easy.

Let's see what that looks like, here is my tests/bootstrap.php file which is my phpunit bootstrap.

<?php

include_once __DIR__ . "/../config/bootstrap.php";

WOAH CRAZY RIGHT?

Well since you are here, I might as well show you how easy it is to inject doctrine into test cases. *Warning* Global Variables are going to be used.

<?php
namespace Tests;

use Doctrine\ORM\EntityManager;
use Persistence\Game;
use Persistence\GameUser;
use Persistence\User;

class BaseCase extends \PHPUnit\Framework\TestCase
{
    /** @var  User */
    protected $user;

    /** @var  Game */
    protected $game;

    /** @var  GameUser */
    protected $gameUser;

    /** @var \Doctrine\ORM\EntityManager */
    protected $entityManager;

    /** @var \Doctrine\ORM\EntityRepository */
    protected $userRepo;
    protected $gameRepo;
    protected $gameUserRepo;

    public function setUp()
    {
        global $conn, $config;

        if (is_null($this->entityManager) || !$this->entityManager->isOpen()) { // ????
            $entityManager = EntityManager::create($conn, $config);
            $this->entityManager = $entityManager;
        }

        $this->user = new User();
        $this->game = new Game();
        $this->gameUser = new GameUser();

        $this->userRepo = $this->entityManager->getRepository(User::class);
        $this->gameRepo = $this->entityManager->getRepository(Game::class);
        $this->gameUserRepo = $this->entityManager->getRepository(GameUser::class);
    }
}

Ok So some of this... will need explanation...

So here's the thing about doctrine. If the Entity Manager throws an exception... it closes it. Which is great in production .... butttt what happens if we Expect a Doctrine Error in our unit tests ... well my friends if that happens ALL THE TESTS AFTERWARDS WILL FAIL... Which leads you to the setup method and having to check if the EntityManager is open or not. The things we have to do for testing.... Most of this stuff should be pushed up maybe a level or two but work in progress atm :)

All in All Doctrine works pretty good in Slim. I look forward to working with it more.

The only thing left for you to do is to write your Doctrine XML Classes and map them to your Persistence Models!

As always hit me up on Slim's slack or via Twitter if you have any questions or problems.

Cheers!

Glenn

Written by Glenn Eggleton on Sunday January 22, 2017
Permalink - Chapter: Slim