Edit

Conventions

The database naming conventions shouldn't affect your PHP naming conventions. Orm is designed to help you not to bother with your database naming relics.

Table name#

Table names are directly resolved in the mapper layer; they are derived from the mapper class name. By default, the names are created as an underscored name of the mapper class with stripped “Mapper” suffix, eg. EventsMapperevents.

If you would like to force some other table name, define $tableName property, or override getTableName() method in the mapper class.

use Nextras\Orm\Mapper\Mapper;

class EventsMapper extends Mapper
{
    protected $tableName = 'events';

    // or

    protected function getTableName(): string
    {
        return 'blog_events';
    }
}
Properties#

Conventions take care about converting column names to property names. Dbal mapper's conventions are represented by interface Nextras\Orm\Mapper\Dbal\Conventions\IConventions interface.

Orm comes with two predefined inflectors, that modify the basic conventions behavior:

  • CamelCaseInflector
  • SnakeCaseInflector

These predefined classes assume “camelCase” naming in entity layer and transform it for the database layer. (CamelCase reflector actually does not do any transformation.)

  • If database column has _id (or Id) suffix and is defined as a foreign key, inflector automatically strips the suffix.
  • If database table has only one primary column, it is automatically mapped to the primary property in entity ($id).

You are free to add your own mapping. Just call setMapping($entityName, $storageName) method. The right way to do this is to inherit createConventions() method in your mapper class.

use Nextras\Orm\Mapper\Mapper;
use Nextras\Orm\Mapper\Dbal\Conventions\IConventions;

class EventsMapper extends Mapper
{
    protected function createConventions(): IConventions
    {
        $conventions = parent::createConventions();
        $conventions->setMapping('entityProperty', 'database_property');
        return $conventions;
    }
}
Properties' converters#

Conventions offers an API for data transformation when the data are passed from storage to PHP and otherwise. The aforementioned setMapping($entityName, $storageName, $toEntityCb, $toStorageCb) method has two optional parameters that accept callbacks. These callbacks receive the value and key parameters and must return the new converted value. The first callback is for conversion from the storage to PHP, the second is for conversion from PHP to the storage. Let's see an example:

/**
 * @param bool $isPublic
 */
class File extends Nextras\Orm\Entity\Entity
{
}

class FilesMapper extends Nextras\Orm\Mapper\Dbal\DbalMapper
{
    protected function createConventions(): Nextras\Orm\Mapper\Dbal\Conventions\IConventions
    {
        $conventions = parent::createConventions();
        $conventions->setMapping('isPublic', 'is_public', function ($val) {
            return $val === 'Y' || $val === 'y';
        }, function ($val) {
            return $val ? 'Y' : 'N';
        });
        return $conventions;
    }
}
Properties' modifiers for Nextras Dbal#

The underlying layer Nextras Dbal takes care about converting and sanitizing the values for SQL INSERT/UPDATE query. By default, the %any modifier is used and the value is transformed by its type. However, you may want to force different behaviour and modifier for Nextras Dbal layer. To do that, use setModifier($storageKey, $modifier) method, which accepts the table's column name and Dbal's modifier. Let's see an example:

/**
 * @param string $contents
 */
class File extends Nextras\Orm\Entity\Entity
{
}

class FilesMapper extends Nextras\Orm\Mapper\Dbal\DbalMapper
{
    protected function createConventions(): Nextras\Orm\Mapper\Dbal\Conventions\IConventions
    {
        $conventions = parent::createConventions();
        $conventions->setModifier('contents', '%blob');
        return $conventions;
    }
}
HasMany joining table#

There are many possibilities to change default table joining conventions. If you are using m:m, you can change its pattern property. By default the pattern is defined as %s_x_%s. The first placeholder is the primary table name.

use Nextras\Orm\Mapper\Mapper;
use Nextras\Orm\Mapper\Dbal\Conventions\Conventions;
use Nextras\Orm\Mapper\Dbal\Conventions\IConventions;

class BaseMapper extends Mapper
{
    protected function createConventions(): IConventions
    {
        $conventions = parent::createConventions();
        assert($conventions instanceof Conventions); // property is not available on interface
        $conventions->manyHasManyStorageNamePattern = '%s_2_%s';
        return $conventions;
    }
}

If you need more advance changes, feel free to override getManyHasManyParameters() method in your mapper. This method returns an array where the first value is a joining table name, the second is an array of joining keys/columns. If you have only one m:m relationship between two entities, you can return result only based on the passed target mapper, source property's metadata are available for more detailed matching.

use Nextras\Orm\Mapper\Mapper;

class EmployeesMapper extends Mapper
{
    public function getManyHasManyParameters(PropertyMetadata $sourceProperty, IMapper $targetMapper)
    {
        if ($targetMapper instanceof DepartmentsMapper) {
            return ['emp_dept', ['emp_no', 'dept_no']];
        }
        return parent::getManyHasManyParameters($sourceProperty, $targetMapper);
    }
}