How to code Mysql DATE_FORMAT in cakephp? - mysql

My Code in Mysql:
SELECT DATE_FORMAT( created , '%Y') from item;
How do you code in CakePHP?

The func() method can be used here.
Considering that you would be writing the query in the Item model, following code snippet can be useful:
$query = $this->find();
$createdYear = $query->func()->date_format([
'created' => 'identifier',
"'%Y'" => 'literal'
]);
$query->select(['id','createdYear'=>$createdYear]);
$result = $query->all();
Cheers !!!

Please code 'date_format("%Y-%m-%d", created)' in fields.
"%Y-%m-%d" is date format.
created is column name.
$this->Item->find('all', array(
'fields' => array(
'date_format("%Y-%m-%d", created)',
)
));

Related

Not equal condition with findAll()

I am trying to pull record from a table using the following code
$userId = Yii::$app->user->id;
$lists = PromoLists::findAll(['user_id' => $userId, 'list_type' => 'custom']);
which outputs a query like below
select * from promo_lists where user_id ='$userId' and list_type='custom'
But i am unable to find any thing in the documentation that would help me achieve it with the following condition.
select * from promo_lists where user_id ='$userId' and list_type='custom' and status!='deleted'
as the status is an ENUM field and there are 4 different status
'active','pending','rejected','deleted'
currently i used the following approach
PromoLists::findAll(['user_id' => $userId, 'list_type' => 'custom', 'status'=>['active','pending','rejected']]);
which outputsthe following query
select * from promo_lists where user_id ='$userId' and list_type='custom' and status in ('active','pending','rejected')
which somehow achieves the same thing but this query would need to be edited every time when there is a new status type added to the table column status.
i know i can do this by using PromoLists::find()->where()->andWhere()->all()
but how to check with != / <> operator using findAll().
Simply like this:
PromoLists::find()->where(['and',
[
'user_id' => $userId,
'list_type' => 'custom',
],
['<>', 'status', 'deleted'],
])->all();
Using operator format in condition
http://www.yiiframework.com/doc-2.0/guide-db-query-builder.html#operator-format
PromoLists::find()
->andWhere([
'user_id' => $userId,
'list_type' => 'custom',
['!=', 'status', 'deleted']
])
->all();

How to use AND and OR in MySQL query?

I want to get those records whose date_last_copied field is empty or less than the current date. I tried this, but it did not give me the desired result:
$tasks = $this->Control->query("
SELECT *
FROM
`controls`
WHERE
`owner_id` = ".$user_id."
AND `control_frequency_id` = ".CONTROL_FREQUENCY_DAILY."
OR `date_last_copied` = ''
OR `date_last_copied` < ". strtotime(Date('Y-m-d'))."
");
Current query looks something like this, I think. That is, find the records with the correct owner_id and frequency_id, where the date_last_copied is null or less than a certain date. Is that logic correct?
SELECT *
FROM controls
WHERE owner_id = ::owner_id::
AND control_frequency_id = ::frequency_id::
AND (
date_last_copied IS NULL
OR date_last_copied < ::date::
)
But we should really be using the CakePHP query builder, rather than running raw SQL. This article gives some details. If I were to take a stab at a solution, we'd want something like the following. But we ideally want someone from the CakePHP community to chime in here. EDIT: Note that this seems to be for CakePHP 3.0, only.
// Build the query
$query = TableRegistry::get('controls')
->find()
->where([
'owner_id' => $ownerId,
'control_frequency_id' => $frequencyId,
'OR' => [
['date_last_copied IS' => null],
['date_last_copied <' => $date]
]
]);
// To make sure the query is what we wanted
debug($query);
// To get all the results of the query
foreach ($query as $control) {
. . .
}
I'm suggesting this, rather than the raw SQL string you have above, because:
We can now leverage the ORM model of CakePHP.
We don't have to worry about SQL injection, which you're currently vulnerable to.
EDIT: OK, this is a guess at the syntax applicable for CakePHP 2.0... YMMV
$controls = $this->controls->find('all', [
'conditions' => [
'owner_id' => $ownerId,
'control_frequency_id' => $frequencyId,
'OR' => [
['date_last_copied IS' => null],
['date_last_copied <' => $date]
]
]
];
Otherwise, we just use the raw query as a prepared statement:
$result = $this->getDataSource()->fetchAll("
SELECT *
FROM controls
WHERE owner_id = ?
AND control_frequency_id = ?
AND (
date_last_copied IS NULL
OR date_last_copied < ?
)",
[$ownerId, $frequencyId, $date]
);
Not sure about your whole logic but your final query statement should be something like:
SELECT * FROM `controls` WHERE (`owner_id` = <some owner_id>)
AND (`control_frequency_id` = <some id value>)
AND (`date_last_copied` = '' OR
`date_last_copied` IS NULL OR
`date_last_copied` < CURDATE() )
Use parentheses carefully to match your logic.
Always specify the version of cakePHP you are using for your App.
This query should work fine in CakePHP 3.0 for SQL AND and OR.
$query = ModelName>find()
->where(['colunm' => 'condition'])
->orWhere(['colunm' => 'otherCondition'])
->andWhere([
'colunm' => 'anotherContion',
'view_count >' => 10
])
->orWhere(['colunm' => 'moreConditions']);

search result in month using mysql or cakephp

Hi everyone i have one question search result month in using MySql or Cakephp my table name is state_supplies and data are
MySql query is:
SELECT * FROM `state_supplies` WHERE created=DATE_FORMAT(NOW(), '%m')
Cakephp search code is
$this->StateSupply->find('all', array(
'conditions'=> array(
'unitid'=>$this->Session->read('Auth.User.unitid'),
'created'=>'MONTH(CURDATE())'
)
)
);
Try this:
In Mysql:
$first_day_this_month = date('Y-m-01 H:i:s'); // hard-coded '01' for first day
$last_day_this_month = date('Y-m-t H:i:s');
$sql="SELECT * FROM state_supplies WHERE created between '$first_day_this_month' and '$last_day_this_month' "
Cakephp code
Details
Update code for right answer
$this->StateSupply->find('all',array(
'conditions'=>array(
'unitid'=>$this->Session->read('Auth.User.unitid'),
'crop'=>$this->request->data['StateSupply']['crop'],
'state'=>$this->request->data['StateSupply']['state'],
'created BETWEEN ? AND ?'=>array(date('Y-m-01',strtotime('this month')),date('Y-m-t',strtotime('this month')))
)
)
);

How to change Mysql DATE_FORMAT for table column in cakephp?

What is the equivalent cakephp find query for the following sql query?
Assume that price_date field type is datetime
$sql = "SELECT id,product_id,date_format("%Y-%m-%d",price_date) AS pd from products"
Not like this $this->Product->query($sql);
I want it like $this->Product->find('...
You would have to define it as a virtualField in your Product model:
class Product extends AppModel {
public $virtualFields = array(
'pd' => 'date_format(price_date, "%Y-%m-%d")'
);
}
Then price_date will always return in Y-m-d format, aliased as pd, as if it were a field in your database. If you want it to return like that under another name, simply change the key in the array. Using it as a find, you can then simply:
$this->Product->find('all', array(
'fields' => array('id', 'product_id', 'pd')
));
try this:
$this->Product->find('all', array(
'recursive' => -1,
'fields' => array('id', 'product_id', 'date_format("%Y-%m-%d",price_date) AS pd from products')
));
Just specify it in your find() fields array:
'fields' => array(
//...
'date_format("%Y-%m-%d", price_date)',
//...
)

Message list: order by and group by query on cakephp and mysql

I want to change my message list page/inbox. Currently it shows all the messages from the DB like if someone send me a message 3 times, it will all appear in my inbox. Now i want to make it simple like every sender will appear only once in the list and will show the latest message that he/she sent.
This is my code in cakephp:
$this->paginate = array(
'Message'=> array(
'conditions'=>array('Message.recipient_id'=>$this->user_id),
'group' => array('Message.sender_id'),
'order'=>'message_sent_date DESC',
'limit'=> 20,
)
);
The problem with this code is it shows the oldest message content. I think it's because group by always first before order by.
I was able to do it on mysql query but i don't know how to make it on cakephp.
Here's my query:
SELECT *
FROM(
SELECT *
FROM messages WHERE recipient_id = 114
ORDER BY message_viewed_date DESC
) AS messages
GROUP BY sender_id
ORDER BY message_viewed_date DESC
Please help me with this.. Thanks.
This should do the trick (make sure your models are set up correctly):
$results = $this->Message->find('all', array(
'conditions' => array(
'recipient_id' => 114
),
'group' => 'sender_id',
'order' => 'message_viewed_date DESC'
));
No need for the sub query there, it's not doing anything fancy. The manual will help you with queries like this.
I've solve this problem using the Model::query() http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-query
here's my code:
$messages = $this->Message->query("SELECT id FROM(SELECT * FROM messages WHERE recepient_id = ". $this->user_id ." ORDER BY message_sent_date DESC) AS Message GROUP BY sender_id ORDER BY message_sent_date DESC");
for($i=0; $i<count($messages); $i++){
$message_id[$i] = $messages[$i]['Message']['id'];
}
$this->paginate = array(
'Message'=> array(
'conditions'=>array('Message.id' => $message_id, 'Message.recepient_id'=>$this->user_id, 'Message.hidden_on_to'=>false),
'limit'=>20,
'order'=>array('Message.message_sent_date' => 'DESC'),
'recursive'=>0,
'fields'=>array('Message.id', 'Message.message_content', 'Message.message_sent_date', 'Message.message_viewed_date', 'Sender.id', 'Sender.username')
)
);