7

Suppose I have 2 identical table having same structure(Call it 'tableA' & 'tableB').

I want to save certain data on table 'A' and certain data on table 'B'.

NOW I want to use the same MODEL for both the table.

I want to change the table linked with the Model(say 'ModelM') to change dynamically based on condition at the controller.

e.g.


In controller:- //sample code

function saveProduct(){

    $this->loadModel('ModelM');

    if(condition){

        $this->ModelM->useTable = 'A';

    }else{

        $this->ModelM->useTable = 'B';

     }
     $this->ModelM->save($this->data);

}

ADDITION ON 14th JANUARY 2011

Following is the copy/paste of code I am working on:

function experiment(){

    $tableName = 'temp_table'.'1234';

    mysql_query('CREATE TABLE '.$tableName.' LIKE temp_home_masters');

    $sql = $this->createInsertQuery($new_arr,$tableName);

    $status = mysql_query($sql);

    if($status){
        echo "saved successfully";
    }else{
        echo "error";
    }

    $this->NewHomeMaster->setSource($tableName);//NewHomeMaster was previously attached to a different table , here I want to change the tableName the model linked with dynamically.Model 'NewHomeMaster' already exists and uses a table ...Here I am willing to link this model to the newly created tempory table.//

    $home_details=$this->paginate('NewHomeMaster',array($new_conditions));

    mysql_query('DROP table '.$tableName);

}

UNFORTUNATELY THIS DOES NOT WORK...

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Libu
  • 213
  • 3
  • 10

3 Answers3

3

I originally set out to figure a solution to your problem, but the more I think about it, I believe your logic is flawed.

I can see how the fact that the tables are similar or identical can lead you to the decision of using a single model to interact with both tables. However, when you look at a what a model is supposed to be (In CakePHP basically an interface to a table), it doesn't make sense to switch back and forth.

The CakePHP docs explain models like this:

In object-oriented programming a data model is an object that represents a "thing", like a car, a person, or a house.

In your example, you really have two separate "things" that look exactly the same. Therefore, they should have their own models.

If your models are really going to have the exact same methods, then "the CakePHP Way" would be to define a custom Behavior that encapsulates your shared methods. Then attach the behavior to both models.

Then you can load the model you need in the Controller condition:

private $DynamicModel;

public function saveProduct() {
    if (condition) {
        App::import('Model', 'ModelZ');
        $this->DynamicModel = new ModelZ;
    } else {
        App::import('Model', 'ModelY');
        $this->DynamicModel = new ModelY;
    }
    $this->DynamicModel->save($this->data);
}
Stephen
  • 18,827
  • 9
  • 60
  • 98
  • My problem was bit different, I just explained it by giving an example...I want to create a random table dynamically(exact replica of an existing table), make some complex calculation(avg_price) and then copy existing table to this new table with the addition of 1 new column to it say 'avg_price'...Now i want to paginate this dynamically created table using an 'order by' to the 'avg_price' field... after paginating I would drop the table.... – Libu Jan 14 '11 at 06:15
  • So each time I run the script a table would be created->calculations->copy the old table with calculated field to the new table->paginate the new table and set the data to view->drop the table.... – Libu Jan 14 '11 at 06:16
  • CAN WE CREATE TEMPORARY TABLE ON THE FLY AND ASSIGN MODEL TO IT?? – Libu Jan 14 '11 at 06:17
  • I don't understand the need. Why are you copying the table? Why not just calculate the average without all the extra steps? – Stephen Jan 14 '11 at 13:06
  • Cake 1.2 has no virtual field concept, so i had to calculate that and store in a new table, keeping in mind that avg_price is variable per record according to the search conditions...please refer http://stackoverflow.com/questions/4733112/paginate-dynamically-created-table-in-cakephp .. In simple words I want to paginate a replica of existing table(having 1 extra field avg_price) in cake 1.2 which donot support model 'virtual_field' concept.. – Libu Jan 19 '11 at 12:33
  • After adding avg_price field, my requirement is to 'order by' it in paginate function.... IN SIMPLE WORDS I WANT TO PAGINATE AND ORDER BY A VIRTUAL FIELD(NON-CONCRETE) IN CAKEPHP...AND THE VALUE OF THE VIRTUAL FIELD FOR A PARTICULAR RECORD VARIES FROM TIME TO TIME!!! HOPE YOU GET MY POINT!!! :( – Libu Jan 19 '11 at 12:39
  • I would recommended upgrading to CakePHP1.3 and use virtual fields. The upgrade process is not that painful, I've done it. http://book.cakephp.org/view/1561/Migrating-from-CakePHP-1-2-to-1-3 – Stephen Jan 19 '11 at 15:02
2

Do this on your controllers before filter function:

$this->CakePHPModelName->setSource('table_name');

This will use different table.

Source: http://www.mainelydesign.com/blog/view/changing-cakephps-model-usetable-on-fly

Jsonras
  • 1,120
  • 13
  • 10
0

The situation is tricky, as Stephen describes it, because your approach somewhat violates the MVC conventions.

However, if you're willing to go to the dark side of custom hacks, you could consider creating you own customized Datasource in CakePHP that handles this kind of logic for you. An option is to extend a given Datasource (presumably the MySQL one) with you own custom logic that aims to perform some prelimary filtering/conditioning before interacting with the database. Not that clean because the logic is placed in the wrong scope, but could work. Have a look here for a start: http://book.cakephp.org/view/1075/DataSources

Alternatively, you could create two different models and make them share the same logic using a behavior. This kinda limits you to take the choice of model earlier in the flow (and thus doesn't only affect the location of data storage), but might be a possibility.

laander
  • 2,243
  • 2
  • 23
  • 15