Important
You are browsing the documentation for version 4.2 of OroCommerce, OroCRM and OroPlatform, which is no longer maintained. Read version 5.1 (the latest LTS version) of the Oro documentation to get up-to-date information.
See our Release Process documentation for more information on the currently supported and upcoming releases.
Create Entities¶
When working with OroPlatform, creating entities and mapping them to the database is no different from doing the same in a common Symfony application. Once you have created your bundle, create the entity classes you need in the bundle’s Entity
namespace, add all the required properties, and add the required mapping annotations as usual.
A task is composed of a brief subject, a more verbose description, a due date, and a priority. Also, each task is identified by a unique identifier that is automatically generated by the database:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
* @ORM\Table(name="app_task")
*/
class Task
{
/**
* @ORM\Id()
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*
* @var int
*/
private $id;
/**
* @ORM\Column(type="string")
*
* @var string
*/
private $subject;
/**
* @ORM\Column(type="text")
*
* @var string
*/
private $description;
/**
* @ORM\Column(type="datetime", name="due_date")
*
* @var \DateTime
*/
private $dueDate;
/**
* @ORM\ManyToOne(targetEntity="Priority")
* @ORM\JoinColumn(name="task_priority_id", onDelete="SET NULL")
*
* @var Priority
*/
private $priority;
/**
* Returns the id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Returns the subject.
*
* @return string
*/
public function getSubject()
{
return $this->subject;
}
/**
* Sets the subject.
*
* @param string $subject
*/
public function setSubject($subject)
{
$this->subject = $subject;
}
/**
* Returns the description.
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Sets the description.
*
* @param string $description
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* Returns the due date.
*
* @return \DateTime
*/
public function getDueDate()
{
return $this->dueDate;
}
/**
* Sets the due date.
*
* @param \DateTime $dueDate
*/
public function setDueDate(\DateTime $dueDate)
{
$this->dueDate = $dueDate;
}
/**
* Returns the priority.
*
* @return Priority
*/
public function getPriority()
{
return $this->priority;
}
/**
* Sets the priority.
*
* @param Priority $priority
*/
public function setPriority(Priority $priority)
{
$this->priority = $priority;
}
}
Users should be able to create and change priorities through the user interface, therefore, they are modeled as separate entities:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
* @ORM\Table(name="app_task_priority")
*/
class Priority
{
/**
* @ORM\Id()
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*
* @var int
*/
private $id;
/**
* @ORM\Column(type="string", unique=true)
*
* @var string
*/
private $label;
/**
* Returns the priority id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Returns the label.
*
* @return string
*/
public function getLabel()
{
return $this->label;
}
/**
* Changes the priority label.
*
* @param string $label
*/
public function setLabel($label)
{
$this->label = $label;
}
}
After you have modeled your entities, you need to update the database schema. To update the schema, use the doctrine:schema:update command
. Use the --dump-sql
option first to make sure that Doctrine makes the expected changes:
php bin/console doctrine:schema:update --dump-sql
If the command displays unexpected information, double-check the configured mapping information and rerun the command.
When everything is displayed as expected, update the database schema by passing the --force
option:
php bin/console doctrine:schema:update --force
Tip
Doctrine caches mapping metadata. If the doctrine:schema:update
command does not recognize your changes to the entity mapping, clear the metadata cache manually and update the schema again:
# clear the metadata cache
php bin/console doctrine:cache:clear-metadata
# check the schema change queries to be executed
php bin/console doctrine:schema:update --dump-sql
# apply the schema changes to the database
php bin/console doctrine:schema:update --force
Caution
Do not use the doctrine:schema:update
command with your production database. Instead,
create migrations to update the schema of your database. You can read more about using
migrations in the Update Database Schema section. To run migrations
and emulate complete migration process, use the oro:platform:update
command.
Doctrine Entities¶
Define Entities¶
You can define entities the same way as in typical Symfony applications. For example, use the annotations provided by Doctrine (you can also use the YAML or XML configuration format):
namespace Acme\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="acme_hotel")
*/
class Hotel
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
}
You can create a class that represents a particular model from your domain and add the getter and setter methods to access and modify the data in your application. Next, add mapping information to tell Doctrine how the data is mapped to your database.
Update Database Schema¶
Once the models are ready, update the database to reflect the changes you have made. Use migrations as a mechanism to extend your model iteratively. Migrations allow you to version your database schema. Every time you modify your model, you create a new migration that reflects the changes for this particular schema version.
However, Doctrine’s migration mechanism only works well on the application level. It is not capable of handling different schema versions per bundle, which means that you cannot use them in a modular architecture. Luckily, you can use the features provided by the OroMigrationBundle to create separate migrations for each bundle.
Organizing migrations is relatively simple if you follow the basic conventions below:
Place all migrations under the
Migrations/Schema/
directory of your bundle.In this directory, create one subdirectory per schema version.
Create as many migration classes as necessary inside a particular schema version directory (see the example below).
Note
The names of the schema version directories are compared to each other using PHP’s
:phpfunction:`version_compare` function. Therefore, it is a good practice to name them following the v1_0
,
v2_0
pattern.
When migration to a particular schema version is performed, all migration classes from the corresponding directory are evaluated. Then, the contents of their up()
method is executed. A class is treated as a migration class when it implements the Oro\Bundle\MigrationBundle\Migration\Migration
interface.
For example, the migration class for the Hotel
entity looks is illustrated below:
namespace Acme\DemoBundle\Migrations\Schema\v1_0;
use Doctrine\DBAL\Schema\Schema;
use Oro\Bundle\MigrationBundle\Migration\Migration;
use Oro\Bundle\MigrationBundle\Migration\QueryBag;
class Hotel implements Migration
{
public function up(Schema $schema, QueryBag $queries)
{
$table = $schema->createTable('acme_hotel');
$table->addColumn('id', 'integer', ['autoincrement' => true]);
$table->addColumn('name', 'string', ['length' => 255]);
$table->setPrimaryKey(['id']);
$table->addIndex(['name'], 'hotel_name_idx', []);
}
}
Note
Entity metadata in the PHP entity classes (annotations) should match exactly what the schema migration is doing. If you create a migration that modifies the type, length or another property of an existing entity field, please remember to make the same change in the PHP entity class annotations.
You can modify the database using the interface the Doctrine DBAL offers with its Schema
class, and you can also execute queries directly using the QueryBag
, if necessary.
Queries executed using the QueryBag, are divided into two groups: use the Oro\Bundle\MigrationBundle\Migration\QueryBag::addPreQuery
to add a query that is executed before the schema changes from the migration class are performed. Queries scheduled with the Oro\Bundle\MigrationBundle\Migration\QueryBag::addPostQuery
method are executed after the schema is modified.
To load and apply migrations to the existing database schema, execute the oro:migration:load
command:
php bin/console oro:migration:load --force
This command checks for present migration versions that are currently not reflected in the existing database schema and executes all missing migrations sequentially in ascending order.
Tip
You can use the --dry-run
option to see what is going to be executed and you can use the
--bundles
option to perform migrations only for a subset of all available bundles (use
--exclude
for a bundle blacklist instead). You can also get more information about each query with the --show-queries
option.