I have a project and I'm using ZendFramework, also I'm a newbie in this Framework.
So my problem is,
I want to create a user defined function that I can use in all the controllers. Example: I want to create a function that will validate an input field in which I'll use trim, htmlspecialchars and mysql_real_escape_string. I want to access this function in all the controllers.
I have a solution for this which is I'll create this function in every controller that I have, which I think is not the best solution.
Thanks
A base controller is a solution, but not the best to me. You should write your own Action Helper, they are meant to do it.
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.
More information here in the manual.
Let's see how to register your Action Helper path, add this in your application.ini:
resources.frontController.actionHelperPaths.My_Controller_Action_Helper = "My/Controller/Action/Helper/"
where My is the name of you custom library.
And in the path My/Controller/Action/Helper/ you can add a file MyActionHelper.php as follow:
class My_Controller_Action_Helper_MyActionHelper extends Zend_Controller_Action_Helper_Abstract
{
public function direct($input)
{
$output = mysql_real_escape_string($input);
// trim, etc.
return $output;
}
}
That's all you need to do! Finally, you can access your action helper from any controller using $this->_helper->myActionHelper($input);.
If you need to validate an input coming from a form, take a look at Zend_Form and Zend_Filter. Zend_Filter can natively StripTags and TrimString, it's even a better way to do it.
Create file Util.php put it inside library folder
and add as many functions you want into it then open index.php (inside public folder)
add
require_once 'Util.php';
after line
require_once 'Zend/Application.php';
So for e.g your Util.php will migh look like
function mysql_real_escape_string($value)
{
return $value
}
function logger($value)
{
Zend_Regsitry::get('logger')->log($value);
}
function _T($translate)
{
return Zend_Registry::get('translator')->translate($translate);
}
Now all of these functions are global and you are free to call them from anywhere in your zf application . I do this with my every ZF project . Adding functions here for translation or logging purpose can be really time saver .
The Zend Framework have Zend_Controller_Action_Helper.
Related
In my current implementation of the MVC design pattern (demonstrated using PHP and CodeIgniter):
Let's say I have a "page" located at "www.mysite.com/blue/page" that is ultimately generated by the following (greatly simplified) files:
/libraries
session_lib.php
/controllers
/red
/white
/blue
page.php
/models
/red
/white
/blue
funky_class.php
page_model.php
/views
/red
/white
/blue
page.php
And here's an easy to understand controller:
// FILE: /controllers/blue/page.php
// Get some paramaters from URL
$params = $this->input->get();
// Use a library to do some stuff with these params with a session
$this->load->library('session_lib');
$this->session_lib->store_in_session($params);
// Use a very page specific class to do some funky stuff with the params
$this->load->model('blue/funky_class');
$funkified_params = $this->funky_class->funkify($params);
// Pass params to a model
$this->load->model('blue/page_model');
$data['output_from_db'] = $this->page_model->get_some_output_from_db($funkified_params);
// Send to view
$this->load->view('blue/page', $data);
And now the question...
What is the best procedure for these "funky" little page specific classes that don't interact with the database? In this example I store the little class with the models, and in some cases might just add additional methods inside the model class to do the funky stuff. Is this good practice? Or should the library and funky class both go inside the model so the controller is even skinnier (however the model might be used in other places without the need for sessions and funkiness)?
I would use a helper.
When a helper is loaded, that function will be available in the global scope so you can call it anywhere.
They're great for small, stand-alone functions that do only one thing that is not necessarily related to code in a model or library
Helpers especially excel for me when converting things between one format or another (slugify, convert_timezone, change_query_string) or doing little tasks that you don't want to think about (force_ssl, is_image, uri_string)
funkify() seems like an appropriate helper function that may prevent a lot of repeated code.
Here's the codeigniter documentation page on them: http://ellislab.com/codeigniter/user-guide/general/helpers.html
If you're in a situation where the helper function is so specific it will be only used in one place, you can still use a helper. Name the helper after your controller, page_helper.php for example.
page_helper.php
function funkify($params) {
// do funky stuff
return $funky_params;
}
then in your controller:
class Page extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->helper('page');
}
public function page() {
// do stuff
$funky_params = funkify($params);
// do more stuff
$this->load->view('blue/page', $data);
}
I have no excuse for it, but sometimes if I am in a situation where I need a razor specific function that will only be used on one location (say, a controller) ever, I will put it right in the controller's file. You can paste a function outside of the class definition and it will act like a helper and be available globally (as long as that controller is loaded). You can also define functions inside of a view. Yucky, but possible. I don't like to do it often because it's unusual and not expected (by myself or other developers)
I want to verify if file/folder exists on my CI system (not system folder), can i do it from controller or I need create a method on my model to do it?
It's basically a matter of choice. You can define your function in both your model and controller. But if you want to use it over and over from different controllers, then better define a new model and put that function in it. I'd define model which is to be used by many controllers that is having some common-general methods. Just to keep things apart and maintaining them later. Helpers are also a way to keep things separate.
You have got many way for this :
You can create an helper and put your function like verify()
You can create a private function into your controller like
private function _verify() { }
enjoy !
Best to add this function in a codeigniter helper or in a library class(if you are fan of OOP). Load this automatically with autoload.php and call from wherever you need it.
I am new to PHP and I have a few questions that follows:
Do I need the init function or can I do the job (whatever I need to do in my code) without the init function?
I am saying this because the NetBeans "kinda" created/added automatically the init() function in my project.
In my code I am suppose to create the CRUD functionality in it.
If I don't use it what's the problems I might have and the downsides?
As the official docs would say:
The init() method is primarily intended for extending the constructor. Typically, your constructor should simply set object state, and not perform much logic. This might include initializing resources used in the controller (such as models, configuration objects, etc.), or assigning values retrieved from the front controller, bootstrap, or a registry.
You can have controllers that don't override the init() method, but it will be called under the sheets anyways.
If you are new to PHP, do not start by using a framework. Instead you should learn the language itself.
There is nothing significant about init() function. It is not a requirement for classes in PHP. Hell .. even __construct() is not mandatory in PHP.
That said, Zend Framework executes it right after the controller is created. It is required if you are using ZF.
You can read more about it here.
init() in Zend_Framework for most practical purposes is where you would put code that you need to affect all of the actions in that controller.(at least to test against all of the actions).
For example I often use the init() method to set up the the flashmessenger helper and to set the session namespace I want to be used.:
public function init() {
if ($this->_helper->FlashMessenger->hasMessages()) {
$this->view->messages = $this->_helper->FlashMessenger->getMessages();
}
//set the session namespace to property for easier access
$this->_session = new Zend_Session_Namespace('location');
}
Also Netbeans did not make this method or the controller, Zend_Tool made the controller and the methods utilizing the interface that Netbeans provided. That's why in your PHP settings for Netbeans you have to provide the path to the ZF.bat file and click the register provider button if you change your ZF install.
One more thing...Be aware that there more methods available to the controller that provide hooks into different parts of the dispatch cycle. You may not need them very often but you need to know they are there.
Simply its a constructor for that class(controller)...
init(){
$this->a = 1; //If we set something like this in the init
}
public function fooAction(){
echo $this->a; //1
}
public function barAction(){
echo $this->a; //1
}
ie the variables,objects..that is initialised in init will be available to all the actions in that controller
I have a Zend project with a lot of controllers and actions using the method
$this->_redirect('/controller_name/action_name');
for redirecting to other actions after data processing. I've observed that this creates a lot of "magic strings" that hurts the DRY principle: if I change a controller or action name I'd have to change this redirection code in all actions that use it. I'd like to know if there is a better way in Zend to avoid this. I've thought about creating constants for all controllers and action names, like this:
$this->_redirect(HOME_CONTROLLER_INDEX);
But I think this approach isn't very good. Is there a better solution?
You could use const instead
class DefaultController extends Zend_Controller_Action {
const IndexAction = '/controller/action/';
...
$this->_redirect(DefaultController::IndexAction);
}
Or SplEnum. See: http://www.php.net/manual/de/class.splenum.php
Your option of defining constant would be a viable one if you don't plan on modifying your router (since you are using the "compiled" url).
$this->_redirect('/controller/action');
Otherwise, you could rely on a few private methods that call the redirector action helper.
public function redirectControllerAction()
{
$this->_helper->redirector('action', 'controller');
}
This way you can have all your redirections localized in your controllers.
If you have to maintain your code in the future you have all your specifics redirection grouped together and you won't cluter your code with a lot of constants that could hinder readability and make it complex to maintain.
You could also use the controller method to send message to your user using the flash messenger without much effort.
public function redirectControllerAction()
{
$this->_helper->flashMessenger('You have been redirected to a better location');
$this->_helper->redirector('action', 'controller');
}
For the destination controller name, you can add this static method:
public static function getName() { return __CLASS__; }
(You need to add code to remove the controller suffix and call Zend_Filter_Word_xxx to perform inflection)
and use it like this:
$this->_redirect('/'.DefaultController::getName().'/action_name');
For projects written in php, can I call more than one (or multiple) controller in class controller? Example in http://img192.imageshack.us/img192/7538/mvc03.gif
ASK: I need to call an action from another controller... And if I do like the picture above, I'm being out-ethics?
Thanks,
Vinicius.
I'm sure that you can do what you want with whichever framework you're using. If you can't do it natively for whatever reason, then you can extend your framework as required.
Having said that, I personally don't like the idea of a controller calling another controller. It seems to somewhat break the MVC paradigm if only from a theoretical standpoint. What I might do instead is build a library class that contains the functionality required and then have both controllers instantiate that class as a member and call the functions required.
For example, using CodeIgniter:
libraries/MyLib.php:
class MyLib
{
public function MyFunc()
{ /* do whatever */ }
}
controllers/ControllerA.php:
class ControllerA extends Controller
{
public function index()
{
$this->load->library('MyLib');
$this->mylib->MyFunc();
}
}
controllers/ControllerB:
class ControllerB extends Controller
{
public function index()
{
$this->load->library('MyLib');
$this->mylib->MyFunc();
}
}
out-ethics? Anywhose... back to reality.
Yes, a controller can call another controller's action. For instance, in cakePHP, this functionality is afforded via requestAction
// pass uri to request action and receive vars back
$ot3 = $this->requestAction('/stories/xenu');
If you're rolling your own, the details of how to implement it will be very specific to your framework.
then you need to modify framework, find place where controller is lounched and add there your second controller.
what framework you are using?
You can do it any way that you want. You don't have to use MVC if you don't want to. However, in MVC you really should only have one controller active at a time. You probably want multiple Views or Models, not another Controller. There is nothing at all wrong in loading, say, a header and footer view for the menu and footer of the site.
If you are building another Controller, then feel that you need to access the functionality of a previous Controller to access its functionality (because it works with a specific / desired Model), then the Model you developed for the latter probably needs to be refactored. IN plain speak, your target Model may be doing too much. Break it up.
You are trying to avoid repeating yourself (DRY) by using calling the methods of a Controller that has already been developed, but in doing so your are creating TIGHT coupling between both controllers! If something changes in the borrowed controller, it will have an effect on the borrowing controller. Not good, Dr. Jones.