ZEND Controllers -- How to call an action from a different controller - zend-framework

I want to display a page that has 2 forms. The top form is unique to this page, but the bottom form can already be rendered from a different controller. I'm using the following code to call the action of the other form but keep getting this error:
"Message: id is not specified"
#0 .../library/Zend/Controller/Router/Rewrite.php(441): Zend_Controller_Router_Route->assemble(Array, true, true)
My code:
First controller:
abc_Controller
public function someAction()
{
$this->_helper->actionStack('other','xyz');
}
Second controller:
xyz_Controller
public function otherAction()
{
// code
}
Desired results:
When calling /abc/some, i want to render the "some" content along with the xyz/other content. I think I followed the doc correctly (http://framework.zend.com/manual/en/zend.controller.actionhelpers.html) but can't find any help on why that error occurs. When I trace the code (using XDebug), the xyz/other action completes ok but when the abc/some action reaches the end, the error is thrown somewhere during the dispatch or the routing.
Any help is greatly appreciated.

You can accomplish this in your phtml for your someAction. So in some.phtml put <?php echo $this->action('other','xyz');?> this will render the form found in the otherAction of XyzController

The urge to do something like this is an indication you're going about it in totally the wrong way. If you have the urge to re-use content, it should likely belong in the model. If it is truly controller code it should be encapsulated by an action controller plugin

In phtml file u can use the $this->action() ; to render the page and that response would be added to current response ..
The syntax for action is as follows::
public function action($action, $controller, $module = null, array $params = array())

You can create new object with second controller and call its method (but it`s not the best way).
You can extend your first controller with the second one and call $this->methodFromSecond(); - it will render second form too with its template.
BTW - what type of code you want to execute in both controllers ?

Just an update. The error had absolutely nothing to do with how the action was being called from the second controller. It turns out that in the layout of the second controller, there was a separate phtml call that was throwing the error (layout/abc.phtml):
<?php echo $this->render('userNavigation.phtml') ?>
line of error:
echo $this->navigation()->menu()->renderMenu(...)
I'll be debugging this separately as not to muddy this thread.
Thanks to Akeem and hsz for the prompt response. I learned from your responses.
To summarize, there were 3 different ways to call an action from an external controller:
Instantiate the second controller from the first controller and call the action.
Use $this->_helper->actionStack
In the phtml of the first controller, action('other','xyz');?> (as Akeem pointed out above)
Hope this helps other Zend noobs out there.

Hm I can't find and idea why you need to use diffrent Controlers for one view. Better practise is to have all in one Controller. I using this like in this example
DemoController extends My_Controller_Action() {
....
public function indexAction() {
$this->view->oForm = new Form_Registration();
}
}
My_Controller_Action extends Zend_Controller_Action() {
public function init() {
parent::init();
$this->setGeneralStuf();
}
public function setGeneralStuf() {
$this->view->oLoginForm = new Form_Login();
}
}

This kind of route definition:
routes.abc.route = "abc/buy/:id/*"
routes.abc.defaults.controller = "deal"
routes.abc.defaults.action = "buy"
routes.abc.reqs.id = "\d+"
requires a parameter in order to function. You can do this with actionStack but you can also specify a default id in case that none is provided:
$this->_helper->actionStack('Action',
'Controller',
'Route',
array('param' => 'value')
);
routes.abc.defaults.id = "1"

For Me this worked like a charm
class abcController extends Zend_Controller_Action
{
public function dashBoardAction()
{
$this->_helper->actionStack('list-User-Data', 'xyz');
}
}
class XyzController extends Zend_Controller_Action {
public function listUserDataAction()
{
$data = array('red','green','blue','yellow');
return $data;
}
}

Related

ZF Render an action and get the html in another action

What I want to do with Zend Framework is to render the action Y from the action X and to obtain the html:
Example:
public xAction(){
$html = some_function_that_render_action('y');
}
public yAction(){
$this->view->somedata = 'sometext';
}
where the y view is something like:
<h1>Y View</h1>
<p>Somedata = <?php echo $this->somedata ?></p>
I fount the action helper, but I cannot use it from a controller. How can I solve it?
It is possible?
Here is one possible way to do what you want.
public function xAction()
{
$this->_helper
->viewRenderer
->setRender('y'); // render y.phtml viewscript instead of x.phtml
$this->yAction();
// now yAction has been called and zend view will render y.phtml instead of x.phtml
}
public function yAction()
{
// action code here that assigns to the view.
}
Instead of using the ViewRenderer to set the view script to use, you could also call yAction as I showed above, but get the html by calling $html = $this->view->render('controller/y.phtml');
See also the ActionStack helper.
You can use the Action View Helper from the controller
public function xAction()
{
$html = $this->view->action(
'y',
$this->getRequest()->getControllerName(),
null,
$this->getRequest()->getParams()
);
}
public function yAction()
{
// action code here that assigns to the view.
}
It's not very beautiful but it works well and you don't have to use $view->setScriptPath($this->view->getScriptPaths());
This helper creates a new Zend_Controller_Request for yAction(), so you can give your own parameters as 4th argument or use $this->getRequest()->getParams() to spread the request parameters of xAction().
http://framework.zend.com/manual/1.12/en/zend.view.helpers.html#zend.view.helpers.initial.action
Finally I found this "solution", it's not what I want to do, but it works, if someone found the real solution, please answer here.
public function xAction(){
$data = $this->_prepareData();
$view = new Zend_View();
$view->somedata = $data;
$view->setScriptPath($this->view->getScriptPaths());
$html = $view->render('controller/y.phtml');
}

Zend_Form::setAction() uses current controller in Zend Framework

I declare a publisher controller:
class PublisherController extends Zend_Controller_Action {
public function indexAction()
{
$this->view->form = $this->_getForm();
$this->render('form');
}
public function dataPostAction()
{
//#TODO
}
protected function _getForm()
{
$form = new Zend_Form();
$form->setAction('publisher/dataPost')//Here, I DO NOT want to do: setAction('*/dataPost') with `*` means current controller.
->setMethod('post')
->setAttrib('id','publisher-form');
$form->addElement('text', 'name',
array(
'label'=>'First Name',
'class'=>'required'
)
);
$form->addElement('submit', 'Save');
return $form;
}
}
Look at the line: $form->setAction('publisher/dataPost')
This means that I want to set the action for the form after submitting is dataPost of publisher controller.
Now I want do do $form->setAction('*/dataPost') with the * means current controller. Because current controller is publisher too.
But it does not work, or am I missing something? Can you tell me what is correct?
publisher/dataPost is much easier to type than $form->setAction($this->getRequest()->getControllerName().'/dataPost'), so I would recommend you stick with what you are already doing.
I don't normally use it in the zend form its self, but preferably in the actions view when calling the form using this code.
<?php echo $this->setAction(url(/.../.../) );?>
This is to echo the form you using in your action and also to set its action. So in short just stick to what you have or use sam's method but I think its better if you have something ACCURATE and working.
I decide the comment of #Sam is the best answer for me.
Using the statement:
$form->setAction($this->getRequest()->getControllerName().'/dataPost')
UPDATE
From this question, I know that: "DO NOT be complex", and some guys here is don't agree so much with the above solution. Now I got this too. But, for this answer, I believe that I SHOULD check and confirm what is correct.

Call Helpers From Zend_Form

I try this codes, but not works:
$this->getView()->translate("Name"); //not work
$this->_view->translate("Name"); //not work
$this->view->translate("Name"); //not work
First of all, Zend_View is not injected into Zend_Form. So when you call $this->view or $this->_view it wont work, because there is nothing to return. Why getHelper() works? Because it fetches view via helper broker (and if your are using viewRenderer). Look below at the code:
// Zend/Form.php
public function getView()
{
if (null === $this->_view) {
require_once 'Zend/Controller/Action/HelperBroker.php';
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
$this->setView($viewRenderer->view);
}
return $this->_view;
}
This is reason why $this->_view->translate() works if you call getView() before, because it's stored as protected property.
According to this, that code should work perfectly and works for me:
class My_Form extends Zend_Form
{
public function init()
{
echo $this->getView()->translate('name'); //fires 'translate' view helper and translating value
//below will also work, because you have view now in _view: getView() fetched it.
echo $this->_view->translate("another thing");
}
}
BTW. If your using translate helper to translate labels or names of fields, you don't have to. Will be enough, if you set translator object as a static property of Zend_Form, best in your bootstrap:
Zend_Form::setDefaultTranslator($translator);
And from that moment all fields names and labels will be translated automatically.
I don't no why, but when I add this function to my form, it work:
public function init() {
$this->getView();
}
this line works:
$this->_view->translate("Name");
View is not injected into Zend_Form (don't ask me why, when it's required for rendering). You have to extend Zend_Form and inject view inside yourself. Other option is using FrontController->getInstance() > getStaticHelper > viewRenderer and recieve view from it.

Zend Framework: Get whole out output in postDispath while using Layout

I have a layout loader plugin which looks like this:
class Controller_Action_Helper_LayoutLoader extends Zend_Controller_Action_Helper_Abstract
{
public function preDispatch()
{
$config = Zend_Registry::get("config");
$module = $this->getRequest()->getModuleName();
if (isset($config->$module->resources->layout->layout) && !$this->getRequest()->format)
{
$layoutScript = $config->$module->resources->layout->layout;
$this->getActionController()->getHelper('layout')->setLayout($layoutScript);
}
}
}
In a controller plugin I then want to get the whole of the response like so
$this->getResponse()->getBody()
This however only returns the output from the action, not the output from the layout too.
How can I get the whole output, layout and action together?
Thanks!
I believe that Zend_Layout operates at postDispatch() with a high stack index. So, to get the content, you might need to do your access later, at dispatchLoopShutdown().

Zend_Form using subforms getValues() problem

I am building a form in Zend Framework 1.9 using subforms as well as Zend_JQuery being enabled on those forms. The form itself is fine and all the error checking etc is working as normal. But the issue I am having is that when I'm trying to retrieve the values in my controller, I'm receiving just the form entry for the last subform e.g.
My master form class (abbreviated for speed):
Master_Form extends Zend_Form
{
public function init()
{
ZendX_JQuery::enableForm($this);
$this->setAction('actioninhere')
...
->setAttrib('id', 'mainForm')
$sub_one = new Form_One();
$sub_one->setDecorators(... in here I add the jQuery as per the docs);
$this->addSubForm($sub_one, 'form-one');
$sub_two = new Form_Two();
$sub_two->setDecorators(... in here I add the jQuery as per the docs);
$this->addSubForm($sub_two, 'form-two');
}
}
So that all works as it should in the display and when I submit without filling in the required values, the correct errors are returned. However, in my controller I have this:
class My_Controller extends Zend_Controller_Action
{
public function createAction()
{
$request = $this->getRequest();
$form = new Master_Form();
if ($request->isPost()) {
if ($form->isValid($request->getPost()) {
// This is where I am having the problems
print_r($form->getValues());
}
}
}
}
When I submit this and it gets past isValid(), the $form->getValues() is only returning the elements from the second subform, not the entire form.
I recently ran into this problem. It seems to me that getValues is using array_merge, instead of array_merge_recursive, which does render to correct results. I submitted a bug report, but have not gotten any feedback on it yet.
I submitted a bug report (http://framework.zend.com/issues/browse/ZF-8078). Perhaps you want to vote on it?
I think that perhaps I must have been misunderstanding the way that the subforms work in Zend, and the code below helps me achieve what I wanted. None of my elements share names across subforms, but I guess this is why Zend_Form works this way.
In my controller I now have:
if($request->isPost()) {
if ($form->isValid($request->getPost()) {
$all_form_details = array();
foreach ($form->getSubForms() as $subform) {
$all_form_details = array_merge($all_form_details, $subform->getValues());
}
// Now I have one nice and tidy array to pass to my model. I know this
// could also be seen as model logic for a skinnier controller, but
// this is just to demonstrate it working.
print_r($all_form_details);
}
}
I have a same problem to get value from subforms I solve it with this but not my desire one
code:
in controller i get value with this code that 'rolesSubform' is my subform name
$this->_request->getParam ( 'rolesSubform' );
Encountered the same problem. Used post instead of getValues.
$post = $this->getRequest()->getPost();
There are times when getValues does not return the same values returned by $post.
Must be a getValues() bug.