I have a strange problem with one of my classes.
The class is the next one
namespace Core;
class RequestHandler{
protected $app;
public function RequestHandler($app){
echo "EEE";
$this->app = $app;
}
}
And the initialization is
$requestHandler = new Core\RequestHandler($app);
I don't know why it doesn't show anything, but if I change the constructor to __construct everything works fine.
I'm using php 5.6.20 and I know that it should execute the constructor by name too.
Check example here:
<?php
namespace Foo;
class Bar {
public function Bar() {
// treated as constructor in PHP 5.3.0-5.3.2
// treated as regular method as of PHP 5.3.3
}
}
?>
Warning
Old style constructors are DEPRECATED in PHP 7.0, and will be removed in a future version. You should always use __construct() in new code.
So in 5.6.20 constructor by name is not deprecated.
As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.
You may try to remove namespace, but I don't think it's good way to solve it.
Related
I have a registration class. The problem I'm facing is that the instantiation itself is somehow causing the functions within that class to be called.
I've tested this by adding an error_log() directly before and after the instantiation: $register = new Register(); every time I receive another error_log() which I placed inside the functions of the class that I'm instantiating.
How can I solve this?
EDIT this is what an example may look like:
testclass.php
class Test {
public function test() {
error_log("Function test() was run.'");
}
}
test.php
require_once("testclass.php");
$test = new Test();
It's because your function, test() has the same name of the class Test so PHP is using it as the constructor and calling it when you instantiate it.
class Bar {
public function Bar() {
// treated as constructor in PHP 5.3.0-5.3.2
// treated as regular method as of PHP 5.3.3
}
}
As the docs say:
Warning Old style constructors are DEPRECATED in PHP 7.0, and will be
removed in a future version. You should always use __construct() in
new code.
Code speaks better than words:
namespaces.php:
<?php
namespace foo;
use foo\models;
class factory
{
public static function create($name)
{
/*
* Note 1: FQN works!
* return call_user_func("\\foo\\models\\$name::getInstance");
*
* Note 2: direct instantiation of relative namespaces works!
* return models\test::getInstance();
*/
// Dynamic instantiation of relative namespaces fails: class 'models\test' not found
return call_user_func("models\\$name::getInstance");
}
}
namespace foo\models;
class test
{
public static $instance;
public static function getInstance()
{
if (!self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
public function __construct()
{
var_dump($this);
}
}
namespace_test.php:
<?php
require_once 'namespaces.php';
foo\factory::create('test');
As commented, if I use the full-qualified name inside call_user_func() it works as expected, but if I use relative namespaces it says the class was not found – but direct instantiations works. Am I missing something or its weird by design?
You have to use the fully qualified classname in callbacks.
See Example #3 call_user_func() using namespace name
<?php
namespace Foobar;
class Foo {
static public function test() {
print "Hello world!\n";
}
}
call_user_func(__NAMESPACE__ .'\Foo::test'); // As of PHP 5.3.0
call_user_func(array(__NAMESPACE__ .'\Foo', 'test')); // As of PHP 5.3.0
I believe this is because call_user_func is a function from the global scope, executing the callback from the global scope as well. In any case, see first sentence.
Also see the note aboveExample #2 Dynamically accessing namespaced elements which states
One must use the fully qualified name (class name with namespace prefix).
In current versions of PHP, the way you have it is the way it is -- when using a string to reference a classname, it needs to be fully qualified with it's complete namespace. It's not great, but that's the way it is.
In the forthcoming PHP v5.5, they will include a feature to address this, by providing a new Classname::class syntax, which you can use instead of putting the FQN classname in a string.
For more info on this, please see the relevant PHP RFC page here: https://wiki.php.net/rfc/class_name_scalars
Your code would look something like this:
return call_user_func([models\$name::class,"getInstance"]);
That may not be exact; I don't have a copy of 5.5 to test with to confirm. But either way, the new syntax will make things a lot better for use cases like yours.
I came across this very strange behavior.
The following code
class TestClass {
function testClass() {
echo "Don't show me!";
}
}
$testing = new TestClass;
executes its method testClass without it being called!
However, testClass won't run if renamed into anything else like testClass1.
Is there any hidden 'PHP magic' behind this behaviour?
EDIT.
At the end I see this question is trivial to ninjas grown up with PHP. As recent newcomer to PHP, I've learned to use __construct as constructor. With that "relic behaviour" carefully removed from modern tutorials. I am so glad people realized how terrible it was, changing class name and forgetting to change that of the constructor - what a nightmare!
Pre-PHP5, the __construct method was not used as the class constructor. Instead, a method with the same name as the class was used.
From the documentation:
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, and the class did not inherit one from a parent class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.
Creating a (empty) constructor (method named __construct) will stop the message from being echoed upon class initialization (only needed for < PHP 5.3.3 *):
class TestClass {
function __construct() {
}
function testClass() {
echo "Don't show me!";
}
}
* As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.
In older versions of PHP a method with the same name as the classname was considered the constructor.
What exactly is the difference in PHP classes when using the __construct constructor and when using the name of the class as constructor?
For example:
class Some
{
public function __construct($id)
{
....
}
....
}
OR
class Some
{
public function Some($id)
{
....
}
....
}
The top is the new way it is done in PHP as of version 5.0 and is how all new code should be written. The latter is the old PHP 4 way and is obsolete. At some point it will be completely deprecated and removed from PHP altogether.
Update
As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.
<?php
namespace Foo;
class Bar {
public function Bar() {
// treated as constructor in PHP 5.3.0-5.3.2
// treated as regular method as of PHP 5.3.3
}
}
?>
Before PHP 5.3.3 the following
class Same {
public function same() { echo 'Not good'; }
}
$c = new Same();
will output Not good.
From 5.3.3+ instead it will not output the string. That's because from PHP 5.3.3 functions with the same name of the class are not considered constructors.
How do I force this behavior even with PHP 5.3.2 or before?
The easiest way is probably just to create an empty constructor:
class Same {
public function same() { echo 'Not good'; }
public function __construct() { }
}
$c = new Same();
That won't echo "Not good" as the __construct() method overrides the "same name as class" method.
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.
Unlike with other methods, PHP will not generate an E_STRICT level error message when __construct() is overridden with different parameters than the parent __construct() method has.
As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.
docs:- http://php.net/manual/en/language.oop5.decon.php
So obvious solution is to declare a __constructors method (even is an empty one)
The construct method is named __construct(). Simply call your same()-method inside __construct() if u wish to have the same name.
According to http://php.net/construct php tries to reserve backwards compatibility. In my opinion the "same" name means writing the method name case-sensitive (as the class name). That should work too.