Help using __call with codeigniter - php

I have a class in codeigniter which deals solely with ajax. I have created a function within this class which checks if the refferal is an ajax refferal, I want to be able to call this function every time that any function from this class is used.
As such I've implemented the __call magic method
class Ajax_content extends Controller {
function __construct()
{
parent::Controller();
}
function __call($method, $arguments){
$this->ajaxCheck(); //set up to return false and exit.
call_user_func_array(array($this,"_".$method),$arguments);
}
At present ajaxCheck() always returns false and exit()s. But it's not being called (at present my ajax request still returns data) Is this a valid way of approaching the problem?

I want to be able to call this
function every time that any function
from this class is used
__call is only triggered when invoking inaccessible methods. If you want certain functionality to be executed every time a controller method is called (and by that, I assume you mean a method that's mapped to a web request, not any function in the class), you should put this functionality in the constructor.

If you want a method to run before any method instead of use magic php __call in codeigniter controller you can use Remaping method for codeigniter
public function _remap($method)
{
// call and start a method before any other method in codeigniter controller
}
for more info see this page

Related

PHP Trait using another trait, calling a method from the used trait

I have a MyTranslatable trait, which uses another OtherTranslatable trait, the one from a third party package. I'm including them as follows.
trait MyTranslatable
{
use OtherTranslatable {
OtherTranslatable::method as public otherTranslatableMethod;
}
public function index()
{
// Perform my actions
// Call otherTranslatableMethod
static::otherTranslatableMethod();
}
I'm wondering if this is valid, the code is working but I'm not so sure if traits are meant to be used this way, and if this is the correct way to call the "parent trait's" method like this after my actions are complete
I think your code from architectural point of view is correct since child blueprints (classes, traits) in PHP can override in use statement of the context, the methods from already used traits (I avoid call this inheritance because using trait is actually copy-paste), but I don't find quite necessary to invoke your otherTranslatableMethod() statically in MyTranslatable (of course except if it's defined as static in OtherTranslatable trait).
If you have non-static definition of OtherTranslatable->method() you can do the following in order to make your code more correct and clean.
trait MyTranslatable
{
use OtherTranslatable {
method as public otherTranslatableMethod;
}
public function index()
{
// Perform my actions
// Call otherTranslatableMethod
$this->otherTranslatableMethod();
}
}
Hope this helps.

PHP call class variable / property with stored closure

So I am making a Magento module in PHP. I want my logging to be consistent across all classes. My idea was to define a method in the helper class and call it. However being the pre-optimizer that I am, I figure making multiple calls to a class via the Mage::Helper() method to be more expensive than it needs to be, especially since most of my logging in singleton models anyways. So my now my idea is to use closures, define my method in the helper, make one call to the helper and register the method in a class variable.
class Comp_Mod_Helper_Data extends Mage_Core_Helper_Abstract {
public function getLogger() {
return function ($obj, $type= Zend_Log::DEBUG) {
Mage::log($obj, $logType, 'comp-mod.log', true);
};
}
}
Use:
class Comp_Mod__IndexController extends age_Core_Controller_Front_Action {
private $_log;
protected function _construct() {
$this->_log = Mage::Helper('mod')->getLogger();
}
}
However while it works ... it is not great to use. I'm either stuck doing:
$log = $this->_log;
$log('hello world');
// one awkward liner
($this->_log)('hello world');
While neat that it works is not readable nor standard, i.e. confusing!. The error that it get when using $this->_log('hello world'); is that the method does not exist. I assume because PHP is looking for a method call when using the syntax $this->method();
I do understand that A) I could just suck it up and use Mage::Helper everywhere, and B) that I could store the helper object in a variable and call like $this->helper->log(), and C) that static variables work, see PHP closure as static class variable
So, is there a way to get a non-static class variable to call the closure instead of looking for a non-existing method?
You could make use of the __call magic method:
class Comp_Mod__IndexController extends age_Core_Controller_Front_Action {
public function __call($method, array $args)
{
switch ($method)
{
case '_log':
return call_user_func_array(Mage::Helper('mod')->getLogger(), $args);
}
return null;
}
}
Then use it like you wanted to:
$this->_log('string to log');

The way of defining class methods without the need of keeping the order of calling them

Hi I have a class which includes two methods.
One of which is to initialize session , another one is for redirect the web page
I ve written the class such that it can be called repeatedly.
$obj->setSession(key,value)->redirect(url);
In this mode , the session is firstly initialized and then it redirects to the next page.
But if it's written like this
$obj->redirect(url)->setSession(key,value);
It just redirects to the defined location qnd the session is not initialized anymore ..
It s cuz when the resirect method is called, the page changes promptly and it causes the second method not to be called ..
Is there any way to be able to call methods repeatedly without the need of considering their order ?
When I usually face that issue, I add a method in the $obj object called render() or done() or something to that effect that checks all the flags I might have defined previously. One of those flags might be a header flag, which is what a redirect method usually does header(Location: $yourDestUrl).
So you end up with something like:
$obj->redirect(url)->setSession(key,value)->render();
When you call a method such as redirect or setSession, put those actions in a "stack" as a property of you class.
Then, when all your methods are called, call a method called exec (for example) that will execute all the actions in the "stack".
Here is a base class based on this idea using magic methods:
class Stack {
private $_stack = array();
public function __call($method, $args) {
// Adding method to stack
$this->_stack[$method] = $args;
return $this;
}
public function __isset($name) {
// Checks if method is in stack
return isset($this->_stack[$name];
}
public function exec() {
// setSession is executed first
if (isset($this->setSession))
call_user_func_array('setSessionMethod', $this->_stack['setSession']);
// redirect is executed second
if (isset($this->redirect))
call_user_func_array('redirectMethod', $this->_stack['redirect']);
}
}
To use this class, you would do:
$stack = new Stack;
$stack->redirect('arg')
->setSession('arg1', 'arg2')
->exec();

Why is __constructor needed in codeigniter

Why does __constructor code needs to run in codeigniter controller and models ? Without those lines, the code is working fine. I am confused !
function __construct()
{
parent::__construct();
}
The reason behind for using the _construct(magic Function) is to load your library and helpers through the controllers, so that you don't have to load libraries and helpers in each of your functions.
Example:
function __construct() {
parent::__construct();
$this->load->library('someclass');
$this->load->helper('someclass');
}
It will work as long as the class from your controller/model does not need it's constructor method to be called. If the class from where it extends defines dependencies needed (for example), you may get unwanted results.
Even though the constructor method is a so called "magic method" and it will be called automatically when you use the new keyword (note that you have to use parenthesis):
$foo = new Foo();
This does not mean that the class from where Foo is extending will get it's constructor method called automatically.

Accessing database from bootstrap.php in CakePHP

Is there any standard method of accessing the database in the bootstrap.php file with CakePHP?
Specifically I want to set "putenv()" to a time zone that's stored in the database. Is there another way of achieving the same thing that I should be using instead?
Thanks.
I don't think it's a good idea to access database in bootstrap. You cannot use models because they haven't yet been initialized. I think that you could extract the connection data and initialize connection and run queries using PHP's mysql_* but that's an ugly thing.
However if you need to run certain action everytime your app is accessed I would suggest placing it in AppController constructor (__construct function).
class AppController extends Controller {
public function __construct() {
// do your magic here
// call parent constructor
parent :: __constructor();
}
}
class YourSpecificController extends AppController {
public function __construct() {
// call parent contructor (this) will cause your magic happen
parent :: __constructor();
// extra controller initialization instructions
}
}
If you don't declare constructor in extending class you won't even have to change anything since PHP will automatically call parent (AppController) constructor.

Categories