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.
Related
I have two simple questions regarding OOP practice of classes. I expect that the answers will lean toward subjective preferences.
Let's say we have a class like a blog POST, which has private variables such as id, author, etc. I see in Symfony demo project the getter and setter methods are declared for almost each variable specifically. If the list is long, this seems quite tedious. So what about creating a method like the following?
function setProp($variable, $val){
if($variable !== 'id'){
$this->$$variable = $val;
}
}
I see that the Symfony demo created three entity classes: Comment, Post, User. The addComment and removeComment methods are in Post class and takes a typecast argument of Comment class. Can we make a removeComment method in the Comment class itself? Because I feel that most of the time the comment id would be the first piece of info passed to the script, so why not have such a method handy in the class itself? And is it 'bad' to have repeated methods that perform the same job in different classes?
The purpose of accessor methods is to provide a way to hook into the action of setting or getting a property.
For basic operations, you don't need accessor methods. They may seem pointless just assigning or returning a value.
One of the main purposes of accessor methods is restricting access to a property. You may want, under some conditions, to prevent the changing of a property. If the property is public, there is nothing you can do to prevent writing to the property. But if your property is private and you have a setter, then you may just not set the property under certain conditions.
private $allowed = true;
private $data;
public function getData() {
return $this->data;
}
public function setData($data) {
if ($this->allowed) {
$this->data = $data;
}
}
public function block() {
$this->allowed = false;
}
In this example, you may block write-access to the data property by setting the allowed property to false.
There are many other cases that make use of accessors (storing data outside the object, converting values, etc.)
It is good practice to use setters and getters from the start because if you create them later, you have to replace all references to the property with references to the setter/getter.
you can look at magique method __set (http://php.net/manual/fr/language.oop5.overloading.php#object.set) but it's better to write each setXxxx
I've generally tried to stay away from PHP's magic methods because they seem to obfuscate an object's public interface. That said, they seem to be used more and more, at least, in the code I've read, so I have to ask: is there any consensus on when to use them? Are there any common patterns for using these three magic methods?
The main reason is that you do not need to type as much. You could use them for, say, an ORM record and act as implicit setters/getters:
using __call():
$user = new User();
$user->setName("Foo Bar");
$user->setAge(42);
$user->save();
using __set():
$user->name = "Foo Bar";
$user->age = 42;
which maps to a simple array:
array(
"name" => "Foo Bar",
"age" => 42
)
It is much easier to write such an array to the database than doing a lot of manual calls to collect all needed information. __set() and __get() have another advantage over public members: You are able to validate/format your data.
__call()
I've seen it used to implement behaviors, as in add extra functions to a class through a pluginable interface.
Pseudo-code like so:
$method = function($self) {};
$events->register('object.method', $method);
$entity->method(); // $method($this);
It also makes it easier to write mostly similar functions, such as in ORMs. e.g.:
$entity->setName('foo'); // set column name to 'foo'
__get()/__set()
I've mostly seen it used to wrap access to private variables.
ORMs are the best example that comes to mind:
$entity->name = 'foo'; // set column name to 'foo'
It allows you to do things like this:
class myclass {
private $propertybag;
public function __get($name) {
if(isset($this->propertybag[$name]) {return $this->propertybag[$name];}
throw new Exception("Unknown property " . (string) $name);
}
}
Then you can populate $propertybag from a SQL query in a single line, rather than setting a whole bunch of properties one by one.
Also, it allows you to have specific properties which are read-only (ie don't allow them to be modified via __set()). Maybe useful for an ID field, for example.
Also, you can put code into __get() and __set(), so you can do something more complex than just getting or setting a single variable. For example, if you have a storeID field, you may also want to provide a storeName property. You could implement that in __get() via a cross-reference lookup, so you may not need the name actually to be stored in the class. And of course storeName would not want to be implemented in __get().
Lots of possibilities there.
There are of course some down-sides of using magic methods. The biggest one for me is the fact that you lose the auto-complete functionality in your IDE. This may or may not matter to you.
Since magic methods can save you a LOT of coding when it comes to repetitive tasks like defining members, populating them and then retrieving them - instead of doing that boring, long piece of work, you can use mentioned 3 methods to shorten the time to code all that. If needed, I can provide a few examples tho they can be found in various tutorials over the net.
I don't know if it's general consensus, but the usual should apply - use where appropriate. If you find yourself to do repetitive task (define member, populate member, get member, call X functions that differ slightly) - magic methods might help you.
One common pattern is to have a single handle for your clients and proxy the calls to encapsulated objects or singletons based on naming conventions or configurations.
class db
{
static private $instance = null;
static public function getInstance()
{
if( self::$instance == NULL )
self::$instance = new db;
return self::$instance;
}
function fetch()
{
echo "I'm fetching\n";
}
}
class dataHandler
{
function __call($name, $argv)
{
if( substr($name, 0, 4) == 'data' )
{
$fn = substr($name, 4);
db::getInstance()->$fn($argv);
}
}
}
$dh = new dataHandler;
$dh->datafetch('foo', 'bar');
Same principles can be used to drive different backends of the same functionality without having to change the driver.
Whenever you'd like, as long as the magic properties/methods are documented; undocumented magic should be avoided unless working with a very abstract layer of code, such as when developing an ORM.
acceptable at an abstract layer
/**
* DB backed model base class.
*/
class Model {
protected $attributes = [];
function __get($name) {
return #$this->attributes[$name];
}
}
acceptable when documented
/**
* User model backed by DB tables.
* #property-read string $first_name
* #property-read string $last_name
*/
class UserModel extends Model {
}
lazy and unacceptable (and common when using ORMs)
/**
* This class is magical and awesome and I am a lazy shithead!
*/
class UserModel extends WhoCaresWhenEverythingIsMagical {
}
Even though there's some discussions regarding this issue I wanted to check on certain example what would be the best approach.
Instead of using existing solutions I created my own persistence layer (like many do)
So my approach is also in question here.
For every table in db I have model class that has appropriate getters and setters and some mandatory methods. I also created only one generic DAO class that handles all types of model objects.
So, for example to save any model object I instantiate genericDAO class and call save method that I pass model object as attribute.
Problem is that in runtime genericDAO class doesn't know whitch model object it gets and what methods (getters and setters) exist in it, so I need to call mandatory model class method that retrieves list of attributes as multiple string array.
For example for every attribute there's array(table_column_name,attribute_name,is_string).
When I call save function it looks like this:
public function save(&$VO) {
$paramArray = $VO->getParamArray();//get array of attributes
$paramIdArray = $paramArray[0]; //first attribute is always id
/*create and execute getId() and store value into $void to check if it's save or update*/
eval('$voId = $VO->get'.ucfirst($paramIdArray[1]).'();');
...
Currently I'm using eval to execute those methods, but as it is well known eval is very slow.
I'm thinking of changing that into call_user_func method
Something like:
$voId = call_user_func(array($VO, 'get'.ucfirst($paramIdArray[1])));
But also there's other solutions. I can maybe use something like this $method = 'get'.ucfirst($paramIdArray[1]));
$voId = $VO->$method();
or else
$method = 'get'.ucfirst($paramIdArray[1]));
$voId = $VO->{$method}();
What would be the best way?
First of all, there's no need to pass references like you are doing. You should give this a read to try to understand how PHP handles object references.
So public function save(&$VO) { should become public function save($VO) {.
Second, there is no need to use eval (in fact, it's better not to because of speed, debugability, etc). You can't stack-trace an eval call like you can a dynamic one.
Third, call_user_func is all but useless since PHP supports dynamic variable functions. Instead of call_user_func(array($obj, $method), $arg1), just call $obj->$foo($arg1). The call_user_func_array function is still useful since it supports variable length arguments and supports passing references.
So, ultimately, I would suggest this:
$method = 'get' . ucfirst($paramIdArray[1]);
$voId = $VO->$method();
Note that there's no need to call method_exists, since it may be callable and not exist due to __get magic method support...
I normally would use:
$method = 'get'.ucfirst($attribute);
if(method_exists($obj, $method){
$obj->$method();
}
But unless there is a very good reason i would just return a key => value array from getParamArray. And operate on that instead of using the getters...
Or in more specific words, is it "ok" to not be relying on setters and getters?
I'm dealing with a class that checks the availability of rooms and sets public properties of which there are more than a dozen. Things such as:
unitNumber
roomTypes ( array )
codeCorporate
codeGroup
numberKids
numberAdults
numberRooms
currency
minRate
maxRate
soapServer
units ( array )
hotelId
And after an object is instantiated those properties are set with $this-> inside various methods. However the code that deals with the object often sets public properties directly instead of using getter/setter methods:
$object->something = 3;
foreach ($object->things as $thing ) { }
If I have the time to refactor this class..
Should I stick all of these properties in a data array that's a private property, and define __set and __get methods?
Should I make a single getter method for each of the properties?
In my opinion, it is rarely a good idea to have any public members. It increases coupling between classes, and makes refactoring very complicated (should you need it.)
Setters/Getters are the way to go, and the very small performance penalty that you pay for it is usually either optimized away, or trumped by elegance.
To answer your question about array vs. single-getter-per-var, it's a matter of taste. I tend to only keep variables of a similar type within an array, and separate the rest.
I personally have yet to find a truly good reason for a public property, though im open for suggestion :-)
Although i much prefer specified getters/setters for each property (whether that's a proxy to a generalized get($name) or not). I assume you have other code already that uses direct assignment so in that case i would say to proceed with using the magic __get/__set methods.
I think most people will recommend using setters & getters. Right now you're limited to simply setting & fetching the property, but what if you want to log when that property is accessed? Or perhaps you want to run the value by a validation function first (email, phonenumber, zip code, etc). Maybe you'll need to call another function, or set another property. I think you see where I'm heading with this. By using setters & getters, you add a valuable layer of encapsulation to your classes, and 99% of the time this is worth the extra typing you'll need to do ;) Imagine trying to do the examples above without setters & getters. It'd be a big headache to say the least.
Edit: I forgot to mention Doctrine. It's an object relation mapper (ORM) that can automatically setup setters & getters for you (amongst other things). You can check it out at http://www.doctrine-project.org/
I would take a step back and ask some more general questions:
Why am I having to expose this much information; what is using it and why?
Is this class really just a data structure without behavior, in which case should be a private class to some other class?
Does this class serve a single purpose, or is it on the path to becoming monolithic?
You may discover that you are able to create views of an instance of a class to export to a database, display in a form, etc. Check out the "Builder" and "Acyclic Visitor" patterns to start with.
Regarding accessors, I do not see a need to use them for what you are describing: retrieving class properties and internal state information, aka a struct. However, for attributes of a class I could see the benefit in certain cases, but more for retrieving attributes, not for mutations of your object's state.
If I may add my grain of salt several months later :
It is very un-OO to have public properties. Everything should be encapsulated, simply because (among other reasons) using direct attribute manipulation doesn't give you ways to easily refactor or perform (more) control checks when some external source modifies the field. For example, let's say you have a class with many fields that is used throughout a project several times, and that project contains several thousands of files; it's a project that has been running and expanded for a few years now. Let's say that the company is changing it's business model, or that a problem is found with some of the field's data type and now is required to have some validation; will you duplicate that validation in all those thousands of source code that is directly accessing the public member? In PHP, the solution may be simple, but not in most OO programming language (i.g. Java). The fact is that OO is based on encapsulation. In short, encapsulation doesn't only produce clean code, but also highly maintainable (not to say cost-effective and cohesive) code.
Your suggestion of having a private member (array) being manipulated by __get / __set is good. This way, if you need some extra validation along the road, simply create your setter and/or your getter and it will be the end of it. Some may argue with that being counter productive as the code completion cannot kick-in on __get / __set. IMHO, relying on code completion is simply lazy coding. But then again, having every member have it's own getter and/or setter allows you to write a more comprehensive API documentation. Personally, I usually use that technique for internal or very general purpose classes. If all your fields do not require any validation, or there are as you said several dozen of them, then using magic methods would be acceptable, in my opinion.
The bottom line is to avoid direct member access on class instances, period. How you decide to achieve this is strictly up to you. Just make sure that the API is well documented the more abstract you make it.
On a final note, in PHP, if you already have classes that are being used that are not encapsulating their fields, for example something like
class SomeObject {
public $foo;
public $bar;
public $baz;
//...
}
you can simply fix this class without having to refactor anything with something like :
class SomeObject {
private $_foo; // having underscore as prefix helps to know what's private/protected
private $_bar; // inside the code.
private $_baz;
public function __get($name) {
$methodName = 'get'.ucfirst($name);
if (method_exists($this, $methodName)) {
return $this->{$methodName}();
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function __set($name, $value) {
$methodName = 'set'.ucfirst($name);
if (method_exists($this, $methodName)) {
$this->{$methodName}($value);
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function getFoo() { return $this->_foo; }
public function setFoo($value) { $this->_foo = $value; }
public function getBar() { return $this->_bar; }
public function setBar($value) { $this->_bar = $value; }
public function getBaz() { return $this->_baz; }
public function setBaz($value) { $this->_baz = $value; }
}
And then
$obj = new SomeObject();
$obj->foo = 'Hello world'; // legacy code support
$obj->setFoo('Hello world'); // same thing, but preferred
And you satisfy both the OO paradigm and having direct access to attributes of an instance. You could also have __call() check for prefix 'get' or 'set' and call __get() and __set() accordingly, but I would not go that far, though this would truly enable general purpose classes to access it's private members via ->member and ->getMember()/->setMember()
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).