I am creating a rest Module for album module of zf2
My Code Snippet for create method :
public function create($data) {
$form=new AlbumForm();
$album = new Album();
$form->setInputFilter($album->getInputFilter());
$form->setData($data);
if ($form->isValid()) {
$album->exchangeArray($form->getData());
$id = $this->getAlbumTable()->saveAlbum($album);
return new JsonModel(array(
'data' => $this->get($id),
));
}
All the functionalities like update,select all,delete are working properly but insertion is not working.
I have selected post method through my Advanced rest client application and passing arguments like title=some&artist=someone its not validating form.
The form having values like
id Auto-incremented,
artist varchar,
title varchar,
Please Help for this problem
just got the answer that you have to add this lines to the top of the create method.
if (empty($data['id'])) $data['id'] = 0;
Its working properly.
Related
I am building a Symfony data transformer class called EventDataMapper. It handles two fields: A TextType field called My mapDataToForms() definition looks like this:
public function mapDataToForms($data, $forms)
{
$existingTitle = $data->getTitle();
$existingAttendees = $data->getAttendees();
$this->propertyPathMapper->mapDataToForms($data, $forms);
foreach ($forms as $index => $form) {
if ($form->getName() === 'title' && !is_null($existingTitle)) {
$form->setData($existingTitle);
}
if ($form->getName() === 'attendees' && !is_null($existingAttendees)) {
$form->setData($existingAttendees);
}
}
}
The problem is that I'm setting data before validation runs, so if I submit a form with a non-numeric string in the "attendees" field, I get an ugly TransformationFailedException ('Unable to transform value for property path "attendees": Expected a numeric'). And if I try to do a check for whether my field is valid by adding a call to $form->isValid() in the line before I call $form->setData(), I get a LogicException. ('Cannot check if an unsubmitted form is valid. Call Form::isSubmitted() before Form::isValid().')
Is there any way for my to preemptively call a validator on this specific field from within my DataMapper?
(Yes, this can be somewhat prevented with frontend logic. But I don't want to rely too much on that.)
Closing the loop on this. Here's what we did.
A colleague made a new form type corresponding to a new adapter class that wraps our two previous classes, providing a uniform set of wrapper methods for interacting with them.
We passed Symfony's validator service into our new form type using the constructor.
In that form type, we're using $builder->addEventListener() to add a callback/listener on the POST_SUBMIT event. Here's the callback:
function(FormEvent $event): void {
$adapter = $event->getData();
$form = $event->getForm();
$errors = $adapter->propagate($this->validator);
foreach ($errors as $error) {
$formError = new FormError($error->getMessage());
$targetPath = self::mapPropertyPath($error->getPropertyPath());
$target = $targetPath !== null ? $form->get($targetPath) : $form;
$target->addError($formError);
}
}
The adapter, in turn, has some logic that does various translations of data into a form that can be used in our legacy classes, followed by this:
return $validator->validate($this->legacyObject);
This works well for us. I hope it helps somebody else out too.
We are using the ZF2 forms as a standalone plugin inside another PHP application. This is working fine, except I'm not able to use some custom view helpers. The ServiceManager (?) doesn't know where my helpers are located and crashes with a fatal error.
Is there a way to register some custom view helpers without a modules.config.php? I haven't found a way to pass an array/config to the HelperConfig below. As a ZF2 rookie I'm a bit lost here.
$form = new \My\Custom\Form\ContactForm();
$renderer = new \Zend\View\Renderer\PhpRenderer();
$config = new \Zend\Form\View\HelperConfig();
$config->configureServiceManager($renderer->getHelperPluginManager());
if(isset($_POST['submit'])) {
$form->setData($_POST);
if($form->isValid()) {
$data = (OBJECT) $form->getData();
// ...
} else {
return $form->render($renderer); // Inside the render() method we use the form-view-helpers to render the form.
}
} else {
return $form->render($renderer);
}
I have also tried to use the HelperPluginManager (Btw. whats the difference between these two?). But there isn't a method to pass a config-array either.
$renderer = new \Zend\View\Renderer\PhpRenderer();
$plugins = $renderer->getHelperPluginManager();
$renderer->setHelperPluginManager($plugins);
i am trying to insert new entity using PHP client library into datastore, i am using datastore_connect.php file from this example, https://github.com/amygdala/appengine_php_datastore_example
I want to insert entity with auto id, not the name. I see that there is function setId(), but i dont know how to generate proper id. Whats the best practice in doing so?
Thanks
function createKeyForTestItem () {
$path = new Google_Service_Datastore_KeyPathElement();
$path->setKind("testkind");
$path->setName("testkeyname");
//$path->setId(??)
$key = new Google_Service_Datastore_Key();
$key->setPath([$path]);
return $key;
}
You can have Cloud Datastore generate the ID for you by populating the insertAutoId field on the mutation instead of the upsert field.
Here's a code snippet (adapted from the datastore_connect.php file you posted):
function create_key() {
$path = new Google_Service_Datastore_KeyPathElement();
$path->setKind("testkind");
// Neither name nor ID is set.
$key = new Google_Service_Datastore_Key();
$key->setPath([$path]);
return $key;
}
function create_entity() {
$entity = new Google_Service_Datastore_Entity();
$entity->setKey(create_key());
// Add properties...
return $entity;
}
function create_commit_request() {
$entity = create_entity();
$mutation = new Google_Service_Datastore_Mutation();
$mutation->setInsertAutoId([$entity]); // Causes ID to be allocated.
$req = new Google_Service_Datastore_CommitRequest();
$req->setMode('NON_TRANSACTIONAL');
$req->setMutation($mutation);
return $req;
}
If you're looking for a PHP library to take away most of the headache of Cloud Datastore, you could try my new library, which sits on top of the official google-api-php-client:
https://github.com/tomwalder/php-gds
And here's a sample code snippet to create an Entity with an auto-generated ID
$obj_book = new GDS\Entity();
$obj_book->title = 'Romeo and Juliet';
$obj_book->author = 'William Shakespeare';
$obj_book->isbn = '1840224339';
// Write it to Datastore
$obj_book_store->upsert($obj_book);
More code snippets and documentation on GitHub.
I am trying to create a form to create a new product.
In my Controller I have the follwoing code:
public function newAction() {
$repo = $this->getEntityManager()->getRepository('Swap\Entity\Product');
$builder = new AnnotationBuilder($this->getEntityManager());
$form = $builder->createForm($repo);
$config = $this->getModuleConfig();
if (isset($config['swap_form_extra'])) {
foreach ($config['swap_form_extra'] as $field) {
$form->add($field);
}
}
$form->setHydrator(new DoctrineHydrator($this->getEntityManager(), 'Swap\Entity\Product'));
$form->bind($repo);
return new ViewModel(array('form' => $form));
}
Now this gives me the follwing error:
Class "Swap\EntityRepository\Product" sub class of "Doctrine\ORM\EntityRepository" is not a valid entity or mapped super class.
I am not sure if this has anything to do with it: But when you want to edit an object in a form you can do:
$repo = $this->getEntityManager()->getRepository('Swap\Entity\Product');
$id = (int) $this->getEvent()->getRouteMatch()->getParam('id', '0');
$product = $repo->find(1);
$productNames = $this->getEntityManager()->getRepository('Swap\Entity\ProductGroup')->findAll();
$product->SetProductGroup($productNames);
$builder = new AnnotationBuilder($this->getEntityManager());
$form = $builder->createForm($product);
But not sure how to get the product in a form to create a new entity.
Any suggestions?
Forms are build around entities, not with repositories. There is a clear distinction between them in Doctrine: entities are objects that hold state, that are related to database tables and where you can create new ones, update existing ones and remove ones for. Repositories are helper classes. They help you to find entities. Usually you find one by id or find them all, but repositories help you also to find one or multiple entities via a specific property.
That said, the form builder requires entities. In both the edit as the new action, you want to build based on the entity. In the editAction, you do this (pseudo):
$product = findMyProductEntity();
$form = $builder->createForm($product);
In the newAction, you do this (pseudo):
$repository = findMyProductRepository();
$form = $builder->buildForm($repository);
In this case, you also need to inject the entity and not the repository. How? Simply, just use new:
public function newAction()
{
$product = new Swap\Entity\Product;
$builder = new AnnotationBuilder($this->getEntityManager());
$form = $builder->createForm($product);
// Rest of your code
}
You told it to build the form from an entity repository instance, and not an entity itself.
$form = $builder->createForm($repo); // $repo is not an entity!
I am learning Zend Framework (2.0), and I'm stuck at creating forms.
Here is the code I used (Inside a controller):
use Zend\Form\Element;
use Zend\Form\Form;
...
public function indexAction()
{
$element = new Element\Text('name');
//Nothing else
}
It always gives a 505 error, but if I comment out the line "$element ..." then it works (so the problem must be there).
Can someone point out what I have overlooked?
Also, as I see it, there are too many ways to create a form. For example, I have tried:
private function getSignupForm() {
//Create Form
$form = new Zend_Form();
$form->setAction('success');
$form->setMethod('post');
$form->setAttrib('sitename', 'mysite');
//Add Elements
//Create Username Field.
$form->addElement('text', 'username');
$usernameElement = $form->getElement('username');
$usernameElement->setLabel('Username:');
$usernameElement->setOrder(1)->setRequired(true);
return $form;
}
This way, it worked, but that is not the way the tutorial says link. So in which way should I should write it?
Thanks.