ZendFramework Send variables from Controller to View (Best pactice) - zend-framework

I have been working in Zend Framework for a while and I am currently refactoring some parts of my code. One of the big thing I would like to eliminate is my abstract controller class which initiate a lot of variables which must be present in all my controller such as $success, $warning and $error. This part can be done in controller pluggins but what would be the best way to send these variables to the related view. Currently I am using a custom method in my abstract controller class which i call from within all my controllers.
protected function sendViewData(){
$this->view->success = $this->success;
$this->view->warning = $this->warning;
$this->view->error = $this->error;
}
which is then called in all the actions of all of my controllers throught
parent::sendViewData();
I was looking to automate this process through a plugin controller or anything better suited for this

You could set a postDisplatch method in your abstract controller to initialize the view data (See section "Pre- and Post-Dispatch Hooks").
That way, in each actions, you could initialize your $this->success, $this->warnning or $this->error variables, and it would be pass to the view after the action is executed.

The Best pactice is, define a base controller and let other controllers to extend this, instead of directly calling the Zend_Controller_Action method
// Your base controller file ApplicationController.php
class ApplicationController extends Zend_Controller_Action {
// method & variable here are available in all controllers
public function preDispatch() {
$this->view->success = $this->success;
$this->view->warning = $this->warning;
$this->view->error = $this->error;
}
}
Your other normal controllers would be like this
// IndexController.php
class IndexController extends ApplicationController {
}
Now these (success, warning & error) variable are available in all views/layout files, In ApplicationController.php you can also hold shared functionality of other controllers.

Related

Zend Framework - how to use in view script variables declared in other controller?

Zend Framework - how to use in view script variables declared in other controller?
Do I need to pass the variable to view in the controller again?
The short answer is yes!, you have to reassign the data to the view.
However there are options.
If this data is going to be used in many view scripts it may be appropriate to build a view helper or an action helper depending on your use case.
A simple View helper:
class Zend_View_Helper_Length extends Zend_View_Helper_Abstract
{
public function length($minutes)
{
$hours = floor($minutes / 60);
$minutes = $minutes % 60;
if ($hours > 0) {
$time = sprintf("%01d Hours %02d Minutes", $hours, $minutes);
} else {
$time = sprintf("%02d Minutes", $minutes);
}
return $time;
}
}
a simple action helper:
class My_Controller_Action_Helper_Login extends Zend_Controller_Action_Helper_Abstract
{
public function direct()
{
$form = new Application_Form_Login();
$form->setAction('/index/login');
return $form;
}
}
If your data is to be used in multiple actions a single controller you can set the data in the init() method:
public function init()
{
//initialize the flash messenger action helper to work in all actions
if ($this->_helper->FlashMessenger->hasMessages()) {
$this->view->messages = $this->_helper->FlashMessenger->getMessages();
}
}
If you simply need to save a piece of data for a short period of time you can save it to the registry or for a longer period you can use the session (I find this solution particularly useful).
These are just some of the more common ways to make different pieces of data available to the application. A more directed question would likely receive more directed answers.
ex: If you have 2 controllers :
Controller A : It has some variable and variable will be pass to the view A
Controller B : It has some variable and variable will be pass to the view B
The view B can't access to the variable of the controller A.
So if you want to use variables of controller A in view B you have to redeclared it in Controller B
If you have some 'core' view variables that you want to add to multiple view instances then you could conceivably have an additional layer of abstraction and declare your core view variables in there. For instance:
class myController extends Zend_Controller_Action
could become
class myController extends myCoreController
and
class mySecondController extends myCoreController
and
class myCoreController extends Zend_Controller_Action
In this way you can have your core variables available across controllers and maintain them all in one place.

Zend Framework - How can i share common code between some of a controller's actions?

To keep my controllers as DRY as possible i need to share some common code (a big chunk of code) between say 2 of my controller's actions and not all of them and i need access variables in this shared code in my actions.
For example:
class FirstController extends Zend_Controller_Action {
public function firstAction() {
//common code here: contains an array $columns
}
public function secondAction() {
//common code here: contains an array $columns also
}
//other actions
}
so how can I refactor this to put the common code in one place and be able to access $columns and in firstAction() and secondAction().
Thanks.
I don't recommend you to use a base controller. It's overkilling and heavy for such a small task. Since you want to share common code within one controller, use instead an action helper and a class attribute $columns that you can send as argument to your action helper.
Read more about action helpers here.
Action Helpers allow developers to inject runtime and/or on-demand
functionality into any Action Controllers that extend
Zend_Controller_Action. Action Helpers aim to minimize the necessity
to extend the abstract Action Controller in order to inject common
Action Controller functionality.
You can create new class and extend Zend_Controller_Action then extend your newly created class not Zend_Controller_Action
example:
class CommonactionsController extends Zend_Controller_Action {
public function firstAction() {
//common code here : contains an array $columns
}
public function secondAction() {
//common code here : contains an array $columns also
}
//other actions
}
and then:
class FirstController extends CommonactionsController {
// here you can use all your common actions...
}
second controller..
class SecondController extends CommonactionsController {
// here you can use all your common actions...
}
and so on...

In asp.net mvc 2 : how to access http post data inside constructor of any controller

My controller has abstract base controller. I want to access the form post data inside abstract base class constructor. How can we do that ?
public abstract class AppController : Controller
{
public AppController()
{
// request post data required here
}
}
public class ProductController : AppController
{
public ProductController() { }
}
Purpose : Updating second dropdown on change of first dropdown. Both are on MASTER page.
Code given above is one of the 2 options to pass data to master page:
Add using ViewData in ALL the action methods.
Do it in only one place using abstract base controller - add the required data using ViewData inside its constructor and make our main controller class implement this abstract base controller class. So that we don't have to add the viewdata for master page in all action methods.
I don't know what is your final goal with this but this is something which is not recommended to be done in MVC. The Request object is not yet initialized in the constructor of the controller. You could try to use the native HttpContext object:
string foo = System.Web.HttpContext.Current.Request["foo"];
but that's something extremely bad and I would never recommend you doing this as now your controller is coupled to the static native HttpContext instance without any chance of unit testing it.
Instead of using the constructor you could override the Initialize method of your controller where you will have access to the request context and you could read posted data:
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
string foo = requestContext.HttpContext.Request["foo"];
}

best practice on rendering several views based on same dynamic data

I would like to have some input on the following:
I would like some views to be systematically rendered (I can call $this->render from
my layout for these views) regardless of which controller/action is executed.
However the content used in these views is based on the same dynamically generated data and the code behind it is quite complex so I can't put the logic inside the views for obvious optimization/performance issues.
I could use $this->_helper->actionStack in each controller to call another controller in which data for the views would be prepared however I would like to do without modifying the existing controllers
I would be tempted to put something in the bootstrap since what I want is common to my application however I just don't know what to do.
That's what View Helpers are for.
In the View Helper you can fetch your data (through models or service layer) and prepare it for output.
<?php
class View_Helper_Foobar extends Zend_View_Helper_Abstract
{
protected $_data;
public function foobar()
{
if (null !== $this->_data) {
$this->_data = some_expensive_data_getter();
}
return $this;
}
public function __toString()
{
return $this->view->partial('foobar.phtml', array('data' => $this->_data));
}
}

How to automatically set and attribute to controller

Maybe the question is not self-explanatory, so I will explain it through.
The deal is: I got the variable $conn in the bootstrap class file. I'd like to make it global for every controller so that I just have to call $this->conn in the controller action scope in order to access the data inside. How would I do it?
Thx
One fairly straightforward way is to create your own base class form which your controller's inherit:
<?PHP
class My_Controller_Action extends Zend_Controller_Action {
public $conn;
public function init(){
//set $this->conn
}
}
class Some_Real_Controller extends My_Controller_Action {
//$this->conn exists!
}
class Some_Other_Real_Controller extends My_Controller_Action {
//$this->conn exists here too!
}
Matthew Weier O'Phinney posted a blog entry recently with some examples of how to use action helpers to do this, see:
http://weierophinney.net/matthew/archives/235-A-Simple-Resource-Injector-for-ZF-Action-Controllers.html
this will achieve the same thing without having to use a base controller class.