What exactly is '$this" in add_action() - php

Some add_action() statements that i see now and then are provided with an array in which the first argument is $this, and the second one, the function.
As far as i know, $this stands as the current instance in POO, but what about in this particular case? Let's say for the sake of example that we have a newsletter system that registers your email adress, except if it still exists in the database.
<?php
public function save_email()
{
if (isset($_POST['zero_newsletter_email']) && !empty($_POST['zero_newsletter_email'])) {
global $wpdb;
$email = $_POST['zero_newsletter_email'];
$row = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}zero_newsletter_email WHERE email = '$email'");
if (is_null($row)) {
$wpdb->insert("{$wpdb->prefix}zero_newsletter_email", array('email' => $email));
}
}
}
Now we need to declare it as an available action. why should we need an array like this one?
add_action('wp_loaded', array($this, 'save_email'));
And why couldn't we simply do as followed?
add_action('wp_loaded','save_email');

Because save_email is a class method and we're adding the action from $this class instance (i.e. from within the class owning the method).
The array represents a PHP callable, see type 3 in the example: http://php.net/manual/en/language.types.callable.php

This is too long for a comment.
$this is the current instance of the current class. So it would be the instance invoking the hook. Or the class the action is being added in.
add_action('wp_loaded', array($this, 'save_email'));
So this is the save email in the current class.
And why couldn't we simply do as followed?
add_action('wp_loaded','save_email');
Because you can't ... Just kidding.
this is due to using call_user_func_array
http://php.net/manual/en/function.call-user-func-array.php
Which is the built in way of doing it. I am sure it also has to do with how functions are called, because without the class it would be ambiguous if this was a function or a method of a class.
In the case you present, PHP would think that was a function. Even if there was a way to tell it, it wasn't, how would you tell it what class that method is in. So it's easier and safer to just put the class in...

Related

PHP OOP inheritance

I have 2 classes: User and Router
In my script, class User is instantiated first to set user data, then class Router is instantiated to set page data.
$user = new User();
$router = new Router();
Inside one of Router's methods, I need to invoke $user->getSuperPrivileges(). This function queries the DB and sets extra parameters in the $user object, then returns them.
I could pass $user as a parameter of Router($user) and save it as a property in the construct function, but I believe this would only create a clone of the real object. Problem with this is that the values set by $this->user->getSuperPrivileges() would only be accessible by the clone, and not in the global script by the real object. In other words, I would need to invoke the getSuperPrivileges() method once again in the real object to set these properties again, which is counterproductive.
What is the best way to achieve what I want (access the real object $user and its methods from inside $router, without having to create a clone passed as a function parameter)?
As pointed out below by #hek2mgl, in php5 every object variable is a reference. The __construct magic method would not work at all prior to that anyway so we can assume that OPs example should work regardless.
http://3v4l.org/6dKL0
The following lines are really pointless given the above example.
have you tried passing the $user object as a reference?
class Router{
function __contruct(&$user){
$this->user=$user;
}
}
new Router($user);
in that case how about a singleton?
function user(&$userO){
static $user;
if(!is_array($user)) $user=array();
if(is_object($userO)) $user[$userO->uid]=$userO;
if(is_string($userO)) return $user[$userO];
}
class Router{
function __construct($user){
$this->uid=$user->uid;
}
function __get($k){if($k=='user') return user($this->uid);}
}
To explain a little more, the user function stored the user objects, keyed by a unique identifier in a static array, the __get magic method allows you to intercept calls to the user property on the router object and return the statically saved object from the singleton function.
You can create the $user object and inject it into $router object using constructor injection. But what you are doing should be just fine. You should be able to use that object for whatever you need within your router class. Especially if the database maintains the privilege state.
If you must use only one instance of the class check out the section on Singleton patterns at: http://www.phptherightway.com/pages/Design-Patterns.html and you can get an idea of how to achieve this.
I'd try and apply the Dependency Injection pattern. The point is that methods should be passed all they need to operate.
Meaning the method in your router which operates on a user should be passed said user.
class Router {
method privilegiateUser(User $user) {
// notice the typehint
// php will enforce that your method receives a User
$user->getSuperPrivileges();
}
}
I'd disapprove passing the User to your Router's __construct() if it's to be used only once and not with each script run. Think about it that way:
Is a User a property of a Router in the same way than a Name is a property of a User?

PHP hooks setting to be called through different classes

I'm going to structure this as best I can. Basically I have a Hook class that works by adding supplied hooks.
An example of this would be:
$this->registry->hook->add('HOOK_NAME', 'CLASS_NAME||METHOD_NAME')
The hook adding, calling, removing functions work great, now the issue resides when I set the hook in a separate method in a completely different class.
An example of this would be when a user logs in.
The path they take is User Controller -> Form Class -> Login Process Function
Now within this login process function, I'd like to set a hook to be called later to end the session. (Would be added as stated above)
The issue seems to be that it gets set but doesn't stay persistently, if that makes sense?
If anyone is interested, this is what the hook add function looks like:
function add($hook, $callback, $params = '') {
//make sure the hook is defined
if (!isset($this->hooks[$hook])) {
$this->hooks[$hook] = array();
}
//add the callback to the hook
$this->hooks[$hook]['callback'] = $callback;
// add the params if supplied
if (!empty($params)) {
$this->hooks[$hook]['params'] = $params;
}
}
Should I be using magic methods __set() and __get() ?
Any help would be appreciated! :)

How to know if a function is called first time or not

I want to create a function such that if it is called the first time, it behaves differently and for rest of the time it behaves differently. Now to do this I know I can use a "state" variable. Some other techniques were also given here:
Check if function has been called yet
However I somehow got a hint from a colleague that debug_backtrace() can be used to solve this problem. I read about it but cannot understand how ? This function gives a stack trace of the function call. How can this tell if the function has been called first time or not ?
The exact code that baffles me is here:
/**
* Holds the states of first timers
* #var array
*/
private static $firstTimeCSS=array();
private static $firstTimeJS=array();
/**
* Tells whether it is the first time this function is called on
* ANY CLASS object or not. Useful for one-time scripts and styles
*
* #param string $class name optional. Usually you should send __CLASS__ to this, otherwise the instance ($this) class would be used.
* #return boolean
*/
final protected function IsFirstTime($class=null)
{
$t=debug_backtrace();
if ($t[1]['function']=="JS")
$arr=&self::$firstTimeJS;
else
$arr=&self::$firstTimeCSS;
if ($class===null)
$class=$this->Class;
if (isset($arr[$class]))
return false;
else
{
$arr[$class]=true;
return true;
}
}
I personally don't see how this is possible or why you would want to do it this way. I suspect debug_backtrace() is a lot more expensive than a static variable, to begin with.
The only backtrace characteristic that seems to change between calls is, as you pointed out, the line number (from where the function was called). And, that wouldn't even change if you ran the functions in, say, a loop, since they would all be called from the same line on each iteration.
Demonstration 1 (individual calls): CodePad
Demonstration 2 (loop): CodePad
If I were you, I'd stick with a state variable; as for your colleague, you could perhaps ask him to show you a code which demonstrates his methodology if you're curious as to how it works (I know I am!).
Edit (from comments): Basically, your colleague's debug_backtrace() method stores a boolean value in an array using the key of the class which is called.
In plain English, here's what happens:
Is the calling function called "JS"?
If so, store in a JS-labelled array; otherwise, use a CSS-labelled array.
Check if a class was specified; if it wasn't, use this class.
If we have a boolean value for the given class in the labelled array, it's not the first time.
Otherwise, set the boolean value for the given class to true.
I know what you're thinking: This makes no sense, it doesn't even store the calling function's name! And you'd be right; this method is not extensible, and has a huge overhead.
If you want to do what this method does, just use a static variable in the class in question to keep track of whether or not functions have been called. Your colleague's method—sorry to say—is inefficient and ineffective.
Take A hidden input field and
<input type="hidden" id="start_function_count" value="0">
and then call a function
<li onclick="myFunction('start_function_count')">
js function
MyFunction(count_id) {
var function_count = $("#"+count_id).val();
if(function_count == 0){
// CODE HERE for 1st time function call
// SET HIDDEN FIELD
$("#"+count_id).val(1);
} else{
// SECOnd time code;
}
}
just use a static field in the function. This static field will only be initialized once and not overwritten on new function calls.
If you use this in class methods, do take care that each inherited child class will have it's own version. So a static function field updated in ParentClass won't update the static function field in ChildClass extends ParentClass.
See it in action https://ideone.com/iR7J5O
function beDifferentFirstTime()
{
static $firstTime = true;
if($firstTime) {
$firstTime = false;
echo "I will say this only once, so listen carefully\n";
}
echo "The cabbage is in the cart. I repeat, the cabbage is in the cart.\n";
}
beDifferentFirstTime();
beDifferentFirstTime();

PHP, passing parameters to object method or using instance variables

This is something I have never been fully sure of or never found a solid answer for.
Lets say I have a User class with a register() method inside it and I'm not sure which way is best to implement this method.
In my register.php page should I have
$user->register($_POST['firstName'], $_POST['lastName'], $_POST['username'], etc..);
and then in the register() method don't bother setting the objects attributes and just use the variables supplied in the signature of the method or should I do
$user->register();
and then in the register function do something like
$this->firstName = $_POST['firstName'];
$this->lastName = $_POST['lastName'];
etc...
Thanks in advance.
If the register method is tied to the object (the instance, not the class), the I'd have it use the internal properties which have to be set in advance. So, you instantiate a user, set the properties and then call $user->register().
$user = new User();
$user->firstName = 'name'; //$user->setFirstName('name') could also work
$user->lastName = 'last name'; // for this to work, the properties have to be public
$user->register();
User A should only be able to register itself, and not anything else.
If you use a method with parameters, you could basically register anything (not only a user).
Also, if registration means writing the parameters to a database, a method that only uses the internals of the user object is more robust. If you decide to change the registration mechanism (if you need some other info from the user object), only the user class has to be modified.
Edit:
Now that I've thought about it a bit more, I think I'd make another class to register users, it would take the entire user object and add a role or whatever and save it to the database. That way, a user object is a bit simpler, and does not need to know how it is registered or unregistered, and if the registration mechanism changes, the users can stay the same.
Edit 2:
Be careful when setting object properties from a method that is not a really a setter (like you would in the register($fname, $lname, ...)). The same approach has brought me headaches when "something" would change my object for no apparent reason, and I couldn't find a setter or a direct call to the property anywhere in code.
The implementation is purely up to you. You can do either way. Here is an example:
class User{
protected $_firstName = null;
protected $_lastName = null;
public function register( array $params = array() ){
if(!empty($params) ){
$this->setParams($params);
}
// Do more processing here...
}
public function setParams($params){
// Set each of the users attributes.
}
public function setFirstName($name = null){
if($name !== null){
$this->_firstName = $name;
return true;
}
return false;
}
public function getFirstName(){
return $this->_firstName;
}
// Same getter and setter methods for other attributes...
}
This way you can pass an array of User attributes to the $_POST or you can do it individually by calling $user->setFirstName(), $user->setLastName(), etc...
Considering $_POST is defined in the global scope, it would make more sense to use your latter approach (not passing in arguments and setting it up from the function). NOTE however, that this will only work in the case that $_POST is declared in the global scope (in this case) and you will lose flexibility in scenarios when you pass in the class from external PHP modules.

Php (eval vs call_user_func vs variable functions ...)

Even though there's some discussions regarding this issue I wanted to check on certain example what would be the best approach.
Instead of using existing solutions I created my own persistence layer (like many do)
So my approach is also in question here.
For every table in db I have model class that has appropriate getters and setters and some mandatory methods. I also created only one generic DAO class that handles all types of model objects.
So, for example to save any model object I instantiate genericDAO class and call save method that I pass model object as attribute.
Problem is that in runtime genericDAO class doesn't know whitch model object it gets and what methods (getters and setters) exist in it, so I need to call mandatory model class method that retrieves list of attributes as multiple string array.
For example for every attribute there's array(table_column_name,attribute_name,is_string).
When I call save function it looks like this:
public function save(&$VO) {
$paramArray = $VO->getParamArray();//get array of attributes
$paramIdArray = $paramArray[0]; //first attribute is always id
/*create and execute getId() and store value into $void to check if it's save or update*/
eval('$voId = $VO->get'.ucfirst($paramIdArray[1]).'();');
...
Currently I'm using eval to execute those methods, but as it is well known eval is very slow.
I'm thinking of changing that into call_user_func method
Something like:
$voId = call_user_func(array($VO, 'get'.ucfirst($paramIdArray[1])));
But also there's other solutions. I can maybe use something like this $method = 'get'.ucfirst($paramIdArray[1]));
$voId = $VO->$method();
or else
$method = 'get'.ucfirst($paramIdArray[1]));
$voId = $VO->{$method}();
What would be the best way?
First of all, there's no need to pass references like you are doing. You should give this a read to try to understand how PHP handles object references.
So public function save(&$VO) { should become public function save($VO) {.
Second, there is no need to use eval (in fact, it's better not to because of speed, debugability, etc). You can't stack-trace an eval call like you can a dynamic one.
Third, call_user_func is all but useless since PHP supports dynamic variable functions. Instead of call_user_func(array($obj, $method), $arg1), just call $obj->$foo($arg1). The call_user_func_array function is still useful since it supports variable length arguments and supports passing references.
So, ultimately, I would suggest this:
$method = 'get' . ucfirst($paramIdArray[1]);
$voId = $VO->$method();
Note that there's no need to call method_exists, since it may be callable and not exist due to __get magic method support...
I normally would use:
$method = 'get'.ucfirst($attribute);
if(method_exists($obj, $method){
$obj->$method();
}
But unless there is a very good reason i would just return a key => value array from getParamArray. And operate on that instead of using the getters...

Categories