📜 ⬆️ ⬇️

Later Static Linking in PHP (Part II: Practice)

php Read the first part here .

Now we will start practice. The most telling example of using LSB, in my opinion, is when you have a set of classes that perform similar actions. In terms of web development, we often encounter such tasks when accessing database tables, especially in ORM systems. All your objects for working with tables will be similar in essence, but they will have their own functionality (and, accordingly, their own subclasses).

Suppose we have a class in the system called Storable , which implements (you guessed it) (note the translator: I did not guess :)) the storable pattern. We define classes that inherit from the Storable class and set the names of the tables in the constructors. Here's what it looks like:

   class ArticleEntry extends Storable {
	   public function __construct ($ id = null) {
		   if (! is_null ($ id)) {
			   $ id = array ('id' => $ id);
		   }
		   parent :: __ construct ('articleEntry', '*', $ id);
	   }
   }
   
   // output the text of the entry:
   $ entry = new ArticleEntry (10);  // Fetching an entry from the articleEntry table for which id = 10;
   echo $ entry-> html ('articleBody');  // output of the body of the loaded entry
   
   // update the record:
   $ entry ['ts'] = time ();  // set the time to NOW
   $ entry-> save ();  // Update Record

')
You can skip the details of the constructor, it’s just to show you how the Storable class works . As you have already understood, this will save us some time and will allow us not to waste it on such trifles as simple SELECT , INSERT and UPDATE queries.

In our system, in addition to the main Article table ( ArticleEntry ), several more tables will be used that contain meta-data (for many-to-one), for example: tags, attachments. I also need a simple way to remove data from sub-tables before updating the data in the main table (it is easier to delete the meta data and recreate it, rather than worry about data synchronization). So, in order to model the code that is closest to the database schema, I stopped at this implementation:

   abstract class ArticleEntryAbstract extends Storable {
	   public function __construct ($ table, $ id = null) {
		   if (! is_null ($ id)) {
			   $ id = array ('id' => $ id);
		   }
		   parent :: __ construct ($ table, '*', $ id);
	   }

	   public function purge () {
		   $ s = $ this-> db-> prepare ('DELETE FROM'. $ this-> tableName. 'WHERE pulseEntryId =?');
		   $ s-> execute (array ($ this-> data ['entryId']));
	   }
   }


The focus is on the purge () method. The $ this-> tableName property is a protected property that we obtained from the Storable class. Here is an example of use:

   class ArticleEntryAttachment extends ArticleEntryAbstract {
	   public function __construct ($ id = null) {
		   parent :: __ construct ('articleEntryAttachment', $ id);
	   }
   }


I have a bunch of small classes for working with meta data tables. Unfortunately, since our system uses PHP version 5.2, I could not use the LSB functionality described in the first part of the article. And in order to delete the meta data, I have to write:

   $ attach = new ArticleEntryAttachment (10);  // SELECTS from the articleEntryAttachment table WHERE entryId = 10
   $ attach-> purge ();


If you look above how the purge () method is defined, you will see that it gets the tableName from the Storable class, which gets it from the constructors of the descendant classes. In addition to these trivial (but absolutely necessary) data, as well as getting the database object in $ this-> db , we have not achieved anything by creating an object of the class of articleentrytachment . The code would be much clearer and cleaner (and, of course, more efficient) if it were possible to call the purge () method statically. Consider this code:

   abstract class ArticleEntryAbstract extends Storable {
	   public function __construct ($ table, $ id = null) {
		   if (! is_null ($ id)) {
			   $ id = array ('id' => $ id);
		   }
		   parent :: __ construct (static :: TABLE_NAME, '*', $ id);
	   }
   
	   static function purge ($ entryId) {
		   $ db = Db :: get ();  // get the singleton database
		   $ s = $ db-> prepare ('DELETE FROM'. static :: TABLE_NAME. 'WHERE pulseEntryId =?');
		   $ s-> execute (array ($ entryId));
	   }
   }
   
   class ArticleEntryAttachment extends ArticleEntryAbstract {
	   const TABLE_NAME = 'articleAttachment';
   }


The first thing I hope you noticed is that ArticleEntryAttachment has become much easier. Now there is no need to override the constructor for subclasses, because the constructor of the parent class is self-sufficient. And now you can use the purge () method (using LSB):

 ArticleEntryAttachment :: purge (10);


Since now the purge () can get the name of the table, which is determined at the time of execution, we can make it static. As a result, the code is cleaner, execution is more efficient, support (for example, adding new subclasses) is trivial, because redundancy has been completely removed. Thanks to the PHP developers for making this possible!

The manual also discusses other ways to use LSB, including using the constant __CLASS__ , so be sure to visit php.net

Via Denis.in.ua: Later Static Linking in PHP (Part II: Practice)

Original: Late Static Binding: a practical example

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


All Articles