pecinaon / doctrine-mapper
实体 doctrine 映射器 - 将 Nette 表单映射到实体,并将实体映射到 Nette 表单,可以从表单构建实体
v1.0.7
2017-02-06 13:00 UTC
Requires
- kdyby/annotations: ~2.3@dev
- kdyby/doctrine: ^3.1.1
- nette/forms: ~2.3@dev
- nette/reflection: ~2.3@dev
- nette/utils: ~2.3@dev
Requires (Dev)
- latte/latte: ~2.3@dev
- nette/application: ~2.3@dev
- nette/bootstrap: ~2.3@dev
- nette/caching: ~2.3@dev
- nette/component-model: ~2.2@dev
- nette/database: ~2.3@dev
- nette/deprecated: ~2.3@dev
- nette/di: ~2.3@dev
- nette/finder: ~2.3@dev
- nette/forms: ~2.3@dev
- nette/http: ~2.3@dev
- nette/mail: ~2.3@dev
- nette/neon: ~2.3@dev
- nette/php-generator: ~2.3@dev
- nette/reflection: ~2.3@dev
- nette/robot-loader: ~2.3@dev
- nette/safe-stream: ~2.3@dev
- nette/security: ~2.3@dev
- nette/tester: ~1.3@rc
- nette/tokenizer: ~2.2@dev
- nette/utils: ~2.3@dev
- tracy/tracy: ~2.3@dev
Conflicts
- nette/nette: <2.2
README
======
要求
DoctrineMapper 需要 PHP 5.5 或更高版本。
安装
安装 pecinaon/doctrine-mapper 的最佳方式是使用 Composer
$ composer require pecinaon/doctrine-mapper
配置
此扩展创建了一个新的配置部分 doctrineMapper
,可用的配置如下所示
doctrineMapper: dateFormat: App\ExampleDateFormat
dateFormat
用于解析来自您格式的 DateTime,您可以更改它。此类必须实现 DoctrineMapper\Parsers\Date\IDateFormat。
<?php namespace App; class ExampleDateFormat implements \DoctrineMapper\Parsers\Date\IDateFormat { /** * Return date and time format * * @return string */ public function getDateTimeFormat() { return "H:i:s"; } /** * Return date format * * @return string */ public function getDateFormat() { return "d/m.y"; } }
将 ArrayHash (表单结果) 映射到实体
<?php namespace App; use DoctrineMapper\ArrayAccessEntityMapper; use Nette\Application\UI\Form; use Doctrine\ORM\Mapping as ORM; use Nette\Object; use Nette\Utils\ArrayHash; /** * Example Entity * * @ORM\Entity(repositoryClass="ExampleRepository") * @ORM\Table(name="tp_example", indexes={ * }) * @author Pecina Ondřej <pecina.ondrej@gmail.com> */ class ExampleEntity extends Object { /** * @ORM\Column(length=128) * @var string */ protected $name; /** * @ORM\Id * @ORM\Column(type="integer", options={"unsigned"=true}) * @ORM\GeneratedValue * @var int */ protected $id; /** * @return int */ public function getId() { return $this->id; } /** * @return string */ public function getName() { return $this->name; } /** * @param string $name * @return ExampleEntity */ public function setName($name) { $this->name = $name; return $this; } } class ExampleFormMapper { /** @var ArrayAccessEntityMapper */ private $arrayAccessEntityMapper; /** * ExampleFormMapper constructor. * @param ArrayAccessEntityMapper $arrayAccessEntityMapper */ public function __construct(ArrayAccessEntityMapper $arrayAccessEntityMapper) { $this->arrayAccessEntityMapper = $arrayAccessEntityMapper; } public function getForm() { $form = new Form(); $form->addText('name', 'Name') ->setRequired(); $form->addSubmit('Sub', 'Save'); $form->onSuccess[] = function(Form $form) { $entity = new ExampleEntity(); // array with name is not reuired - if is not set, set all values with existing properties in entity $this->arrayAccessEntityMapper->setToEntity($form->getValues(), $entity, ['name']); // works same like line above $this->arrayAccessEntityMapper->setToEntity($form->getValues(), $entity); // you can map also in this way $this->arrayAccessEntityMapper->setToEntity(ArrayHash::from([ 'name' => 'Testing name' ]), $entity); // do stuff with entity }; return $form; } }
setToEntity 中的第三个参数是可选的,因为当它为空时,映射器会将 ArrayHash 中的所有值填充到实体中,当属性与 doctrine 实体中的同名属性存在时。映射器可以将所有关系映射 @ManyToMany, @ManyToOne - 映射器通过抛出带有主键的 Kdyby EntityManager 的相关实体存储库来将实体设置到映射实体中。
将实体映射到 Nette 表单
<?php namespace App; use DoctrineMapper\EntityFormMapper; use Nette\Application\UI\Form; use Doctrine\ORM\Mapping as ORM; use Nette\Object; /** * Example entity * * @ORM\Entity(repositoryClass="ExampleRepository") * @ORM\Table(name="tp_example", indexes={ * }) * @author Pecina Ondřej <pecina.ondrej@gmail.com> */ class ExampleEntity extends Object { /** * @ORM\Column(length=128) * @var string */ protected $name; /** * @ORM\Id * @ORM\Column(type="integer", options={"unsigned"=true}) * @ORM\GeneratedValue * @var int */ protected $id; /** * @return int */ public function getId() { return $this->id; } /** * @return string */ public function getName() { return $this->name; } /** * @param string $name * @return ExampleEntity */ public function setName($name) { $this->name = $name; return $this; } } class ExampleFormMapper { /** @var EntityFormMapper */ private $entityFormMapper; /** * ExampleFormMapper constructor. * @param EntityFormMapper $entityFormMapper */ public function __construct(EntityFormMapper $entityFormMapper) { $this->entityFormMapper = $entityFormMapper; } public function getForm() { $form = new Form(); $form->addText('name', 'Name') ->setRequired(); $form->addSubmit('Sub', 'Save'); $form->onSuccess[] = function(Form $form) { // do stuff }; $entity = new ExampleEntity(); $entity->setName('Example name'); // this line map all values in entity to form in this case set to component with name name' value "Example name" $this->entityFormMapper->setEntityToContainer($entity, $form); return $form; } }
从实体构建表单
<?php namespace App; use DoctrineMapper\Builder\BuilderDefinition; use DoctrineMapper\FormEntityBuilder; use Nette\Application\UI\Form; use Doctrine\ORM\Mapping as ORM; use Nette\Object; /** * Test related entity * * @ORM\Entity(repositoryClass="ExampleRepositoryRel") * @ORM\Table(name="tp_example_re", indexes={ * }) * @author Pecina Ondřej <pecina.ondrej@gmail.com> */ class TestExampleEntityRel extends Object { /** * @ORM\Column(length=128) * @var string */ protected $name; /** * @ORM\Id * @ORM\Column(type="integer", options={"unsigned"=true}) * @ORM\GeneratedValue * @var int */ protected $id; /** * @return int */ public function getId() { return $this->id; } /** * @return string */ public function getName() { return $this->name; } /** * @param string $name * @return TestExampleEntityRel */ public function setName($name) { $this->name = $name; return $this; } } /** * Example entity * * @ORM\Entity(repositoryClass="ExampleRepository") * @ORM\Table(name="tp_example", indexes={ * }) * @author Pecina Ondřej <pecina.ondrej@gmail.com> */ class ExampleEntity extends Object { /** * @ORM\Column(length=128) * @var string */ protected $name; /** * @ORM\ManyToOne(targetEntity="App\TestExampleEntityRel") * @ORM\JoinColumn(name="rel_id", referencedColumnName="id") * @var OwnerEntity */ protected $related; /** * @ORM\Id * @ORM\Column(type="integer", options={"unsigned"=true}) * @ORM\GeneratedValue * @var int */ protected $id; /** * @return int */ public function getId() { return $this->id; } /** * @return string */ public function getName() { return $this->name; } /** * @param string $name * @return ExampleEntity */ public function setName($name) { $this->name = $name; return $this; } /** * @param TestExampleEntityRel $related * @return ExampleEntity */ public function setRelated(TestExampleEntityRel $related) { $this->related = $related; return $this; } /** * @return TestExampleEntityRel */ public function getRelated() { return $this->related; } } class ExampleFormMapper { /** @var FormEntityBuilder */ private $formEntityBuilder; /** * ExampleFormMapper constructor. * @param FormEntityBuilder $formEntityBuilder */ public function __construct(FormEntityBuilder $formEntityBuilder) { $this->formEntityBuilder = $formEntityBuilder; } public function getForm() { $entity = new ExampleEntity(); $entity->setName('Example name'); // TRUE param build form automatically $builder = $this->formEntityBuilder->getBuilder($entity, TRUE); $form = $builder->getForm(); $form->addSubmit('Sub', 'Save'); $form->onSuccess[] = function(Form $form) { // do stuff }; // FALSE param is manual render form $builder = $this->formEntityBuilder->getBuilder($entity, FALSE); $builder->add([ 'propertyName' => 'name', // allowed types in BuilderDefinition::COMPONENT_TYPE_* 'componentType' => BuilderDefinition::COMPONENT_TYPE_TEXT_AREA, // override component type (component type is generated automatically from entity) 'settings' => [ 'label' => 'Name', 'placeholder' => 'example@example.com', 'required' => TRUE, 'value' => 'New name', // override value 'values' => ['key' => 'Value', 'key2' => 'Value 2'], // set possible values for list (CheckboxList, RadioList, SelectBox,...) 'appendValidationRules' => [ // append validation rules [ 'validator' => Form::EMAIL, 'text' => 'Please fill valid email' ] ], 'validationRules' => [ // replace validation rules [ 'validator' => Form::NUMERIC, 'text' => 'Please fill number' ] ], ] ]); // this create container with name related and edit box for name and hidden id value $builder->add([ 'propertyName' => 'related', 'componentType' => BuilderDefinition::COMPONENT_TYPE_CONTAINER, 'settings' => [ [ 'propertyName' => 'name', 'componentType' => BuilderDefinition::COMPONENT_TYPE_TEXT, 'settings' => [ 'label' => 'Name' ] ], [ 'propertyName' => 'id', 'componentType' => BuilderDefinition::COMPONENT_TYPE_HIDDEN, ] ] ]); return $form; } }
表单构建器会自动从属性类型中建议类型。此构建器会自动建议必填和数值类型。自动从属性类型创建组件类型并查找关系。当您通过任何注释映射关系时,构建器会从 Kdyby 的 EntityManager 中查找值和键。目标实体必须指定 __toString 方法,因为它用于 select、radio 等标签。