CakePHP 3 Between two date - orm

I try to do an query in my controller, I want find all entity where the start and en date are between NOW(),
if $start and $end are between NOW() so show all entity, but i didn't succeed
My find is :
$day = date('l');
$now = Time::now();
$tvs = $this->Tvs
->find('all')
->contain(['Users'])
->where(['Tvs.day' => $day])
->andWhere(function($exp) {
return $exp->between($now, 'Tvs.start', 'tvs.end', $now);
});
How make this query ?
Thanks for you'r help !

Assuming you are trying to find all twhe record having $now between start and end the query is
sice the manual says that the first argument of the between fucntion should be name of the field (so it can't be a date) instead of between you can use two comparison
$tvs = $this->Tvs
->find('all')
->contain(['Users'])
->where(['Tvs.day' => $day])
->andWhere(function($exp) use($now) {
$exp->lte('Tvs.start', $now);
$exp->gte('Tvs.end', $now);
return $exp;
});
anyway you can make use of the mysql NOW() function directly into the query if the $now variable contains the same value of the NOW() function
->andWhere(function($exp, $q) {
return $exp->between($q->func()->now(), 'Tvs.start', 'Tvs.end');
});
there's anothe method: you can use BETWEEN and a palceholder to bind the value of $now
->andWhere([':now BETWEEN Tvs.start AND Tvs.end'])
->bind(':now', $now, 'datetime');
or using cakephp sql functions
->where(function($exp, $q) {
return $exp->between(':now', 'Tvs.start', 'Tvs.end');
})
->bind(':now', $now, 'datetime');

Since CakePHP 3.6 you can use identifiers:
return $query->where(function ($exp, $q) {
$today = $q->func()->now();
$start = $q->identifier('Tvs.start');
$end = $q->identifier('Tvs.end');
return $exp
->between($today,$start,$end);
});

Related

Laravel QueryBuilder condition

In Laravel, I want to build a query like following.
There is a status column, value should be 0 or 1.
And there is another column, device_ids with array.
Now,in query, I want to apply different logic on device_ids, when status is 0 and status is 1.
Can someone suggest me best possible way.
$builder->where('status','0')->whereJsonDoesntContain('device_ids', $imei_id->id)
$builder->where('status','1')->whereJsonContains('device_ids', $imei_id->id)
How can I combine both ?
$all_applications = $builder->where('status', $model->status)
->when($status, function ($query) {
Log::error("One");
return $query->whereJsonContains('device_ids', 107); },
function($query) {
Log::error("Zero"); return $query
->whereJsonDoesntContain('device_ids', 107); });
If I use $model->status , it gives me error like , "Undefined variable: model"
You have to use when.
$result = YourModel::where('status', $status)
->when($status, function ($query) {
return $query->whereJsonContains('device_ids', $imei_id->id);
}, function ($query) {
return $query->whereJsonDoesntContain('device_ids', $imei_id->id);
});

How can I concat 2 columns with eachother without using Raw Sql Concat

I am working on a new project in Laravel 8 where I am allowed to use as little RAW SQL as possible.
For a number of situations I have to Concat 2 columns together (as it is shown below) and that is actually easy to do with Raw Sql. But I am not allowed to use Raw Sql for that.
BoekhoudingVerdichting::select('boekhouding_verdichting.id', DB::raw("CONCAT(boekhouding_verdichting.verdichtingnr,' - ',verdichting) AS verdichting, CONCAT(boekhouding_hoofdverdichting.hoofdverdichtingnr,' - ',hoofdverdichting) AS hoofdverdichting"))
->join('boekhouding_hoofdverdichting', function ($q) {
$q->on('boekhouding_hoofdverdichting.id', 'boekhouding_verdichting.id_hoofdverdichting');
})
->join('boekhouding_grootboek', function ($q) {
$q->on('boekhouding_grootboek.id_verdichting', 'boekhouding_verdichting.id');
})
->groupBy('boekhouding_verdichting.id')
->orderBy('boekhouding_verdichting.verdichtingnr')
->orderBy('boekhouding_verdichting.verdichting')
->get();
I got a tip that I first have to get the data from the database as a Collection (as it is shown below) and then put the Collection through a map-function and in the map-function I can Concat the columns and return them! I searched the internet but I couldn't find any soloution.
Maybe you have another solution?
I hope you can help me with it.
BoekhoudingVerdichting::select('boekhouding_verdichting.id', 'boekhouding_verdichting.verdichtingnr', 'verdichting', 'boekhouding_hoofdverdichting.hoofdverdichtingnr', 'hoofdverdichting')
->join('boekhouding_hoofdverdichting', function ($q) {
$q->on('boekhouding_hoofdverdichting.id', 'boekhouding_verdichting.id_hoofdverdichting');
})
->join('boekhouding_grootboek', function ($q) {
$q->on('boekhouding_grootboek.id_verdichting', 'boekhouding_verdichting.id');
})
->groupBy('boekhouding_verdichting.id')
->orderBy('boekhouding_verdichting.verdichtingnr')
->orderBy('boekhouding_verdichting.verdichting')
->get();
Solved the problem!
$collection = BoekhoudingVerdichting::select('boekhouding_verdichting.id', 'boekhouding_verdichting.verdichtingnr', 'verdichting', 'boekhouding_hoofdverdichting.hoofdverdichtingnr', 'hoofdverdichting')
->join('boekhouding_hoofdverdichting', function ($q) {
$q->on('boekhouding_hoofdverdichting.id', 'boekhouding_verdichting.id_hoofdverdichting');
})
->join('boekhouding_grootboek', function ($q) {
$q->on('boekhouding_grootboek.id_verdichting', 'boekhouding_verdichting.id');
})
->groupBy('boekhouding_verdichting.id')
->orderBy('boekhouding_verdichting.verdichtingnr')
->orderBy('boekhouding_verdichting.verdichting')
->get();
$newCollection = $collection->map(function ($item, $key) {
$item['verdichting'] = $item['verdichtingnr'] . ' - ' . $item['verdichting'];
$item['hoofdverdichting'] = $item['hoofdverdichtingnr'] . ' - ' . $item['hoofdverdichting'];
return $item;
});
$solved = $newCollection->all();

use field as recursive function in where condition in yii2

I want to send content of date1 to exp function in where() condition and return the result.
Note: Actually I want to compare two date, that I need to change one of dates to explode
Here is my code:
function exp($date){
$date = explode('/', $date);
$Y = $date[0];
$m = $date[1];
$d = $date[2];
return $Y;
}
$promise = new ActiveDataProvider([
'query' => Post::find()
->where('status = "show"')
->andWhere(['<=', exp('date1'), 'date2'])// date1 is: 2018/02/03
->orderBy('id'),
]);
Is there any way else to do this?
exp is a PHP function, in andWhere you prepare an SQL query that will run on the SQL server. The SQL parser on the SQL server can not execute PHP functions. You should use MySQL DATE_FORMAT function here:
$promise = new ActiveDataProvider([
'query' => Post::find()
->where('status = "show"')
->andWhere(['<=', 'DATE_FORMAT(date1, "%Y")', 'date2'])
->orderBy('id'),
]);
Please change the name of the fields date1 and date2 to make them more informative. For ex. order_date, delivery_date etc.
If status values are often used in your code, you should replace them with a constants of the Postclass.
If date2 contains only year values, it is better to use the YEAR type.

Yii min date validation rule

How can I add a minimum date validation rule in a Model?
Example:
I have a column dt_ini as DATE, which I need to restrict the input as D+7, on create.
If today is: october 1st, 2012
the minimum valid date on create would be: october 8th, 2012.
Otherwise, I would throw a validation error as: Your date must be at least 7 days from now.
The code I would expect is something like this: (this is NOT tested, and probably won't work)
public function rules(){
return array('dt_ini', 'date', 'minDate' => '+7'),
}
Thanks.
Is this what you are looking for?
Create custom valid rule as follows:
class YourModel extends CActiveModel
{
// some....
public function rules(){
return array('dt_ini', 'dateValid', 'minDate' => '+7 day', 'on' => 'create');
}
public function dateValid($attribute, $params)
{
$valid=null;
$today = date('Y-m-d', time());
if(isset($params['minDate']))
$valid = date('Y-m-d', strtotime($params['minDate'])); //+7 day
if( !is_null($valid) )
{ //for increamental date
if($this->dt_ini > $valid || $this->dt_ini < $today )
$this->addError($attribute, 'enter error message');
}
}
}

MySQL: Query Cacheing (How do I use memcache?)

I have an query like:
SELECT id as OfferId FROM offers
WHERE concat(partycode, connectioncode) = ?
AND CURDATE() BETWEEN offer_start_date
AND offer_end_date AND id IN ("121211, 123341,151512,5145626 ");
Now I want to cache the results of this query using memcache and so my question is
How can I cache an query using memcache.
I am currently using CURDATE() which cannot be used if we want to implement caching and so how can I get current date functionality without using CURDATE() function ?
Something like this should work:
function getOffers($ids) {
$key = implode(',', $ids);
$cache = new Memcache();
$cache->connect('localhost');
$content = $cache->get($key);
if ($content === false) {
// content is not cached, so we have to run the query
$content = $yourDb->query('your query here');
$cache->add($key, $content);
}
$cache->close();
return $content;
}
getOffers(array('121211','123341','151512','5145626'));
You can take this a step further by sorting $ids so that the same "set" of IDs (but in a different order) will still take advantage of an available cache for that set.
This isn't date-sensitive, but you can make it date sensitive by adding the date string to $key