EmbedMany in Form - mongodb

I've created a small Symfony2-Website (with Symfony PR11) with MongoDB as DB.
I could create a form, that use a normal document, but how do I use a document with an embeddedDocument?
here are the documents:
/**
* #mongodb:Document(collection="location")
*/
class Location
{
/**
* #mongodb:Id
*/
protected $id;
/**
* #mongodb:String
*/
protected $locationName;
/**
* #mongodb:EmbedMany(targetDocument="LocationTerminal")
*/
protected $terminals = array();
// Setter
public function setTerminals(LocationTerminal $terminal)
{
array_push($this->terminals, $terminal);
}
public function setLocationName($locationName)
{
$this->locationName = $locationName;
}
// Getter
public function getId()
{
return $this->$id;
}
public function getLocationName()
{
return $this->locationName;
}
public function getTerminals()
{
return $this->terminals;
}
}
The EmbeddedDocument:
/**
* #mongodb:EmbeddedDocument
*/
class LocationTerminal
{
/**
* #mongodb:String
*/
protected $terminalName;
/**
* #mongodb:Int
*/
protected $since;
/**
* #mongodb:Int
*/
protected $to;
// Setter
public function setTerminalName($terminalName)
{
$this->terminalName = $terminalName;
}
public function setSince($since)
{
$this->since = $since;
}
public function setTo($to)
{
$this->to = $to;
}
// Getter
public function getTerminalName()
{
return $this->terminalName;
}
public function getSince()
{
return $this->since;
}
public function getTo()
{
return $this->to;
}
}
As you can see $terminals holds an EmbedMany-Document
Here's the form:
class LocationForm extends Form
{
public function configure()
{
$this->add(new TextField('locationName', array('max_length' => 255, 'required' => true)));
}
public function addTerminals($dm)
{
$this->add(new ChoiceField('terminals.terminalName', array('choices' => $dm)));
$this->add(new DateField('terminals.since', array('required' => true)));
$this->add(new DateField('terminals.to', array('required' => false)));
}
}
The used Controller looks like this:
class LocationController extends Controller
{
protected $location;
protected $locationTerminal;
protected function getDm()
{
return $this->get('doctrine.odm.mongodb.document_manager');
}
protected function getLocation($name = null)
{
if ($name != null)
{
$dm = $this->getDm();
$this->location = $dm->getRepository('RalfBundle:Location')->findOneBy(array('locationName' => $name));
if (! $this->location)
{
$this->location = new Location();
$this->locationTerminal = new LocationTerminal();
$this->location->setLocation($name);
$this->location->setTerminals($this->locationTerminal);
}
}
else
{
$this->location = new Location();
$this->locationTerminal = new LocationTerminal();
$this->location->setTerminals($this->locationTerminal);
$this->locationTerminal->setSince(0);
$this->locationTerminal->setTerminalName("");
$this->locationTerminal->setTo(0);
}
}
protected function getForm()
{
$form = LocationForm::create($this->get('form.context'), 'location');
$dm = $this->getDm();
$form->addTerminals($dm->getRepository('RalfBundle:Terminal')->findAll()->toArray());
return $form;
}
//... some Actions
public function createAction()
{
$this->getLocation();
$form = $this->getForm();
$form->bind($this->get('request'), $this->location);
if ($form->isValid())
{
$dm = $this->getDm();
$dm->persist($this->location);
$dm->flush();
return $this->redirect($this->generateUrl('Location'));
}
return $this->render('RalfBundle:Ralf:location_create.html.twig', array('form' => $form));
}
I could see, that locationName recieve the entered values in the form, but the EmbedMany-Array terminals is still empty.
What did I wrong?
Thanks for helping :D
UPDATED:
Ok, found a solution.
in public function addTerminals($dm) in LocationForm it should look like this:
public function addTerminals($dm)
{
$this->add(new ChoiceField('terminals.0.terminalName', array('choices' => $dm)));
$this->add(new DateField('terminals.0.since', array('required' => true, 'type'=> 'timestamp')));
$this->add(new DateField('terminals.0.to', array('required' => false, 'type' => 'timestamp')));
}
'type' => 'timestamp' is necessary, 'cause DateField will create an DateTime-Object, but the document expected an Int for timestamp.
a field from the terminals-array could be accessed by normal dot-notation.

Ok, found a solution.
in public function addTerminals($dm) in LocationForm it should look like this:
public function addTerminals($dm)
{
$this->add(new ChoiceField('terminals.0.terminalName', array('choices' => $dm)));
$this->add(new DateField('terminals.0.since', array('required' => true, 'type'=> 'timestamp')));
$this->add(new DateField('terminals.0.to', array('required' => false, 'type' => 'timestamp')));
}
'type' => 'timestamp' is necessary, 'cause DateField will create an DateTime-Object, but the document expected an Int for timestamp.
a field from the terminals-array could be accessed by normal dot-notation.

Symfony 2 actually gives you a tool to handle embedded documents in forms: It's called "collection field type" and it enables you to embed other formtypes (from other embedded documents) in a parent form.
It can be configured to allow/forbid addition/deletion of embedded documents and is actually quite powerful.

Related

TYPO3 Repository query returns uid and pid but no other fields

I'm doing a query on a really simple table in a typo 3 task. However, only the fields "uid" and "pid" are returned, the other fields are NULL.
My Entity:
<?php
namespace Name\SampleExtension\Domain\Model;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class MailAgent extends AbstractEntity
{
/**
* #var integer
*/
protected $uid;
/**
* #var string
*/
protected $customeremail;
/**
* #var string
*/
protected $searchparameters;
/**
* #var string
*/
protected $resultlist;
public function getUid()
{
return $this->uid;
}
public function setCustomerEmail($customeremail)
{
$this->customeremail = $customeremail;
}
public function getCustomerEmail()
{
return $this->customeremail;
}
public function setSearchParameters($searchparameters)
{
$this->searchparameters = $searchparameters;
}
public function getSearchParameters()
{
return $this->searchparameters;
}
public function setResultList($resultlist)
{
$this->resultlist = $resultlist;
}
public function getResultList()
{
return $this->resultlist;
}
}
?>
The Repository:
<?php
namespace Name\SampleExtension\Domain\Repository;
use TYPO3\CMS\Extbase\Persistence\Repository;
class MailAgentRepository extends Repository
{
public function findByUids($uids)
{
$query = $this->createQuery();
foreach ($uids as $uid) {
$constraints[] = $query->equals('uid', $uid);
}
return $query->matching(
$query->logicalOr(
$constraints
)
)->execute();
}
}
?>
And the query inside the task:
<?php
namespace Name\SampleExtension\Task;
use TYPO3\CMS\Scheduler\Task\AbstractTask;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use Name\SampleExtension\Domain\Model\MailAgent;
use Name\SampleExtension\Domain\Repository\MailAgentRepository;
class MailAgentCheckup extends AbstractTask
{
public function execute() {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$this->MailAgentRepository = $objectManager->get(MailAgentRepository::class);
$query = $this->MailAgentRepository->createQuery();
$allCustomers = $this->MailAgentRepository->findAll();
foreach ($allCustomers as $customer) {
var_dump($customer);
}
return true;
}
}
?>
I have no idea why the other fields are not returned, but the uid and the pid are. My guess is that I need to declare the mapping somewhere else.
EDIT: Heres the content of my TCA, which is probably wrong or not enough, but since I'm working on a existing extension I was copying from the TCA's of the tables that work.
tx_sampleextension_domain_model_mailagent.php
return [
'columns' => [
'uid' => [],
'customer_email' => [],
'search_parameters' => [],
'result_list' => [],
],
'types' => [],
];
This is from another table for which querys etc work
return [
'columns' => [
'immovable' => [],
'type' => [],
'title' => [],
'path' => [],
'mark_to_delete' => [],
],
];
Give a try to inject your repository
<?php
namespace Name\SampleExtension\Task;
use TYPO3\CMS\Scheduler\Task\AbstractTask;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use Name\SampleExtension\Domain\Model\MailAgent;
use Name\SampleExtension\Domain\Repository\MailAgentRepository;
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
class MailAgentCheckup extends AbstractTask
{
/**
* mailAgentRepository
*
* #var \Name\SampleExtension\Domain\Repository\MailAgentRepository
* #inject
*/
protected $mailAgentRepository = NULL;
public function injectMailAgentRepository(\Name\SampleExtension\Domain\Repository\MailAgentRepository $mailAgentRepository) {
$this->mailAgentRepository = $mailAgentRepository;
}
public function execute() {
$allCustomers = $this->mailAgentRepository->findAll();
DebuggerUtility::var_dump($allCustomers);exit;
// OR
$arguments = $this->request->getArguments();
$uid = $arguments['uid'];
$singleCustomer = $this->mailAgentRepository->findByUid(intval($uid));
DebuggerUtility::var_dump($singleCustomer);exit;
/*foreach ($allCustomers as $customer) {
var_dump($customer);
}*/
return true;
}
}
?>
I was missing the TCA file for the table. After adding it and declaring all the columns in there, the extbase domain object variables got filled.

yii2 losing user identity after login redirect

i have looked at the other similar questions, and while this one (Yii2 user identity loss after page redirection) asks pretty much the same question, there is no solution that applies to my situation.
i have created a new identity class, i have implemented all the necessary methods and implemented the IdentityInterface. note that it does NOT extend ActiveRecord, but rather extends my own base Model class that does not derive from AR.
everything seems to work fine, i can log in and be correctly authenticated. i have traced the code and i can see that my identity class is correctly set in Yii::$app->user after IdentityInterface::validatePassword() and User::login() have been called.
however, once the login succeeds and the user is redirected, Yii::$app->user contains an empty IdentityInterface, rather than the one that was there immediately prior to the redirect.
in SiteController::actionLogin(), i have modified the code from:
return $this->goHome();
to:
$tmp = $this->goHome();
// echo '<pre>';var_dump(Yii::$app->user);echo '</pre>';exit;
return($tmp);
and i can see that Yii::$app->user still has the correct identity up until the return() statement.
can anyone tell me why i am losing my identity? i have traced through everything i can think of: yii\web\Controller, yii\base\Controller, yii\web\Response, SiteController, yii\web\User, etc...
any help at all would be greatly appreciated. thanks!
Same problem, after 3 days find solution and I it working.
My User model is:
namespace app\models;
use Yii;
class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface
{
public $username;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'tbl_users';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['name', 'email', 'password'], 'required'],
[['email'], 'unique'],
[['role', 'status'], 'integer'],
[['created', 'last_update'], 'safe'],
[['name', 'email', 'password'], 'string', 'max' => 250]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'name' => 'Name',
'email' => 'Email',
'password' => 'Password',
'role' => 'Role',
'status' => 'Status',
'created' => 'Created',
'last_update' => 'Last Update',
];
}
public function getAuthKey() {
}
public function getId() {
return $this->id;
}
public function validateAuthKey($authKey) {
}
public static function findIdentity($id) {
}
public static function findIdentityByAccessToken($token, $type = null) {
}
public static function findByEmail($email)
{
return static::findOne(array('email'=>$email));
}
public function validatePassword($password)
{
return $this->password === $password;
}
}
I change:
public static function findIdentity($id) {
}
to:
public static function findIdentity($id) {
return self::findOne(array('id'=>$id));
}
It working for me.
I had the same problem. I had my custom class implementing yii\web\IdentityInterface. I made sure that session was enabled and enableAutologin was also true, but I had no luck at all.
Finally, I realized that in config/web.php there's a setting 'user' => [ 'identityClass' => 'app\models\User', 'enableAutoLogin' => true]
Of course, the identityClass is the default in a basic yii application. After setting this value to my custom class, identity was finally persisted.
try like this
implement implements \yii\web\IdentityInterface for your Active
record and Implement all method from \yii\web\IdentityInterface.
declare $users as static variable as private static $users = []; in your class.
Alter findByUsername() function for Get user details form Username.
In Config file add
'user' => ['identityClass' => 'app\models\active record class',
'enableAutoLogin' => true,
],
class User extends \yii\db\ActiveRecord
implements\yii\web\IdentityInterface {
private $_user = false;
public $rememberMe = true;
/*
* static variable
*/
private static $users = [];
/**
* #inheritdoc
*/
public static function tableName() {
return 'user';
}
/**
* #inheritdoc
*/
public function rules() {
return [
[['username', 'email', 'password', 'loginType'], 'required'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels() {
return [
'id' => Yii::t('app', 'ID'),
'username' => Yii::t('app', 'Username'),
'email' => Yii::t('app', 'Email'),
'password' => Yii::t('app', 'Password'),
];
}
/**
* Logs in a user using the provided username and password.
* #return boolean whether the user is logged in successfully
*/
public function login() {
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
} else {
return false;
}
}
/**
* Finds user by [[username]]
*
* #return User|null
*/
public function getUser() {
if ($this->_user === false) {
$this->_user = self::findByUsername($this->username);
}
return $this->_user;
}
public function validatePassword($password) {
if ($this->password == md5($password)) {
return true;
}
return false;
}
public static function findIdentity($id) {
return static::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null) {
return static::findOne(['access_token' => $token]);
}
public function getId() {
return $this->id;
}
public function getAuthKey() {
return $this->authkey;
}
public function validateAuthKey($authKey) {
return $this->authkey === $authKey;
}
public static function findByUsername($username) {
/*
* Get Record from Usertable
*/
$user = User::findOne(["username" => $username]);
if (!empty($user)) {
/* Create array with your active record like below */
$identity_use = ['id' => $user['id'],
'username' => $user['username'],
'password' => $user['password'],
'authKey' => '',
'accessToken' =>'',];
return new static($identity_use);
}
return null;
}
}
Another simple mistake that could result in session loss would be calling
$this->redirect(...);
instead of
return $this->redirect(...);
As Yii does not call die() or exit() in this method and the code on the lines following your redirect will be executed. Being used to CodeIgniter, I had assumed this and it took me days to figure it out.
I hope this can help you
<?php
namespace app\models;
use Yii;
class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface {
private $_notification;
public static function tableName()
{
return 'users';
}
public function setNotification($n) {
Yii::$app->session['user_' .$this->id . '_notification'] = $n;
}
public function getNotification() {
$n = Yii::$app->session['user_' .$this->id . '_notification'];
Yii::$app->session['user_' .$this->id . '_notification'] = NULL;
return $n;
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['email', 'password', 'first_name'], 'required'],
[['role'], 'integer'],
[['email', 'first_name'], 'string', 'max' => 128],
[['password'], 'string', 'max' => 32]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'email' => 'E-mail',
'password' => 'Пароль',
'first_name' => 'Имя',
'role' => 'Роль',
];
}
public static function findByEmail($email) {
return self::find()->where(['email' => $email])->one();
}
public function validatePassword($password) {
if ($this->password == md5($password)) {
return true;
}
return false;
}
public static function findIdentity($id)
{
return static::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['access_token' => $token]);
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->authkey;
}
public function validateAuthKey($authKey)
{
return $this->authkey === $authKey;
}
}

How to add data transformer inside a event listener

So, here's my problem: I have to add a field to a form based on it's underlying data but i've to add a data transformer to the field.
I thought the solution will be simple, just add a PRE_SET_DATA event listener to the form (just to access to the underlying data) and add the field and the transformer inside the listener. But i can't add the transformer inside the listener because the form is already locked.
I´ve tried many workarounds but i couldn't solved it. Her's my code:
$builder->...
->add(
$builder->create('date', 'choice', array(
'label' => 'form.game.date',
'empty_value' => 'form.game.date',
'required' => false,
'choices' => array(
'2014-04-10' => '10/Apr', // just to test
'2014-04-11' => '11/Apr',
)
))
->addModelTransformer(new DateToStringTransformer())
);
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($builder) {
$game = $event->getData();
$form = $event->getForm();
$period = new \DatePeriod(
$game->getTournament()->getBeginDate(),
new \DateInterval('P1D'),
$game->getTournament()->getEndDate()->add(new \DateInterval('P1D'))
);
$dates = array();
foreach($period as $date){
$dates[$date->format("Y-m-d")] = $date->format("j/M");
}
$form->add('date', 'choice', array(
'label' => 'form.game.date',
'choices' => $dates,
));
});
When i add the date field to the form inside event listener, the previously added data field is replaced so it's data transformer...
Is there a way to do it?
I wrote some test and updated your code a bit. Check if i understand your question correctly.
SomeTypeTest.php:
<?php
class SomeTypeTest extends TypeTestCase
{
/**
* #test
*/
public function testSubmitValidData()
{
$begin = new \DateTime();
$formData = array(
'date' => '2014-01-15'
);
$type = new SomeType();
$form = $this->factory->create($type);
$form->submit($formData);
$this->assertTrue($form->isSynchronized());
$this->assertEquals(['date' => \DateTime::createFromFormat('Y-m-d', '2014-01-15')], $form->getData());
$view = $form->createView();
$children = $view->children;
foreach (array_keys($formData) as $key) {
$this->assertArrayHasKey($key, $children);
}
}
}
SomeType.php:
<?php
class SomeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($builder) {
//$game = $event->getData();
$form = $event->getForm();
$period = new \DatePeriod(
\DateTime::createFromFormat('Y-m-d', '2014-01-01'), // for test
new \DateInterval('P1D'),
\DateTime::createFromFormat('Y-m-d', '2014-01-30') // for test
);
$dates = array();
foreach ($period as $date) {
$dates[$date->format("Y-m-d")] = $date->format("j/M");
}
$form->add($builder->create('date', 'choice', array(
'label' => 'form.game.date',
'empty_value' => 'form.game.date',
'auto_initialize' => false,
'required' => false,
'choices' => $dates
))
->addModelTransformer(new DateToStringTransformer())->getForm()
);
});
}
public function getName()
{
return 'st';
}
}
DateToStringTransformer.php:
<?php
class DateToStringTransformer implements DataTransformerInterface
{
/**
* #param mixed $value
* #return mixed|void
*/
public function transform($value)
{
if (!$value) {
return null;
}
return $value->format('Y-m-d');
}
/**
* #param mixed $value
* #return mixed|void
*/
public function reverseTransform($value)
{
return \DateTime::createFromFormat('Y-m-d', $value);
}
}
https://gist.github.com/ChubV/11348928
I've managed to get it work by creating a custom type that always add the data transformer. Then i can call "form->add('date', 'my_type',..)" from any event listener without loosing the data transformer.
MyType.php
class MyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('field1')
->add('field2')
...;
$builder->addEventSubscriber(new AddDateSubscriber());
}
}
CustomType.php
class DateChoiceType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addModelTransformer(new DateToStringTransformer());
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'invalid_message' => 'The selected date does not exist',
));
}
public function getParent()
{
return 'choice';
}
public function getName()
{
return 'date_choice';
}
}
Every time i add a date_choice type to a form the data transformer will be added too.
class AddDateSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(FormEvents::PRE_SET_DATA => 'preSetData');
}
public function preSetData(FormEvent $event)
{
$game = $event->getData();
$form = $event->getForm();
$endDate = \DateTime::createFromFormat('Y-m-d', $game->getTournament()->getEndDate()->format('Y-m-d'));
$period = new \DatePeriod(
$game->getTournament()->getBeginDate(),
new \DateInterval('P1D'),
$endDate
);
$dates = array();
foreach($period as $date){
$dates[$date->format("Y-m-d")] = $date->format("j/M");
}
$form->add('date', 'date_choice', array(
'label' => 'form.game.date.label',
'empty_value' => 'form.game.date.none',
'required' => false,
'choices' => $dates,
));
}
}
DateToStringTransformer.php
class DateToStringTransformer implements DataTransformerInterface
{
public function transform($date)
{
if (null === $date) {
return "";
}
return $date->format("Y-m-d");
}
public function reverseTransform($stringDate)
{
if (!$stringDate) {
return null;
}
$date = \DateTime::createFromFormat('Y-m-d', $stringDate);
if (false === $date) {
throw new TransformationFailedException('Sting to date transformation failed!');
}
return $date;
}
}
Hope that this will help someone.

ZF2 (2.1 method) Populating select/drop down element in form

I used Zend Framework 2.1(not 2.0x) method to populate a select/drop down that is described in following links:
http://zf2.readthedocs.org/en/develop/modules/zend.form.advanced-use-of-forms.html#handling-dependencies
http://www.michaelgallego.fr/blog/2012/11/09/discover-whats-coming-for-zendform-in-zf-2-1/
Though it seems I have done as they told I got a error message like:
*... ::__construct() must be an instance of Zend\Db\TableGateway\TableGateway, none given, called in ...*
which seems service locator is not used properly.
My form code that adds my FieldSet SupplierFieldset:
namespace Inventory\Form;
use Zend\Form\Form;
use Inventory\Model;
class ItemForm extends Form
{
public function init()
{
$this->add(array(
'name' => 'sup_code',
'type' => 'Inventory\Form\SupplierFieldset'
));
}
}
My 'SupplierFieldset' class:
namespace Inventory\Form;
use Inventory\Model;
use Zend\Form\Element;
use Zend\Form\Fieldset;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\InputFilter\InputFilterProviderInterface;
use Inventory\Model\SupplierTable;
use Inventory\Model\Supplier;
class SupplierFieldset extends Fieldset implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
protected $supplierTable;
public function init()
{
parent::__construct('Suppliers Code');
$this->setLabel('Supplier Code');
$this->setName('supplier_code');
$suppliers = $this->getSupplierTable()->fetchAll();
$select = new Element\Select('supplier_code');
$options = array();
foreach ($suppliers as $supplier) {
$options[$supplier->id] = $supplier->sup_code;
}
$select->setValueOptions($options);
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
public function getSupplierTable()
{
if (!$this->supplierTable) {
$sm = $this->getServiceLocator();
$this->supplierTable = $sm->get('Inventory\Model\SupplierTable');
}
return $this->supplierTable;
}
}
My Module.php getFormElementConfig() function:
public function getFormElementConfig()
{
return array(
'factories' => array(
'SupplierFieldset' => function($sm) {
$serviceLocator = $sm->getServiceLocator();
$supplierTable = $serviceLocator->get('Inventory\Model\SupplierTable');
$fieldset = new SupplierFieldset($supplierTable);
return $fieldset;
}
)
);
}
My SupplierTable.php model:
namespace Inventory\Model;
use Zend\Db\TableGateway\TableGateway;
class SupplierTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
}
I know SupplierTable model's constructor needs a TableGateway $tableGateway parameter. But this model is working properly when called from SupplierController.

Symfony 2 Form Validation Groups

I am trying to use a form class for add & edit. In add mode, iconFile is required. In edit mode, iconFile is optional (to replace the current icon). How can I acheive this?
I tried setting a mode in the constructor
class ItemForm extends AbstractType {
public function __construct($mode) {
$this->mode = $mode;
}
public function getDefaultOptions(array $opts) {
if ($mode == 'add') {
return array('validation_groups' => array('Default', 'add'));
} else {
return array('validation_groups' => array('Default'));
}
}
}
// doctrine entity, data_class of form
class Item {
/**
* #Assert\NotBlank(groups={"add"})
* #Assert\Image
*/
protected $iconFile;
}
// creating the form in controller
$form = $this->createForm(new ItemForm($mode));
Problem is even in edit mode, I still need to select an image. HTML5 validation triggers
In your ItemForm constructor, you are setting $mode to $this->mode, but you are then trying to access $mode from getDefaultOptions(). $mode obviously doesn't exist within this scope - try changing to the following:
public function getDefaultOptions(array $opts) {
if ($this->mode == 'add') {
return array('validation_groups' => array('Default', 'add'));
} else {
return array('validation_groups' => array('Default'));
}
}
You can do :
public function setDefaultOptions(OptionsResolver\OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'LIG\Bundle\UserBundle\Entity\User',
'validation_groups' => function(Form\FormInterface $form) {
$data= $form->getData();
if($data->getId())
{
return array('Default', 'Edit');
}
else
{
return array('Default', 'Add');
}
},
));
}