Why pass variables to a class instead of method - php

I was wondering what is the benefit of passing parameters to a class rather than to a method.
In terms of code, what's the benefit of doing this:
$books = new Books($book_id, $book_name);
instead of
$books = new Books;
$books->setBook($book_id, $book_name);
Thanks!

"Passing to a class" is not a thing. new Foo($bar, $baz) is instantiating a new object and is passing parameters to the constructor method:
class Foo {
public function __construct($bar, $baz) {
...
}
}
There's no difference as such between passing parameters to a regular method and to the constructor. The only difference is that the constructor is called when an object is instantiated, and other methods are called anytime later.
You should pass parameters to the constructor which the object requires at construction time. Typically this means you pass parameters which are required for the object to work at all. The constructor can throw an exception if it doesn't like the parameters, which means the object will fail to instantiate at all. This guarantees that the object is in a known, consistent state. Compare:
$api = new FooAPI($id, $password);
$api->doSomething();
$api = new FooAPI;
// $api->setId($id);
// $api->setPassword($password);
$api->doSomething(); // Error! No id and password given

While #deceze answer covers the major facts, I'd like to additionally state one of the most crucial point - perhaps emphasizing
paraphrasing from here
Each concrete object would have a constructor with a signature which
represents how a consumer should fully instantiate the object.

if you will see the assembly code of same code snippet which u have giv en you ll notice it increases around 5-6 instruction so it depends if you which method u want to prefer.but generally the first one is prefered if you know the values for instance variables while creating the object else the second one is prefered as it saves load of 5-6 instructions on processor.i have written the both code snippets in c++ and analysed their assembly code.

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?

Calling methods of embedded objects

Assuming we have an object that gets 3 objects in constructor:
$SomeObject = new Object($UrlChecker, $UrlModifier, $UrlComposer);
Wouldn't it be better to create an wrapper object $Url like this:
class Url {
public $Modifier;
public $Composer;
public $Checker;
public function __construct(){
$this->Modifier = new UrlModifier();
$this->Composer = new UrlComposer();
$this->Checker = new UrlChecker();
}
}
And then pass only this $Url object:
$Url = new Url();
$SomeObject = new Object($Url);
Now all the objects will be created in the $Url object and I can call their memebers within the object $SomeObject like this:
$Url->modifier->set_parameter($param);
Is it a good practice to set embedded object as public or should I create for every object a getter-method? Or maybe I should stick with the first variant by passing all three objects to the $SomeClass?
I thought I could use public methods like Java's "System.out" does, where "out" is an public member/object within the System-object.
I don't see how this:
$this->url->modifier->set_parameter($param);
is better than this:
$this->modifier->set_parameter($param);
You're requiring additional steps for the caller and the callee without clear benefit. The first approach makes it appear that the methods are somehow working of the same base data (somehow stored in $url). However, that is not the case (your goal appears to be organization but really you should be driven by which object controls the state/base data). The base data would/should be stored in the controlling object (represented by $this). So, having said that...
Is it a good practice to set embedded object as public or should I
create for every object a getter-method?
... you should hide the objects and create getters/setters on the main object since it needs to control (the basis of encapsulation) the injected objects (which is why you injected them in the first place).
Definitely use private variable if you intend to use $modifier, $composer, and $checker internally and create getter and setter method for those variables. It's OOP concept called encapsulation. The main purpose is to protect an object integrity by preventing users from setting the internal data of the component into an invalid or inconsistent state.

php constructor inheritance

I want to clarify a problem i am having
I have a base DataBase class that will be inherited by a bunch of other classes.The constructor looks like this:
public function __construct ($table)
{
$this->table = $table;
$this->db = new Database();
$this->db->connect();
}
I will call from this constructor from children as following:
public function __construct ($something)
{
parent::__construct("planets_games");
}
My problem is that php doesn't allow me to make the child's constructor without the $something parameter
i get the following:
Fatal error: Declaration of planetsGames::__construct() must be compatible with that of IScaffold::__construct()
I am currently bypassing this by instantiating an object like this:
$pg = new planetsGames('uselessStringHereThatHasNoUtilityAtAll');
I think i am missing something very important in my basic php knowledge
Thank you very much for the help in advance
This error message refers to the liskov substitution principle.
It applies to every IS-A relationship (which is the meaning of using inheritance (extends)) and states that every subtype should be fully replacable for the super type.
But this doesn´t apply to constructors! Which php version you are using?
It seems the base class has marked the constructor as abstract. That´s the only way
this error can appear.
You should never mark constructors abstract, final or put them in interfaces!
In most languages this isn´t even possible.
What you should take away from this is that the best-practice is that
each concrete object has a constructor with a signature that best
represents how a consumer should fully instantiate that particular
object. In some cases where inheritance is involved, “borrowing” the
parents constructor is acceptable and useful. Furthermore, it is
encouraged that when you subclass a particular type, that your new
type should, when appropriate, have its own constructor that makes the
most sense to the new subtype.
http://ralphschindler.com/2012/03/09/php-constructor-best-practices-and-the-prototype-pattern
A few years late to the party....
The problem is your constructor is needing a value. You can prevent the fatal error by setting a default value such as an empty string.
public function __construct($something = "")
{
parent::__construct("planets_games");
}
Then just instantiate the class like normal
$pg = new planetsGames();

PHP constructor uses? [duplicate]

In my quest in trying to learn more about OOP in PHP. I have come across the constructor function a good few times and simply can't ignore it anymore. In my understanding, the constructor is called upon the moment I create an object, is this correct?
But why would I need to create this constructor if I can use "normal" functions or methods as their called?
cheers,
Keith
The constructor allows you to ensure that the object is put in a particular state before you attempt to use it. For example, if your object has certain properties that are required for it to be used, you could initialize them in the constructor. Also, constructors allow a efficient way to initialize objects.
Yes the constructor is called when the object is created.
A small example of the usefulness of a constructor is this
class Bar
{
// The variable we will be using within our class
var $val;
// This function is called when someone does $foo = new Bar();
// But this constructor has also an $var within its definition,
// So you have to do $foo = new Bar("some data")
function __construct($var)
{
// Assign's the $var from the constructor to the $val variable
// we defined above
$this->val = $var
}
}
$foo = new Bar("baz");
echo $foo->val // baz
// You can also do this to see everything defined within the class
print_r($foo);
UPDATE:
A question also asked why this should be used, a real life example is a database class, where you call the object with the username and password and table to connect to, which the constructor would connect to. Then you have the functions to do all the work within that database.
The idea of constructor is to prepare initial bunch of data for the object, so it can behave expectedly.
Just call a method is not a deal, because you can forget to do that, and this cannot be specified as "required before work" in syntax - so you'll get "broken" object.
Constructors are good for a variety of things. They initialize variables in your class. Say you are creating a BankAccount class. $b = new BankAccount(60); has a constructor that gives the bank account an initial value. They set variables within the class basically or they can also initialize other classes (inheritance).
The constructor is for initialisation done when an object is created.
You would not want to call an arbitrary method on a newly created object because this goes against the idea of encapsulation, and would require code using this object to have inherent knowledge of its inner workings (and requires more effort).

Benefits of using a constructor?

In my quest in trying to learn more about OOP in PHP. I have come across the constructor function a good few times and simply can't ignore it anymore. In my understanding, the constructor is called upon the moment I create an object, is this correct?
But why would I need to create this constructor if I can use "normal" functions or methods as their called?
cheers,
Keith
The constructor allows you to ensure that the object is put in a particular state before you attempt to use it. For example, if your object has certain properties that are required for it to be used, you could initialize them in the constructor. Also, constructors allow a efficient way to initialize objects.
Yes the constructor is called when the object is created.
A small example of the usefulness of a constructor is this
class Bar
{
// The variable we will be using within our class
var $val;
// This function is called when someone does $foo = new Bar();
// But this constructor has also an $var within its definition,
// So you have to do $foo = new Bar("some data")
function __construct($var)
{
// Assign's the $var from the constructor to the $val variable
// we defined above
$this->val = $var
}
}
$foo = new Bar("baz");
echo $foo->val // baz
// You can also do this to see everything defined within the class
print_r($foo);
UPDATE:
A question also asked why this should be used, a real life example is a database class, where you call the object with the username and password and table to connect to, which the constructor would connect to. Then you have the functions to do all the work within that database.
The idea of constructor is to prepare initial bunch of data for the object, so it can behave expectedly.
Just call a method is not a deal, because you can forget to do that, and this cannot be specified as "required before work" in syntax - so you'll get "broken" object.
Constructors are good for a variety of things. They initialize variables in your class. Say you are creating a BankAccount class. $b = new BankAccount(60); has a constructor that gives the bank account an initial value. They set variables within the class basically or they can also initialize other classes (inheritance).
The constructor is for initialisation done when an object is created.
You would not want to call an arbitrary method on a newly created object because this goes against the idea of encapsulation, and would require code using this object to have inherent knowledge of its inner workings (and requires more effort).

Categories