How can I solve the error in zendframework - zend-framework

I have got an error in zf3:
Error
C:\xampp\htdocs\zf3\module\Application\view\application\index\contact.phtml:21
Message:
Call to a member function prepare() on string
<?php
// within a view script
$form = $this->form;
//var_dump($form);
$form->prepare();
// Assuming the "contact/process" route exists...
$form->setAttribute('action', $this->url('process'));
// Set the method attribute for the form
$form->setAttribute('method', 'post');
// Get the form label plugin
$formLabel=$this->plugin ('formLabel');
// Render the opening tag
echo $this->form()->openTag($form);
?>

You did not post the controller action code but it is possible to say for sure that you are assigning the form property in the view model with a string instead of a Zend\Form instance.
Just check the "form" property within the returned view model.

Related

passing two tableadaptercolletions to view

I'm still trying to get as "hierarchical" view the recordssets of a second tableadapter collection.
In my controlleraction I passed a second argument to the view:
return new ViewModel([
'projects' => $this->projectTable->fetchAll(),
'dcls' => $this->table->fetchAll()
]);
In my view I thought I could grab the second collection as I did with the first:
foreach ($projects as $project) :
?>
<tr>
<td><?= $project['Projectname']?></td>
<td><?= $project['ProjectShortcut']?></td>
<td><?= $project['ProjectCiNumber']?></td>
<td><?= $project['Unitname']?></td>
<td><?= $project['UnitShortcut']?></td>
<td><?= $project['UnitCiNumber']?></td>
<td>
Edit
Delete
</td>
<?php foreach ($dcls->getImportunit($project['UnitID']) as $dcl) : ?>
<td><?= $dcl['Importdate']?></td>
<?php endforeach; ?>
<?php endforeach; ?>
But that doesn't work, I have some understanding issues.
if I try $dcls->getImportunit($project['UnitID']) as $dcl
then I get an error
Call to undefined method Zend\Db\ResultSet\ResultSet::getImportunit()
The method is placed in my model and it is public.
If I call just to try: <?php foreach ($dcls as $dcl) :
<td><?= $dcl['Importdate']?></td>
<?php endforeach; ?>
I get an error
Cannot use object of type Import\Model\Import as array
Interesting I used the same syntax like for projects?
If I use as an object attribut :
<?php foreach ($dcls as $dcl) :
<td><?= $dcl->Importdate?></td>
<?php endforeach; ?>
I get an error
This result is a forward only result set, calling rewind() after moving forward is not supported
This one makes sense for, I just tried different possibilies to get a clue if my dcl Records are usable in my view.
So I have two questions. why can't I grad the columns as an error like I have done with projects.
And why can't I use my method? It seems like the collection dcls is not properly passed.
So besides the little understanding issues my target shall be to scroll through the second collection (dcl) while using a parameter of the first collection (project)
EDIT1: following the suggestions from jobaer
Here first my new code:
Controller/indexAction
$dcls = $this->table->fetchAll();
// make an array for dcl
$secondCollection = array($dcls);
foreach ($dcls as $dcl) {
// if this is a resultset pass into view as you need
$importUnits = $dcl->getImportunit($project['UnitID']);
$secondCollection['importdate'] = $dcl->importdate;
$secondCollection['DCL_Path'] = $dcl->DCL_Path;
}
// pass $secondCollection via model
return new ViewModel([
'projects' => $this->projectTable->fetchAll(),
'dcls' => $secondCollection,
]);
Question: How could this work as how I understand the view gets every recordset of projects and if I here try to get the secondCollection related to UnitID, how can it work in the view? For my understanding the passing to the view is executed only once if I call the route, isn't it? or am I wrong in this case?
This one $importUnits = $dcl->getImportunit($project['UnitID']); in this snipped might have no effect?
Call to undefined method Zend\Db\ResultSet\ResultSet::getImportunit()
This is you are getting because you are not calling that method in a way that should not be.
Cannot use object of type Import\Model\Import as array
You cant call an object as array unless it is implicitly defined to be called as an array inside that class you are calling on.
This result is a forward only result set, calling rewind() after moving forward is not supported
You are getting this because, generally you cant loop over over again for the result set you are returning if you do not rewind the internal pointer to the beginning, this result set uses SPL Iterator.
So to meet this issue you can use buffer() method with the result set before returning it.
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
$resultSet->buffer(); // This is the point here
return $resultSet ;
}
Buffering is a feature of Zend\Db\ResultSet\ResultSet, which you can use to wrap a driver result.
Edit:
Whatever is related to model, you must do that in the model. As you are coming across loop problem with the result sets, you do the trick with the help of the model. What this means is to create an array from the result set in your controller method and then pass it to the view.
For example, you are doing so as the following in the view to fulfill your needs.
foreach ($projects as $project) :
// here you are looping for project
foreach ($dcls as $dcl) :
// Here you want to loop for dcl
endforeach;
endforeach;
But for the above described reason you cant use loop inside another loop.
'projects' => $this->projectTable->fetchAll(),
'dcls' => $this->table->fetchAll()
As you know $projects and $dcls return resultsets. That's why I told you to make arrays from those resultsets in the controller methods.
You already know what to display from $projects and $dcls. So make arrays from resultsets as below
$secondCollection = array();
foreach ($dcls as $dcl) {
$secondCollection['importdate'] = $dcl->importdate;
$secondCollection['DCL_Path'] = $dcl->DCL_Path;
}
Do the same technic for others if you need.
Now if you need any resultset by specific ID or NAME then you should process the thing in your controller method using model's method help. For example
$projects = $this->projectTable->getProjectByUnitId($unitId);
Now you know $projects is also a resultset, so you can make it an array as above.
Then pass all of the arrays made from different resultsets in the view...
return new ViewModel([
'array_name1' => $array_name1,
'array_name_2' => $array_name_2,
]);
Hope this would help you!

Zend Framework View Helper - how to get it to work

I'm trying to get started with Zend Framework , followed the quickstart project and am trying to start a new module of my own.
Am trying to implement view helpers and I keep getting the following message:
Message: Method formDate does not exist
Last entry at the stack trace:
0 D:\work\quickstart_zend\application\views\scripts\users\register.phtml(38): Zend_Form_Element->__call('formDate', Array)
I have the following file structure:
quickstart_zend
+ application
+ configs
+ controllers
[...]
+ views
+ helpers
+ scripts
[...]
+ library
+ Application
+ Form
+ Element
Date.php
+ View
+ Helper
FormDate.php
+ public
I have added in my public/Bootstrap.php this method:
protected function _initActionHelpers()
{
Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH.'/../library/Application/View/Helper', 'Application_View_Helper');
Zend_Controller_Action_HelperBroker::addPrefix('Application_View_Helper');
}
I have also added in my application.ini:
autoloaderNamespaces[] = "Application"
resources.view.helperPath.Application_View_Helper = APPLICATION_PATH "/../library/Application/View/Helper/"
And i have seen a version and also have tried with resources.view.helperPath.Application_View_Helper_, nothing seems to get it to work.
Of course, i have a Users.php form where i create a 'date' element:
// Add a dateOfBirth element
$element = new Application_Form_Element_Date('dateOfBirth');
$this->addElement($element);
Of course, i have a Users.php form where i create a 'date' element:
// Add a dateOfBirth element
$element = new Application_Form_Element_Date('dateOfBirth');
$this->addElement($element);
And in my view script, where the errors shows up:
<? echo $form->dateOfBirth->formDate() ?>
What am i missing to get it to work? :-( i've spent a day so far looking for solutions
You are receiving this error because there is no such method in Zend_Form_Element. I think you are trying to use your view helper to display in some way this form element, but if this is the case it is better to use form decorators. You can use the standard decorators or you can create a custom one. Check the documentation for more info - http://framework.zend.com/manual/en/zend.form.decorators.html
to properly use your view helper on that data you would use it like:
In your view (.phtml)
//a view helper should act on a piece of data and return something
//so I assume your formDate() helper takes a date value and reformats it.
<?php echo $this->formDate($this->form->dateOfBirth) ?>
assuming you assigned your form to the view in your controller using the standard:
$this->view->form = $form;

subform within a subform

I'm working on a model using Zend Form. I have a subform called $product_item. I would like to add multiple instances of it to another subform called $items. How would I go about doing that? I'm not finding the Zend reference guide particularly helpful.
You can just add sub-forms to sub-forms:-
$form = new Application_Form_Test();
$subForm1 = new Application_Form_TestSubForm();
$subForm2 = new Application_Form_TestSubForm();
$subForm1->addSubForm($subForm2, 'sub2');
$form->addSubForm($subForm1, 'sub1');
$this->view->form = $form;
On submission the subform values will be available in arrays in the $_POST array. $value=$_POST['sub1']['sub2']['name'] for example.
http://framework.zend.com/manual/en/zend.form.forms.html#zend.form.forms.subforms
To print or access elements in sub forms you have several options:-
If $subForm1 has an element declared thus:-
$email = new Zend_Form_Element_Text('email');
Then the email field can be rendered in the view like this:-
<?php echo $this->element->sub1->email; ?>
Remember that the elements are referenced by their names not by the variables you use to declare them.
Also, remember that $this->element is referencing an instance of Zend_Form so you have all of those methods available. That means you can do this:-
<?php
$form = $this->element;
$formElements = $form->getElements();
?>

Zend_Paginator with result of Zend_Db_Table_Abstract

i have many class in model directory that those are extend of Zend_Db_Table_Abstract.
but i need use of zend_paginator and this need to result of Zend_Db_Select !!
so when i use of this code (productCat is a model class)
$productCat = new ProductCat();
$rows = $productCat->FetchOrderByPriority();
// Get a Paginator object using Zend_Paginator's built-in factory.
$paginator = Zend_Paginator::factory($rows);
$this->view->paginator = $paginator;
it don`t work!
it show me this error :
Catchable fatal error: Object of class Zend_Db_Table_Row could not be converted to string in
this is my view code :
<ul><?php foreach ($this->paginator as $item): ?>
<li><?php echo $item; ?></li><?php endforeach; ?></ul>
is there any idea?
Pagination definitely works. The problem is in your view where you're trying to echo $item.
And it obviously doesn't work since Zend_Paginator::factory($rows) has returned a rowset; so when you're iterating over $paginator object, you're getting objects of Zend_Db_Table_Row type, and you simply cannot echo them.
What you're trying to do, I believe, is to echo a particular property of the item object, something like:
echo $item->name;

Zend Avoid submit button value in GET parameters in url

I have a form, created with Zend_Form, with method = GET used for searching records with elements as below:
[form]
user name [input type="text" name="uname"]
[input type="submit" value="Search" name="search"]
[/form]
After form is submitted all the GET parameters along with submit button value are appearing in the url.
http://mysite.com/users/search?uname=abc&search=Search
How to avoid submit button value appearing in the url? is custom routing the solution ?
When you create your element, you can simply remove the name attribute that was automatically set at creation
$submit = new Zend_Form_Element_Submit('search')->setAttrib('name', '');
Or inside a Zend_Form
// Input element
$submit = $this->createElement('submit', 'search')->setAttrib('name', '');
// Or Button element
$submit = $this->createElement('button', 'search')->setAttribs(array
(
'name' => '', 'type' => 'submit',
);
When a form gets submitted, all of its elements with their names and values become a part of a GET / POST - query.
So, if you don't want an element to appear in your GET - query, all you need to do is to create this element without a name. That's probably not the best approach, but since we're talking about the 'submit' element, I guess it doesn't matter that much.
Looking at Zend_View_Helper_FormSubmit helper, you can see that it's creating the 'submit' element and setting its name. So, the possible solution would be to create your own view helper and use it for rendering the 'submit' element instead of the default helper.
You can set a custom helper with
$element->setAttribs( array('helper' => 'My_Helper_FormSubmit') );
Then build your own form element class and remove the name attribute from the element with preg_replace. The beauty of it is, it will not interfere with the other decorators.
So the something like this:
class My_Button extends Zend_Form_Element_Submit
{
public function render()
{
return preg_replace('/(<input.*?)( name="[^"]*")([^>]*>)/', "$1$3", parent::render(), 1);
}
}
You can remove name attribute for submit button in javascript.
jQuery example:
$('input[name="submit"]').removeAttr('name');
In the controller that represents the form's action, redirect to another (or the same controller) only including the relevant params.
Pseudocode:
$params = $this->getRequest()->getParams();
if isset($params['search'])
unset($params['search']);
return $this->_helper->Redirector->setGotoSimple('thisAction', null, null, $params);
handle form here
This is basically the same idea as Post/Redirect/Get except that you want to modify the request (by unsetting a parameter) in between the different stages, instead of doing something persistent (the images on that Wiki-page shows inserting data into a database).
If I were you, I would leave it in. IMO it's not worth an extra request to the webserver.