1. Go to this page and download the library: Download kassko/data-mapper library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
$id = 1;
//Construct a person, set an id to it.
$person = new Kassko\Sample\Person($id);
echo $person->getName();//Implicitly load the name from the given id by fetching the source configured.
//Here some stuff to retrieve the entityManager.
$id = 1;
$person = $entityManager->getRepository('Kassko\Sample\Person')->find($id);
echo $person->getName();
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
use Kassko\DataMapper\ObjectExtension\LoadableTrait;
class Person
{
use LoadableTrait;
private $id;
/**
* @DM\DataSource(class="Kassko\Sample\PersonDataSource", method="getData", args="#id", lazyLoading=true)
*/
private $name;
/**
* @DM\DataSource(class="Kassko\Sample\PersonDataSource", method="getData", args="#id", lazyLoading=true)
*/
private $email;
public function __construct($id) { $this->id = $id; }
public function getId() { return $this->id; }
public function getName() { $this->loadProperty('name'); return $this->name; }
public function getEmail() { $this->loadProperty('email'); return $this->email; }
}
namespace Kassko\Sample;
class PersonDataSource
{
public function getData($id)
{
return [
'name' => 'foo',
'email' => '[email protected]'
];
}
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
use Kassko\DataMapper\ObjectExtension\LoadableTrait;
/**
* @DM\DataSourcesStore({
* @DM\DataSource(
* id="nameSource",
* class="Kassko\Sample\PersonDataSource",
* method="getData",
* args="#id",
* lazyLoading=true
* ),
* @DM\DataSource(
* id="emailSource",
* class="Kassko\Sample\PersonDataSource",
* method="getData",
* args="#id",
* lazyLoading=true
* )
* })
*/
class Person
{
use LoadableTrait;
private $id;
/**
* @DM\RefSource(id="nameSource")
*/
private $name;
/**
* @DM\RefSource(id="emailSource")
*/
private $email;
public function __construct($id) { $this->id = $id; }
public function getId() { return $this->id; }
public function getName() { $this->loadProperty('name'); return $this->name; }
public function getEmail() { $this->loadProperty('email'); return $this->email; }
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
use Kassko\DataMapper\ObjectExtension\LoadableTrait;
/**
* @DM\DataSourcesStore({
* @DM\DataSource(
* id="personSource",
* class="Kassko\Sample\PersonDataSource",
* method="getData",
* args="#id",
* lazyLoading=true,
* supplySeveralFields=true
* )
* })
*/
class Person
{
use LoadableTrait;
private $id;
/**
* @DM\RefSource(id="personSource")
* @DM\Field("name"="first_name")
*/
private $firstName;
/**
* @DM\RefSource(id="personSource")
*/
private $name;
/**
* @DM\RefSource(id="personSource")
*/
private $email;
/**
* @DM\RefSource(id="personSource")
*/
private $phone;
public function __construct($id) { $this->id = $id; }
public function getId() { return $this->id; }
public function getFirstName() { $this->loadProperty('firstName'); return $this->firstName; }
public function getName() { $this->loadProperty('name'); return $this->name; }
public function getEmail() { $this->loadProperty('email'); return $this->email; }
public function getPhone() { $this->loadProperty('phone'); return $this->phone; }
}
namespace Kassko\Sample;
class PersonDataSource
{
public function getData($id)
{
return [
'first_name' => 'foo',
'name' => 'bar',
'email' => 'foo@bar',
'phone' => '01 02 03 04 05',
];
}
}
namespace Kassko\Sample;
use Kassko\DataMapper\ObjectExtension\LoadableTrait;
/**
* @DM\DataSourcesStore({
* @DM\DataSource(
* id="personSource",
* class="Kassko\Sample\PersonDataSource",
* method="getData",
* args="#id",
* lazyLoading=true,
* supplySeveralFields=true
* ),
* @DM\DataSource(
* id="carSource",
* class="Kassko\Sample\CarRepository",
* method="find",
* args="expr(source('personSource')['car_id'])",
* lazyLoading=true
* )
* })
*/
class Person
{
private $id;
/**
* @DM\RefSource(id="personSource")
*/
private $firstName;
/**
* @DM\RefSource(id="personSource")
*/
private $name;
/**
* @DM\RefSource(id="personSource")
*/
private $email;
/**
* @DM\RefSource(id="personSource")
*/
private $phone;
/**
* @DM\RefSource(id="carSource")
*/
private $car;
public function __construct($id) { $this->id = $id; }
public function getId() { return $this->id; }
public function getFirstName() { return $this->firstName; }
public function getName() { return $this->name; }
public function getEmail() { return $this->email; }
public function getPhone() { return $this->phone; }
public function getCar() { return $this->car; }
}
namespace Kassko\Sample;
class PersonDataSource
{
public function getData($id)
{
return [
'first_name' => 'foo',
'name' => 'bar',
'email' => 'foo@bar',
'phone' => '01 02 03 04 05',
];
}
}
namespace Kassko\Sample;
use Doctrine\ORM\EntityRepository;
/**
* CarRepository is a Doctrine source that feed the property $car.
*/
class CarRepository extends EntityRepository
{
}
namespace Kassko\Sample;
class Watch
{
private $brand;
private $color;
public function getBrand() { return $this->brand; }
public function setBrand($brand) { $this->brand = $brand; }
public function getColor() { return $this->color; }
public function setColor($color) { $this->color = $color; }
}
$data = [
0 => [
'brand' => 'some brand',
'color' => 'blue',
],
1 => [
'brand' => 'some other brand',
'color' => 'green',
],
];
$dataMapper = (new Kassko\DataMapper\DataMapperBuilder)->instance();
$dataMapper->resultBuilder('Kassko\Sample\Watch', $data)->all();//The result will be an array with two objects.
$dataMapper->resultBuilder('Kassko\Sample\Watch', $data)->first();//The result will be a watch object representing the first record.
$dataMapper = (new Kassko\DataMapper\DataMapperBuilder)->instance();
$dataMapper->resultBuilder('Kassko\Sample\Watch')->raw($object);
$dataMapper->resultBuilder('Kassko\Sample\Watch')->raw($collection);
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
class Watch
{
private $brand;
/**
* @DM\Fields(name="COLOR")
*/
private $color;
public function getBrand() { return $this->brand; }
public function setBrand($brand) { $this->brand = $brand; }
public function getColor() { return $this->color; }
public function setColor($color) { $this->color = $color; }
}
$loader = \Common\Annotations\AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
$dataMapper = (new Kassko\DataMapper\DataMapperBuilder)->instance();
$dataMapper->resultBuilder('Kassko\Sample\Watch', $data)->all();
/*
Return an array of objects.
So return an array with only one object, if only one fullfill the request.
*/
$resultBuilder->all();
/*
Return the object found.
If more than one result are found, throw an exception
Kassko\DataMapper\Result\Exception\NonUniqueResultException.
If no result found, throw an exception
Kassko\DataMapper\Result\Exception\NoResultException.
*/
$resultBuilder->single();
/*
Return the object found or null.
*/
$resultBuilder->one();
/*
Return the object found or a default result (like false).
*/
$resultBuilder->one(false);
/*
If more than one result are found, throw an exception
Kassko\DataMapper\Result\Exception\NonUniqueResultException.
*/
/*
Return the first object found or null.
*/
$resultBuilder->first();
/*
Return the first object found or a default result (like value false).
*/
$resultBuilder->first(false);
/*
If no result found, throw an exception
Kassko\DataMapper\Result\Exception\NoResultException.
*/
/*
Return an array indexed by a property value.
If the index does not exists (allIndexedByUnknown()), throw an exception Kassko\DataMapper\Result\Exception\NotFoundIndexException.
If the same index is found twice, throw an exception
Kassko\DataMapper\Result\Exception\DuplicatedIndexException.
Examples:
allIndexedByBrand() will index by brand value:
[
'BrandA' => $theWatchInstanceWithBrandA,
'BrandB' => $theWatchInstanceWithBrandB,
]
allIndexedByColor() will index by color value:
[
'Blue' => $theWatchInstanceWithColorBlue,
'Red' => $theWatchInstanceWithColorRed,
]
allIndexedByUnknown() will throw a Kassko\DataMapper\Result\Exception\NotFoundIndexException.
*/
$resultBuilder->allIndexedByBrand();//Indexed by brand value
//or
$resultBuilder->allIndexedByColor();//Indexed by color value
/*
Return an iterator.
Result will not be hydrated immediately but only when you will iterate the results (with "foreach" for example).
*/
$result = $resultBuilder->iterable();
foreach ($result as $object) {//$object is hydrated
if ($object->getColor() === 'blue') {
break;
//We found the good object then we stop the loop and others objects in results will not be hydrated.
}
}
/*
Return an iterator indexed by a property value.
If the index does not exists, throw an exception Kassko\DataMapper\Result\Exception\NotFoundIndexException.
If the same index is found twice, throw an exception Kassko\DataMapper\Result\Exception\DuplicatedIndexException.
*/
$resultBuilder->iterableIndexedByBrand();
//or
$resultBuilder->iterableIndexedByColor();
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
use Kassko\DataMapper\Hydrator\HydrationContextInterface;
use Kassko\DataMapper\Hydrator\Value;
use \DateTime;
class Watch
{
private static $brandCodeToLabelMap = [1 => 'Brand A', 2 => 'Brand B'];
private static $brandLabelToCodeMap = ['Brand A' => 1, 'Brand B' => 2];
/**
* @DM\Field(readConverter="readBrand", writeConverter="writeBrand")
*/
private $brand;
/**
* @DM\Field(readConverter="hydrateBool", writeConverter="extractBool")
*/
private $waterProof;
/**
* @DM\Field(readConverter="hydrateBoolFromSymbol", writeConverter="extractBoolToSymbol")
*/
private $stopWatch;
/**
* @DM\Field(type="date", readDateConverter="Y-m-d H:i:s", writeDateConverter="Y-m-d H:i:s")
*/
private $createdDate;
public function getBrand() { return $this->brand; }
public function setBrand($brand) { $this->brand = $brand; }
public function isWaterProof() { return $this->waterProof; }
public function setWaterProof($waterProof) { $this->waterProof = $waterProof; }
public function hasStopWatch() { return $this->stopWatch; }
public function setStopWatch($stopWatch) { $this->stopWatch = $stopWatch; }
public function getCreatedDate() { return $this->createdDate; }
public function setCreatedDate(DateTime $createdDate) { $this->createdDate = $createdDate; }
public static function readBrand(Value $value, HydrationContextInterface $context)
{
if (isset(self::$brandCodeToLabelMap[$value->value])) {
$value->value = self::$brandCodeToLabelMap[$value->value];
}
}
public static function writeBrand(Value $value, HydrationContextInterface $context)
{
if (isset(self::$brandLabelToCodeMap[$value->value])) {
$value->value = self::$brandLabelToCodeMap[$value->value];
}
}
public static function hydrateBool(Value $value, HydrationContextInterface $context)
{
$value->value = $value->value == '1';
}
public static function extractBool(Value $value, HydrationContextInterface $context)
{
$value->value = $value->value ? '1' : '0';
}
public static function hydrateBoolFromSymbol(Value $value, HydrationContextInterface $context)
{
$value->value = $value->value == 'X';
}
public static function extractBoolToSymbol(Value $value, HydrationContextInterface $context)
{
$value->value = $value->value ? 'X' : ' ';
}
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
class Watch
{
/**
* @DM\Field
*/
private $brand;
/**
* @DM\Field
*/
private $waterProof;
/**
* @DM\Field
*/
private $stopWatch;
public function getBrand() { return $this->brand; }
public function setBrand($brand) { $this->brand = $brand; }
public function isWaterProof() { return $this->waterProof; }
public function setWaterProof($waterProof) { $this->waterProof = $waterProof; }
public function hasStopWatch() { return $this->stopWatch; }
public function setStopWatch($stopWatch) { $this->stopWatch = $stopWatch; }
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
class Watch
{
/**
* @DM\Field(prefix="is")
*/
private $waterProof;
/**
* @DM\Getter(prefix="has")
*/
private $alarm;
/**
* @DM\Getter(prefix="are")
*/
private $handsYellow;
/**
* @DM\Field(name="hasStopWatch")
*/
private $stopWatch;
/**
* @DM\Getter(name="canColorChange")
* @DM\Setter(name="colorCanChange")
*/
private $variableColor;
public function isWaterProof() { return $this->waterProof; }
public function setWaterProof($waterProof) { $this->waterProof = $waterProof; }
public function hasAlarm() { return $this->alarm; }
public function setAlarm($stopWatch) { $this->alarm = $alarm; }
public function areHandsYellow() { return $this->handsYellow; }
public function setHandsyellow($handsYellow) { $this->handsYellow = $handsYellow; }
public function hasStopWatch() { return $this->stopWatch; }
public function setStopWatch($stopWatch) { $this->stopWatch = $stopWatch; }
public function canColorChange() { return $this->variableColor; }
public function colorCanChange($colorCanChange) { $this->variableColor = $colorCanChange; }
}
namespace Kassko\Sample;
class Color
{
private $red;
private $green;
private $blue;
public function getRed() { return $this->red; }
public function setRed($red) { $this->red = $red; }
public function getGreen() { return $this->green; }
public function setGreen($green) { $this->green = $green; }
public function getBlue() { return $this->blue; }
public function setBlue($blue) { $this->blue = $blue; }
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
class Customer
{
/**
* @DM\Field
* @DM\Id
*/
private $id;
/**
* @DM\Field(class="Kassko\Sample\Address")
* @DM\Config(mappingResourceType="yaml", mappingResourceName="billing_address.yml")
*/
private $billingAddress;//$billingAddress is a value object.
/**
* @DM\Field(class="Kassko\Sample\Address")
* @DM\Config(mappingResourceType="yaml", mappingResourceName="shipping_address.yml")
*/
private $shippingAddress;//$shippingAddress is a value object too.
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
class Information
{
/**
* @DM\DataSource(class="Kassko\Sample\ShopDataSource", method="getBestShop")
* @DM\Field(class='Kassko\Sample\Shop')
*/
private $bestShop;
/**
* @DM\DataSource(class="Kassko\Sample\ShopDataSource", method="getNbShops")
*/
private $nbShops;
public function getBestShop() { return $this->bestShop; }
public function setBestShop(Shop $shop) { $this->bestShop = $bestShop; }
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
class Shop
{
/**
* @DM\Field
*/
private $name;
/**
* @DM\Field
*/
private $address;
}
namespace Kassko\Sample;
class ShopDataSource
{
public function getBestShop()
{
return [
'name' => 'The best',
'address' => 'Street of the bests',
];
}
public function getNbShops()
{
return 25;
}
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
use Kassko\DataMapper\ObjectExtension\LazyLoadableTrait;
class Information
{
use LazyLoadableTrait;
/**
* @DM\DataSource(class="Kassko\Sample\ShopDataSource", method="getBestShop", lazyLoading=true)
* @DM\Field(class='Kassko\Sample\Shop')
*/
private $bestShop;
/**
* @DM\DataSource(class="Kassko\Sample\ShopDataSource", method="getNbShops", lazyLoading=true)
*/
private $nbShops;
public function getBestShop()
{
$this->loadProperty('bestShop');//<= Load the best shop from the property name if not loaded.
return $this->bestShop;
}
public function getNbShop()
{
$this->loadProperty('nbShops');//<= Load the best shop from the property name if not loaded.
return $this->nbShops;
}
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
class Shop
{
/**
* @DM\Field
*/
private $name;
/**
* @DM\Field
*/
private $address;
}
namespace Kassko\Sample;
class ShopDataSource
{
public function getBestShop()
{
return [
'name' => 'The best',
'address' => 'Street of the bests',
];
}
public function getNbShops()
{
return 25;
}
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
/**
* @DM\DataSourcesStore({
* @DM\DataSource(
* id="sourceA", class="Kassko\Sample\ShopDataSource", method="getData", lazyLoading=true,
* fallbackSourceId="sourceB", onFail="checkException", exceptionClass="Kassko\Sample\NotStableSourceException"
* )
* })
*/
class Person
{
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
/**
* @DM\DataSourcesStore({
* @DM\DataSource(
* id="sourceA", class="Kassko\Sample\ShopDataSource", method="getData", lazyLoading=true,
* fallbackSourceId="sourceB", onFail="checkReturnValue", badReturnValue="null"
* )
* })
*/
class Person
{
}
namespace Kassko\Sample;
use Kassko\DataMapper\Annotation as DM;
class Key
{
use LazyLoadableTrait;
private $note;
private $octave = 3;
/**
* @DM\DataSource(
* id="ida",
* class="Kassko\Samples\KeyLLManager",
* method="getData", supplySeveralFields=true,
* preprocessors = @DM\Methods({
* @DM\Method(method="somePreprocessor"),
* @DM\Method(class="Kassko\Sample\KeyProcessor", method="preprocess", args="##this")
* })
* processors = @DM\Methods({
* @DM\Method(method="someProcessor"),
* @DM\Method(class="Kassko\Sample\KeyProcessor", method="process", args="##this")
* })
*)
*/
public $color;
public function getColor()
{
$this->loadProperty('color');
return $this->color;
}
public function somePrepocessor()
{
//Some stuff
}
public function someProcessor())
{
//Some stuff
}
}
namespace Kassko\Sample;
class KeyPreprocessor
{
public function preprocess(Key $key)
{
$this->logger->info(sprintf('Before key hydration %s', $key->getId()));
}
public function process($keyColor)
{
$this->logger->info(sprintf('After key hydration %s', $key->getId()));
}
}
class Key
{
use LazyLoadableTrait;
private $note;
private $octave = 3;
/**
* @DM\DataSource(
* id="ida",
* class="Kassko\Samples\KeyLLManager",
* method="getData", supplySeveralFields=true,
* preprocessor = @DM\Method(method="somePreprocessor"),
* processor = @DM\Method(method="someProcessor")
*)
*/
public $color;
public function getColor()
{
$this->loadProperty('color');
return $this->color;
}
public function somePrepocessor()
{
//Some stuff
}
public function someProcessor())
{
//Some stuff
}
}
[
'mapping' =>
[
//Default is "annotations" or other type (1).
'default_resource_type' => 'annotations',
//Optional key.
'default_resource_dir' => 'some_dir',
//Optional key. Has only sense if you use inner_php or inner_yaml format.
//It's the method whereby you provide the mapping.
'default_provider_method' => 'some_method_name',
//Optional section.
'groups' =>
[
'some_group' =>
[
//Default is "annotations" or other type (1).
'resource_type' => annotations,
//The resource dir of the given bundle.
'resource_dir' => 'some_dir',
//Default value is null.
'provider_method' => null,
],
],
//Optional section
'objects':
[
[
//Required (the full qualified object class name).
'class' => 'some_fqcn',
//Optional key. Allows to inherit settings from a group if there are not specified.
'group' => 'some_group',
//Optional key.
'resource_type' => 'yaml_file',
//Optional key.
//The resource directory with the resource name.
//If not defined, data-mapper fallback to resource_name and prepend to it a resource_dir (this object resource_dir or a group resource_dir or the default_resource_dir).
//So if resource_path is not defined, keys resource_name and a resource_dir should be defined.
'resource_path' => 'some_path',
//Optional key. Only the resource name (so without the directory).
'resource_name' => 'some_ressource.yml',
//Optional key. Override default_provider_method.
'provider_method' => 'some_method_name',
],
],
],
//Optional section.
'cache' =>
[
//Optional section. The cache for mapping metadata.
'metadata_cache' =>
[
//A cache instance which implements Kassko\Cache\CacheInterface. Default is Kassko\Cache\ArrayCache.
//If you use a third-party cache provider, maybe you need to wrap it into an adapter to enforce compatibility with Kassko\Cache\CacheInterface.
'instance' => $someCacheInstance,
//Default value is 0.
//0 means the data will never been deleted from the cache.
//Obviously, 'life_time' has no sense with an "ArrayCache" implementation.
'life_time' => 0,
//Default value is false. Indicates if the cache is shared or not.
//If you don't specify it, you're not wrong. It optimises the
'is_shared' => false,
],
//Optional section. The cache for query results.
//This section has the same keys as 'metadata_cache' section.
'result_cache': => [],
],
//Optional key. A logger instance which implements Psr\Logger\LoggerInterface.
'logger' => $logger,
//Optional key. Needed to retrieve repositories specified in 'repository_class' mapping attributes and which creation is assigned to a creator (a factory, a container, a callable).
'class_resolver' => $someClassResolver,
//Optional key. Needed to retrieve object listener specified in 'object_listener' mapping attributes and which creation is assigned to a creator (a factory, a container, a callable).
'object_listener_resolver' => $someObjectListenerResolver,
]
use Kassko\DataMapper\Annotation as DM;
class SomeClass
{
/**
* @DM\Config(
* class="\ValueObjectClass",
* mappingResourceName="valueObjectResourceName",
* mappingResourcePath="valueObjectResourcePath",
* mappingResourceType="valueObjectResourceType"
* )
*/
protected $firstField;
class SomeClassHydrator
{
/**
* Hydrate a SomeClass object from raw data $data.
*
* @param array The raw data
* @return SomeClass
*/
public function hydrateMethod(array $data)
{
}
/**
* Extract data from a SomeClass instance $object.
*
* @param SomeClass The object
* @return array
*/
public function extractMethod(SomeClass $object)
{
}
}
use Kassko\DataMapper\Annotation as DM;
/**
* @DM\Object(classMappingExtensionClass="mappingExtensionClass")
*
* @DM\PostExtract(method="postExtractMethodName")
*/
class SomeClass
{
}
use Kassko\DataMapper\Annotation as DM;
/**
* @DM\Object(classMappingExtensionClass="mappingExtensionClass")
*
* @DM\PostHydrate(method="postHydrateMethodName")
*/
class SomeClass
{
}
use Kassko\DataMapper\Annotation as DM;
/**
* @DM\Object(classMappingExtensionClass="mappingExtensionClass")
*
* @DM\PreHydrate(method="preHydrateMethodName")
*/
class SomeClass
{
}
use Kassko\DataMapper\Annotation as DM;
/**
* Optional because it's the default settings for fieldExclusionPolicy.
* @DM\Object(fieldExclusionPolicy="}
[
/*
//Optional because it's the default settings for fieldExclusionPolicy.
'object' => [
'fieldExclusionPolicy' => '' => 'excludedField'
],
'anotherField' => [
'name' => 'anotherField'
]
]
];
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.