I have these tables in my database: 'products' belongs to a 'company', and 'company' has many 'company_addresses'. And I am building a search action in my controller which will return the products based on user's inputted company address. How can I get something like the followin?
SELECT *
FROM products
LEFT JOIN companies ON products.company_id = companies.id
LEFT JOIN company_addresses ON companies.id = company_addresses.company_id
WHERE company_addresses.address1 LIKE '%'.$this->data['Product']['keyword'].'%'
OR company_addresses.address2 LIKE '%'.$this->data['Product']['keyword'].'%'
This doesn't seem to work:
$results = $this->Product->find('all', array(
'conditions' => array(
'OR' => array(
array('CompanyAddress.address1 LIKE' => '%'.$this->data['Product']['keyword'].'%'),
array('CompanyAddress.address2 LIKE' => '%'.$this->data['Product']['keyword'].'%')
)
),
'order' => array(
'Product.id' => 'ASC'
),
'contain' => array(
'Company' => array(
'CompanyAddress' => array(
'State',
'City'
)
)
)
));
Nor this:
$results = $this->Product->find('all', array(
'order' => array(
'Product.id' => 'ASC'
),
'contain' => array(
'Company' => array(
'CompanyAddress' => array(
'conditions' => array(
'OR' => array(
array('CompanyAddress.address1 LIKE' => '%'.$this->data['Product']['keyword'].'%'),
array('CompanyAddress.address2 LIKE' => '%'.$this->data['Product']['keyword'].'%')
)
),
'State',
'City'
)
)
)
));
I think the best for you is to use the join of CakePHP.
Something like this:
$this->Product->find('all', array(
'joins' => array(
array(
'table' => 'companies',
'alias' => 'Company',
'type' => 'left',
'conditions' => array(
'Company.id = Product.company_id'
),
),
array(
'table' => 'companies_addresses',
'alias' => 'CompaniesAddress',
'type' => 'left',
'conditions' => array(
'CompaniesAdress.company_id = Company.id',
'OR' => array(
'CompanyAdress.address1 LIKE' => '%' . $this->data['Product']['keyword'] . '%',
'CompanyAdress.address2 LIKE' => '%' . $this->data['Product']['keyword'] . '%',
),
),
),
),
));
Related
thanks to the help i have gotten on Stackoverflow while learning php i am able to Join tables and use Count.
I am unable to do both in one query.
I am wanting to count records in a joined table.
This is what i have tryed and i seem to get errors:
$options = array(
'fields' => array(
'toutcome.AffCommission',
),
'joins' => array(
array(
'conditions' => array(
'tapplicant.AppID = toutcome.AppID',
),
'table' => 'toutcome',
'alias' => 'Toutcome',
'type' => 'join',
),
),
'limit' => 'Toutcome',
'offset' => 'Toutcome',
'contain' => array(
'Toutcome',
),
);
$data = $this->Tapplicant->find('count', $options);
$this->set('count', $data );
Try this
$options = array(
'fields' => array(
'toutcome.AffCommission',
),
'joins' => array(
array(
'conditions' => array(
'tapplicant.AppID = toutcome.AppID',
),
'table' => 'toutcome',
'alias' => 'Toutcome',
'type' => 'join',
),
),
'limit' => n, // its should be integer
'offset' => n, // its should be integer
'contain' => array(
'Toutcome',
),
);
I want to get last_deadline and the count of instalments of all instalments but obviously this query will show me 1 order and the last_deadline.
$orders = $this->find('all', array(
'fields' => array(
'Order.order_id', 'Order.summary', 'Order.fee',
'BriefInstalment.id',
'MAX(`BriefInstalment`.`deadline`) AS last_deadline'
),
'conditions' => $conditions,
'joins' => array(
array(
'table' => $this->getTableName('default', 'brief_instalments'),
'alias' => 'BriefInstalment',
'type' => 'RIGHT',
'conditions' => array(
'Order.order_id = BriefInstalment.order_id',
'BriefInstalment.deleted' => 0,
),
'order' => 'BriefInstalment.deadline ASC',
)
),
'order' => 'BriefInstalment.deadline ASC'
));
I have tried 'contain' and doesn't work.
'contain' => array(
'BriefInstalment' => array(
'fields' => 'BriefInstalment.id',
'fields' => array(
'BriefInstalment.id',
'MAX(`BriefInstalment`.`deadline`) AS last_deadline', 'COUNT(`BriefInstalment`.`id`) AS total_instalments'
),
'conditions' => array(
'BriefInstalment.deleted' => 0
)
)
),
By the way I don't want to use loop to get last_intalments and cout brief_instalments. e.g.
// Determine deadlines
foreach ($orders as $i => $order) {
$deadline = $this->BriefInstalment->getLastDeadline($order['Order']['order_id']);
$orders[$i] += array(
...
'last-deadline' => $deadline,
'total-instalments' => count($order['BriefInstalment'])
);
}
The reason is it decrease the speed of loading.
Any help plz
Here is how to create custom query
$conditionsSubQuery['"User2"."status"'] = 'B';
$db = $this->User->getDataSource();
$subQuery = $db->buildStatement(
array(
'fields' => array('"User2"."id"'),
'table' => $db->fullTableName($this->User),
'alias' => 'User2',
'limit' => null,
'offset' => null,
'joins' => array(),
'conditions' => $conditionsSubQuery,
'order' => null,
'group' => null
),
$this->User
);
$subQuery = ' "User"."id" NOT IN (' . $subQuery . ') ';
$subQueryExpression = $db->expression($subQuery);
$conditions[] = $subQueryExpression;
$this->User->find('all', compact('conditions'));
Reference:
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#sub-queries
User has many User_Questionaries. I want paginate users that have particular questionnaire. I used following pagination for it.
$paginate = array(
'conditions' => array(
'User.role' => IWOA,
'UserQuestionary.questionary_id' => $id
),
'recursive' => 1,
'limit' => 10,
'order' => array(
'name' => 'asc'
),
'contain' => array('UserQuestionary')
);
But it is not create join query. It is showing Unknown column UserQuestionary.questionary_id' in 'where clause'
What is the issue? How can i do it?
Finally I used join query for do this.
$paginate = array(
'conditions' => array(
'Iwoa.role' => IWOA,
),
'joins' => array(
array(
'alias' => 'UserQuestionary',
'table' => 'user_questionaries',
'type' => 'LEFT',
'conditions' => 'UserQuestionary.user_id = Iwoa.id AND UserQuestionary.questionary_id = ' . $id
)
),
'limit' => 10,
'order' => array(
'name' => 'asc'
),
);
I'm using CakePHP 1.3 and am having some trouble converting a SQL query to CakePHP. The concept behind the query is to retrieve all products associated with a specified account and belonging to a certain product category or the specified category's immediate child.
There are three tables involved here, products, product_categories and category_types. product_categories is a link table that joins products to category_types. The category_types table is a tree structure that can join to itself.
The SQL for the query should end up looking something like this if the category's id was 1 and the account's id was 1:
SELECT Product.id, Product.name, Product.account_id
FROM products AS Product
INNER JOIN product_categories AS pc ON (Product.id = pc.product_id)
INNER JOIN category_types AS ct ON (ct.id = pc.category_type_id)
WHERE (
((Product.account_id IS NULL) OR (Product.account_id = '1'))
AND ((ct.id = '1') OR (ct.parent_id = '1'))
)
Here is the code I'm using to try and do this, which is located in a function in my model:
$this->find('all', array(
'joins' => array(
array(
'table' => 'product_categories',
'alias' => 'pc',
'type' => 'INNER',
'conditions' => array(
'Product.id = pc.product_id'
)
),
// get category type
array(
'table' => 'category_types',
'alias' => 'ct',
'type' => 'INNER',
'conditions' => array(
'pc.category_type_id = ct.id'
)
)
)
, 'conditions'=> array(
'OR' => array(
'Product.account_id IS NULL'
, 'Product.account_id' => $account_id
)
, 'OR' => array(
'ct.id' => $categoryTypeId
, 'ct.parent_id' => $categoryTypeId
)
)
));
The problem is that the query is ignoring the account_id OR conditions resulting in SQL like this:
SELECT Product.id, Product.name, Product.account_id
FROM products AS Product
INNER JOIN product_categories AS pc ON (Product.id = pc.product_id)
INNER JOIN category_types AS ct ON (ct.id = pc.category_type_id)
WHERE ((ct.id = '1') OR (ct.parent_id = '1'))
How can I alter my php code to get the desired results?
Thanks to user2076809 for pointing me in the right direction. The solution is to wrap the two OR conditions each in their own array.
$this->find('all', array(
'joins' => array(
array(
'table' => 'product_categories',
'alias' => 'pc',
'type' => 'INNER',
'conditions' => array(
'Product.id = pc.product_id'
)
),
// get category type
array(
'table' => 'category_types',
'alias' => 'ct',
'type' => 'INNER',
'conditions' => array(
'pc.category_type_id = ct.id'
)
)
),
'conditions'=> array(
array(
'OR' => array(
'Product.account_id IS NULL'
, 'Product.account_id' => $account_id
)
),
array(
'OR' => array(
'ct.id' => $categoryTypeId
, 'ct.parent_id' => $categoryTypeId
)
)
)
));
I think, you should wrap the both of the array in only one OR condition like:-
$this->find('all', array(
'joins' => array(
array(
'table' => 'product_categories',
'alias' => 'pc',
'type' => 'INNER',
'conditions' => array(
'Product.id = pc.product_id'
)
),
// get category type
array(
'table' => 'category_types',
'alias' => 'ct',
'type' => 'INNER',
'conditions' => array(
'pc.category_type_id = ct.id'
)
)
),
'conditions'=> array(
'OR' => array(
array(
'Product.account_id IS NULL'
, 'Product.account_id' => $account_id
),
array(
'ct.id' => $categoryTypeId
, 'ct.parent_id' => $categoryTypeId
)
)
)
));
This is driving me crazy. This is not throwing any errors but it is also not performing the joins. I'm hoping that this is one where I've spent too long looking at it and the answer is obvious to someone else...
$lines = $this->RevenueLine->find('all', array(
'conditions' => array(
'RevenueLine.is_triggered' => 1,
'RevenueLine.date_triggered >=' => $sqldate1,
'RevenueLine.date_triggered <=' => $sqldate2,
),
'joins' => array(
array(
'table' => 'projects',
'alias' => 'Project',
'type' => 'INNER',
'conditions' => array(
'RevenueLine.project_id = Project.id'
)
),
array(
'table' => 'clients',
'alias' => 'Client',
'type' => 'INNER',
'conditions' => array(
'Project.client_id = Client.id'
)
),
array(
'table' => 'classifications',
'alias' => 'Classification',
'type' => 'INNER',
'conditions' => array(
'Project.classification_id = Classification.id'
)
)
),
'order' => array(
'Client.client_number ASC',
'Project.pn_counter ASC'
)
)
);
You need to select the fields from the joined tables:
'fields' => array(
'JoinTable1.*',
'JoinTable2.*',
'JoinTable3.*',
'JoinTable4.*'
)
as a parameter of your find.