I'm trying to create a customer attribute on magento 2.0.1. I have checked all the answered questions here but my code still does not work.
Here my InstallData.php located in Mymodule\Cus\Setup
namespace Mymodule\Cus\Setup;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Customer\Model\Customer;
use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
/**
* #codeCoverageIgnore
*/
class InstallData implements InstallDataInterface
{
/**
* #var CustomerSetupFactory
*/
protected $customerSetupFactory;
/**
* #var AttributeSetFactory
*/
private $attributeSetFactory;
/**
* #param CustomerSetupFactory $customerSetupFactory
* #param AttributeSetFactory $attributeSetFactory
*/
public function __construct(
CustomerSetupFactory $customerSetupFactory,
AttributeSetFactory $attributeSetFactory
) {
$this->customerSetupFactory = $customerSetupFactory;
$this->attributeSetFactory = $attributeSetFactory;
}
/**
* {#inheritdoc}
*/
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
/** #var CustomerSetup $customerSetup */
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
$attributeSetId = $customerEntity->getDefaultAttributeSetId();
/** #var $attributeSet AttributeSet */
$attributeSet = $this->attributeSetFactory->create();
$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
$customerSetup->addAttribute(Customer::ENTITY, 'test_att', [
'type' => 'varchar',
'label' => 'Test ATT',
'input' => 'text',
'required' => false,
'visible' => true,
'user_defined' => true,
'sort_order' => 1000,
'position' => 1000,
'system' => 0,
]);
$attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'test_att')
->addData(['attribute_set_id' => $attributeSetId,
'attribute_group_id' => $attributeGroupId,
'used_in_forms' => ['adminhtml_customer','adminhtml_customer_address','customer_account_edit','customer_address_edit','customer_register_address','adminhtml_checkout'],
]);
$attribute->save();
}
}
When i run both :
php bin\magento setup:upgrade
php bin\magento setup:flush
the attribute is not created.
My module is registrated and i'm using for others things and it's working.
Try to locate Setup folder in the root of module also do not forget change namespace in the file
Try to clean row in the db setup_module table with your module version
Try to create attribute in this way:
$eavTable = $installer->getTable('needded table');
$columns = [
'column_name' => [
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
'nullable' => false,
'comment' => '',
],
];
$connection = $installer->getConnection();
foreach ($columns as $name => $definition) {
$connection->addColumn($eavTable, $name, $definition);
}
Related
I tried display customer attribute on frontend from admin. But I dont know how to display it, because attribute is type "select" and when I got value of it I got value of option of source model.
My layout ArseniyInk/TaskTwo/view/frontend/layout/customer_account_index.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="Magento\Customer\Block\Account\Dashboard\Info" name="customer_account_dashboard_info" as="info" template="Magento_Customer::account/dashboard/info.phtml" cacheable="false">
<container name="customer.account.dashboard.info.extra">
<block class="Magento\Customer\Block\Account\Dashboard\Info" name="customer.account.dashboard.info.extra.magento.username" template="ArseniyInk_TaskTwo::account/dashboard/info.phtml"/>
</container>
</block>
</referenceContainer>
</body>
My Source Model ArseniyInk/TaskTwo/Model/Customer/Attribute/Source/Employment.php
<?php
namespace ArseniyInk\TaskTwo\Model\Customer\Attribute\Source;
class Employment extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
{
public function getAllOptions()
{
if (!$this->_options) {
$this->_options = [
['label' => __('Unemployment'), 'value' => '1'],
['label' => __('Pupil'), 'value' => '2'],
['label' => __('Student'), 'value' => '3'],
['label' => __('Employee'), 'value' => '4']
];
}
return $this->_options;
}
}
My Attribute ArseniyInk/TaskTwo/Setup/Patch/Data/AddTestEmploymentAttribute.php
<?php declare(strict_types=1);
/**
* Patch to create Customer Attribute
*
*
*/
namespace ArseniyInk\TaskTwo\Setup\Patch\Data;
use Zend_Validate_Exception;
use Magento\Eav\Model\Config;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Eav\Model\Entity\Attribute\Source\Boolean;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
class AddTestEmploymentAttribute implements DataPatchInterface
{
/**
* #var Config
*/
private $eavConfig;
/**
* #var EavSetupFactory
*/
private $eavSetupFactory;
/**
* #var AttributeSetFactory
*/
private $attributeSetFactory;
/**
*
*
* #param Config $eavConfig
* #param EavSetupFactory $eavSetupFactory
* #param AttributeSetFactory $attributeSetFactory
*/
public function __construct(
Config $eavConfig,
EavSetupFactory $eavSetupFactory,
AttributeSetFactory $attributeSetFactory
) {
$this->eavConfig = $eavConfig;
$this->eavSetupFactory = $eavSetupFactory;
$this->attributeSetFactory = $attributeSetFactory;
}
/**
* {#inheritdoc}
*/
public static function getDependencies(): array
{
return [];
}
/**
* Create account customer attribute
* #return void
* #throws LocalizedException
* #throws Zend_Validate_Exception
*/
public function apply(): void
{
$eavSetup = $this->eavSetupFactory->create();
$customerEntity = $this->eavConfig->getEntityType('customer');
$attributeSetId = $customerEntity->getDefaultAttributeSetId();
$attributeSet = $this->attributeSetFactory->create();
$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
$eavSetup->addAttribute('customer', 'new_test_employment', [
'type' => 'int',
'input' => 'select',
'source' => 'ArseniyInk\TaskTwo\Model\Customer\Attribute\Source\Employment',
'label' => 'NEmployment',
'visible' => false,
'required' => false,
'user_defined' => true,
'system' => false,
'global' => true,
'default' => 0,
'visible_on_front' => false,
'sort_order' => 52,
'position' => 52
]);
$customAttribute = $this->eavConfig->getAttribute('customer', 'new_test_employment');
$customAttribute->addData([
'attribute_set_id' => $attributeSetId,
'attribute_group_id' => $attributeGroupId,
'used_in_forms' => ['adminhtml_customer', 'customer_account_edit', 'customer_account_create']
]);
$customAttribute->save();
}
/**
* {#inheritdoc}
*/
public function getAliases(): array
{
return [];
}
}
My Template ArseniyInk/TaskTwo/view/frontend/templates/account/dashboard/info.phtml
<p>
Employment =
<?= $block->escapeHtml($block->getCustomer()->getCustomAttribute('new_test_employment')->getValue()) ?><br>
</p>
Photo
I added a new field in the Magento 2 backend for the customer which is visible. I created this using mage2gen but whatever i try, the new field is not being saved when i update it in the backend.
Since the field is visible in the backend and both the view and api is working as expected i have no clue why it is not working. Below the actual patch i do to add the field and the xml config to make it visible as well.
I tried to add it to the attributeset but as far as i can see the field is registered properly and is also there in customer_eav_attribute
<?xml version="1.0" ?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<fieldset name="general">
<field formElement="text" name="external_reference" sortOrder="20">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="source" xsi:type="string">external_reference</item>
</item>
</argument>
<settings>
<dataType>text</dataType>
<label translate="true">External reference</label>
<dataScope>external_reference</dataScope>
<validation>
<rule name="required-entry" xsi:type="boolean">false</rule>
</validation>
</settings>
</field>
</fieldset>
</form>
<?php
declare(strict_types=1);
namespace Me\DirectLogin\Setup\Patch\Data;
use Magento\Customer\Api\CustomerMetadataInterface;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\Patch\PatchRevertableInterface;
class AddExternalReferenceCustomerAttribute implements DataPatchInterface, PatchRevertableInterface
{
/**
* #var ModuleDataSetupInterface
*/
private $moduleDataSetup;
/**
* #var EavSetupFactory
*/
private $eavSetupFactory;
/**
* Constructor
*
* #param ModuleDataSetupInterface $moduleDataSetup
* #param EavSetupFactory $eavSetupFactory
*/
public function __construct(
ModuleDataSetupInterface $moduleDataSetup,
EavSetupFactory $eavSetupFactory
) {
$this->moduleDataSetup = $moduleDataSetup;
$this->eavSetupFactory = $eavSetupFactory;
}
/**
* {#inheritdoc}
*/
public function apply()
{
$this->moduleDataSetup->getConnection()->startSetup();
/** #var EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
$eavSetup->addAttribute(
\Magento\Customer\Model\Customer::ENTITY,
'external_reference',
[
'type' => 'varchar',
'label' => 'External reference',
'input' => 'text',
'source' => '',
'frontend' => '',
'required' => false,
'backend' => '',
'default' => null,
'user_defined' => true,
'unique' => true,
'group' => 'General',
'system' => 0,
'order' => 1000,
'note' => 'Reference to external managed user',
'is_used_in_grid' => false,
'is_visible_in_grid' => true,
'is_filterable_in_grid' => true,
'is_searchable_in_grid' => true,
]
);
$eavSetup->addAttributeToSet(
CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER,
null,
'external_reference'
);
$this->moduleDataSetup->getConnection()->endSetup();
}
public function revert()
{
$this->moduleDataSetup->getConnection()->startSetup();
/** #var EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
$eavSetup->removeAttribute(\Magento\Customer\Model\Customer::ENTITY, 'external_reference');
$this->moduleDataSetup->getConnection()->endSetup();
}
/**
* {#inheritdoc}
*/
public function getAliases()
{
return [];
}
/**
* {#inheritdoc}
*/
public static function getDependencies()
{
return [
];
}
}
Hope someone can point me to a solution
Best,
Pim
I have checked that your code little bit different from the actual mage2gen code. Like you did not add data for "used_in_forms". You can try the below code to create a custom customer attribute (If you want to go with mage2gen)
https://mage2gen.com/snippets/customerattribute/
Or else you can try with the install method. Check below Mageplaza blog url:
https://www.mageplaza.com/magento-2-module-development/magento-2-add-customer-attribute-programmatically.html
Try to use the following in Setup/Patch/Data path
<?php
namespace Vendor\Customer\Setup\Patch\Data;
use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
class AddCustomerRefId implements DataPatchInterface
{
const EXTERNAL_REFERENCE = "external_reference";
/**
* #var ModuleDataSetupInterface
*/
protected $moduleDataSetup;
/**
* #var CustomerSetupFactory
*/
protected $customerSetupFactory;
/**
* #var AttributeSetFactory
*/
protected $attributeSetFactory;
/**
* AddCustomerPhoneNumberAttribute constructor.
* #param ModuleDataSetupInterface $moduleDataSetup
* #param CustomerSetupFactory $customerSetupFactory
* #param AttributeSetFactory $attributeSetFactory
*/
public function __construct(
ModuleDataSetupInterface $moduleDataSetup,
CustomerSetupFactory $customerSetupFactory,
AttributeSetFactory $attributeSetFactory
) {
$this->moduleDataSetup = $moduleDataSetup;
$this->customerSetupFactory = $customerSetupFactory;
$this->attributeSetFactory = $attributeSetFactory;
}
/**
* {#inheritdoc}
*/
public function apply()
{
$customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]);
$customerSetup->removeAttribute(
Customer::ENTITY,
self::EXTERNAL_REFERENCE
);
$customerEntity = $customerSetup->getEavConfig()->getEntityType(Customer::ENTITY);
$attributeSetId = $customerEntity->getDefaultAttributeSetId();
$attributeSet = $this->attributeSetFactory->create();
$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
$customerSetup->addAttribute(
Customer::ENTITY,
self::EXTERNAL_REFERENCE,
[
'type' => 'varchar',
'label' => 'External Reference',
'required' => false,
'user_defined' => true,
'sort_order' => 1000,
'position' => 1000,
'default' => 0,
'system' => 0
]
);
$attribute = $customerSetup->getEavConfig()->getAttribute(
Customer::ENTITY,
self::EXTERNAL_REFERENCE
);
$attribute->addData(
[
'attribute_set_id' => $attributeSetId,
'attribute_group_id' => $attributeGroupId,
'used_in_forms' => ['adminhtml_customer','customer_account_create','customer_account_edit']
]
);
$attribute->save();
}
/**
* {#inheritdoc}
*/
public static function getDependencies()
{
return [];
}
/**
* {#inheritdoc}
*/
public function getAliases()
{
return [];
}
}
I'm using this guide and guide2 as reference to add a custom attribute to catalog_product, but the patch isn't working.
Here is the Patch file (JKM\CustomModule\Setup\Patch\Data\AddShopAttribute.php):
<?php
namespace JKM\CustomModule\Patch\Data;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
class AddShopAttribute implements DataPatchInterface
{
/** #var ModuleDataSetupInterface */
private $moduleDataSetup;
/** #var EavSetupFactory */
private $eavSetupFactory;
/**
* #param ModuleDataSetupInterface $moduleDataSetup
* #param EavSetupFactory $eavSetupFactory
*/
public function __construct(
ModuleDataSetupInterface $moduleDataSetup,
EavSetupFactory $eavSetupFactory
) {
$this->moduleDataSetup = $moduleDataSetup;
$this->eavSetupFactory = $eavSetupFactory;
}
/**
* {#inheritdoc}
*/
public function apply()
{
/** #var EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
$eavSetup->addAttribute('catalog_product', 'shop', [
'type' => 'int',
'label' => 'Shop',
'input' => 'select',
'used_in_product_listing' => true,
'user_defined' => true,
]);
}
/**
* {#inheritdoc}
*/
public static function getDependencies()
{
return [];
}
/**
* {#inheritdoc}
*/
public function getAliases()
{
return [];
}
}
I'm getting this error when running command bin/magento setup:upgrade:
Module 'CustomModule': Warning: call_user_func()
expects parameter 1 to be a valid callback, class
'CustomModule\Setup\Patch\Data\AddShopAttribute' not found in
magento-root-folder/vendor/magento/framework/Setup/Patch/PatchRegistry.php
on line 139
Here is PatchRegistry.php
private function getDependencies(string $patch)
{
$depInstances = [];
$deps = call_user_func([$patch, 'getDependencies']); // LINE 139
$this->cyclomaticStack[$patch] = true;
foreach ($deps as $dep) {
if (isset($this->cyclomaticStack[$dep])) {
throw new \LogicException("Cyclomatic dependency during patch installation");
}
$depInstance = $this->registerPatch($dep);
/**
* If a patch already have applied dependency - than we definently know
* that all other dependencies in dependency chain are applied too, so we can skip this dep
*/
if (!$depInstance) {
continue;
}
$depInstances = array_replace($depInstances, $this->getDependencies($this->patches[$dep]));
$depInstances[$depInstance] = $depInstance;
}
unset($this->cyclomaticStack[$patch]);
return $depInstances;
}
Ive managed to create a table (db_schema.xml works) but its empty. For some reason Data/Schema Patch isn't working for me. Is the module path right (app/code/namespace/module)? What could be causing this behavior? Any help would be appreciated.
It seems like your attribute parameters aren't completed. Try to use this code instead.
<?php
namespace JKM\CustomModule\Patch\Data;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
class AddShopAttribute implements DataPatchInterface
{
/** #var ModuleDataSetupInterface */
private $moduleDataSetup;
/** #var EavSetupFactory */
private $eavSetupFactory;
/**
* #param ModuleDataSetupInterface $moduleDataSetup
* #param EavSetupFactory $eavSetupFactory
*/
public function __construct(
ModuleDataSetupInterface $moduleDataSetup,
EavSetupFactory $eavSetupFactory
) {
$this->moduleDataSetup = $moduleDataSetup;
$this->eavSetupFactory = $eavSetupFactory;
}
/**
* {#inheritdoc}
*/
public function apply()
{
/** #var EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
$eavSetup->addAttribute(\Magento\Catalog\Model\Product::ENTITY, 'shop', [
'type' => 'int',
'backend' => '',
'frontend' => '',
'label' => 'Shop',
'input' => 'select',
'class' => '',
'source' => \Magento\Catalog\Model\Product\Attribute\Source\Boolean::class,
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
]);
$groupName = 'Autosettings';
$entityTypeId = $catalogSetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY);
$attributeSetId = $catalogSetup->getAttributeSetId($entityTypeId, 'Default');
$attribute = $catalogSetup->getAttribute($entityTypeId, 'shop');
if ($attribute) {
$catalogSetup->addAttributeToGroup(
$entityTypeId,
$attributeSetId,
$groupName,
$attribute['attribute_id'],
60
);
}
}
/**
* {#inheritdoc}
*/
public static function getDependencies()
{
return [];
}
/**
* {#inheritdoc}
*/
public function getAliases()
{
return [];
}
}
I have two classes. Lets says it is Album and AlbumManager. Album is a intake class which I am using for generating basic entity function. I do not want to touch Album for custom functions. All other custom function I wrote in AlbumManager class.
Now from controller, when I try to access Album class through AlbumManager, it through me an error:
Can not be mapped or accessed.
How can I handle this type of dependency? Here are the classes:
Album.php
<?php
namespace Album\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Album
*
* #ORM\Table(name="album")
* #ORM\Entity
*/
class Album
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="artist", type="string", length=255, precision=0, scale=0, nullable=false, unique=false)
*/
private $artist;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set artist
*
* #param string $artist
* #return Album
*/
public function setArtist($artist)
{
$this->artist = $artist;
return $this;
}
/**
* Get artist
*
* #return string
*/
public function getArtist()
{
return $this->artist;
}
?>
AlbumManager.php
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace Album\Manager;
use Album\Entity as Album;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilterInterface;
class AlbumManager
{
private $album;
protected $inputFilter;
public function __construct(Album\Entity $album)
{
$this->album = $album;
}
public function getAlbum()
{
return $this->album;
}
/**
* Magic getter to expose protected properties.
*
* #param string $property
* #return mixed
*/
public function __get($property)
{
return $this->$property;
}
/**
* Magic setter to save protected properties.
*
* #param string $property
* #param mixed $value
*/
public function __set($property, $value)
{
$this->$property = $value;
}
/**
* Convert the object to an array.
*
* #return array
*/
public function getArrayCopy()
{
return get_object_vars($this);
}
/**
* Populate from an array.
*
* #param array $data
*/
public function populate($data = array())
{
$this->album->setId($data['id']);
$this->album->setArtist($data['artist']);
$this->album->setTitle($data['title']);
}
public function setInputFilter(InputFilterInterface $inputFilter)
{
throw new \Exception("Not used");
}
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'id',
'required' => true,
'filters' => array(
array('name' => 'Int'),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'artist',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'title',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
AlbumController.php
<?php
namespace Album\Controller;
use Zend\Mvc\Controller\AbstractActionController,
Zend\View\Model\ViewModel,
Album\Form\AlbumForm,
Doctrine\ORM\EntityManager,
Doctrine\ORM\EntityRepository,
Album\Entity\Album,
Album\Manager\AlbumManager,
class AlbumController extends AbstractActionController
{
public function addAction()
{
$form = new AlbumForm();
$form->get('submit')->setAttribute('label', 'Add');
$request = $this->getRequest();
if ($request->isPost()) {
$album = new Album();
$albumManager = new AlbumManager($album);
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$album->populate($form->getData());
$this->getEntityManager()->persist($album);
$this->getEntityManager()->flush();
// Redirect to list of albums
return $this->redirect()->toRoute('album');
}
}
return array('form' => $form);
}
?>
See the code at AlbumController
$album = new Album();
$albumManager = new AlbumManager($album);
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$album->populate($form->getData());
The album object can not get access to the getInputFilter and populate function which I write down in the Album Repository. I understood this happened because of the dependency injected. But what would be the solution so that I can access the album object, set the form data and also can use the album manger functions?
I am using zendframework 2 and doctrine 2. My addAction doesn't work i don't have any error but when i valid my form no row created in my database !!
i think that i have problem in populating foreign key !
this is my Form:
<?php
// filename : module/Users/src/Users/Form/addForm.php
namespace Vehicules\Form;
use Zend\Form\Form;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Doctrine\Common\Persistence\ObjectManager;
class VehiculeForm extends form implements ObjectManagerAwareInterface
{
protected $objectManager;
public function setObjectManager(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
}
public function getObjectManager()
{
return $this->objectManager;
}
//public function init()
public function __construct(ObjectManager $objectManager)
{
parent::__construct('add');
$this->objectManager = $objectManager;
$this->init();
}
public function init(){
$this->setAttribute('method', 'post');
$this->setAttribute('enctype','multipart/formdata');
$this->add(array(
'name' => 'matricule',
'attributes' => array(
'type' => 'text',
'required' => true
),
'options' => array(
'label' => 'Matricule',
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'carburant',
'options' => array(
'label' => 'Carburant',
'value_options' => array(
'0' => 'Essence',
'1' => 'Gasoil',
'2' => 'Hybride',
),
)
));
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectMultiCheckbox',
'name' => 'option',
'options' => array(
'label' => 'Options Véhicule',
'object_manager' => $this->getObjectManager(),
'target_class' => 'Vehicules\Entity\optionsvehicule',
'property' => 'libellee',
)));
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'categorie',
'options' => array(
'label' => 'categorie',
'object_manager' => $this->getObjectManager(),
'target_class' => 'Vehicules\Entity\categorie',
'property' => 'idcat',
)
));
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'modele',
'options' => array(
'label' => 'Modèle',
'object_manager' => $this->getObjectManager(),
'target_class' => 'Vehicules\Entity\modele',
'property' => 'nom',
)
));
/*$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'modele',
'options' => array(
'label' => 'Modèle',
'object_manager' => $this->getObjectManager(),
'target_class' => 'Vehicules\Entity\modele',
'property' => 'nom',
'is_method' => true,
'find_method' => array(
'name' => 'findBy',
'params' => array(
'criteria' => array('active' => 1),
// Use key 'orderBy' if using ORM
'orderBy' => array('lastname' => 'ASC'),
// Use key 'sort' if using ODM
'sort' => array('lastname' => 'ASC')
),
),
),
));*/
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'marque',
'options' => array(
'label' => 'Marque',
'object_manager' => $this->getObjectManager(),
'target_class' => 'Vehicules\Entity\marque',
'property' => 'nom',
)
));
$this->add(array(
'name' => 'dateMiseCirculation',
'attributes' => array(
'type' => 'Zend\Form\Element\Date',
),
'options' => array(
'label' => 'Date de Mise en Circulation',
),
));
$this->add(array(
'name' => 'numChasis',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Numero de Chasis',
),
));
$this->add(array(
'name' => "Prix d'achat",
'attributes' => array(
'type' => 'int',
),
'options' => array(
'label' => "Prix d'achat",
),
));
$this->add(array(
'name' => 'concessionnaire',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'concessionnaire',
),
));
$this->add(array(
'name' => 'souslocation',
'attributes' => array(
'type' => 'string',
),
'options' => array(
'label' => 'Sous-location',
),
));
$this->add(array(
'name' => 'remarque',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'remarque',
),
));
$this->add(array(
'name' => 'puisfiscal',
'attributes' => array(
'type' => 'int',
),
'options' => array(
'label' => "puissance fiscale",
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'nbreport',
'options' => array(
'label' => 'Nombre de portes',
'value_options' => array(
'0' => '4',
'1' => '2',
'2' => '5',
'3' => '6',
'4' => '7',
'5' => '7',
),
)
));
$this->add(array(
'name' => 'dernierKm',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Dernier kilométrage',
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Valider'
),
));
}}
and this is my Entity Vehicule:
<?php
namespace Vehicules\Entity;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterInterface;
use Zend\InputFilter\Factory as InputFactory;
use Doctrine\ORM\Mapping as ORM;
/**
* Vehicule
*
* #ORM\Table(name="vehicule", uniqueConstraints={#ORM\UniqueConstraint(name="VEHICULE_PK", columns={"idVeh"})}, indexes={#ORM\Index(name="ASSOCIATION11_FK", columns={"idCat"}), #ORM\Index(name="ASSOCIATION13_FK", columns={"idMod"})})
* #ORM\Entity
*/
class Vehicule
{ protected $inputFilter;
/**
* #var integer
*
* #ORM\Column(name="idVeh", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idveh;
/**
* #var string
*
* #ORM\Column(name="matricule", type="string", length=254, nullable=false)
*/
private $matricule;
/**
* #var string
*
* #ORM\Column(name="dateMiseCirculation", type="string", length=254, nullable=true)
*/
private $datemisecirculation;
/**
* #var string
*
* #ORM\Column(name="numChasis", type="string", length=254, nullable=false)
*/
private $numchasis;
/**
* #var string
*
* #ORM\Column(name="carburant", type="string", length=254, nullable=true)
*/
private $carburant;
/**
* #var string
*
* #ORM\Column(name="dernierKm", type="decimal", precision=10, scale=0, nullable=false)
*/
private $dernierkm;
/**
* #var integer
*
* #ORM\Column(name="prixachat", type="integer", precision=10, scale=0, nullable=false)
*/
private $prixachat;
/**
* #var string
*
* #ORM\Column(name="concessionnaire", type="string", length=254, nullable=true)
*/
private $concessionnaire;
/**
* #var integer
*
* #ORM\Column(name="sousLocation", type="smallint", nullable=true)
*/
private $souslocation;
/**
* #var string
*
* #ORM\Column(name="remarque", type="string", length=254, nullable=true)
*/
private $remarque;
/**
* #var integer
*
* #ORM\Column(name="puisFiscal", type="integer", nullable=true)
*/
private $puisfiscal;
/**
* #var integer
*
* #ORM\Column(name="nbrePort", type="integer", nullable=true)
*/
private $nbreport;
/**
* #var \Vehicules\Entity\Categorie
*
* #ORM\ManyToOne(targetEntity="Vehicules\Entity\Categorie")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="idCat", referencedColumnName="idCat")
* })
*/
private $idcat;
/**
* #var \Vehicules\Entity\Modele
*
* #ORM\ManyToOne(targetEntity="Vehicules\Entity\Modele")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="idMod", referencedColumnName="idMod")
* })
*/
private $idmod;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Vehicules\Entity\Optionsvehicule", inversedBy="idveh")
* #ORM\JoinTable(name="veh_option",
* joinColumns={
* #ORM\JoinColumn(name="idVeh", referencedColumnName="idVeh")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="idOptVeh", referencedColumnName="idOptVeh")
* }
* )
*/
private $idoptveh;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Vehicules\Entity\Vehiculestatut", inversedBy="idveh")
* #ORM\JoinTable(name="veh_status",
* joinColumns={
* #ORM\JoinColumn(name="idVeh", referencedColumnName="idVeh")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="idStatut", referencedColumnName="idStatut")
* }
* )
*/
private $idstatut;
/**
* Constructor
*/
public function __construct()
{
$this->idoptveh = new \Doctrine\Common\Collections\ArrayCollection();
$this->idstatut = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get idveh
*
* #return integer
*/
public function getIdveh()
{
return $this->idveh;
}
/**
* Set matricule
*
* #param string $matricule
* #return Vehicule
*/
public function setMatricule($matricule)
{
$this->matricule = $matricule;
return $this;
}
/**
* Get matricule
*
* #return string
*/
public function getMatricule()
{
return $this->matricule;
}
/**
* Set datemisecirculation
*
* #param string $datemisecirculation
* #return Vehicule
*/
public function setDatemisecirculation($datemisecirculation)
{
$this->datemisecirculation = $datemisecirculation;
return $this;
}
/**
* Get datemisecirculation
*
* #return string
*/
public function getDatemisecirculation()
{
return $this->datemisecirculation;
}
/**
* Set numchasis
*
* #param string $numchasis
* #return Vehicule
*/
public function setNumchasis($numchasis)
{
$this->numchasis = $numchasis;
return $this;
}
/**
* Get numchasis
*
* #return string
*/
public function getNumchasis()
{
return $this->numchasis;
}
/**
* Set carburant
*
* #param string $carburant
* #return Vehicule
*/
public function setCarburant($carburant)
{
$this->carburant = $carburant;
return $this;
}
/**
* Get carburant
*
* #return string
*/
public function getCarburant()
{
return $this->carburant;
}
/**
* Set dernierkm
*
* #param string $dernierkm
* #return Vehicule
*/
public function setDernierkm($dernierkm)
{
$this->dernierkm = $dernierkm;
return $this;
}
/**
* Get dernierkm
*
* #return string
*/
public function getDernierkm()
{
return $this->dernierkm;
}
/**
* Set prixachat
*
* #param integer $prixachat
* #return Vehicule
*/
public function setPrixachat($prixachat)
{
$this->prixachat = $prixachat;
return $this;
}
/**
* Get prixachat
*
* #return integer
*/
public function getPrixachat()
{
return $this->prixachat;
}
/**
* Set concessionnaire
*
* #param string $concessionnaire
* #return Vehicule
*/
public function setConcessionnaire($concessionnaire)
{
$this->concessionnaire = $concessionnaire;
return $this;
}
/**
* Get concessionnaire
*
* #return string
*/
public function getConcessionnaire()
{
return $this->concessionnaire;
}
/**
* Set souslocation
*
* #param integer $souslocation
* #return Vehicule
*/
public function setSouslocation($souslocation)
{
$this->souslocation = $souslocation;
return $this;
}
/**
* Get souslocation
*
* #return integer
*/
public function getSouslocation()
{
return $this->souslocation;
}
/**
* Set remarque
*
* #param string $remarque
* #return Vehicule
*/
public function setRemarque($remarque)
{
$this->remarque = $remarque;
return $this;
}
/**
* Get remarque
*
* #return string
*/
public function getRemarque()
{
return $this->remarque;
}
/**
* Set puisfiscal
*
* #param integer $puisfiscal
* #return Vehicule
*/
public function setPuisfiscal($puisfiscal)
{
$this->puisfiscal = $puisfiscal;
return $this;
}
/**
* Get puisfiscal
*
* #return integer
*/
public function getPuisfiscal()
{
return $this->puisfiscal;
}
/**
* Set nbreport
*
* #param integer $nbreport
* #return Vehicule
*/
public function setNbreport($nbreport)
{
$this->nbreport = $nbreport;
return $this;
}
/**
* Get nbreport
*
* #return integer
*/
public function getNbreport()
{
return $this->nbreport;
}
/**
* Set idcat
*
* #param \Vehicules\Entity\Categorie $idcat
* #return Vehicule
*/
public function setIdcat(\Vehicules\Entity\Categorie $idcat = null)
{
$this->idcat = $idcat;
return $this;
}
/**
* Get idcat
*
* #return \Vehicules\Entity\Categorie
*/
public function getIdcat()
{
return $this->idcat;
}
/**
* Set idmod
*
* #param \Vehicules\Entity\Modele $idmod
* #return Vehicule
*/
public function setIdmod(\Vehicules\Entity\Modele $idmod = null)
{
$this->idmod = $idmod;
return $this;
}
/**
* Get idmod
*
* #return \Vehicules\Entity\Modele
*/
public function getIdmod()
{
return $this->idmod;
}
/**
* Add idoptveh
*
* #param \Vehicules\Entity\Optionsvehicule $idoptveh
* #return Vehicule
*/
public function addIdoptveh(\Vehicules\Entity\Optionsvehicule $idoptveh)
{
$this->idoptveh[] = $idoptveh;
return $this;
}
/**
* Remove idoptveh
*
* #param \Vehicules\Entity\Optionsvehicule $idoptveh
*/
public function removeIdoptveh(\Vehicules\Entity\Optionsvehicule $idoptveh)
{
$this->idoptveh->removeElement($idoptveh);
}
/**
* Get idoptveh
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdoptveh()
{
return $this->idoptveh;
}
/**
* Add idstatut
*
* #param \Vehicules\Entity\Vehiculestatut $idstatut
* #return Vehicule
*/
public function addIdstatut(\Vehicules\Entity\Vehiculestatut $idstatut)
{
$this->idstatut[] = $idstatut;
return $this;
}
/**
* Remove idstatut
*
* #param \Vehicules\Entity\Vehiculestatut $idstatut
*/
public function removeIdstatut(\Vehicules\Entity\Vehiculestatut $idstatut)
{
$this->idstatut->removeElement($idstatut);
}
/**
* Get idstatut
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdstatut()
{
return $this->idstatut;
}
public function populate($data) {
$this->setMatricule($data['matricule']) ;
$this->setDatemisecirculation($data['dateMiseCirculation']) ;
$this->setNumchasis($data['numChasis']) ;
$this->setCarburant($data['carburant']) ;
$this->setDernierkm($data['dernierKm']) ;
$this->setPrixachat($data["Prix d'achat"]) ;
$this->setConcessionnaire($data['concessionnaire']) ;
$this->setSouslocation($data['souslocation']) ;
$this->setRemarque($data['remarque']) ;
$this->setPuisfiscal($data['puisfiscal']) ;
$this->setNbreport($data['nbreport']) ;
//$this->addIdoptveh($data['option']) ; /* select................*/
//$this->setIdmod() ; /* select................*/
//$this->addIdstatut() ; /*ghanakhd l option dyal libre */
}
public function setInputFilter(InputFilterInterface $inputFilter)
{
throw new \Exception("Not used");
}
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'matricule',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 4,
'max' => 14,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'option',
'required' => false,
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
public function getArrayCopy()
{
return get_object_vars($this);
}
}
this is my controller VehiculeController:
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* #link http://github.com/zendframework/Vehicules for the canonical source repository
* #copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*
*/
namespace Vehicules\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Vehicules\Form\VehiculeForm;
use Vehicules\Entity\Vehicule;
class VehiculesController extends AbstractActionController
{
/**
* #var Doctrine\ORM\EntityManager
*/
protected $_objectManager;
protected function getObjectManager()
{
if (!$this->_objectManager) {
$this->_objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
}
return $this->_objectManager;
}
public function indexAction()
{
$vehicules = $this->getObjectManager()->getRepository('Vehicules\Entity\Vehicule')->findAll();
return new ViewModel(array('vehicules' => $vehicules));
}
public function addAction()
{ $_objectManager=$this->getObjectManager();
$form = new VehiculeForm($_objectManager);
$request = $this->getRequest();
$post = $this->request->getPost();
if ($this->request->isPost()) {
$Vehicule= new Vehicule();
$form->setData($post);
$form->setInputFilter($Vehicule->getInputFilter());
if ($form->isValid()) {
$f=$form->getData();
$Vehicule->populate($f);
$cat = $this->getObjectManager()->getRepository('Vehicules\Entity\categorie')->findAll();
foreach ($cat as $c){
if($c->getIdcat()==$f['categorie'] ){
$Vehicule->setIdcat($c) ;
exit;
}
}
$mod = $this->getObjectManager()->getRepository('Vehicules\Entity\modele')->findAll();
foreach ($mod as $m){
if($m->getNom()==$f['modele'] ){
$Vehicule->setIdmod($m->getIdmod()) ;
exit;
}
}
$objectManager = $this->getObjectManager();
$objectManager->persist($Vehicule);
$objectManager->flush();
$id=$Vehicule->getIdveh();
var_dump($id);
$viewModel = new ViewModel(array('form' =>$form,'donne'=>$id));
return $viewModel;
}
}
$viewModel = new ViewModel(array('form' =>$form));
return $viewModel;
}
public function editAction()
{
$id = (int) $this->getEvent()->getRouteMatch()->getParam('id');
if (!$id) {
return $this->redirect()->toRoute('vehicules/default', array('controller'=>'vehicules','action'=>'add'));
}
$vehicule = $this->getObjectManager()->find('Vehicules\Entity\vehicule', $id);
$objectManager= $this->getObjectManager();
$form = new VehiculeForm($objectManager);
$form->setBindOnValidate(false);
$form->bind($vehicule);
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->post());
if ($form->isValid()) {
$form->bindValues();
$this->getEntityManager()->flush();
// Redirect to list of vehicules
return $this->redirect()->toRoute('vehicules/default', array('controller'=>'vehicules','action'=>'index'));
}
}
return array(
'id' => $id,
'form' => $form,
);
}
public function deleteAction()
{
$id = (int)$this->getEvent()->getRouteMatch()->getParam('idVeh');
if (!$id) {
return $this->redirect()->toRoute('vehicules');
}
$request = $this->getRequest();
if ($request->isPost()) {
$del = $request->post()->get('del', 'No');
if ($del == 'Yes') {
$id = (int)$request->post()->get('id');
$vehicule = $this->getEntityManager()->find('Vehicules\Entity\vehicule', $id);
if ($vehicule) {
$this->getEntityManager()->remove($vehicule);
$this->getEntityManager()->flush();
}
}
// Redirect to list of albums
return $this->redirect()->toRoute('default', array(
'controller' => 'vehicules',
'action' => 'index',
));
}
return array(
'id' => $id,
'vehicule' => $this->getEntityManager()->find('Vehicules\Entity\vehicule', $id)->getArrayCopy()
);
}
}
to populate forgnein key idMod and idCat i tried with this:
$mod = $this->getObjectManager()->getRepository('Vehicules\Entity\modele')->findAll();
foreach ($mod as $m){
if($m->getNom()==$f['modele'] ){
$Vehicule->setIdmod($m->getIdmod()) ;
exit;
}
}
but id doesn't work :/
Your issue is the form/entity hydration. You don't need to reinvent the wheel here as Zend\Form already takes care of getting the data in and out of a form.
Currently your form uses the default ArraySerializable hydrator, so when the form is validated and you fetch the data (using $form->getData()) you are given an array. What you want is a already populated Vehicule entity.
The DoctrineModule\Stdlib\Hydrator\DoctrineObject is a hydrator specifically for Doctrine. If you attach it as the hydrator to your form it will return hydrated entity.
To solve this you need to STOP creating the form using new
$form = new VehiculeForm($_objectManager);
Instead create it via the ServiceManager
$form = $this->getServiceLocator()->get('MyModule\Form\VehiculeForm');
Now create the form from a service factory; allowing the injection of the form dependencies, including the hydrator.
MyModule/Factory/Form/VehiculeFormFactory.php
namespace MyModule\Factory\Form;
use MyModule\Entity;
use MyModule\Form;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
use DoctrineModule\Stdlib\Hydrator;
class VehiculeFormFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $sl)
{
$objectManager = $sl->get('Doctrine\ORM\EntityManager');
$form = new Form\VehiculeForm($objectManager);
$vehicule = new Entity\Vehicule();
// create the hydrator; this could also be done via the
// hydrator manager but create here for the example
$hydrator = new DoctrineObject($objectManager);
$form->setHydrator($hydrator);
$form->setObject($vehicule);
// We can also take care of the input filter here too!
// meaning less code in the controller and only
// one place to modify should it change
$form->setInputFilter($Vehicule->getInputFilter());
return $form;
}
}
Module.php
public function getFormElementConfig()
{
return array(
'factories' => array(
'MyModule\Form\VehiculeForm' => 'MyModule\Factory\Form\VehiculeForm' // path to our new factory
),
);
}
You can now get rid of your populate() method and allot of the controller code.
FooController.php
//...
protected function getVehiculeForm()
{
return $this->getServiceLocator()->get('MyModule\Form\VehiculeForm');
}
public function addAction()
{
$request = $this->getRequest();
$form = $this->getVehiculeForm();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$vehicule = $form->getData(); // returns the entity!
if ($vehicule instanceof Vehicule) {
/// Fully hydrated entity!
var_dump($vehicule);
}
}
}
//...
}
//...