cake php custom query - php

I have use custom query in cakephp but I dont understand how to run custom join query.
I am using this code
$arrayTemp1 = $this->User->query('SELECT DISTINCT
u.id,u.hunting_association FROM ht_users as u LEFT JOIN
`ht_user_animal_prices` as uap ON uap.user_id=u.id WHERE
uap.animal_type_id='.$this->request->data['User']['animal'].' ');
User is the model for ht_users and UserAnimalPrice is the model for ht_user_animal_prices. How to combine the query?
Please help.

If you want to use custom queries and you want the data of UserAnimalPrice model, you just have to put the fields in the query. Something like:
$arrayTemp1 = $this->User->query('SELECT DISTINCT u.id,u.hunting_association, uap.* FROM ht_users as u LEFT JOIN ht_user_animal_prices as uap ON uap.user_id=u.id WHERE uap.animal_type_id='.$this->request->data['User']['animal'].' ');
If you prefer not to use custom queries:
$fields = array('User.id','User.hunting_association','UserAnimalPrice.*');
$join = array(
array(
'table' => 'ht_user_animal_prices',
'alias' => 'UserAnimalPrice',
'type' => 'LEFT',
'conditions' => array('UserAnimalPrice.user_id = User.id')
)
);
$conditions = array('UserAnimalPrice.animal_type_id' => $this->request->data['User']['animal']);
$group = array('User.id');
arrayTemp1=arrayTemp1->find('all',array('fields'=>$fields,'joins'=>$join,'conditions'=>$conditions,'group'=>$group));

This is Correct Query u used .You can also use it in User Model like
public function getCustomUsersQuery()
{
$arrayTemp1 = $this->query("
SELECT
DISTINCT u.id,u.hunting_association FROM ht_users as u
LEFT JOIN
ht_user_animal_prices as uap ON uap.user_id=u.id
WHERE
uap.animal_type_id='".$this->request->data['User']['animal']."'");
return $arrayTemp1;
}
And call inside Users Controller
$result = $this->getCustomUsersQuery();

Sorry I cannot comment on Rizwan answer. If you received the "Call to a member function..." problem, make sure you have the following code
public $uses = array('User');
this tells that you want to access the user model in that controller. Then you will be allowed to do so.

Related

Yii2 model to exclude related records

I have two related tables, posts and hidden_posts, where posts.id corresponds to hidden_posts.post_id.
In my posts model I have this relation to return a record if the post should be hidden:
public function getHiddenPosts()
{
return $this->hasOne(HiddenPost::className(), ['post_id' => 'id']);
}
Now I need to return all posts that are NOT hidden. So I am looking for the equivalent of this pseudo code:
return $this->hasNone(HiddenPost::className(), ['post_id' => 'id'])->all();
Which is saying, "show me all posts that are not in the hidden_posts table".
So does this use an outer join query or is there a statement that I can't find do do this in one line?
You can do it this way. Get all posts that are not listed in Hidden table:
$posts = Post::find()
->andFilterWhere(['not in',
'post.id',
HiddenPost::find()
->select(['hidden_post.post_id'])
->all();
In any case, it is best to proceed from the raw SQL statement. Write a statement that satisfies your results and transfer it to ActiveRecord query.
Post items could be retrieved using an inner join
$res = Post::find()
->select('post.*')
->innerJoin('hdn_post', '`post`.`id` = `hdn_post`.`post_id`')
->all();
It could be good practice using yii2 owned function instead of adding queries inside the model such as using select queries in your model.
Instead you can use ORM functions in yii2 has already done by gii inner functions created for to make u=your work easy.
Add * #property YourModel $hidden_post
and inside this model add you post_id such as ( * #property integer $post_id ) to create relation.
public function getHiddenPosts($hidden_post) {
return $this->find()->joinWith('hidden_post')
->where(['hidden_post' => $hidden_post])
->all();
}
You could retrive the Post items using an inner join
$posts = Post::find()
->select('post.*')
->innerJoin('hidden_post', '`post`.`id` = `hidden_post`.`post_id`')
->all();
for not hidden then use left join and check for null result of related table
$posts = Post::find()
->select('post.*')
->leftJoin('hidden_post', '`post`.`id` = `hidden_post`.`post_id`')
->where('ISNULL(`hidden_post`.console_id)')
->all();

How can I do a join with last entries in CakePHP?

So, I'm trying to do a query to get the last entries of each user using CakePHP relationship. In my Map and User model I have:
class Map (and User) extends AppModel {
public $hasMany = 'Geolog';
}
And I'm trying to doing this query to catch the last entry of each user. dg_maps and dg_users have a many to many relation.
SELECT
dg_users.id,
dg_users.email,
dg_maps.id,
dg_maps.latitude,
dg_maps.longitude,
dg_maps.timestamp
FROM
(SELECT
*
FROM
dg_maps
ORDER BY dg_maps.timestamp DESC) dg_maps
JOIN
dg_geologs ON dg_geologs.map_id = dg_maps.id
JOIN
dg_users ON dg_users.id = dg_geologs.user_id
GROUP BY dg_geologs.user_id;
What I'm doing now is:
$this->Map->query('SELECT dg_users.id, dg_users.email, dg_maps.id, dg_maps.latitude, dg_maps.longitude, dg_maps.timestamp FROM (SELECT * FROM dg_maps ORDER BY dg_maps.timestamp DESC) dg_maps JOIN dg_geologs ON dg_geologs.map_id = dg_maps.id JOIN dg_users ON dg_users.id = dg_geologs.user_id GROUP BY dg_geologs.user_id');
But, I know that a better method then this, using Cake methods. So, how can I do this?
Thank you all!
I used this for my project it is very simple
Easy way to generate CakePHP HABTM joins for use in pagination.
So put this in your model (note for function arguments - there is error in function from link )
public function generateHabtmJoin ($joinModel, $joinType = 'INNER') {
// If the relation does not exist, return an empty array.
if (!isset($this->hasAndBelongsToMany[$joinModel])) {
return array();
}
// Init joins, and get HABTM relation.
$joins = array();
$assoc = $this->hasAndBelongsToMany[$joinModel];
// Add the join table.
$bind = "{$assoc['with']}.{$assoc['foreignKey']} = {$this->alias}.{$this->primaryKey}";
$joins[] = array(
'table' => $assoc['joinTable'],
'alias' => $assoc['with'],
'type' => $joinType,
'foreignKey' => false,
'conditions' => array($bind),
);
// Add the next table.
$bind = "{$joinModel}.{$this->{$joinModel}->primaryKey} = {$assoc['with']}.{$assoc['associationForeignKey']}";
$joins[] = array(
'table' => $this->{$joinModel}->table,
'alias' => $joinModel,
'type' => $joinType,
'foreignKey' => false,
'conditions' => array($bind),
);
return $joins;
}
and you can call this function from your controller
You have example in link

select column magento

I was wondering how you can select columns. Above you can see the sql I wanna write in the controller. But I want to do this the wright way. Like other sql statements in magento.
I tried to add ->columns('o.sku AS SKU') but this didn't work.
Any ideas? Thanks in advance!
//sql
$readresult="SELECT o.name AS 'Product', o.sku AS 'SKU', c.entity_id AS 'Order', c.customer_email AS 'Email', c.customer_firstname AS 'Voornaam', c.customer_lastname AS 'Achternaam', c.customer_middlename AS 'Tussenvoegsel', o.product_options AS 'Options', a.telephone AS 'Telefoon', a.postcode AS 'Postcode', a.street AS 'Street', a.city AS 'City', c.increment_id AS 'Bestelnr' FROM magento_sales_flat_order AS c INNER JOIN magento_sales_flat_order_item AS o ON c.entity_id = o.order_id INNER JOIN magento_sales_flat_order_address AS a ON a.parent_id = c.entity_id WHERE o.product_id =".$product." GROUP BY c.entity_id ORDER BY o.sku;";
//THE MAGENTO WAY!
$resource = Mage::getSingleton('core/resource');
$read = $resource->getConnection('core_read');
$o = $resource->getTableName('magento_sales_flat_order');
$o_item = $resource->getTableName('magento_sales_flat_order_item');
$o_address = $resource->getTableName('magento_sales_flat_order_address');
$select = $read->select()->from(array('c'=>$o))
->join(array('o'=>$o_item), 'c.entity_id = o.order_id', array(o.sku AS 'SKU'))
->join(array('a'=>$o_address), 'a.parent_id = c.entity_id', array())
->where('o.product_id', $product)
->group('c.entity_id')
->order('o.sku');
You souldn't work like this with core modules at all. Those low level SQL queries should be used by resource models only. Especially not within a controller.
You should get an instance of Mage_Sales_Model_Resource_Order_Collection by calling Mage::getModel('sales/order')->getCollection() and build your query from there. Just have a look at the source code to find out about how to do that exactly; start at app/code/core/Mage/Sales/Model/Resource/Order/Collection.php and work your way down the inheritance chain.
For example, you can add a WHERE using something like $collection->addAttributeToSearchFilter().
Magento's got great database abstraction and you sould definately be using it.
Hope this helps.

converting SQL to cakephp ORM

So I have this query that I am trying to convert to cake ORM and I do not know how to go about it.
I have a user table and a word table. Users have many words (thats the relationship). I want to write a query that will give me the users that have added the most words in the system. This is the current query I wrote but I am having trouble converting it to cakephp ORM syntax, any ideas?
SELECT
users.username,
COUNT(word) AS n
FROM
users AS users
INNER JOIN words AS words
ON users.userid=words.userid
GROUP BY
users.username
ORDER BY
n DESC
LIMIT 3
There are many ways to write the query:- In controller you can write as -
$options = array(
'fields' => array(
'User.name',
'COUNT(Word.id) as word_count',
),
'group' => 'Word.user_id',
'order' => 'word_count DESC',
);
$users = $this->User->Word->find('first', $options);
debug($users);
In User model you have to write:
public $hasMany = 'Word';
In Word model you have to write:
public $belongsTo = 'User';

Doing Join query using CDBCriteria

I am trying to do a Join query using CDBCriteria in Yii framework. The issue is the join query works successfully but it does not display the columns from other tables.
I am doing in the following way
$criteria = new CDbCriteria;
$criteria->order = 't.id desc';
$criteria->select = '*';
$criteria->join = ' INNER JOIN table2 INNER JOIN table3 INNER JOIN table4';
When i run this, I can see only the mail table1 columns displayed. Other columns are not shown.
In my model class, I have the relation has
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'user' => array(self::BELONGS_TO, 'DmPhoneUser', 'user_id'),
'command' => array(self::BELONGS_TO, 'DmOtaCommand', 'command_id'),
'partner' => array(self::BELONGS_TO, 'DmPartner', 'partner_id'),
);
}
********************************************************
public function actionGetHistory($start, $per_page)
{
$partner_id = '10';
$criteria = new CDbCriteria;
$criteria->order = 't.history_id desc';
$criteria->select = 't.*, table2.*';
$criteria->join = ' INNER JOIN table2 ON t.command_id = table2.command_id';
$result = Table_1_class::model()->with('command')->findAll();
$history_data = CJSON::encode($result);
echo $history_data;
}
here command_id is common in table1 and table2.
This is how I am using the criteria code.
As I said, Yii's Active Record implementation will only use columns which are defined in the table itself or the tables you are linking to through with, not arbitrary columns you return in the resultset.
Solution 1: Define a relation to table2, add that relation to with, and get rid of join. Then you'll probably need to convert each returned object to an array - CJSON::encode will not handle a model with relations well.
Solution 2: Use Yii::app()->db->createCommand("SQL query")->queryAll(); instead of Active Record. This will produce an array of arrays, which CJSON::encode will have no problem with.

Categories