I have a set of classes which share some functionality -- they build an object from a database row, and can use fetch, insert, update, delete methods to communicate with the database via respective queries, and they also have some distinct methods and fields. I reckon it would be best to set all of these as child classes of an abstract class.

However, I want as little code duplication as possible, and it would seem creating an abstract method for each of these would simply result in me writing the same methods out in each class, the table name and columns being the only difference between them. I've got three classes -- abstract class A, class B (child of A), and class C (child of A) -- and I want B::update() to do the exact same thing as C::update(), on a different database table. Likewise for insert(), delete(), etc. What's the most effective solution here?

    I believe that you might want to define some object vars in your B and C classes which specify a list of fields that exist in their respective tables. Then in your abstract class, rather than having an explicit piece of sql, you can loop through these field lists to generate your update/insert/select statements dynamically.

      So if I understand this correctly, I define the database methods and a common field (e.g. $columns) in class A, set $this->columns as an array in the constructors of classes B and C, and reference $this->columns in class A's methods to build the queries?

        You can use the template method pattern and have abstract methods declared in the parent so the child classes are forced to return them and the parent then has the responsibility of setting them. The Template Method Pattern is useful where the parent class needs child classes to fulfill a concrete design it has ownership of. Forcing child classes to set parent class members needlessly directly is not the best design( it possibly requires comparing other sibling child classes when writing a new one ).

        eg. using return method

        abstract class  ParentClass{
        	private $table_name;
        
        function __construct(){
        	$this->table_name = $this->GetTableName();
        
        	echo $this->table_name;
        }
        
        abstract protected function GetTableName();
        
        }
        
        
        
        class ChildClass extends ParentClass{
        	function __construct(){
        	   parent::__construct();
        	}
        
        protected function GetTableName(){
        	return 'table_name';
        }
        
        }
        
        $ParentClass = new ChildClass();
        
          mpb001;10923627 wrote:

          You can use the template method pattern and have abstract methods declared in the parent so the child classes are forced to return them and the parent then has the responsibility of setting them. The Template Method Pattern is useful where the parent class needs child classes to fulfill a concrete design it has ownership of. Forcing child classes to set parent class members needlessly directly is not the best design( it possibly requires comparing other sibling child classes when writing a new one ).
          ...
          [/code]

          Thanks for that. I had neither seen that pattern before nor discovered it for myself, but it immediately makes sense when I think about it. (Or if I did see it before, it didn't "click" in my mind at that time. 🙂 )

            mpb001;10923627 wrote:

            eg. using return method

            abstract class  ParentClass{
            	private $table_name;
            
            function __construct(){
            	$this->table_name = $this->GetTableName();
            
            	echo $this->table_name;
            }
            
            abstract protected function GetTableName();
            
            }
            
            
            
            class ChildClass extends ParentClass{
            	function __construct(){
            	   parent::__construct();
            	}
            
            protected function GetTableName(){
            	return 'table_name';
            }
            
            }
            
            $ParentClass = new ChildClass();
            

            Unless I'm missing something here, why include a parent::__construct() override within ChildClass if it already inherits the parent constructor to begin with?

              Purely more to do as a matter of taste. It is not an issue when the constructor has no parameters but when there are some PDT and maybe Zend still cannot autocomplete.

              Basically this bug has popped up again
              https://bugs.eclipse.org/bugs/show_bug.cgi?id=207169

              I don't know if it works in Netbeans etc.

              Constructors are special so I am in two minds about whether it is good design to leave them out even though it is allowed( maybe by design or as a by product ). I did think about leaving it out but as I am in two minds I kept it in 🙂

                All right, I've got that. Now let's say I want the database methods to use prepared statements. I've got a field in class A, $columns, which is set by classes B and C by the method noted above as an associative array (column name => data type).

                I've got another field in class A, $info, which is an associative array of the column name and value which is either retrieved by the fetch() method or set by the PHP script. How would I, say, use bind_result to set the $info array's values (in the fetch() method), or use bind_param (in update()) to tell the database to update the row? I imagine it would involve call_user_func_array() in some fashion but the details elude me.

                  Ryodox;10923670 wrote:

                  All right, I've got that. Now let's say I want the database methods to use prepared statements. I've got a field in class A, $columns, which is set by classes B and C by the method noted above as an associative array (column name => data type).

                  I've got another field in class A, $info, which is an associative array of the column name and value which is either retrieved by the fetch() method or set by the PHP script. How would I, say, use bind_result to set the $info array's values (in the fetch() method), or use bind_param (in update()) to tell the database to update the row? I imagine it would involve call_user_func_array() in some fashion but the details elude me.

                  Yes, call_user_func_array() is a definite option. See this thread and this article for a couple examples (bind_param in the first and bind_result in the second).

                    All right, I think I've got it. Thanks a bunch. 🙂

                      Write a Reply...