-1

I have 3 models Product having product_family_id as foreign key to ProductFamily and ProductFamily have customer_id as foreign key to Customer. Putting recursive to 2 in Product model allow me to get Customer name from Customer for a product. But its too slow as data is vast

Tried Using Bind model as below. Didn't worked for me. Using Cakephp framework.

$this->Product->bindModel(array(
'belongsTo' => array(
               'ProductFamily' => array(
                   'foreignKey' => false,
                   'conditions' => 
                        array('Product.product_family_id = ProductFamily.id')
                   ),
               'Customer' => array(
                   'foreignKey' => false,
                   'conditions' => 
                        array('ProductFamily.customer_id = Customer.id')
                   )
               )
           )); 
liyakat
  • 11,825
  • 2
  • 40
  • 46

2 Answers2

1

Use Containable

The Containable behaviour will help you get exactly the data you want without the overhead of recursive 2

set it in your AppModel to make it apply to all models at once and read up on the docs on how to use it

class AppModel extends Model {

    public $actsAs = array('Containable');
    public $recursive = -1;
}

For some interfaces in your application, you may not need that much information from the model. One thing the ContainableBehavior does is help you cut down on what find() returns.

It is possbible to only set this on the models where you would use it and set recursive to -1 right before your find (in wich you would use 'contain') but it is in my eyes a best practise to do this for all models

Alex Stallen
  • 2,223
  • 15
  • 17
  • Tried using Containable behavior, didn't work. Might have used wrong way. – New_Programmer Jul 11 '13 at 07:33
  • did you read the docs on how to use it? on the page: http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html there is an example with an extensive search that needs to be toned down, that sounds like exactly your problem – Alex Stallen Jul 11 '13 at 07:48
  • @New_Programmer "didn't work" doesn't help anyone understand what you've done wrong – AD7six Jul 11 '13 at 08:20
  • Yes I did read this and when i try to use containable behavior, error that shows is " Model "Product" is not associated with model "Customer" " – New_Programmer Jul 11 '13 at 18:15
  • sounds like the relations in the models are wrong then. Can't comment in more detail since no details are given – Alex Stallen Jul 11 '13 at 18:46
  • products table have Id, Product_family_id, product number and productfamilies have id , customer_id, name and – New_Programmer Jul 11 '13 at 19:27
  • products table have Id, Product_family_id, product number and productfamilies have id , customer_id, name and customers table have id, name . So Product table have no common field with customer table. Product belongs to ProductFamily and ProductFamily belongs to Customer. Also Product.product_family_id = ProductFamily.id and ProductFamily.customer_id=Customer.id. I need a query that gives Customer.name for products. Setting recursive =2 works. But it take more than a minute to load as DB is vast. – New_Programmer Jul 11 '13 at 19:37
  • so a customer can only buy a productFamily and not just one product? wouldn't a relation between product and customer make more sence? Productfamily HasMany Products and Products HasAndBelongsToMany Customers? – Alex Stallen Jul 11 '13 at 20:08
  • ALex have got it using containable behavior. In all it fetches 11 pages of data. For 10 pages it works fine and displays as expected and for the last page i.e the 11th page, it gives me error "Undefined index: Customer". Will try to resolve this problem and post my answer that worked for me. Thanks a lot for your help. – New_Programmer Jul 11 '13 at 21:33
  • included 'contain' => array('ProductFamily'=>array('Customer')) in My find all query and it works. Thanks – New_Programmer Jul 12 '13 at 17:00
  • great to hear, accept an answer to close the issue – Alex Stallen Jul 12 '13 at 18:05
0

Like Alex mentioned in his response, you can use the containable behavior. His idea is to use the Containable behavior for the whole AppModel, i.e it affects all the Models. And if you have already used recursions at other places of the code, you will have to adjust the models to contain in each part of them.

But if you only want to limit data for this model. You can do

$this->Product->Behaviors->attach('Containable');
$this->Product->contain(array(
    'ProductFamily' => array('Fields you need from product family'), 
    'Customer' => array('Fields from customer')
);

If you need all fields from ProductFamily and Customer, you can do

$this->Product->contain(array('ProductFamily', 'Customer'));
  • Yes I did read this and when i try to use containable behavior, error that shows is " Model "Product" is not associated with model "Customer" " – New_Programmer Jul 11 '13 at 18:35
  • included 'contain' => array('ProductFamily'=>array('Customer')) in My find all query and it works. Thanks – New_Programmer Jul 12 '13 at 17:01