I understand why there should be no return values in constuctor, because it will not return any.
But still I see exactly this in a lot of scripts on the internet and I haven't managed to find an answer and it's buggin me for a while. If anyone would be kind enough to explain me, I would really apreciate.
Code I am refering to:
function __construct() {
return;
}
Actually, you may (no error will be occurred) use the return keyword in the __construct method but (you don't) that would be useless and won't return anything.
The __construct method doesn't create an object instance
It's not true that, the constructor creates the object instead, it's the new keyword which creates an object instance and returns the object. So, when we use something like this:
$obj = new SomeClass;
Then PHP creates the object returns the object instance. If this class contains any constructor method then this method is called by PHP after creation of that object instance. So, you can imagine, something similar:
class SomeClass {
public $prop = null;
public function init() {
$this->prop = 'SomeValue';
}
}
Now create the object and call the init method manually
$obj = new SomeClass;
$obj->init();
We created an instance of SomeClass and called the init methos manually but in the case of __construct method PHP calls the method automatically just after the creation of that object. So, we don't have to manually set the value to the prop property.
So, before the __construct method is called the object instance is created and without creating the object instance, the __construct method couldn't be called by PHP because $this refers to current object which is already created and if the object is not initialized then how can we call:
public function __construct()
{
$this->prop = 'SomeValue'; // $this refers to current object
}
The new keyword always returns an object instance:
Let's see this example:
class SomeClass {
public $prop = null;
public function __construct() {
$this->prop = 'SomeValue';
return $this->prop; // won't work
}
public function getProp() { ... }
}
Now check this:
$obj = new SomeClass;
If we were able to return a value from the constructor then how could we use the object instance using something like $obj->getProp() because logically it would contain SomeValue instead of the object reference/identifier, so it makes sense that PHP should not allow to return anything from the __construct method because this magic method get called automatically just after the creation of the object and we use new keyword to create the object instance that returned to us (into a variable) by the new keyword and if we return anything from the __construct method, it prevented by PHP and only an instance of the created object is returned if we didn't throw an exception explicitly.
To create an instance of a class, the new keyword must be used. An
object will always be created unless the object has a constructor
defined that throws an exception on error. Reference:PHP Manual
Though it's possible to use the return in the __constructor but it would be meaningless for example, check this:
class SomeClass {
public function __construct() {
return 'SomeValue'; // won't work
// or blank return
return;
}
}
Perhaps, you may do this (only for example):
class SomeClass {
public function __construct() {
if('some condition does not met then ...') return;
$this->prop = 'Prop is set';
}
public function doSomething(){
return $this->prop ? $this->prop : 'Sorry! Prop is set.';
}
}
Now try this:
$obj = new SomeClass;
echo $obj->doSomething();
If we just return before the second line in the constructor then the property won't be set otherwise the property will be set and doSomething method will output Prop is set. This may not a good way but for the example, I think this could be a valid code where return will stop execution of rest of the code. But it's not a good idea and maybe not required but for he sake of the example I can think the use of return, otherwise there is no need to use the return keyword in constructor and if someone uses it then it could be a personal choice of style or I don't know why.
That usually is a sign of poor implementation. A constructor "returns" nothing but an instance of it's own class.
Related
I have a class setup like this:
class myClass {
public function __construct() {
echo 'foo bar';
}
}
To run it, I can simply do:
$object = new myClass;
Is there any way to run the class so __construct initiates without creating a new variable with the class object.
For example, a basic function can be run with:
functionname();
Don't call __construct directly. If you need something in the constructor to occur but you don't want an object created as a result, then use a static method.
class Thing{
public static function talk(){echo "I talk";}
}
Thing::talk(); // 'I talk'
Static methods can be called without the need for an object instance of the class.
__construct is part of a special group of methods in PHP, called Magic Methods. You don't call these directly, but PHP will call them when some event occurs. For instance when you call new on a class, __construct is executed.
Another example: if you try to get a property that doesn't exist, __get will be executed (if found):
Class Thing{
public property $name = 'Berry';
public function __get($propertyName){
return "$propertyName does not exist!";
}
}
$t = new Thing();
echo $t->name; // 'Berry'
echo $t->weight; // 'weight does not exist!';
You can try something like this if you want to avoid static:
(new MyClass)->myFunction();
I have no idea why you need this but you don't need to create a variable. You can just create object without store it anywhere.
class myClass {
public function __construct() {
echo 'foo bar';
}
}
new myClass();
In this case only the constructor will be call.
PHP has a magic method __getStatic() that allows overloading of static method calls. I have a class with a fluent interface which performs integrity checks. I call it like this:-
$check = new CheckSomeCondition();
$check->forActive()->sites(array(1,2,3))->check();
However, I would like to call it like this:-
CheckSomeCondition::forActive()->sites(array(1,2,3))->check();
I thought that having this magic method in my base class would allow me to do this:-
public static function __callStatic($method, $args)
{
$instance = new self();
return call_user_func_array(array($instance, $method), $args);
}
But new self() produces an instance of the class that the calling code is in, and not the class which __callStatic() exists in, why is this? and how can I get around it?
I have also tried new static and this does the same thing.
I know this must be possible because Laravel's QueryBuilder has an interface like DB::table()->... and this uses method chaining, returning object instances, not static classes. I have had a look at the Laravel code, but I think they create the instances somewhere else in the application and they are stored in a class member ready to be returned.
The magic method __callStatic is only called for methods which don't exist, so in this case it will simply not run.
Consider the following simplified example:
class Foo
{
public function bar()
{
echo "Running instance method bar()";
}
public static function __callStatic($method, $args)
{
echo "__callStatic called for non-existent method $method";
}
}
Foo::bar();
If you run this (here's an online demo) you will see that it is the "real" bar() method that is called.
There can only be one method named bar on the class, so PHP's only other option would be to complain that bar() should be static - which it does, but non-fatally.
The reason you see an instance of the calling class is not that $instance is instantiated with the wrong class, but because when your method is called non-statically, $this "leaks" from the enclosing scope.
In the following example, $this ends up being the instance of Bar:
class Foo
{
public function doSomething()
{
echo get_class($this);
}
}
class Bar
{
public function doSomethingElse()
{
Foo::doSomething();
}
}
$bar = new Bar();
$bar->doSomethingElse();
Live Demo
As #IMSoP pointed out, __getStatic() is only called if there is no method with the name called - not just if there isn't a static method with the name.
So the workaround to allow calls such as CheckClass::forActive->sites() is to give all the non static method names a prefix such as '_' and have a magic method __call() which will add the prefix in.
This means if I do CheckClass::forActive() the method forActive() doesn't exist, so __getStatic() will be called and will create an instance of the object and try to call the desired method. But the method doesn't exist because we've prefix it, so PHP will call the __call() magic method which will add the prefix and call the prefixed method.
So the 2 functions are:-
public static function __callStatic($method, $args)
{
$instance = new self;
return call_user_func_array(array($instance, $method), $args);
}
public static function __call($method, $args)
{
$method = 'prefix_' . $method;
return call_user_func_array(array($instance, $method), $args);
}
// Then all our method names need to be prefixed, like so:-
public static function prefix_SomeMethod($method, $args)
{
// Do something
return $this;
}
I've seen this use of syntax a few times on the Yii framework. I tried searching for an explanation but got no examples. A link will be nice if possible. It goes something like class::model()->function();
My understanding is that model is an object of class therefore it can access the function. So I tried to code it but I get " Call to a member function sound() on a non-object in". Here's my code
class animal
{
private static $obj;
public static function obj($className = __CLASS__)
{
return self::$obj;
}
public static function walk()
{
return "walking";
}
}
include('animal.php');
class cat extends animal
{
public static function obj($className = __CLASS__)
{
return parent::obj($className);
}
public static function sound()
{
return "meow";
}
}
echo cat::obj()->sound();
Also what benefits does it have?
That is called an object operator and this, ->, calls a class method from your created object which is defined in that class.
Here is an explanation and some examples.
$obj = new Class; // Object of the class
$obj->classMethod(); // Calling a method from that class with the object
echo cat::obj()->sound();
This will display the output of the sound() method, called on the object that is returned from cat::obj().
The reason it's failing for you is because cat::obj() is not returning a valid object.
And the reason for that is because the obj() method returns the static obj property, but you're not actually setting that obj property anywhere.
The pattern you're trying to use here is known as a "Singleton" object. In this pattern, you call an obj() method to get the single instance of the class; every call to the method will give you the same object.
However the first call to the method needs to instantiate the object; this is what you're missing.
public static function obj($className = __CLASS__){
if(!static::$obj) {static::$obj = new static;}
return static::$obj;
}
See the new line where the object is created if it doesn't exist.
Also note that I've changed self to static. The way you're using this with class inheritance means that you probably expect to have a different static object for each class type, self will always return the root animal::$obj property, whereas static will return the $obj property for whichever class you're calling it from.
There are a few other bugs you need to watch out for too. For example, you've defined the sound() method as static, but you're calling it with ->, so it shouldn't be static.
Hope that helps.
The cat::obj() returns you a object of the type cat. With ->sound(); you're executing the function sound() from the class cat. All that should return "meow".
cat::obj() returns an object; ->sound(); execute a method of this object. Equivalent is
$o = cat::obj();
$o->sound();
Given the following classes:
<?php
class test{
static public function statfunc()
{
echo "this is the static function<br/>";
$api= new object;
}
}
class traductor
{
public function display()
{
echo "this is the object function";
}
}
test::statfunc();
$api->display();
This does not display the message "this is the static function<br/>".
Is there a way to instantiate through a static function and get that object outside?
Thanks... I am inexperienced regarding object programming code.
You should return the object from your static function:
static public function statfunc()
{
$api = new traductor;
return $api;
}
And then store the returned object in a variable that you can use.
$api = test::statfunc();
$api->display();
Your use of declaration is a bit off. Your code results in 2 fatal errors. First, class object is not found, you should replace:
$api= new object;
With
return new traductor;
Being a static class, they perform an action, they don't hold data, hence the static keyword. Down the line when you start working with $this and etc, remember that. You need to return the result to another variable.
test::statfunc();
$api->display();
Should become:
$api = test::statfunc();
$api->display();
See, http://php.net/manual/en/language.oop5.static.php for some more information on static keywords and examples.
I am not sure whether the technique I use is appropriate or not.
I have a class, singleton, with a subinstance like this:
final class Singleton {
public $subinstance;
private static $instance = NULL;
private function __construct() {
$this->subinstance = new subinstance();
}
public static function getInstance() {
if (NULL === self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
private function __clone() {}
}
And now if I want to access the subinstance from outside the class in another class, I do:
$s = singleton::getInstance();
$s->subinstance->....
Is this the right way to do this?
And what happens when I do $s=singleton::getInstance();, does the entire singleton class gets copied into $s or is this more like a pointer?
What you are doing is fine, although in your example code I'm assuming you meant to write:
$s = Singleton::getInstance(); // with the S capitalized
When you call the getInstance method, the class is looking to see if a version of itself has already been instantiated. If it has, it will return a reference to that instance instead of creating an entirely new instance. If the instance has not been created yet, it will create the instance and then return a reference to it.
I'm not sure why sixeightzero has stated that you shouldn't instantiate a class in the constructor of your instance. You shouldn't experience any issues when doing so.
If you do $a = singleton, $a will be a reference to the singleton class. Any changes in $a will reflect in access by singleton:: etc.. (pointer)
Why are you doing a subinstance in the constructor? This can cause issues, and should create a method to handle the subinstance outside the constructor inside a protected method. What does your subinstance look like?