is __call() function available in CakePHP's controllers? I used this function in Zend Framework.
class UsersController extends AppController {
function home(){
/*some action*/
}
function __call($m, $p){
print_r($m);
print_r($p);
}
}
I'm getting error like this:
Missing Method in UsersController
<?php
class UsersController extends AppController {
var $name = 'Users';
function somemethodsnotincontoller() {
}
}
?>
for the URL site.com/users/somemethodsnotincontoller
As many have pointed out here, __call() is a native PHP5 language "magic" method for catching calls to class methods that don't exist.
HOWEVER, Cake's core (I think it's the dispatcher) checks to see if the method exists first before calling it, and if it doesn't it renders the missing method error.
A solution might be for you to create your own AppError class, and handle the "catch all" method in there.
There is a limited amount of information in the cook book under Error handling
Yes but it won't work because CakePHP invokes actions through ReflectionMethod
// CakePHP 2.4.3
// Controller.php
public function invokeAction(CakeRequest $request) {
try {
$method = new ReflectionMethod($this, $request->params['action']);
and methods called this way are not processed by _call.
Used it for what?
The __call() method is a construct in PHP that you can use from within classes that allow you to "catch" calls to methods that don't exist in the class explicitly.
From PHP.net:
__call() is triggered when invoking inaccessible methods in an object
context.
So the answer is yes, as long as you are using PHP 5 or up.
__call() is a language construct so it is available in all versions of php that support it.
__call() is a magic-method of PHP, not any particular framework. It's impossible to answer this question without any context since __call() is defined in a particular object, not globally. Since CakePHP touts the fact that it is php4 compatible and __call() was introduced in php5 I would say no.
I looked at the production branch for Models and there is a call__() method, which looks like it tries to emulate PHP5's __call().
https://trac.cakephp.org/browser/branches/1.2.x.x/cake/libs/model/model.php?rev=4211#L437
Edit (Responding to comment):
Looking at Cake's base controller, there does not appear to be a 'catch-all' method available in controllers that mimics Zend's implementation of __call(). Your alternative to accomplish this would be to setup a route similar to cake's page route to catch all actions directed at a controller and send them to a single method.
Cake Trac for base controller:
https://trac.cakephp.org/browser/branches/1.2.x.x/cake/libs/controller/controller.php?rev=4211
Cake documentation on routing:
http://book.cakephp.org/view/46/Routes-Configuration
One of the examples in that documentation I referenced looks like something you can play with to accomplish what I mentioned above:
Router::connect(
'/cooks/:action/*', array('controller' => 'users', 'action' => 'index')
);
Regardless of the given-action, always use the index action.
In CakePHP 3, you definitely can use __call, just ensure that the controller defines isAction(). For example:
public function isAction($action) {
// To allow all actions to go to __call:
return TRUE;
}
public function __call($name, $arguments) {
//** your code called for every undefined action here **/
}
__call is one of PHP 5's magic methods (see "Method overloading" for more details).
If you are using PHP 5 (and you are, if you are usinf Zend Framework), you can have a __call method in your classes, not depending on the framework you are working with.
Related
I have looked online for the meaning of parent::init(); . All I was able to find was that init() is to initialize some settings which want to be present every time the application runs.
Can anyone please explain the meaning of parent::init() in exact sense, like significance of both the words?
Thanks in advance.( I am sorry if its too simple! )
When we use parent::init(), we are just calling the parent method (in this case init()) inside a method of the current class.
About parent::
For example, let's say we have a class called MyClass. This class have a awesome method that runs alot of things:
class MyClass
{
public function runStuffs()
{
// trigger events, configure external stuff, adding default values to properties.
}
}
Now, after some time, we decided to create a new Class that extends from the first one. And we called MySecondClass:
class MySecondClass extends MyClass
{
}
It already have the method runStuffs(), but, for this second class, we need to do more things in this method, but maintaining what it have.
Sure we could rewrite the whole method and just copy and paste what we have in MyClass and add the new content. But this isn't elegant or even a good practice. what if later on We change the method in MyClass, you probably would like that MysecondClass have that changes too.
So, to solve that problem, we can call the parent method before write your new content:
class MySecondClass extends MyClass
{
public function runStuffs()
{
parent::runStuffs();
// do more things!
}
}
Now MySecondClass->runStuffs() will always do what its parent do and, after that, more stuff.
About the init() method.
init() is a method used in almost all classes from Yii2 framework (since most of then extends from yii\base\Object at some point) and works just like the __constructor() method (native from PHP). But there is some differences, you can read more here.
Actually the init() method is called inside the __constructor(), and the framework encorage us to use init() instead of __construct() whenever is possible.
Now if both are pretty much the same thing, why do they create this method? There is an answer for that here. (take a look at qiang's answer, from the dev team):
One of the reasons for init() is about life cycles of an object (or a component to be exact).
With an init() method, it is possible to configure an object after it is instantiated while before fully initialized. For example, an application component could be configured using app config. If you override its init() method, you will be sure that the configuration is applied and you can safely to check if everything is ready. Similar thing happens to a widget and other configurable components.
Even if init() is called within constructor rather than by another object, it has meaning. For example, in CApplication, there are preInit() and init(). They set up the life cycles of an application and may be overridden so that the customization only occurs at expected life cycles.
Conclusion
So, when you use a init() method and calls parent::init() you are just saying you want to add more things to that method without removing what it already was doing.
The parent::init(); Method is useful to execute a code before every controller and action,
With an init() method, it is possible to configure an object after it is instantiated while before fully initialized.
For example, an application component could be configured using app config.
If you override its init() method, you will be sure that the configuration is applied and you can safely to check if everything is ready.
Similar thing happens to a widget and other configurable components.
In Yii, init() method means that an object is already fully configured and some additional initialization work should be done in this method.
For More Information check this link :
https://stackoverflow.com/questions/27180059/execute-my-code-before-any-action-of-any-controller
Execute my code before any action of any controller
might be helpful to you.
I am working on an MVC framework in PHP.
I have several controller classes called "index" with methods called "index" within them. The classes do not have __construct() methods.
Inevitably, this is resulting in PHP calling the "index" method as the constructor instead, using the old PHP4 convention of the constructor being the method with the same name as the class.
Is there any way to disable this behaviour or do I have to define an empty __construct() to prevent it? (Or just change my own coding style so I don't have methods with the same name as their classes.)
I want PHP5 to stop parsing for the PHP4 constructors essentially.
Ilmiont
I have been down the same road with MVC frameworks before and I have never heard of an index() function being called like this. Upon instanciation it will call the __constructor if present or do nothing. When calling your controller you should be geting the class and method name and checking if they exist and if they do then instantiate it. However if you have the same general setup as me you should have a registry storing all of your variables being passed to the controller when you create an instance, then when/if the view is called from index it should pass the altered registry to the view
I'm very new to codeigniter ,
I wanted to know what is the meaning of a constructor in a controller . I saw the following code in a codeigniter tutorial -
class upload extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->helper(form);
}
// rest of the class...
My question is when is the constructor invoked - is it called every time the controller serves a request (e.g the controller class is instantiated for each request it receives?)
Well, that's a more general PHP question. Anyway, yes, the magic method __construct() is called (automatically) upon each instantiation of the class, as you can see in the manual: http://www.php.net/manual/en/language.oop5.decon.php
Usually, in CI is not necessary to call a constructor, unless you actually want one. In the example you posted, the code loads the helper on every instantiation of the class - which is the same as loading the helper in every method, just saves a lot of typing and ensures it's not forgotten. You can alternatively put the library/helper/model you want to have alywas loaded in the respective autoload array in config/autoload.php (check "autoloading" in CI's manual)
Once you define a constructor in your child Controller you're compelled to call the parent constructor (of the mail CI_Controller class), because there is where the main CI object is created and all the classes are loaded, and you need those in your child controller too; if fail to do so your child class will construct separately and won't inherit.
I hope I made myself clear, english is not my mothertongue :)
the constructor is magic Literally its called a magic method.
what makes the constructor cool is that it will do things for you BEFORE any of the methods. So if you have an admin class, and someone should be logged in in order to access it - you can check for login in the constructor and bounce them out if they are not authorized.
in the constructor you can load the models, libraries, helpers, etc that your class needs, and they will be available for any method in the class.
you can load in variables that are used by methods. this is really useful for models.
Don't use _construct() function in latest apache & codeigniter
Use helperlin in index() function
That's a general question. Constructor is a function that is automatically called when instantiated. this function helps us to intialize the things that we are going to need frequently in our code like when we have to load the models of helpers like form e.t.c.
$this->load->model('Model_name');
now when you write this line in your constructor you don't need to load this model again and again in your methods of that class.
I am writing a controller plugin in zf2.
I use the following method to get controller from within plugin, but it returns null.
$controller = $this->getController()
Any suggestion?
Note, this answer was based on my experience with ZF1, and a quick look at the ZF2 code. Check out this answer.
I haven't played with ZF2 yet, but if the dispatch process and plugins are similar to ZF1, a plugin can't access the controller (at least not in a trivial way) as the controller isn't even instantiated for some of the plugin hooks.
Update: Took a quick look at some of the stock ZF2 controller plugins (as I can't seem to find official docs on creating a custom plugin), and see checks like the following:
$controller = $this->getController();
if (!$controller || !method_exists($controller, 'plugin')) {
//...
So it seems like the controller may not be set in some cases. Since the plugins also support (what I understand to be) an event listener, my guess is that they still can be used at various times in the response process, which may be before a controller is assigned.
Hopefully someone who's used ZF2 can come along and set me straight; but perhaps I've at least pointed you in a somewhat reasonable direction.
There are two options for which you have no controller set in your plugin.
You call the plugin from the plugin manager prior to dispatch, so no controller is set yet
You call the controller inside the plugin during __construct()
For the first one, a typical example is an onBootstrap() method in a module class where obviously you have no controller:
public function onBootstrap($e)
{
$app = $e->getApplication();
$sm = $app->getServiceManager();
$plugins = $sm->get('ControllerPluginManager');
$plugin = $plugins->get('my-plugin');
// $plugin->getController() === null
}
This seems an obvious example, but there are other occasions where you are mistakenly assuming a controller exists already (for example, during run of the application, at the route phase; the dispatch still has to come).
The second example is because the controller is injected with setter injection. The setter is called after construction. In pseudo code, this happens:
$plugin = new $class;
$plugin->setController($controller);
If you have a plugin like this:
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
class MyPlugin extends AbstractPlugin
{
public function __construct()
{
// $this->getController() === null
}
}
You notice there is no controller set at that phase.
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