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 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.
EventsMapper
→ events
.
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()
{
return 'blog_events';
}
}
StorageReflection takes care about converting column names. Conventions are
represented by interface
Nextras\Orm\StorageReflection\IStorageReflection
. However, Nette
mapper requires slightly advanced IDbStorageReflection
, which is
introduced because of joining table in many to many pattern.
Orm comes with two predefined reflections implementing
IDbStorageReflection
:
These predefined classes assume “camelCase” naming in Orm layer, and transform it for the database layer. (In fact, CamelCase reflection does no transform in column naming.)
_id
(or Id
) suffix and is
defined as a foreign key, they automatically strip it.$id
).However, you are free to add your own mapping. Just call
addMapping($entityName, $storageName)
method. The right way to do
this is to inherit createStorageReflection()
method in your
mapper class.
use Nextras\Orm\Mapper\Mapper;
class EventsMapper extends Mapper
{
protected function createStorageReflection()
{
$reflection = parent::createStorageReflection();
$reflection->addMapping('entityProperty', 'database_property');
return $reflection;
}
}
StorageReflection offers API for data transformation when they are passed
from storage to PHP and otherwise. The aforementioned
addMapping($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 createStorageReflection()
{
$reflection = parent::createStorageReflection();
$reflection->addMapping('isPublic', 'is_public', function ($val) {
return $val === 'Y' || $val === 'y';
}, function ($val) {
return $val ? 'Y' : 'N';
});
return $reflection;
}
}
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 values is trasformed by its type. However, you may want to
force different behavior and modifier for Nextras Dbal layer. To do that, use
addModifier($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 createStorageReflection()
{
$reflection = parent::createStorageReflection();
$reflection->addModifier('contents', '%blob');
return $reflection;
}
}
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;
class BaseMapper extends Mapper
{
protected function createStorageReflection()
{
$reflection = parent::createStorageReflection();
$reflection->manyHasManyStorageNamePattern = '%s_2_%s';
return $reflection;
}
}
If you need more advanced changes, feel free to override
getManyHasManyParameters()
method in your mapper. This method
should return array, where the first value is the joining table name, the second
is the 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);
}
}