Mapping Overrides

You can change the mapping information programatically for a specific query - useful for overriding lazy/eager loading, or pointing to a different database or table for testing.

For the most part, you will want to specify your mapping information once, up-front. However, there may be occasions when you want to override mapping information programatically, perhaps to load records of a certain type from a different table than the one that is usually used (eg. when running integration tests). All of the attributes on Table, Column, and Relationship definitions can be overridden in code, or by loading mapping information from a json file at runtime.

Overriding Table Mapping

To override a mapping attribute for a table, set the entity config option with the attribute name and value required like this:

$repository->setEntityConfigOption(
    MyEntity::class,
    ConfigEntity::TABLE_OVERRIDES,
    ['name' => 'alternative_table_name']
);

Overriding Column Mapping

With columns (and relationships), you must also specify which property to apply the override to, so you must pass in a multi-dimensional array, like this:

$repository->setEntityConfigOption(
    MyEntity::class,
    ConfigEntity::COLUMN_OVERRIDES,
    ['someProperty' => ['isReadOnly' => false]]
);

Overriding Relationship Mapping

The same principle is used for relationships:

$repository->setEntityConfigOption(
    MyEntity::class,
    ConfigEntity::RELATIONSHIP_OVERRIDES,
    [
        'user' => [
            'joinTable' => 'user_alternative',
            'sourceJoinColumn' => 'user_id',
            'targetJoinColumn' => 'id'
        ]
    ]
);

For all overrides, you can specify multiple override values simply by adding more elements to the override arrays you pass in.

Overriding Mappings Using JSON Files

As well as programatically overriding individual mappings in code, you can tell Objectiphy to use a particular JSON file containing mapping information, or even to scan a directory to load mapping information for multiple classes at once. As with programmatic overrides, the mapping information provided using a JSON file will override any existing mapping information - you can combine mapping information on the entity with overridden mappings in a file (the file will take precedence).

The format of a JSON file for specifying mapping information is similar to the arrays described above. A mapping file should contain an element at the root level called className which holds the fully qualified class name of the entity to which the mapping relates. As siblings of that element, you can specify table, column and relationship elements with the mapping override information specified in the same way as shown above. For example:

{
  "className": "App\\Entity\\MyEntity",
  "table": {
    "name": "alternative_table"
  },
  "relationships": {
    "user": {
      "joinTable": "user_alternative",
      "sourceJoinColumn": "user_id",
      "targetJoinColumn": "id"
    }
  },
  "columns": {
    "someProperty": {
      "isReadOnly": true
    },
    "someOtherProperty": {
      "name": "other_stuff",
      "dataMap": {
        "A": "The Letter A",
        "B": "The Letter B",
        "ELSE": "Some other letter"
      }
    }
  }
}

To specify a particular file to be used to override mappings for an entity, set the mapping file enitty config option, like this:

$repository->setEntityConfigOption(
    MyEntity::class,
    ConfigEntity::MAPPING_FILE,
    '/my/project/directory/mapping/MyEntityMapping.json'
);

You can also use a general configuration option to load multiple mapping files for different entities by scanning a directory. When you do this, Objectiphy will look at all files in the directory and try to json_decode them and extract the value from className. If it cannot do that, the file will be ignored. Any sub-directories will be traversed, so make sure you use a directory that only contains the mapping files you want to use (but you can organise them into sub-directories if you wish). If the file can be decoded, and has a className element in the root, it will be loaded and the mapping information will be applied to the given entity class name. To specify a directory, set the main config option like this:

$repository->setConfigOption(
    ConfigOptions::MAPPING_DIRECTORY,
    '/my/project/directory/mapping'
);

There is a performance sacrifice involved in applying mapping a runtime, so only do this if you need to, and try to avoid using it for very large object hierarchies.

Last updated