override __construct in ActiveRecord

Hi there ,

Firstly thank you for Yii. It is a framework that is generally a total pleasure to work with ;)

Hope you can help with a problem. I have a load of foreign keyed reference tables that hold info

like gender (male / female ) , title (mr / mrs ) and so on. The table schemas are identical except for

the table name. Therefore I would like one active record that can process any of these tables. All I need

to do is pass the the table name into the constructor and my active record now models the correct table.

But it doesn’t work… not sure why Yii just seems to bomb out.

This what I have done :





class RefTable extends CActiveRecord 

{

     private $_myTable; 

     public function __construct($table , $scenario = 'insert')

     {

          if ($table === null) 

                 throw CException(500, sprintf('cannot instantiate %s without table param' , __CLASS__ )); 


          parent::_construct($scenario); 

          $this->_myTable = $table;  

         // parent::_construct($scenario); 

     }




     public function tableName()

	{

		return $this->_myTable;


	}


}


/*

Usage: the title value does not seem to enter __construct() 

*/ 

$obj = new RefTable('title'); 







This worked for me




<?php


private $myTable;


  

  public function __construct($scenario = 'insert',$table="") {

  if($table == ""){

         		throw CException(500, sprintf('cannot instantiate %s without table param' , __CLASS__ )); 

  }

	$this->myTable = $table;

   

	parent::__construct($scenario);

  }


   /**

   * @return string the associated database table name

   */

  public function tableName() {

	return $this->myTable;

   

  }

?>



You didn’t say what error is shown but i suppose it’s about change of method signature. PHP doesn’t allow to change the method signature in derived classes, and that’s what you do with the constructor.

How about using a factory method instead:




class RefTable extend CActiveRecord

{

    protected $_table;


    public function tableName() 

     {

        return $this->_table;

    }


    // factory method

    public static createTableRecord($table,$scenario='insert')

    {

        $record=new self($scenario);

        $record->_table=$table;

        return $record;

    }

}


$obj=RefTable::createTableRecord('title');

Hi Mike and Spyros,

Thanks for the reply. I don’t think the factory suggestion will help as the factory method still will not allow me to

add the table name before the modelling code gets initialised within the AR.




        $record=new self($scenario);

        $record->_table=$table; // too late for this. AR has been initilised already 

        return $record;



I have my logging and debugging environment set to full blast and it looks like Yii just bombs out. It does not log anything

and the __contructor is not recognising parameters passed in.

I need to come clean on one thing though. My active record is actually based on a derived custom class that inherits from CActiveRecord. It does some work before validation, nothing serious but here it is.

Cheers,

Spiro




abstract class ExtendedActiveRecord extends CActiveRecord { 

   

       protected function beforeValidate()

	{

		if ( $this->isNewRecord )

		{

			$this->create_time = time(); 

			$this->create_user_id = Yii::app()->user->id; 

		}

		else

		{

			$this->update_time = time();

			$this->update_user_id = Yii::app()->user->id;

		}

		return parent::beforeValidate(); 

        } 


} 

/*  ************************* */ 

class RefTable extends ExtendedRecord {

   private $_table ; 

   public function __construct($table='title')

   {

        $this->_table = $table; 

        parent::__construct('insert'); 

            

   }

   public function getTable()

   {

         return $this->_table; 

   } 

} 


/*  ************************* */ 

// usage : 

$obj = new RefTable('title'); 




Hi there,

Thanks for the guidance. In the end did it this way:

public function __construct($scenario = ‘insert’,$table="") {

if($table == ""){

                    throw new CHttpException(500, sprintf('cannot instantiate %s without table param' , __CLASS__ )); 

}

    &#036;this-&gt;myTable = &#036;table;





    parent::__construct(&#036;scenario);

}

But would like to do it factory method as this is what the pattern is designed for.

Cheers !

Spiro