PHP Database Object Class

Recently, I have done several projects using the Database Object superclass, which I use to quickly query / update records and expand with the corresponding classes, such as the User class.

I found that many classes that I wrote have the same methods: query_values โ€‹โ€‹(), update (), delete (), etc.

So, I came up with a constructor class 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 the constructor of the child class is as follows:

 public function __construct($db_object, $record_id = null){ parent::__construct($this->table, $db_object, $record_id); } 

Where the $ table property is defined above, since we need to know which table this particular object is working with.

Now all the common methods of managing the record are in one place, and the methods specific to this class are all that is defined in their respective child classes.

The biggest drawback that I see here is that all data fields are extruded and encapsulated in the $ fields property, so you need to define common get and set methods (which I usually do), which almost negates encapsulation *, or the method should be defined specifically for each property that we want to expose.

* Example: $ user_id = $ User-> id; // DO NOT USE MY METHOD against $ user_id = $ User โ†’ _ get ('id'); // ACCESSES $ User-> fields ['id']

Do you see this as a flaw, or a plus? The goal is ease of use, object orientation (encapsulation) and just awesome!

+4
source share
3 answers

Well, you could make your life easy and use the PHP magic overloading __call method to create generic getters and seters. You can add the following method to your "database object superclass":

 /** * 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 is going on here. The __call magic method will receive calls to any method of the object that does not match one of the specific methods of the object. It receives as parameters the name of the called method and an array of its arguments.

The __call method __call performs a quick substr test to determine if the method was "getter" or "setter" (using the first three letters of the method name). It expects your $fields array to store the "property" names in lower case ( lcfirst ) and use everything after the setter / getter prefix as the expected property name.

If the property matches the getter method, then this property is returned. If not, a SplException BadMethodCallException . This is best practice since including Spl exceptions in PHP.

Similarly, the setter method also throws a SplException InvalidArgumentException if no argument is specified.

PHP magic methods will change your life. You can also use __get and __set to assign the values โ€‹โ€‹of the $fields array in a similar way, without making artificial method calls. Excited:)

+2
source

There are two main approaches:

PHP file creation

All the large ORM / database projects that I know do not allow the user to write all getter methods on their own. Both Doctrine and Propel use automatic generators to create real PHP files using getter methods when invoking the command line script. These files contain the so-called base methods, which are automatically extended by some classes into which you put your own code (so re-creating the base class will not delete your own code).

The advantage of creating a file is that you have a well-defined interface (some people do not like this when the called methods do not appear directly in the source code).

Magic methods / overload

The database engine that I saw in client applications used magic methods to model getters and setters. You can use the magic methods __get() and __set() or __call() (called "overload" in the PHP documentation ). Which method to use depends on how you want to access your values โ€‹โ€‹(the most common $obj->property or $obj->getProperty() ).

The advantage of overloading is that you do not need to write a complex PHP code generator, and you do not need to invoke the script command line every time the database design changes.

+1
source

You can have the best of both worlds by implementing several magic methods on your objects. For example, by implementing __get , __set and __isset , you can make access to properties "natural" (for example, $user->id ) and at the same time not define properties in each individual subclass.

For example, the __get implementation may check the $fields member at runtime to see if the property you are trying to get is valid for a particular class of the object. You can write this general implementation once in the base class and simply populate $fields accordingly so that it works with any kind of object. In fact, this is all that all modern display tools do, including, probably, all the PHP frameworks you've heard about.

As a side, I hope you cache the table schema inside the class inside get_column_data . It would be inefficient to require a database for the schema of the same table every time you create an object of the corresponding class.

0
source

Source: https://habr.com/ru/post/1391891/


All Articles