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.
Related
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?
Sometimes when I look at code other people have written I see something like the following:
<?php
namespace sys\database;
class Statistics {
public function __construct() {
// Database statistics are gathered here using
// private methods of the class and then set to
// class properties
}
public static function getInstance() {
return new \sys\database\Statistics();
}
// ...
}
So the static function getInstance() simply returns an object of the class it belongs to. Then, somewhere else in the code I come across this:
$stats = \sys\database\Statistics::getInstance();
Which simply sets $stats to an instance of the Statistics object, ready for its class properties to be accessed to get various database statistics.
I was wondering why it was done this way as opposed to just using $stats = new \sys\database\Statistics();. At the end of the day, all the logic to gather statistics is in the constructor and the getInstance() method doesn't do anything other than returning a new object.
Is there something I'm missing here?
This is supposed to be an implementation of the Singleton pattern: http://www.oodesign.com/singleton-pattern.html
The pattern is used to never allow more than one instance of the class to be created.
However, there are a couple of flaws with the implementation you provided: the constructor should be private, and there should be a single private static instance of the class, returned every time the getInstance method is called.
This is supposed to be an implementation of the Singleton pattern, which is a term used to describe a class which can only exist once for run-time.
It seems the implementation you have is flawed however because:
there is no check to see if the class exists yet and
code can create multiple instances by calling the constructor directly (it should be made private)
That's a [bad] implementation of the Singleton pattern.
As a rule of thumb, you should avoid such pattern in favour of more convenient Dependency Injection, for instance.
How can I ensure that an object will be instantiated only via another particular object?
For example, say I have a Registry object to store my Mappers. When client code calls the get() method on the Registry, it lazy loads and returns the requested Mapper. That's fine, except there is nothing to stop client code from creating a duplicate instance of the Mapper using the new operator.
The only option I can think of is that my Mappers require a Registry object as a parameter. Are there other options?
What do you do? Should I even bother about preventing this kind of duplication?
Perhaps you should not try to prevent people from creating instances themselves? If you don't trust yourself or your colleagues not to instantiate objects in places where they should not instantiate them, you have a problem.
If the mappers do not need a registry to function, you should not object it via the constructor. Passing it to some static method seems rather odd, and makes your code less flexible since you're using static. And how are you going to unit test the mappers, without writing some hacks to properly instantiate them via the registry you should not have need for in these tests? Good post on that here: http://kore-nordmann.de/blog/0103_static_considered_harmful.html
You can't protect from the new operator. What you could do though is that you have a get() method in your class to make your class/object singleton (or using a Registry as you do).
class clTest {
private static $oInstance;
public static function get() {
if( !self::$oInstance ) {
self::$oInstance = new clText;
}
return self::$oInstance;
}
}
if you wish to prevent outside instantiation you only need to declare __construct as private and then use a call to a static method to get an instance of the Mapper class. You can then pass in an instance of the registry class and only return a new instance if the parameter is an instance of the registry class.
class Mapper{
private __construct(){}
public static function getInstance($registry){
if($registry instanceof Registry){
return new Mapper();
}
}
}
$registry = new Registry();
$mapper = Mapper::getInstance($registry);
I have done a few projects lately using a Database Object super class which I use for quick one off record query/update, and extending with appropriate classes, such as a User class.
I found that many classes I was writing had the exact same methods: query_values(), update(), delete(), etc.
So I came up with a class with a constructor that looks like this:
public function __construct($table, $db_object, $record_id = null){
$this->db = $db_object; // Database object with query methods
$this->table = $table; // The name of the database table
$this->get_column_data();
if(!is_null($record_id)){
// This retrieves all column values,
// stores into private $fields array property
$this->query_values($record_id);
}
}
And a child class constructor looks like this:
public function __construct($db_object, $record_id = null){
parent::__construct($this->table, $db_object, $record_id);
}
Where the $table property is defined at the top, as we should know which table this specific object works with.
Now, all common record management methods are in one place, and methods specific to the class are all that is defined in their respective child-classes.
The biggest drawback I see here is that all data fields are pulled and are encapsulated within the $fields property, so either generic get and set methods need to be defined (which I typically do) which almost negates the encapsulation*, or a method must be defined specifically for each property we want to expose.
*Example:
$user_id = $User->id; // NOT USING MY METHOD
vs.
$user_id = $User->_get('id'); // ACCESSES $User->fields['id']
Do you see this as a drawback, or a plus? The goal being ease of use, object-orientation (encapsulation), and just being plain awesome!
Well, you could make your life easy and use PHP's magic overloading __call method to create generic getters and setters. You could add the following method to your "Database Object super-class":
/**
* Create magic getter and setter methods to access private $fields array
*/
public function __call($method, $args)
{
$prefix = substr($method, 0, 3);
$prop = lcfirst(substr($method, 3));
if (isset($this->fields[$prop])) {
if ($prefix == 'get') {
return $this->fields[$prop];
} elseif ($prefix == 'set') {
if ( ! isset($args[0])) {
$msg = 'Missing argument: ' . get_class($this) . "::$method must specify a value";
throw new InvalidArgumentException($msg);
}
$this->fields[$prop] = $args[0];
return;
}
}
$msg = 'Invalid method: ' . get_class($this) . "::$method does not exist";
throw new BadMethodCallException($msg);
}
So let me explain what's going on here. The magic __call method will receive calls to any object method that does not match one of the object's concrete methods. It receives as parameters the name of the method that was called and an array of its arguments.
The __call method above does a quick substr check to see if the method was a "getter" or "setter" (using the first three letters of the method name). It expects that your $fields array stores lower-case "property" names (lcfirst) and uses everything after the setter/getter prefix as the expected property name.
If a property matches the getter method then that property it is returned. If not, the SplException BadMethodCallException is thrown. This is a best practice since the inclusion of the Spl exceptions in PHP.
Likewise a setter method will also throw the SplException InvalidArgumentException if no argument was specified.
PHP's magic methods will change your life. You can also use __get and __set to assign $fields array values in a similar fashion without making faux method calls. Get excited :)
You can have the best of both worlds by implementing a few magic methods on your objects. For example, by implementing __get, __set and __isset you can make the property accesses look "natural" (e.g. $user->id) while at the same time not having to define properties in each separate subclass.
For example, the implementation of __get could check at runtime the $fields member to see if the property you are attempting to get is valid for the specific object class. You can write this generic implementation once in the base class, and just populate $fields accordingly to make it work with any kind of object. This is actually what all modern mapping tools do, including probably all of the PHP frameworks that you have heard of.
As an aside, I hope you are caching the table schema per-class inside get_column_data. It would be really inefficient to requery the database for the schema of the same table every time you construct an object of the corresponding class.
There are two major approaches:
PHP file creation
All big ORM / database projects I know do not let the user write all getter methods himself. Both Doctrine and Propel use automatical generators to create real PHP files with the getter methods when you call a command line script. These files contain so called Base methods which are automatically extended by some classes you will put your own code in (so recreation of the base class will not delete your own code).
Advantage of file creation is that you have a well defined interface (some people dislike it when callable methods are not visible directly within the source code).
Magic methods / overloading
A database engine I have seen at client’s application used magic methods to simulate getters and setters. You could either use magic methods __get() and __set() or __call() (called “overloading” in PHP documentation) for this. Which method to use depends on how you want to access your values (most common $obj->property or $obj->getProperty()).
Advantage of overloading is that you do not need to write a complex PHP code generator, nor do you need to call a command line script each time you change your database design.
I'm trying to learn when static functions should be used, and have had a difficult time finding an answer my questions. I am creating a class User, which is related to a class Group. If I have a user id and I want to get a user object from that, is it better to do something like
$existingUser = User::get($userId);
where the class is defined like this
class User()
{
public static function get($id){
$user = new User();
return $user->findById($id);
}
public function findById($id) {
//find and populate user object
}
}
or
$existingUser=new User();
$existingUser->findById($userId);
where the class is defined like this
class User()
{
public function findById($id) {
//find and populate user object
}
}
What about if I were to write a function which returns an array of Group objects based on a user id?
class User()
{
//stuff
$groupArray = Group::getAllByUserId($this->getId())
//stuff
}
or
class User()
{
//stuff
$group = new Group();
$groupArray = $group->findAllByUserId($this->getId());
//stuff
}
The second method creates an empty group object which is never used. Does it matter?
Am I misunderstanding the concept of static? I know it is useful for not having to instantiate a class, so if the function instantiates one anyway, does that kind of defeat the purpose? If so, what would be an example of when a static function would be used?
Anything else I should be considering in this over simplified example?
You don't need a static function int he case you show above.
Static functions are really just global functions with a namespace.
Use them when the global state of the application needs to be controlled, or if multiple copies of the function lead to inonsistant results.
Callbacks sometimes need to be static, especially if they are passed as a string.
I'm trying to learn when static functions should be used
Oh, it's so simple: never.
To understand it, read:
http://www.objectmentor.com/resources/articles/ocp.pdf
http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/
I find a good rule of thumb is thinking "If I don't have a [class-name], would I expect to be able to call [method-name]?"
If I don't have a user, would I expect to be able to call findByID?
Probably not. This is one of the exceptions I come across; a "load" or a "save" method sometimes makes sense to be static.
A perfect example of when to use non-static methods is (most methods in) a Database class - you should always have a database object before you try to run a query on it.
An example of when to use a static method would be a "helper" class, essentially a collection of handy functions. Say you have some methods that help you output HTML, you might have HTML::image(), HTML::url() and HTML::script(). On these, you shouldn't need a HTML object to create an image, URL, and so on.
As for stopping multiple copies of objects being created (one argument for using static methods), you should use a Singleton pattern instead (Google it) to ensure only one copy of the object ever exists.
You should probably check out this question on Active Record vs data mapper:
https://stackoverflow.com/questions/2169832/data-mapper-vs-active-record
One take from this question is that static methods on the class for loading/saving aren't really the core functionality of the class in most cases. Further, storing and loading is a kind of abstract concept that is separate from your class objects in most cases.
Isa "user" a data storage and retrieval object? In most cases, no, it is a person represented in your system that has various properties and functions. When you start tying the persistence of that object into the object, you break encapsulation and make it harder to maintain the code. What if next week you want to load your users out of memcache? It's hardly relevant to if a user can have some property or functionality.