Can php call non static method without instantiating the class first? - php

I register class methods for actions in my Wordpress plugin. When my method gets called by Wordpress, if I try to use the $this variable, php throws an error saying the call to $this variable is illegal outside the context of an object.
How can that be? I thought unless the method is static, you're not supposed to be able to call class methods if the class isn't instantiated! My method isn't static! What is happening?
The source code
Obviously the initialize is called from the main plugin file:
add_action('init', array('AffiliateMarketting', 'initialize'), 1);
My class looks like this:
class AffiliateMarketting
{
public function __construct()
{
// some initialization code
}
public function initialize()
{
add_action('woocommerce_before_single_product', array("AffiliateMarketting", "handleAffiliateReferral"));
}
public function handleAffiliateReferral($post)
{
$this->xxx(); // <---- offending function call
}
public function xxx()
{
}
}
The received error message is in fact Fatal error: Using $this when not in object context in <filename> on line <linenumber>.

You have to instantiate the class first. Something like this:
$affiliatemarketing = new AffiliateMarketing;
and then do the following:
add_action('init', array(&$affiliatemarketing, 'initialize'), 1);
Edit: forgot to add, your action in your method should be added like this:
add_action('woocommerce_before_single_product', array(&$this, "handleAffiliateReferral"));

You're not supposed to be. That's why you're getting an error.
I don't know exactly how you're registering the method (code would help), but probably, you're expecting Wordpress to take care of creating an instance, but that's not its role.

I found thought the Codex documented if the class name is specified using its string representation, then the add_action function will assume the call is to a static method.
On the other hand if and instance of the class is passed along then add_action will use that instance to make the method call.

Although Arman hasn't specified which php version he is using, I would assume it's probably 5.3.2 or 5.3.3. The error itself is rather similar to the one described in this question and the solution also would be to upgrade to the latest version of php 5.3.

Related

Why is a PHP class method called on instantiation?

Need some help understanding what's going on in my PHP code.
index.php
include("cache.php");
$cache = new Cache();
cache.php
class Cache {
private static $URL_CACHE;
public function cache($url, $entityId) {
echo '<br>caching '.$url.' as '.$entityId;
}
When I request index.php, I get 'caching as' displayed, which is a surprise. I never called $cache->cache('', '');
What's calling the method?
As per Blake's answer, since the method name matches (somewhat) the class name, it's called on instantiation. For Java developers this will certainly be a surprise.
This is using deprecated PHP functionality to act as a __contruct() method. In older versions of PHP (Removed in 7) If you had a class named Foo and a function named foo() it was how you would call it as a constructor.
In short, this is being called by you instantiating the class. If you change your cache() method to makeCache() I bet it will go away.
Another solution is to have an empty constructor as well, thanks JimL.
public function __construct() {
}

Non-static method tNG_log::log() should not be called statically, assuming $this from incompatible context

I am getting the above error - here is the code that it is referring to:
function executeTransaction() {
tNG_log::log('tNG' . $this->transactionType, 'executeTransaction', 'begin');
if ($this->started) {
tNG_log::log('tNG' . $this->transactionType, 'executeTransaction', 'end');
return false;
}
I am unsure how to edit the above code effectively to make the error message go away. I am aware that I can edit the php.ini file so that these errors do not show, however I would rather fix the code
The method log() of the class tNG_log() is not defined as a static function.
Static methods can be called without creating an object from the class, like in your example, class::staticFunction().
This only works when in the class, the code is something like:
class tNG_log {
public static function log(...) {
// ...
}
}
Assuming the tNG_log-code is correct and should not be called staticly, the solution is to create an object from the class:
$tnglog = new tNG_log();
$tnglog->log(...);
If you want more information, please start with reading http://php.net/manual/en/language.oop5.static.php

PHP OOP MVC Fatal Error: Using $this when not in object context

So I've been looking all around, but nothing seems to be relevant to my problem.
I have an MVC, with some controllers and some tools like Session handling.
The session class consists of non-static methods, and in my controller I'm instantiating the session class like this:
public $sessions;
public function __construct () {
$this->sessions = new Session();
}
However, when I call it from a method in the controller, it returns the infamous "Using $this when not in object context". It doesn't make any sense to me.
public function index() {
$this->sessions->get('sessionToGet');
}
This will return the error.
Okay, I think it's a fault of how I wrote it. I came up with a better solution, which enabled me to switch to static calls instead on the session wrapper.
Fixed my problem, and now it atleast works very well.

Using PHP function_exists in a class?

I am using OpenCart and installed the module sizes.xml, it edits the catalog/product/model/catalog/product.php file
It adds a class method;
I have an issue with some code where in a function I have:
class ModelCatalogProduct extends Model {
public function getSizes($product_id) {
...
} // end function
} // end class
We always get an error saying that we cannot redeclare getSizes method.
I want to either force redeclaration, or alternatively check whether the function exists before calling the method but I cannot use function_exists in a class.
ie, this seems illegal;
class ModelCatalogProduct extends Model {
// This throws up an error
if (function_exists('getSizes')==FALSE) {
public function getSizes($product_id) {
} // end function
}// end if
} // end class
It will throw up an error issue. But I need the function in there.
I would like to use function_exists in this class or alternatively force the method to be redeclared.
How would I make function_exists work inside a class?
You can't have executable code in a class that is outside of a method, so there's no way you can do what you're asking, as your if() condition would need to be in the class body.
So despite what others are saying, method_exists() is not a suitable answer to this question.
If you're getting an error stating that the method is already declared, then there are a few possible reasons for this:
It is actually already declared elsewhere in the same class. In which case, of course you can't redeclare it. But since the code for the class ought to all be in a single file, then it should be fairly easy to see that and avoid doing it.
It's declared in the parent class (ie in your case Model or one of its parents).
Under normal circumstances, you should be able to redeclare a method that is already declared in a parent class; your method would override the method of the same name from the parent class. So for most cases, your whole question is entirely unnecessary.
But you say you're getting errors, so clearly something is going wrong It would help if you'd told us the exact error message, but there are two reasons I can think of this might not work:
If the method in the parent class is declared as Final, then it means the author of the parent class explicitly doesn't want it to be overridden. This means that you cannot have your own method of the same name.
If the method in the parent class has a different signature - eg it's private in the parent but public in your class, or static in one but not in the other, then you will get errors complaining about that. In this case, you'll need to make sure that the methods have the same signature, or else give your method a different name.
Hope that helps.
The answer of #Spudley is correctly chosen as the right answer.
Just more explanation on the first case mentioned in the answer: if you wand to declare the function inside of a method of a class, you should also consider the namespace of the class:
class MyClass
{
function myFunction()
{
//here, check if the function is defined in the root namespace globally
// or in the current namespace:
if(!function_exists('someFunction')
&& !function_exists(__NAMESPACE__ . '\someFunction'))
{
function someFunction()
{
}
}
//....
someFunction();
}
}
If you don't check the second condition of if, calling myFunction() more than once would throw exception

PHP create_function Instance variable - Unable to call anonymous function: Follow up

This is somewhat a follow up to a previous question - but I've distilled the question down and have the "works" vs. "doesn't work" cases narrowed down much more precisely.
My Goal:
I have a class MyClass that has an instance variable myFunction. Upon creating a MyClass object (instantiating), the constructor assigns the instance variable myFunction with the result of a call to create_function (where the code and args come from a db call).
Once this object of type MyClass is created (and stored as an instance variable of another class elsewhere) I want to be able to call myFunction (the instance variable anonymous function) from "anywhere" that I have the MyClass object.
Experimental Cases -- below is my highly simplified test code to illustrate what works vs. what doesn't (i.e. when the expected functionality breaks)
class MyClass extends AnotherClass {
public $myFunction;
function __construct() {
$functionCode = 'echo "NyanNyanNyan";';
$this->myFunction();
/*Now the following code works as expected if put in here for testing*/
$anonFunc = $this->myFunction;
$anonFunc(); //This call works just fine (echos to page)!
/*And if i make this call, it works too! */
self::TestCallAnon();
}
public function TestCallAnon() {
$anonFunc2 = $this->myFunction;
$anonFunc2();
}
}
However, if I do the following (in another file, it errors saying undefined function () in... within the Apache error log.
//I'm using Yii framework, and this is getting the user
//objects instance variable 'myClass'.
$object = Yii::app()->user->myClass;
$object->TestCallAnon(); // **FAILS**
or
$func = $object->myFunction;
$func(); // ** ALSO FAILS **
In addition, several variations of calls to call_user_func and call_user_func_array don't work.
If anyone is able to offer any insight or help that would be great :).
Thanks in advance!
You can't pass references to functions around in PHP like you can in for instance JavaScript.
call_user_func has limited functionality. You can use it like so:
class MyClass {
function func() {}
static function func() {}
}
function myfunc() {}
$i = new MyClass();
call_user_func("myfunc", $args);
call_user_func(array($i, "func"), $args);
call_user_func(array(MyClass, "staticFunc"), $args);
I ended up solving this issue via a workaround that ended up being a better choice anyways.
In the end I ended up having a static class that had a method to randomly return one of the possible identifiers, and then another method which accepted that identifier to build the anonymous function upon each class.
Slightly less elegant than I would like but it ends up working well.
Thanks to everyone for your efforts.

Categories