passing two tableadaptercolletions to view - zend-framework

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!

Related

How can I solve the error in zendframework

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.

Zend_Session not carrying values across to view

I have setup in my MVC site a Session variable to carry ids to be used on any subsequent pages.
In my controller, var_dumping the session shows its there with the correct values but when I pass said values to the view and trying to echo them there, it comes up blank.
Any pointers as to whats going on to cause them to not appear.
Please note, the view is a partial view, not the main one.
Bootstrap session related code:
protected function _initSession(){
Zend_Session::start();
$SessAuto2Auto = new Zend_Session_Namespace('SessAuto2Auto');
$SessAuto2Auto->cityIds = "1,2,3"; // Hard code values for testing purposes
$SessAuto2Auto->IndustryIds = "3,4"; // Hard code values for testing purposes
}
Controller related code : ProductController.php
public function indexAction()
{
// .. Unrelated code removed for brevity
$response = $this->getResponse();
$response->insert('sidebar', $this->view->render('sidebar.phtml'));
// This code is dumping the values correctly
echo('<pre>');
var_dump($this->sessionAuto2Auto);
echo('</pre>');
// .. Unrelated code removed for brevity
$this->view->filterCity = $this->sessionAuto2Auto['cityIds'];
$this->view->filterIndustryIds = $this->sessionAuto2Auto['IndustryIds'];
}
View partial : sidebar.phtml
<?php
// This code does NOT show the value, comes up blank
echo($this->filterCity);
?>
If you are calling sidebar.phtml using the partial helper, partials have their own variable scope, they can only access variables which are passed in to them. You need to either include your session variables in your partial helper call:
echo $this->partial('sidebar.phtml', array(
'filterCity' => $this->filterCity,
'filterIndustryIds' => $this->filterIndustryIds
)
or use render instead (which uses the same scope as the other view scripts):
<?=$this->render('sidebar.phtml')?>

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;

$_post in Kohana controller

i was wondering if i can get a variable with $_post, in a kohana controller if the controller doesn't 'control' a form.
So, if i insert in a view something like:
<form name="ordering" id="ordering" method="post" action="">
<input type="hidden" id="ordering" value="0">
<select id="ordering" name="ordering">
....
in the controller i put :
$ordering = $_POST['ordering'];
but gives me an error
or
if ($this->request->method == 'POST') {
$ordering = $_POST['ordering'];
}
but in this case it never gets there(at this bunch of code).
so my question is: how can i retrieve in a controller a $_post variable if the controller doesn't handle only a form? thank you!
Kohana 3.0 :
if ($_POST)
{
$ordering = arr::get($_POST, 'ordering');
...
Kohana 3.1 :
if ($ordering = $this->request->post('ordering')) // or just $this->request->post()
{
...
PHP will issue a notice if you attempt to access an undefined array element.
So if the "ordering" form was never submitted, attempting to access $_POST['ordering'] will result in
PHP Notice: Undefined index: ordering in ...
Kohana's Arr class provides a nice helper method to get around this.
If you call
$ordering = Arr::get($_POST, 'ordering', 0);
It will retrieve the ordering value from the post variable. If $_POST['ordering'] is not set, it will return the third parameter instead. You can then try if ($ordering) ...
This is useful for $_POST/$_GET arrays, or any function that accepts arrays – it allows you to concisely specify a fallback behavior rather than having to test with isset.
One of the advantages of Kohana is that the source code tends to be very clean and easy to understand (which is nice because documentation is sparse.) I'd suggest you take a check out the Kohana_Arr class and look at the methods available!
ID's are unique! Use class insted or different IDs.
Your form and the select both have got ordering, change one to something else, like:
<form name="ordering_form" id="ordering_form" method="post" action="">
<input type="hidden" id="ordering_input" value="0">
<select id="ordering" name="ordering">
...
</select>
</form>
and in your Kohana Controller:
if( isset( $_POST['ordering'] ) )
{
$ordering = $_POST['ordering'];
}
this should work, because i cant find any other error

Display Zend_Form form errors in ViewScript

I'm trying to display all form errors before the form using a ViewScript. Here is the code that I'm currently trying to use within my ViewScript:
<div class="errors">
<?php echo $this->formErrors($this->element->getMessages()); ?>
</div>
This call gives me an error message:
Warning: htmlspecialchars() expects parameter 1 to be string, array given
I've seen this same code suggested other places but its not working for me. If I print out $this->element->getMessages() I do see the error messages as the following:
Array ( [myField] => Array ( [isEmpty] => Value is required and can't be empty ) )
Any ideas?
The getMessages() returns an array of form element names as keys which each contain an array of errors for that element. So basically instead of handing the formErrors view helper:
Array ( [isEmpty] => Value is required and can't be empty )
You are handing it:
Array ( [myField] => Array ( [isEmpty] => Value is required and can't be empty ) )
You would want to do something like this instead:
$arrMessages = $this->myForm->getMessages();
foreach($arrMessages as $field => $arrErrors) {
echo sprintf(
'<ul><li>%s</li>%s</ul>',
$this->myForm->getElement($field)->getLabel(),
$this->formErrors($arrErrors)
);
}
As Mark points out in his answer, the getMessages() returns an array of form element names as keys which each contain an array of errors for that element; and his solution is:
$arrMessages = $this->myForm->getMessages();
foreach($arrMessages as $field => $arrErrors) {
echo sprintf(
'<ul><li>%s</li>%s</ul>',
$this->myForm->getElement($field)->getLabel(),
$this->formErrors($arrErrors)
);
}
This works, as long as getMessages() results in a two-dimensional array. However, if the form is based on relational data sets generated by Doctrine (or some other plugin), the error message associated with a field might also be an array and the above code will crash because it treats $arrErrors as a string when it turns out to be an array.
To capture the error messages if there's a second data set we could introduce a foreach statement nested inside the first foreach statement, but that won't work when getMessages() results in a two-dimensional array; nor does it work if the data sets are more than two-deep.
In a relational data scenario where we don't know how deep the error message comes from, a scalable solution is
$arrMessages = $this->myForm->getMessages();
print_r ($arrMessages);