Is there any difference in constructor or unified constructor. I have a class which have a constructor and a unified constructor. When i intialise object of the class then unified constructor call why not normal constructor.
<?php
class test {
function __construct() {
print "In BaseClass constructor\n";
}
function test() {
echo 'Class loeaded';
}
}
$obj = new test();
?>
OUTPUI
In BaseClass constructor
PHP Version 5.2.6
Since PHP 5, the best way to declare a constructor method in a class is to use the standardized
__construct()
So if you have
class myA {
public function __construct() {
echo "hello construct myA";
}
public function myA() {
echo "hello basic way myA";
}
}
$myA = new myA();
It will echo
hello construct myA
because the __constructor() has priority
But, for compatibility reason, the old way may work if there is not __construct() method.
And:
class myA {
//public function __construct() {
// echo "hello construct A";
//}
public function myA() {
echo "hello basic way myA";
}
}
$myA = new myA();
will give you:
hello basic way myA
In all cases, I advise you to use __construct()
the old constructor (method with class name) is only there for compatibility reasons. so if you have the new constructor (__construct) in the class php won't bother to call the old one.
edit
interesting note is that calling parent::__construct when the class being extended has only the old constructor type will still work (it becomes like a alias to the real constructor)
Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.
Read documentation of constructor (link)
Instances of classes are created using the new keyword. What happens during the new call is that a new object is allocated with its own copies of the properties defined in the class you requested, and then the constructor of the object is called in case one was defined. The constructor is a method named __construct(), which is automatically called by the new keyword after creating the object. It is usually used to automatically perform various initializations such as property initializations. Constructors can also accept arguments, in which case, when the new statement is written, you also need to send the constructor the function parameters in between the parentheses.
In PHP 4, instead of using __construct() as the constructor’s name, you had to define a method with the classes’ names, like C++. This still works with PHP 5, but you should use the new unified constructor naming convention for new applications.
We could pass the names of the people on the new line in the following class example :
class Person {
function __construct($name)
{
$this->name = $name;
}
function getName()
{
return $this->name;
}
private $name;
};
$judy = new Person("Judy") . "\n";
$joe = new Person("Joe") . "\n";
print $judy->getName();
print $joe->getName();
Tip: Because a constructor cannot return a value, the most common practice for raising an error from within the constructor is by throwing an exception.
According to documentation As of PHP 5.3.3, methods with the same name as that of class will no longer be treated as constructor .. They are like regular methods ...
<?php
class myclass
{
public function myclass()
{
// treated as constructor in PHP 5.3.0-5.3.2
// treated as regular method as of PHP 5.3.3
}
}
?>
`
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.
It means that there if you have constructor myclass() and __construct .. then __construct will be searched for first and taken as constructor instead of myclass()
class myclass
{
public function myclass()
{
echo 'hello';
}
function __construct() {
print "new constructor"
}
}
$obj = new myclass(); // will echo new constructor
Related
I want to declare a non-public constructor so it's users of the class can't call new Message() directly but have to instantiate the object from a static builder method declared on an abstract class that Message extends.
So far my code is:
abstract class SqlDecodable {
public function instanceFromRawSql (array $rawSql) {
$newInstanceToReturn = new static() // problem is here
// .. map the new instance ..
return $newInstance ;
}
}
// for exemple...
class Message extends SqlDecodable {
private $receiverId ;
private $senderId ;
private $text ;
private/protected/public?? function __construct() {
// problem here : this constructor should be usable only by
parent class, not for user of Message
}
static function propertiesToSqlFields() {
return [
"receiverId" => "receiver_id_field_in_db",
"senderId" => "sender_id",
"text" => "text"
]
}
}
This is actually more complicated, but I simplified the system for this question
When I implement my method instanceFromRawSqlArray, I have to create a new instance of the child class: $instanceToReturn = new static(), and set the variables one by one afterwards.
Though, I don't want to let a __construct that takes no args in my model classes. I don't want the dev user of Message to be able to new Message().
This constructor should be usable only by instanceFromRawSqlArray.
The problem is that, as I saw, there is no C++ friends class in PHP. I can't make my __construct protected, because, as I saw, protected methods are accessibles for childs, not for parent.
Do you have ideas to map this new instance in the method instanceFromRawSqlArray, without creating any constructor or setter that would corrupt my model class "encapsulation protections"?
You were very close. You can simply declare your constructor to be protected.
Instantiating the class directly won't work, but you can call new from the static method declared in the abstract class.
E.g.:
abstract class SuperAbstract {
static function create() {
return new static();
}
}
class Extended extends SuperAbstract {
private $hello = '';
protected function __construct() {
$this->hello = "world";
}
public function hello() {
return "hello " . $this->hello;
}
}
// works
$a = Extended::create();
echo $a->hello(); // outputs "hello world"
// can't touch this. This will fail because the constructor is `protected`.
$b = new Extended();
Of course, since it's protected the constructor could also be called from children classes. That's unavoidable, as long as children classes are a possibility. But you could also declare Extended as final, making extension of the class impossible. Thus, it would only be possible to create new instances from the factory method defined in the abstract parent.
final Extended extends SuperAbstract
protected function __construct() { }
}
You can see it working (and failing), here: https://3v4l.org/LliKj
This question already has an answer here:
Too few arguments to function Db::__construct(), 0 passed in
(1 answer)
Closed 4 years ago.
When I run this, it complains that
Too few arguments to function Base::__construct(), 0 passed in [FileName].php on line 18 and exactly 1 expected
class Base {
protected $var;
public function __construct($var){
$this->var = $var;
}
}
class ChildA extends Base {
public function handle(){
echo $this->var;
}
}
$base = new Base(10);
(new ChildA())->handle();
But as you can see, I have passed:
$base = new Base(10);
Edit: As mentioned in answers and comments, the problem was not in here:
$base = new Base(10);
...but here:
(new ChildA())->handle();
What am I doing wrong? Also, what I am trying to achieve is that, there are many ChildX classes who need to extend Base and all these child classes must have the $var property. So, Instead of duplicating the $var in each child classes, I wanted to reduce typing effort by putting it in a parent class. But apparently, my plan didn't work out.
Your problem is actually this line:
(new ChildA())->handle();
Do this instead:
$child = new ChildA(10);
$child->handle();
You don't need to instantiate the base class separately.
One other thing. When both parent and child classes have a constructor, you can put parent::__construct($whatever); in the child's constructor to run the parent code also.
This is a simple concept of class instantiation, I think which you are getting it wrong.
When you did
$base = new Base(10);
you are creating an instance of the Base class only.
However, the following statement invokes another instance of the Child class. Note, the base variable and this child instance are two different entities, hence their behaviour will not impact each other.
(new ChildA())->handle();
So, currently base variable will have a value of 10, but the handle() function call cannot be instantiated since it requires an argument which is to be supplied to the new instance of the Base class.
You'll need to instantiate the child class, due to which the constructor of the inherited class will be called first and your variable will be set. Your handle() function can then successfully return the correct value.
$child = new Child(10); $child->handle(); //returns 10
When you extend a class, all the methods on that class exist on the child class by default, including "magic" methods like __construct.
So when you write this:
class Base {
protected $var;
public function __construct($var){
$this->var = $var;
}
}
class ChildA extends Base {
public function handle(){
echo $this->var;
}
}
Your child class actually looks something like this:
class ChildA extends Base {
// Inherited property from Base class
protected $var;
// Inherited method from Base class
public function __construct($var){
$this->var = $var;
}
// New method in this class
public function handle(){
echo $this->var;
}
}
This is a slight simplification, as we'll see below, but it explains what happens in your example:
$base = new Base(10);
$base is an instance of the Base class; it is completely separate from any other instance of that class, and from any instance of the ChildA class.
(new ChildA())->handle();
This attempts to run the __construct method in the ChildA class; the copy of that method inherited from Base requires an argument, but you didn't supply one, so you get an error. It is expecting you to call it like this:
(new ChildA(10))->handle();
If we define __construct directly in the child class, we can give it a different number of arguments:
class ChildB extends Base {
public function __construct() {
// Do nothing
}
public function handle(){
echo $this->var;
}
}
(new ChildB())->handle();
But now we have a different problem: the logic in the Base class isn't running, so $this->var is never set to anything.
This is where I over-simplified things above. In reality, the parent __construct method and child __construct method both exist, they just "hide" each other. You can access the parent copy with the syntax parent::method.
So you can make a child class, with a constructor which takes no arguments, and when that constructor is run, run the base constructor with a hard-coded value of 10:
class ChildC extends Base {
public function __construct() {
// Run the constructor in the Base class
parent::__construct(10);
}
public function handle(){
echo $this->var;
}
}
(new ChildC())->handle();
Your new ChildA() is calling constructor from Base and you are not passing any arguments here.
You make mistake here: when you do new Base(10) your $var is not passed to new instance of new ChildA()
In your case I would use static parameter instead of constructor value
class Base {
protected static $var;
public function __construct(){
}
public static function setVar($var) {
self::$var = $var;
}
}
class ChildA extends Base {
public function handle(){
echo self::$var;
}
}
Base::setVar(10);
(new ChildA())->handle();
Looking for a clean way to determine the class (in this case, either parent or child class) of the method that calls a method in the parent class.
I thought late static binding could handle this, but seems like that only really works for calling a static method directly, and not from within an instantiated object's method.
Consider the following:
abstract class ParentClass {
public function parentMethod() {
self::_log("parent.non.static");
}
public static function parentStatic() {
self::_log("parent.static");
}
public static function getClassName() {
return __CLASS__;
}
protected static function _log($key) {
$prefix = 'graphite.key.prefix';
$class = static::getClassName(); // gets the object's class, not calling class
$g_key = "{$prefix}.{$class}.{$key}";
echo "{$g_key} \n";
// Graphite::increment($g_key);
}
}
class ChildClass extends ParentClass {
public function childMethod() {
self::_log("child.non.static");
}
public static function childStatic() {
self::_log("child.static");
}
public static function getClassName() {
return __CLASS__;
}
}
$obj = new ChildClass;
$obj->childMethod(); // graphite.key.prefix.ChildClass.child.non.static
$obj->parentMethod(); // graphite.key.prefix.ChildClass.parent.non.static
ParentClass::parentStatic(); // graphite.key.prefix.ParentClass.parent.static
ChildClass::childStatic(); // graphite.key.prefix.ChildClass.child.static
Looking for a clean way to get the class that calls the _log() method without having to pass it in as a parameter. Doesn't have to be static at all, but I was playing around with the late static binding, because I thought that would work, but it just gets the name of the instantiated object, not the child/parent class of the method that calls the _log() method :-/
Edit:
Just to be clear, I'm after getting the class name of the method that called _log() from within the instantiated object (like parentMethod() and childMethod()) Don't care if _log() is static or not. If that makes it easier, fine. But the static ParentClass::parentStatic() and ChildClass::childStatic() were just to show late static bindings and what I figured might work, but not from calling within an instantiated object
http://php.net/manual/en/function.get-called-class.php
class One {
public static function test() {
echo get_called_class() . PHP_EOL;
}
}
class Two extends One {}
One::test();
Two::test();
Output:
One
Two
Also, according to the top comment in the docs static::class also works as of PHP 5.5.
get_class will get the class name of a class instance. This can also be called on $this within a class. If you have a class that extends/implements another, $this will refer the the instantiated class, meaning the child class.
Another option is to use debug_backtrace to get the stack of functions that lead up to where you currently are. You can parse the returned array to get whatever you need including line numbers, classes, functions, methods, whatever.
First, quote from PHP manual (http://php.net/manual/en/keyword.extends.php):
The extended or derived class has all variables and functions of the
base class (this is called 'inheritance' despite the fact that nobody
died) and what you add in the extended definition.
So why is that this simple example doesn't work:
<?php
class A
{
private function a()
{
echo 'a';
}
public function b()
{
echo 'b';
}
}
class B extends A
{
//no extended definition, only what's inherited
}
$object_B = new B();
echo $object_B->b(); // fatal error: Call to private A::a() from invalid context
?>
After some experimenting, it turns out that removing method a from class A
makes it work. And I'm not even calling it anywhere.
You can use a method of the same name as a constructor with a PHP class. So, your method a is acting as a constructor for class A.
Rename your method, and it should work:
class First
{
private function another()
{
echo 'a';
}
public function b()
{
echo 'b';
}
}
See __construct() vs SameAsClassName() for constructor in PHP
"Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP" - Reports PHP 7 after executing the sample code.
I think you can't name the method with the same name as the class. In older PHP-Versions you could define the constructor of the class by naming the method like the class. PHP assumes the functions a to be a constructor. So it won't work that way.
Like Zac Brown said, you have to use the __construct() method.
In class A you have define a() method it with same name of class. so it is constructor method of A class. but in PHP you can not make private constructor method. your code should be like this.
<?php
class A
{
public function a()
{
echo 'a';
}
public function b()
{
echo 'b';
}
}
class B extends A
{
//no extended definition, only what's inherited
}
$object_B = new B();
echo $object_B->b();
Here's the clarification:
You are defining method a() in Class A. They have the same name so method a() is treated as constructor of Class A. Therefore, the moment you initialize Class B in $object_B = new B();, you initialize Class A too since A is extending B and the constructor method is called. Because Classes which have a constructor method call this method on each newly-created object PHP Constructor. and hence the error.
I believe this clarifies your doubt.
I have some code:
class a {
public static function getCl() {
echo __CLASS__;
}
public function test() {
static::getCl();
}
}
class b extends a {
public static function getCl() {
echo __CLASS__;
}
}
$testClass = new b();
$testClass->test();
and this result : b. Then i try this:
class a {
public static function getCl() {
echo __CLASS__;
}
public function test() {
$this->getCl();
}
}
class b extends a {
public static function getCl() {
echo __CLASS__;
}
}
$testClass = new b();
$testClass->test();
this result is still b. I already know the different between static:: and self:: but can someone show me what is the different between static:: and $this-> in my code. Which one should i use?
Your context will produce the same result.
Here is simply description about both.
static:- refers late static binding As of PHP 5.3.0, PHP implements a feature called late static bindings which can be used to reference the called class in a context of static inheritance.
Static references to the current class like self:: or CLASS are resolved using the class in which the function belongs, as in where it was defined:
While Late static bindings tries to solve that limitation by introducing a keyword that references the class that was initially called at runtime. Basically, a keyword that would allow you to reference child class from parent class method. It was decided not to introduce a new keyword but rather use static that was already reserved.
$this:- refers current object.
Once inside an object's function, you have complete access to its variables, but to set them you need to be more specific than just using the variable name you want to work with. To properly specify you want to work with a local variable, you need to use the special $this variable, which PHP always sets to point to the object you are currently working with.