Creating Your Database and First Entity with Doctrine
In this first video we are going to get started with a hands-on tutorial using Doctrine with Symfony 3.
The first step we must take is to tell Doctrine how it can interact with our database. This is achieved by entering your database configuration parameters in the rather intuitively named parameters.yml
file:
# app/config/parameters.yml
parameters:
database_driver: pdo_mysql
database_host: localhost
database_name: your_db_name_here
database_user: your_db_username_here
database_password: your_db_password_here
These values will be unique to your system.
What's interesting about these parameters is how they are used inside Symfony's configuration files (e.g. app/config/config.yml
). Let's quickly take a look:
# app/config/config.yml
doctrine:
dbal:
driver: '%database_driver%'
host: '%database_host%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
Again, so far, so copy / paste from the Symfony documentation.
Where this gets interesting is how we can override these configuration values for different environments. If you look inside your app/config
directory, you will see - by default - there are a number of configuration files:
config.yml
config_dev.yml
config_prod.yml
config_test.yml
Each of these maps directly to a given Symfony environment which are essentially different situations in which we might want to interact with our application. During development we can make use of the dev
environment (also commonly called app_dev
after the app_dev.php
file in the web/
directory) which gives us access to the web debug toolbar, or the test
environment for running our test suite etc.
The really smart thing is - we can selectively override individual pieces of config for any of these given environments. This is really cool.
An example might be that we have a different database name in our dev
environment. We could set this up really easily:
# app/config/config_dev.yml
# Doctrine Configuration
doctrine:
dbal:
dbname: "%test_database_name%"
Now all we need to do is add in the extra parameter to parameters.yml
:
# app/config/parameters.yml
parameters:
# etc
database_name: your_db_name_here
database_user: your_db_username_here
database_password: your_db_password_here
test_database_name: a_test_db
And now the development environment works identically to production / other environments, but uses a separate database. This is awesome.
Once these parameters have been added, and assuming the provided username / password combination matches a user with the relevant database privileges, you should be able to run:
php bin/console doctrine:database:create
And Doctrine will go ahead and create your database, as named in your parameters.yml
file for you.
You may be wondering though - how do I make it create my development environment database? Good question:
php bin/console doctrine:database:create --env=dev
# equivalent to
php bin/console doctrine:database:create -e=dev
There are a number of other Doctrine commands we can use, and we will cover only a small number of them in this series:
php bin/console
Will list out all the commands that are available in your application, not just for Doctrine but in general.
Entities
You can't talk about Doctrine without talking about Entities.
As I mentioned in the course description, there are a large number of new terms to know and use when using Doctrine. 'Entity' is the most commonly used one by far.
Doctrine's documentation describes entities as:
Entities are PHP Objects that can be identified over many requests by a unique identifier or primary key. These classes don’t need to extend any abstract base class or interface. An entity class must not be final or contain final methods. Additionally it must not implement clone nor wakeup, unless it does so safely.
An entity contains persistable properties. A persistable property is an instance variable of the entity that is saved into and retrieved from the database by Doctrine’s data mapping capabilities.
A basic way to think about an entity is that it is a PHP class that represents a record from your database. This isn't strictly true. An entity can be made up of data from multiple tables. But it's a good place to start, just be aware that it's not technically correct.
An entity is a class with an ID. This is exactly like a row in your database that has an ID.
An entity contains mapping information (usually by way of annotations) that tell Doctrine which fields in your PHP class map to which columns in your database table. Likewise, it will contain mapping information to tell Doctrine which table this entity represents.
An entity usually looks something like this:
<?php
// src/AppBundle/Entity/RedditPost.php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="reddit_posts")
*/
class RedditPost
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string")
*/
protected $title;
Entities generally have singular names. RedditPost
not RedditPosts
. This makes sense a little later when working with entities.
Doctrine will guess at your table name from your entity name, but I always like to specify a table name, and use the plural version of my entity name. This is just personal preference.
I'd advise to type out these annotations for the first 10 or more times you create an entity. It is a little laborious, but it drills it into your fingers for future reference. There is a handy PHPStorm plugin for Symfony that can make this a little easier for you though.
For reference, the list of available property mapping and mapping types are available on the Doctrine documentation. Just be aware, when copying from the Doctrine documentation, that they do not use the @ORM
prefix to the annotation, like we do in Symfony land - e.g.:
// official Doctrine docs:
/** @Column(name="`number`", type="integer") */
private $number;
// vs Symfony style:
/** @ORM\Column(name="`number`", type="integer") */
private $number;
Once you have created an entity like the above, there is another Doctrine command that we can run from the command line to create a table for the entity:
php bin/console doctrine:schema:update --force
If you don't include the --force
flag then you will do a 'dry-run' where nothing happens, but you get to see what would have happened. Useful to validate before you run the real command.
Assuming this all went well, then now you should have a brand new, empty table in your database called reddit_posts
, just waiting for you to add some data. Which is exactly what we shall do in the very next video.
Automated Builds
As mentioned in this video series, I use a tool called Ansible for all my server builds. This is partly because I do a heck of a lot of new server setup for all my tutorial series, but also in a large part because Ansible helps not only automate, but document the process of any particular server.
This is a more advanced devops topic, and definitely not required to work with Symfony at all. But it is cool, and if you're into that sort of thing, then I highly recommend Ansible as a build tool.