The class 'Login\Entity\User' was not found in the chain configured namespaces \Entity - zend-framework2

i'm using zf2 and doctrine that i've configured module.config.php like this
return array(
'doctrine' => array(
'driver' => array(
__NAMESPACE__. '_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Entity')
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__.'\Entity' => __NAMESPACE__.'_driver'
)
)
)
),
and my LoginController
class LoginController extends AbstractRestfulController {
public function indexAction() {
$em = $this->getServiceLocator()-> get('Doctrine\ORM\EntityManager');
$usr = new User();
$usr->setUsername('yassine');
$usr->setPassword('yassine');
$usr->setEmail('yassine#gmail.com');
$em->persist($usr);
$em->flush(); } }
and my class user /Login/Entity/User
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(name="id")
*/
protected $id;
/**
* #ORM\Column(name="username")
*/
protected $username;
/**
* #ORM\Column(name="password")
*/
protected $password;
/**
* #ORM\Column(name="email")
*/
protected $email;
// Returns ID of the user
public function getId()
{
return $this->id;
}
// Sets ID of the user.
public function setId($id)
{
$this->id = $id;
}
// Returns username.
public function getUsername()
{
return $this->username;
}
// Sets username.
public function setUsername($username)
{
$this->username = $username;
}
// Returns password.
public function getPassword()
{
return $this->password;
}
// Sets Password.
public function setPassword($password)
{
$this->password = $password;
}
// Sets email.
public function setEmail($email)
{
$this->email = $email;
}
// Returns email.
public function getEmail()
{
return $this->email;
}
}
The problem that it shows me this message Mapping Exception :
The class 'Login\Entity\User' was not found in the chain configured namespaces \Entity

It seems __NAMESPACE__ is empty in your module.config.php and that’s why Doctrine sees the following:
'drivers' => [
'\Entity' => '_driver'
]
instead of:
'drivers' => [
'Login\Entity' => 'Login_driver'
]
To fix this issue, you have to declare the namespace used in module.config.php. In other words, put the following:
namespace Login;
at the top of the file, right after PHP opening tag.
Another solution would be to replace all __NAMESPACE__ occurrences with 'Login' string.

Related

How to include EntityManager in ZendFramework 2 AbstractValidator

I have a custom validator, extending Zend AbstractValidator. The thing is, i want to include Doctrine EntityManager, but i keep failing! I tried to make a Factory for my Validator, but it doesn't seem to work. Help!! What am I doing wrong?
Validator:
$this->objectRepository stays empty, while i expect content.
namespace Rentals\Validator;
use Rentals\Response;
use Zend\Validator\AbstractValidator;
use Zend\Stdlib\ArrayUtils;
class ExistentialQuantification extends AbstractValidator
{
const NO_ENTITY_ID = 'noEntityId';
const ENTITY_NOT_FOUND = 'entityNotFound';
const INVALID_ID = 'invalidId';
protected $messageTemplates = [
self::NO_ENTITY_ID => 'The input does not contain an entity id.',
self::ENTITY_NOT_FOUND => 'The entity could not be found.',
self::INVALID_ID => 'The input does not contain an entity id.',
];
protected $objectRepository;
public function __construct(array $options)
{
$this->objectRepository = $options['object_repository'];
parent::__construct($options);
}
public function isValid($value)
{
if ($value === null) {
return true;
}
if (! isset($value->id)) {
$this->error(self::NO_ENTITY_ID);
return false;
}
$entityClass = $this->getOption('entity_class');
$controller = new Controller();
$entity = (new FactoryInterface)(EntityManager::class)->find($entityClass, $entity->id);
if (! $entity instanceof $entityClass) {
$this->error(self::ENTITY_NOT_FOUND);
return false;
}
if (! $entity->getId()) {
$this->error(self::NO_ENTITY_ID);
return false;
}
return true;
}
}
Factory:
namespace Rentals\Validator;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\MutableCreationOptionsInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Stdlib\ArrayUtils;
class ExistentialQuantificationFactory implements FactoryInterface, MutableCreationOptionsInterface
{
protected $options = [];
public function setCreationOptions(array $options)
{
$this->options = $options;
}
public function createService(ServiceLocatorInterface $serviceLocator)
{
if (! isset($this->options['object_manager'])) {
$this->options['object_manager'] = 'doctrine.entitymanager.orm_default';
}
$objectManager = $serviceLocator->get($this->options['object_manager']);
$objectRepository = $objectManager->getRepository($this->options['entity_class']);
return new ExistentialQuantification(ArrayUtils::merge(
$this->options, [
'objectManager' => $objectManager,
'objectRepository' => $objectRepository
]
));
}
}
Module config:
<?php
return [
'service_manager' => [
'factories' => [
'Rentals\\Validator\\ExistentialQuantification' => 'Rentals\\Validator\\ExistentialQuantificationFactory'
]
]
];
?>
What if you change your config entry like the following example?
return [
'validators' => [
'factories' => [
ExistentialQuantification::class => ExistentialQuantificationFactory::class,
],
],
];
This change will result in further changes for your factory, because the service locator for the entity manager differs from the one you injected.
namespace Application\Validator\Factory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\MutableCreationOptionsInterface;
use Zend\ServiceManager\MutableCreationOptionsTrait;
use Zend\ServiceManager\ServiceLocatorInterface;
class ExistentialQuantificationFactory implements FactoryInterface, MutableCreationOptionsInterface
{
use MutableCreatinOptionsTrait;
public function createService(ServiceLocatorInterface $serviceLocator)
{
$parentLocator = $serviceLocator->getServiceLocator();
if (! isset($this->creationOptions['object_manager'])) {
$this->creationOptions['object_manager'] = 'doctrine.entitymanager.orm_default';
}
$objectManager = $parentLocator->get($this->creationOptions['object_manager']);
$objectRepository = $objectManager->getRepository($this->creationOptions['entity_class']);
return new ExistentialQuantification(ArrayUtils::merge(
$this->options, [
'objectManager' => $objectManager,
'objectRepository' => $objectRepository
]
));
}
}
What I 've done here? First I implemented the MutableCreationOptionsTrait class. This trait implements the needed functions for working with creation options. But this is just a little hint for avoiding unnecessary work.
Because of setting the validator class as validator in the config, we have to use the parent service locator for getting the entity manager. The inherited service locator just provides access to validators.
Now you can try to access your validator in your controller like in the following examaple.
$validator = $this->getServiceLocator()
->get('ValidatorManager')
->get(ExistentialQuantification::class, [
'entity_class' => YourEntityClass::class,
]);
\Zend\Debug\Debug::dump($validator, __METHOD__);
The validator manager should return your validator so that you can test it.

FormElementError for login failed

I am very new to Zend Framework 2. When I try to login on false credentials it don't show any error. So what should be the code to display FormElementError in this case.
My LoginFilter.php is given below:
use Zend\InputFilter\InputFilter;
class LoginFilter extends InputFilter
{
public function __construct()
{
$this->add(array(
'name' => 'email',
'required' => true,
'validators' => array(
array(
'name' => 'EmailAddress',
'options' => array(
'domain' => true,
),
),
),
));
$this->add(array(
'name' => 'password',
'required' => true,
//'validators' => array(),
));
}
}
So this is how I do it with a custom InputFilter. I apply the setMessage to the Zend-Validator, which is being stuffed into the ValidatorChain, via setMessage().Below you can see $emailDoesNotExist->setMessage('This e-mail address is already in use'); is here I set my error message. You can also do it to like StringLength variable ($stringLength).
namespace User\InputFilter;
use Zend\Db\Adapter\Adapter;
use Zend\Filter\FilterChain;
use Zend\Filter\StringTrim;
use Zend\I18n\Validator\Alnum;
use Zend\InputFilter\Input;
use Zend\InputFilter\InputFilter;
use Zend\Validator\Db\NoRecordExists;
use Zend\Validator\EmailAddress;
use Zend\Validator\Identical;
use Zend\Validator\Regex;
use Zend\Validator\StringLength;
use Zend\Validator\ValidatorChain;
class AddUser extends InputFilter
{
/**
*
* #var InputFilter $dbAdapter
*/
protected $dbAdapter;
public function __construct(Adapter $dbAdapter)
{
$this->dbAdapter = $dbAdapter;
$firstName = new Input('first_name');
$firstName->setRequired(true);
$firstName->setValidatorChain($this->getNameValidatorChain());
$firstName->setFilterChain($this->getStringTrimFilterChain());
$lastName = new Input('last_name');
$lastName->setRequired(true);
$lastName->setValidatorChain($this->getNameValidatorChain());
$lastName->setFilterChain($this->getStringTrimFilterChain());
$email = new Input('email');
$email->setRequired(true);
$email->setValidatorChain($this->getEmailValidatorChain());
$email->setFilterChain($this->getStringTrimFilterChain());
$password = new Input('password');
$password->setRequired(true);
$password->setValidatorChain($this->getPasswordValidatorChain());
$password->setFilterChain($this->getStringTrimFilterChain());
$repeatPassword = new Input('repeat_password');
$repeatPassword->setRequired(true);
$repeatPassword->setValidatorChain($this->getRepeatPasswordValidatorChain());
$repeatPassword->setFilterChain($this->getStringTrimFilterChain());
$this->add($firstName);
$this->add($lastName);
$this->add($email);
$this->add($password);
$this->add($repeatPassword);
}
/**
* Gets the validation chain for the first name and last name inputs
*
* #return ValidatorChain
*/
protected function getNameValidatorChain()
{
$stringLength = new StringLength();
$stringLength->setMin(2);
$stringLength->setMax(50);
$validatorChain = new ValidatorChain();
$validatorChain->attach(new Alnum(true));
$validatorChain->attach($stringLength);
return $validatorChain;
}
/**
* Gets the validation chain for the email input
*
* #return ValidatorChain
*/
protected function getEmailValidatorChain()
{
$stringLength = new StringLength();
$stringLength->setMin(2);
$stringLength->setMax(50);
$emailDoesNotExist = new NoRecordExists(
array(
'table' => 'user',
'field' => 'email',
'adapter' => $this->dbAdapter
)
);
$emailDoesNotExist->setMessage('This e-mail address is already in use');
$validatorChain = new ValidatorChain();
$validatorChain->attach($stringLength, true);
$validatorChain->attach(new EmailAddress(), true);
$validatorChain->attach($emailDoesNotExist, true);
return $validatorChain;
}
/**
*
* #return ValidatorChain
*/
protected function getPasswordValidatorChain()
{
$stringLength = new StringLength();
$stringLength->setMax(6);
$oneNumber = new Regex('/\d/'); //checking to make sure it has at least one number
$oneNumber->setMessage('Must contain at least one number');
$validatorChain = new ValidatorChain();
$validatorChain->attach($stringLength);
$validatorChain->attach($oneNumber);
return $validatorChain;
}
/**
*
* #return ValidatorChain
*/
protected function getRepeatPasswordValidatorChain()
{
$identical = new Identical();
$identical->setToken('password'); // Name of the input whose value to match
$identical->setMessage('Passwords must match');
$validatorChain = new ValidatorChain();
$validatorChain->attach($identical);
return $validatorChain;
}
/**
*
* #return \User\InputFilter\FilterChain
*/
protected function getStringTrimFilterChain()
{
$filterChain = new FilterChain();
$filterChain->attach(new StringTrim());
return $filterChain;
}
}

DataMapper not called on child FormType with 'inherit_data' => true (Symfony)

Is this always the case? I've searched the web and read the docs but am none the wiser. I did read that DataTransformers can't be applied when inherit_data is true, which also seems a shame. (What could be the reason?)
I have a FormType 'PermissionType' which maps a 'Permission'. Permission has, as do some other entities, a creation/lastModification DateTime. Having read How to Reduce Code Duplication with "inherit_data" I naturally went on my way to implement the newly found good advice and created a TimeTrackedType.
This child form to PermissionType displays two DateTimeType fields and has inherit_data set to true. They are correctly rendered to the browser but they remain empty however I try to enter data into them. I started off by adding a DataMapper but the one of TimeTrackedType is not getting called. The DataMapper of its parent PermissionType however is, it being a child form itself, and that seems the only place where I can change the value of the DateTimeType fields of TimeTrackedType.
I do hope it's me doing something wrong here because it seems wrong having the inputs created in the child form but having to map to them in the parent class. Can anyone elaborate on this? Any pointers are greatly appreciated.
Here are the entities, first User:
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User implements AdvancedUserInterface, \Serializable {
use HasSingleId, TimeTrackedEntityTrait, EntityCreatorTrait;
// ^^^ This trait has two DateTime fields and that's it.
// (...)
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Permission", mappedBy="user")
* #Assert\Valid()
*/
private $permissions;
// (...)
}
Then Permission:
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\PermissionRepository")
*/
class Permission {
use TimeTrackedEntityTrait, EntityCreatorTrait;
/**
* #var User
* #ORM\Id
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="permissions")
*/
private $user;
/**
* #var array
* #ORM\Id
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Role", inversedBy="permissions")
*/
private $role;
// (...getters and setters...)
}
Lastly class Role:
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\RoleRepository")
*/
class Role implements RoleInterface {
use HasSingleId, TimeTrackedEntityTrait, EntityCreatorTrait;
/**
* #var type string
* #ORM\Column(type="string", nullable=false, unique=true);
*/
private $name;
/**
* #var type ArrayCollection
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Permission", mappedBy="role")
* #Assert\Valid()
*/
private $permissions;
}
And now the FormTypes:
class UserType extends AbstractType {
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('username', TextType::class, [ 'attr' => [ 'size' => 10 ] ] )
->add('password', RepeatedType::class, [
'type' => PasswordType::class,
'attr' => ['size' => 10 ],
'first_options' => [ 'label' => 'Password' ],
'second_options' => [ 'label' => 'Confirm' ] ]);
$entity = $builder->getData();
$admin = $entity->hasRole('ROLE_ADMIN');
if($admin) {
$builder->add('id', TextType::class, [ 'attr' => [ 'size' => 4 ] ]);
$builder->add('isEnabled', CheckboxType::class, [ 'required' => false ]);
}
$builder->add('permissions', CollectionType::class, [
'data_class' => 'Doctrine\ORM\PersistentCollection',
'mapped'=>true,
'prototype'=>true,
'allow_add'=>true,
'allow_delete'=>true,
'entry_type' => PermissionType::class]);
$builder->add('email', EmailType::class);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'required' => true,
'mapped' => true,
'data_class' => 'AppBundle\Entity\User'
]);
}
}
...and...
class PermissionType extends AbstractType implements DataMapperInterface {
public function mapDataToForms($permission, $forms) {
$forms = iterator_to_array($forms);
if($permission instanceof Permission && $permission) {
$forms['role']->setData($permission->getRole()->getName());
// These two statements get the job done, but not as was intended.
$forms['created']->setData($permission->getCreated());
$forms['lastModified']->setData($permission->getLastModified());
}
}
public function mapFormsToData($forms, &$permission) {
$forms = iterator_to_array($forms);
if($permission instanceof Permission) {
$permission->setCreated($forms['created']->getData());
$permission->setLastModified($forms['lastModified']->getData());
}
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->setDataMapper($this);
$builder->add('role', TextType::class, [ 'mapped' => true ]);
$builder->add('timing', TimeTrackedEntityType::class, [
'data_class' => 'AppBundle\Entity\Permission',
'inherit_data' => true, 'mapped'=>true ]);
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Permission',
'mapped'=>true,
'compound'=>true,
));
}
public function getParent() {
return FormType::class;
}
public function getName() { return 'PermissionType'; }
}
...and finally:
class TimeTrackedEntityType extends AbstractType implements DataMapperInterface {
// This is the method that doesn't get called
public function mapDataToForms($permission, $forms) {
$forms = iterator_to_array($forms);
$forms['created']->setData($permission->getCreated()->format("d/m/Y H:i:s"));
$forms['lastModified']->setData($permission->getLastModified()->format("d/m/Y H:i:s"));
}
public function mapFormsToData($forms, &$data) {
$forms = iterator_to_array($forms);
$data->setCreated($forms['created']->getData());
$data->setLastModified($forms['lastModified']->getData());
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->setDataMapper($this);
$builder->add('created', DateTimeType::class, [
'format' => 'd/M/Y H:i:s',
'input' => 'datetime',
'widget' => 'single_text',
'attr'=>['size'=>14, 'class'=>'right'],
'mapped' => true ]);
$builder->add('lastModified', DateTimeType::class, [
'format' => 'd/M/Y H:i:s',
'input' => 'datetime',
'widget' => 'single_text',
'attr'=>['size'=>14, 'class'=>'right'],
'mapped' => true ]);
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'mapped'=>true,
'compound'=>true,
'inherit_data' => true,
));
}
public function getName() { return 'TimeTrackedEntityType'; }
}
The article does not use DataMapper at all.
Using a trait means the properties are part of the PermissionEntity object as normal, so instead of holding these properties like the other fields in the corresponding PermissionType form, they are nested in you sub form type TimeTrackedEntityType.
Then you just need to set inherit_data to true and the right data_class option if you need this sub form else where, and that's what you already do in TimeTrackedEntityType, since the sub form gets its parent form's data, so no need for DataMapper.
If you want to use one, it should only be with the parent form not its child, it is ignored as expected.

Dynamic generated form with Zend Framework 2

I'm creating ZF2 Poll Module. I have poll with many questions. Every question has answers that can be multiple answers or single answer(Radio or MultiCheckbox). How to create a dynamic form that I can show to front-end?
This is what I've tried, but the form doesn't validate correctly...
module\Polls\src\Polls\Form\PollFillingQuestionsForm.php
<?php
namespace Polls\Form;
use Zend\Form\Form;
use Polls\Form\Fieldset\PollFillingQuestionAnswerFieldset;
use Polls\Form\Fieldset\PollFillingQuestionFieldset;
class PollFillingQuestionsForm extends Form {
public function __construct($questionsObject) {
parent::__construct('questionsForm');
$questionsFieldset = new PollFillingQuestionFieldset('questions');
//$questionsObject is array of question objects.
foreach ($questionsObject as $questionObject) {
$fieldset = new PollFillingQuestionAnswerFieldset($questionObject->id, array(), $questionObject);
$questionsFieldset->add($fieldset);
}
$this->add($questionsFieldset);
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Submit Poll',
'class' => 'btn btn-success',
),
));
}
}
module\Polls\src\Polls\Form\Fieldset\PollFillingQuestionAnswerFieldset.php
<?php
namespace Polls\Form\Fieldset;
use Polls\Model\QuestionAnswer;
use Zend\Form\Fieldset;
use Zend\Stdlib\Hydrator\ArraySerializable;
class PollFillingQuestionAnswerFieldset extends Fieldset {
public function __construct($name, $options, $questionObject) {
parent::__construct($name, $options);
$question = $questionObject;
$this->setLabel($question->title);
$type = 'Radio';
$elementType = 'radio';
switch ($question->answer_type) {
case 'many':
$type = 'MultiCheckbox';
$elementType = 'checkbox';
break;
case 'one':
$type = 'Radio';
$elementType = 'radio';
break;
default:
$type = 'Radio';
$elementType = 'radio';
break;
}
$this->setHydrator(new ArraySerializable())
->setObject(new QuestionAnswer());
$answers = $question->getAnswers();
$answerValues = array();
foreach ($answers as $answer) {
$answerValues[$answer->id] = $answer->title;
}
$this->add(array(
'name' => 'answer',
'type' => $type,
'options' => array(
'type' => $elementType,
'value_options' => $answerValues,
),
));
}
}
I've done this in the past, with a clean Factory strategy you can inject the dependencies into your form and your input filter. The magic lies in your Factories.
Start by wiring things in your service manager config:
'form_elements' => [
'factories' => [
DynamicForm::class => DynamicFormFactory::class,
],
],
'input_filters' => [
'factories' => [
DynamicInputFilter::class => DynamicInputFilterFactory::class,
],
],
First task is to get your FormFactory done up right.
class DynamicFormFactory implements FactoryInterface, MutableCreationOptionsInterface
{
/**
* #var array
*/
protected $options;
/**
* Set creation options
*
* #param array $options
* #return void
*/
public function setCreationOptions( array $options )
{
$this->options = $options;
}
/**
* {#inheritdoc}
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
/**
* #var \Zend\Form\FormElementManager $serviceLocator
* #var \Zend\ServiceManager\ServiceManager $serviceManager
*/
$serviceManager = $serviceLocator->getServiceLocator();
try
{
$options = /* set up your form's config, you have the service manager here */;
$form = new DynamicForm( $options );
$form->setInputFilter( $serviceManager->get('InputFilterManager')->get( DynamicFormFilter::class, $options ) );
}
catch( \Exception $x )
{
die( $x->getMessage() );
}
return $form;
}
}
Then, react to $options in your DynamicInputFilterFactory through the MutableCreationOptionsInterface implementation. You generally don't want forms and filters to be 'option aware', let the factories take care of that.
class DynamicInputFilterFactory implements FactoryInterface, MutableCreationOptionsInterface
{
protected $options;
/**
* Set creation options
*
* #param array $options
* #return void
*/
public function setCreationOptions( array $options )
{
$this->options = $options;
}
public function createService( ServiceLocatorInterface $serviceLocator )
{
/* do stuff with $this->options */
return new DynamicInputFilter(
/* pass your transformed options */
);
}
}
Next, all you have to do is create your form and input filter per what was passed to them through MutableOptions. Set your dependencies in __construct (don't forget to call parent::__construct) and initialize your form in init per the options passed in.
I suspect you have a good base in ZF2, so I'll stop here. This ought to get you on your way. Take-aways are MutableCreationOptionsInterface and separating your InputFilter and Form construction, combining the two in your Form Factory.

Can't get bind() to work

I want my form fields to contain the previous data contained in database when the form page opens. I went through lots of queries here and came to know using populate() or bind() method is the way to do it. But when I try to use it, I get an undefined method error.
Is there any other way to do it?
I am unable to use bind() as well. I am getting a fresh form with default values after I submit.
Sorry if this is a stupid question. Its been only 4-5 days since I started learning Zend framework. Also, most of the methods I get online are for older frameworks. I am using Zend Framework2.
This is Controller Code
<?php
class ChatController extends AbstractActionController
{
protected $chatTable;
public function indexAction()
{
$form = new ChatForm();
$model= new Chat();
$form->bind($model);
$form->get('submit')->setValue('Save');
$request = $this->getRequest();
if ($request->isPost()) {
$gen_set = new Chat();
$form->setInputFilter($gen_set->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$gen_set->exchangeArray($form->getData());
$this->getChatTable()->saveChat($gen_set);
// Redirect to list of albums
return $this->redirect()->toRoute('chat');
}
}
return array('form' => $form);
}
public function getChatTable()
{
if (!$this->chatTable) {
$sm = $this->getServiceLocator();
$this->chatTable = $sm->get('Chat\Model\ChatTable');
}
return $this->chatTable;
}
}
My Entity Class, Here api_key and anon_prefix are rows of the column 'settings' and there is one more column with value.
<?php
class Chat implements InputFilterAwareInterface
{
protected $inputFilter;
public function exchangeArray($data)
{
$this->api_key=(isset($data['api_key'])) ? $data['api_key'] : null;
$this->anon_prefix = (isset($data['anon_prefix'])) ? $data['anon_prefix'] : null;
}
// Add content to these methods:
public function setInputFilter(InputFilterInterface $inputFilter)
{
throw new \Exception("Not used");
}
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$inputFilter->add(array(
'name' => 'iflychat_external_api_key',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
));
$inputFilter->add(array(
'name' => 'iflychat_show_admin_list',
'required' => true,
'validators' => array(
array(
'name' => 'InArray',
'options' => array(
'haystack' => array(1,2),
),
),
),
));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
public function getArrayCopy()
{
return get_object_vars($this);
}
}
This is used to enter values into db
<?php
class ChatTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
public function saveChat(Chat $gen_set)
{
$data = array(
'value' => $gen_set->api_key,
);
$id='iflychat_external_api_key';
$this->tableGateway->update($data,array('settings' => $id));
$data = array(
'value' => $gen_set->anon_prefix,
);
$id='anon_prefix';
$this->tableGateway->update($data,array('settings' => $id));
}
}
I am getting this error, 'Cannot use object of type Chat\Model\Chat as array'
Your action doesn't make much sense as it is, you instantiate a Chat instance as $model and later another instance as $gen_set. What you should be doing is binding the first one, and using the form class getData method to later return the instance you bound to it, along with the values you gave it in the setData method. There's no need for any transformations from object to array and back again.
Here's how it should look ...
public function indexAction()
{
$form = new ChatForm();
// bind the model
$model= new Chat();
$form->bind($model);
$form->get('submit')->setValue('Save');
$request = $this->getRequest();
if ($request->isPost()) {
$form->setInputFilter($gen_set->getInputFilter());
// set data from POST as properties of the bound model ...
$form->setData($request->getPost());
if ($form->isValid()) {
// get the bound model instance with the POSTed values
// ($gen_set is now the original $model object instance bound above)
$gen_set = $form->getData();
// and save it
$this->getChatTable()->saveChat($gen_set);
// Redirect to list of albums
return $this->redirect()->toRoute('chat');
}
}
return array('form' => $form);
}
Controller Code -
<?php
class ChatController extends AbstractActionController {
protected $chatTable;
public function indexAction() {
$model = $this->getChatTable()->fetchLastChat();
if($model === null || $model->count() == 0)
$model = new Chat();
//Now if no record exists in the database then $model will be empty
//Else $model will contain data of last record.
$form = new ChatForm();
$form->bind($model);
$form->get('submit')->setValue('Save');
$request = $this->getRequest();
if ($request->isPost()) {
$gen_set = new Chat();
$form->setInputFilter($gen_set->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$gen_set->exchangeArray($form->getData());
$this->getChatTable()->saveChat($gen_set);
}
}
return array('form' => $form);
}
public function getChatTable() {
if (!$this->chatTable) {
$sm = $this->getServiceLocator();
$this->chatTable = $sm->get('Chat\Model\ChatTable');
}
return $this->chatTable;
}
}
ChatTable Class Code -
<?php
//Other use statements
use Zend\Db\Sql\Select;
class ChatTable {
protected $tableGateway;
public function __construct(TableGateway $tableGateway) {
$this->tableGateway = $tableGateway;
}
public function fetchAll() {
$resultSet = $this->tableGateway->select();
return $resultSet;
}
public function fetchLastChat() {
$select = new Select('TABLE_NAME'); //Change the tablename accordingly
$select->order('PRIMARY_KEY DESC'); //Set the Primary Key of the table
$select->limit(1);
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet->current();
}
//Rest of the Code ....
Please take the idea from the above code.

Resources