Entities and schema

Mautic uses Doctrine ORM to define the schema. Plugins define their schema using entity classes stored in its Entity directory. Define the schema for the entity through Doctrine’s PHP static function mapping or annotations.

Warning

You use the PHP mapping or annotations. You can’t use a mix of the two.

Entity PHP static function mapping

You can build the schema through Doctrine’s Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder class. Refer to Doctrine ORM PHP mapping for methods available. Mautic also provides a decorated ClassMetadataBuilder class through Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder described below.

<?php

declare(strict_types=1);

namespace MauticPlugin\HelloWorldBundle\Entity;

use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\Mapping\ClassMetadata;
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;

class World
{
    private ?int $id;
    private ?string $world;
    private ?int $isEnabled;

    /**
     * @param ClassMetadata<self> $metadata
     */
    public static function loadMetadata(ClassMetadata $metadata): void
    {
        $builder = new ClassMetadataBuilder($metadata);

        $builder
            ->setTable('hello_world')
            ->setCustomRepositoryClass(WorldRepository::class)
            ->addIndex(['is_enabled'], 'is_enabled');

        $builder->addId();

        $builder
            ->createField('world', Type::STRING)
            ->build();

        $builder
            ->createField('isEnabled', Type::BOOLEAN)
            ->columnName('is_enabled')
            ->build();
    }

    public function getId(): int
    {
        return $this->id;
    }

    public function setId(int $id): void
    {
        $this->id = $id;
    }

    public function getWorld(): string
    {
        return $this->world;
    }

    public function setWorld(string $world): void
    {
        $this->world = $world;
    }

    public function isEnabled(): bool
    {
        return (bool) $this->isEnabled;
    }

    public function getIsEnabled(): int
    {
        return $this->isEnabled;
    }

    public function setIsEnabled(int $isEnabled): void
    {
        $this->isEnabled = $isEnabled;
    }
}
Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder
addBigIntIdField([string $fieldName = 'id', string $columnName = 'id', bool $isPrimary = true, boolean $isNullable = false])

Adds autogenerated ID field type of BIGINT UNSIGNED

Parameters:
  • $fieldName (string) – Name of the ORM field.

  • $columnName (string) – Name of the column created in the database table.

  • $isPrimary (boolean) – TRUE to configure this field as a primary key for the table.

  • $isNullable (bool) – TRUE to allow NULL values.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addCategory()

Creates a many to one relationship with MauticCategoryBundleEntityCategory. Defines a category ORM property mapped to a category_id column on the table with a foreign key to categories.id.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addContact([bool $nullable = false, string $onDelete = 'CASCADE', bool $isPrimaryKey = false, ?string $inversedBy = null)

Creates a many to one relationship with MauticLeadBundleEntityLead. Defines a contact ORM property mapped to a contact_id column on the table with a foreign key to leads.id.

Parameters:
  • $nullable (bool) – TRUE to allow NULL values.

  • $onDelete (string) – Foreign key reference option such as CASCADE or SET NULL.

  • $isPrimaryKey (bool) – TRUE to configure this field as a primary key for the table.

  • $inversedBy (string|null) – Property on the Mautic\LeadBundle\Entity\Lead entity this relates to. This is only used by Core.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addDateAdded([bool $nullable = false])

Creates a mutable date/time field. Defines a dateAdded ORM property mapped to a date_added column on the table.

Parameters:
  • $nullable (bool) – TRUE to allow NULL values.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addField(string $name, string $type[, array $mapping = []])

Decorates Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder::addField that sets the max length to 191 characters for string typed or indexed fields for compatibility with UTF8MB4 encoding.

Parameters:
  • $name (string) – Name of the ORM field.

  • $type (string) – Doctrine field type. See Doctrine\DBAL\Types\Types.

  • $mapping (array) – Custom field definitions.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addId()
Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addIdColumns([string $nameColumn = 'name', string $descriptionColumn = 'description'])

Creates id, name, and description ORM fields. id is an auto-incremented unsigned integer set as a primary key. name is created as varchar(191) and description as longtext. Customize the ORM names for name and description through the optional parameters.

Parameters:
  • $nameColumn (string) – Customize the name for the name field.

  • $descriptionColumn (string) – Customize the name for the description field.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addIpAddress([bool $nullable = false])

Creates a many to one relationship with MauticCoreBundleEntityIpAddress. Defines a ipAddress ORM property mapped to a ip_id column on the table with a foreign key to ip_addresses.id.

Parameters:
  • $nullable (bool) – TRUE to allow NULL values.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addNamedField(string $name, string $type, string $columnName[, $nullable = false])

Creates a field with a custom column name.

Parameters:
  • $name (string) – Name of the ORM field.

  • $type (string) – Doctrine field type. See Doctrine\DBAL\Types\Types.

  • $columnName (string) – Name of the table’s column name.

  • $nullable (bool) – TRUE to allow NULL values.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addNullableField(string $name[, string $type = Types::STRING, ?string $columnName = null])

Creates a field that allows a NULL value.

Parameters:
  • $name (string) – Name of the ORM field.

  • $type (string) – Doctrine field type. See Doctrine\DBAL\Types\Types.

  • $columnName (string) – Name of the table’s column name.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addPublishDates()

Creates publishUp and publishDown nullable mutable date/time fields as publish_up and publish_down respectively.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

addUuid()

Creates a id GUID field as a primary key. You should generate a UUID in the entity’s __construct or pass one into the __construct when creating a new entity. You can use $this->id = Ramsey\Uuid\Uuid::uuid4()->toString();.

Returns:

$this

Return type:

\Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder

createField(string $name, string $type)

Instantiates and returns a Doctrine\ORM\Mapping\Builder\FieldBuilder object. length is set if the field is a string type or indexed.

Returns:

\Doctrine\ORM\Mapping\Builder\FieldBuilder

createManyToMany(string $name, string $targetEntity)

Creates a many to many field to the targeted entity. Instantiates and returns a Mautic\CoreBundle\Doctrine\Mapping\ManyToManyAssociationBuilder object that decorates Doctrine\ORM\Mapping\Builder\ManyToManyAssociationBuilder with orphanRemoval() support.

Parameters:
  • $name (string) – Name of the ORM field.

  • $targetEntity (string) – Fully qualified classname for the targeted entity.

Returns:

\Mautic\CoreBundle\Doctrine\Mapping\ManyToManyAssociationBuilder

createManyToOne(string $name, string $targetEntity)

Creates a field with a many to one relationship to the targeted entity. Instantiates and returns a Mautic\CoreBundle\Doctrine\Mapping\AssociationBuilder object that decorates Doctrine\ORM\Mapping\Builder\AssociationBuilder with orphanRemoval() and isPrimaryKey() support.

Parameters:
  • $name (string) – Name of the ORM field.

  • $targetEntity (string) – Fully qualified classname for the targeted entity.

Returns:

\Mautic\CoreBundle\Doctrine\Mapping\AssociationBuilder

createOneToMany(string $name, string $targetEntity)

Creates a field with a one to many relationship to the targeted entity. Instantiates and returns a Mautic\CoreBundle\Doctrine\Mapping\OneToManyAssociationBuilder object that decorates Doctrine\ORM\Mapping\Builder\OneToManyAssociationBuilder with orphanRemoval() support.

Parameters:
  • $name (string) – Name of the ORM field.

  • $targetEntity (string) – Fully qualified classname for the targeted entity.

Returns:

\Mautic\CoreBundle\Doctrine\Mapping\OneToManyAssociationBuilder

createOneToOne(string $name, string $targetEntity)

Creates a field with a one to one relationship to the targeted entity. Instantiates and returns a Mautic\CoreBundle\Doctrine\Mapping\AssociationBuilder object that decorates Doctrine\ORM\Mapping\Builder\AssociationBuilder with orphanRemoval() and isPrimaryKey() support.

Parameters:
  • $name (string) – Name of the ORM field.

  • $targetEntity (string) – Fully qualified classname for the targeted entity.

Returns:

\Mautic\CoreBundle\Doctrine\Mapping\AssociationBuilder

isIndexedVarchar(string $name, string $type)

Checks whether the field should have a max length of 191 configured for compatibility with UTF8MB4 encoded fields.

Returns:

Returns TRUE if the field is a string type or is indexed.

Return type:

bool

Entity annotations

You can choose to use annotations instead of the PHP static method. Refer to Doctrine’s documentation on available annotations.

<?php

declare(strict_types=1);

namespace Mautic\UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Ramsey\Uuid\Uuid;

/**
 * @ORM\Table (name="worlds")
 */
class World
{
    /**
     * @ORM\Column(type="guid")
     * @ORM\Id
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=191)
     */
    private $name;

    public function __construct()
    {
        $this->id = Uuid::uuid4()->toString();
    }

    public function getId(): string
    {
        return $this->id;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): void
    {
        $this->name = $name;
    }
}

Plugin schema migrations

Mautic Core uses Doctrine migrations to manage schema changes. Plugins don’t have access to this as migration files are in Core’s migrations directory.

Mautic provides a way for Plugins to manage their schema changes through the Integration bundle’s \Mautic\IntegrationsBundle\Migration\Engine. Mautic automatically handles migrations if the Plugin’s bundle class extends Mautic\IntegrationsBundle\Bundle\AbstractPluginBundle.

<?php

declare(strict_types=1);

namespace MauticPlugin\HelloWorldBundle;

use Mautic\IntegrationsBundle\Bundle\AbstractPluginBundle;

class HelloWorldBundle extends AbstractPluginBundle
{
}

Define migrations in the Plugin’s Migrations directory. The file and class names can be anything but it’s recommended to match the version of the Plugin that introduces the change. For example, Version_1_0_1.php. Extend each migration class with \Mautic\IntegrationsBundle\Migration\AbstractMigration.

Warning

Mautic executes every migration file when it upgrades the Plugin. Therefore, you must define the isApplicable() method to let Mautic know to execute the migration’s SQL queries. Otherwise, Doctrine throws an exception if MySQL returns an error such as when an index or column already exists.

<?php

declare(strict_types=1);

namespace MauticPlugin\HelloWorldBundle\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Mautic\IntegrationsBundle\Migration\AbstractMigration;

class Version_1_0_1 extends AbstractMigration
{
    private $table = 'hello_world';

    protected function isApplicable(Schema $schema): bool
    {
        try {
            return !$schema->getTable($this->concatPrefix($this->table))->hasColumn('is_enabled');
        } catch (SchemaException $e) {
            return false;
        }
    }

    protected function up(): void
    {
        $this->addSql("ALTER TABLE `{$this->concatPrefix($this->table)}` ADD `is_enabled` tinyint(1) 0");

        $this->addSql("CREATE INDEX {$this->concatPrefix('is_enabled')} ON {$this->concatPrefix($this->table)}(is_enabled);");
    }
}
Mautic\IntegrationsBundle\Migration\AbstractMigration
protected property tablePrefix

Mautic’s configured database table prefix.

protected abstract isApplicable(Schema $schema)
Parameters:
  • $schema (Doctrine\DBAL\Schema\Schema) – Use the Schema object to evaluate Mautic’s current schema.

Returns:

Return FALSE to skip this migration. Otherwise, TRUE.

Return type:

bool

protected abstract up()

Define the SQL queries through addSql.

Return type:

void

protected addSql(string $sql)
Parameters:
Return type:

void

protected columnsToString(array $columns)
Parameters:
  • $columns (array) – Array of column names.

Returns:

Returns a comma separated value list from the values given in the array. For example, $this->columnsToString(['a', 'b', 'c']) will return 'a,b,c'.

Return type:

string

protected concatPrefix(string $name)

Prefixes the given name with the configured table prefix.

Parameters:
  • $name (string) – Name of column or index to prefix.

Returns:

Prefixed name.

Return type:

string

protected generateAlterTableForeignKeyStatement(string $table, array $columns, string $referenceTable, array $referenceColumns[, string $suffix = ''])

Generates full SQL statement to add a new foreign key to a table.

Parameters:
  • $table (string) – Name of the current table without the table prefix.

  • $columns (array) – Array of columns for the current table.

  • $referenceTable (string) – Name of the referenced table without the table prefix.

  • $referenceColumns (array) – Array of columns for the referenced table.

  • $suffix (string) – String to append to the query such as ON DELETE CASCADE.

Returns:

SQL statement for adding a new foreign key.

Return type:

string

protected generateIndexStatement(string $table, array $columns)

Generates an INDEX statement to be used within a CREATE TABLE or ALTER TABLE statement to create an index.

Parameters:
  • $table (string) – Name of the table where the index will be added.

  • $columns (array) – Array of columns to included in the index.

Returns:

INDEX {tableName} ($columns...) statement

Return type:

string