Yii2 : Active Record add Not In condition - activerecord

What is the active Record way of adding IN condition to an active Query
in yii 1.x you could use CDbCriteria like this
$cr = new CDbCriteria();
$cr->addNotInCondition('attribute', $array);
There seem to be no equivalent API call in yii2 active record implementation, how to do this via active record ?

Well all query operands seems now merged within in yii\db\QueryInterface::Where() per documentation
an In condition can now be added using something like
$query = MyModel::find()->where(['attribute'=>$array]);
for a not In condition it is slightly different format
$query = MyModel::find()->where(['not in','attribute',$array]);

$query = MyModel::findAll(['not in ','attribute',$array]);
http://www.yiiframework.com/doc-2.0/guide-db-active-record.html

For numbers:
$query = MyModel::find()->where('NOT IN('.implode(',', $array).')');
For strings
$deleteContracts = Contract::find()
->where([
'session_id' => $session_id,
'status' => Contract::STATUS_COMPLETED
])
->andWhere(['not in', 'contract_id', $contracts])
->all();

For me the only working solution was :
$query = MyModel::find()->where('`your-attribute` NOT IN(' . implode(',', $array) . ')')->all();

Related

Check if all the elements of an array are in a string in a where clause in Laravel

I have a model that has a field type which consists of several words. The string looks like this: modern premium hot.
How to get relevant results if I want to filter it with an array like this one:
$filter = [0 => 'modern', 1 => 'hot'];
$search = implode(' ', $filter);
$results = Model::where('type', $search)->get();
The above example will not return anything because it will try to match modern premium hot with modern hot and its not the same, but how to get all relevant results that contain the words modern and hot at the same time in the type fields?
In other words how to get all results that have all elements of the array in the type field, which is a string?
Maybe you need a fulltext service like Elastic Search or Algolia, or even look at fulltext search on your database engine (assuming MySQL, check this link).
But if you really need to move on as it is going, you may try something like that:
$query = Model::query();
foreach ($filter as $term) {
$query->orWhere('type', 'LIKE', "%{$term}%");
}
$results = $query->get();
You use orWhere()
$filter = [0 => 'modern', 1 => 'hot'];
$query= Model::query();
foreach($filter as $term) {
$query->orWhere('type', $term);
}
$results = $query->get();
if you have other where() in your query, use this
$filter = [0 => 'modern', 1 => 'hot'];
$results = Model::where(function($query) use($filter) {
foreach($filter as $term) {
$query->orWhere('type', $term);
}
})
//->where(....)
->get();

Filter record through dates not working laravel

I have a expiry_date (type=date) column in my table
$currentDate = date('Y-m-d');
$Data = Post::whereDate('expiry_date','<=',$currentDate)->where(['status' => 'active'])->orWhere(['p_id' => 3])->select('id','title','status','p_id','expiry_date')->orderBy('id', 'DESC')->get();
i want to filter data if current date is greater than expiry date then those record should not be shown but in my scenario i'm still getting record.
Any solution Thanks.
You must group orWhere clause in closure. Grouping in closure is like () in real query.
$Data = Post::whereDate('expiry_date','<=',$currentDate)
->where(function($query){
return $query
->where(['status' => 'active'])
->orWhere(['p_id' => 3]);
})
->select('id','title','status','p_id','expiry_date')
->orderBy('id', 'DESC')
->get();
But, because I don't know your project - i may wrong with grouping.

Laravel eloquent using loop

I am using eloquent query to filter data. My query is like this and it is working perfectly for now.
$users = User::where('username','LIKE','%'.request('username').'%')
->where('first_name','LIKE','%'.request('first_name').'%')
->where('last_name','LIKE','%'.request('last_name').'%')
->where('gender','LIKE','%'.request('gender').'%')
->where('password','LIKE','%'.request('password').'%')
->SimplePaginate(15);
My request data was like this.
However I need to update this query for dynamic fields. There can be different fields. What I did was to send the request in an associative array. So, my request data turned into like this,
What I intend to do is to put all request data in a search array. Then use a loop to run like the above query. How can I do that?
P.S. I checked in the forum and found some similar questions. Some of them are outdated. Others didn't solve my problem.
If I understand you right you can do like this:
$search = request('search', []);
$users = User::query();
foreach($search as $field=>$value)
{
$users = $users->where($field,'LIKE','%'.$value.'%');
}
$users = $users->SimplePaginate(15);
You can try this.
$search = $request->get('search');
User::where(function ($q) use ($search){
foreach ($search as $key=>$value) {
if($value != null ){
$q->where($key, 'like', "%{$value}%");
}
}
})->get();
The where() clause can also accept an array. With that in mind, you could map over your search parameters and convert it to the format you want and then feed it into the query.
For example:
$search = [
'first_name' => 'John',
'last_name' => 'Smith'
];
$filters = collect($search)->map(function($value, $key) {
return [$key, 'LIKE', "%{$value}%"];
})->values()->toArray();
return User::where($filters)->SimplePaginate(15);

Laravel simplePaginate() for Grouped Data

I have the following query.
$projects = Project::orderBy('created_at', 'desc');
$data['sorted'] = $projects->groupBy(function ($project) {
return Carbon::parse($project->created_at)->format('Y-m-d');
})->simplePaginate(5);
When I try to paginate with the simplePaginate() method I get this error.
stripos() expects parameter 1 to be string, object given
How can I paginate grouped data in this case?
The created_at attribute is already casted as a Carbon Object (by default in laravel models). that's why you are getting that error. Try this:
$projects = Project::orderBy('created_at', 'desc')->get();
$data['sorted'] = $projects->groupBy(function ($project) {
return $project->created_at->format('Y-m-d');
})->simplePaginate(5);
this answer is just for the error you're getting. now if you want help with the QueryBuilder, can you provide an example of the results you're expecting to have and an example of the database structure ?
The pagination methods should be called on queries instead of collection.
You could try:
$projects = Project::orderBy('created_at', 'desc');
$data['sorted'] = $projects->groupBy('created_at');
The problem was solved. I was create custom paginator via this example:
https://stackoverflow.com/a/30014621/6405083
$page = $request->has('page') ? $request->input('page') : 1; // Use ?page=x if given, otherwise start at 1
$numPerPage = 15; // Number of results per page
$count = Project::count(); // Get the total number of entries you'll be paging through
// Get the actual items
$projects = Project::orderBy('created_at', 'desc')
->take($numPerPage)->offset(($page-1)*$numPerPage)->get()->groupBy(function($project) {
return $project->created_at->format('Y-m-d');
});
$data['sorted'] = new Paginator($projects, $count, $numPerPage, $page, ['path' => $request->url(), 'query' => $request->query()]);
simplePaginate Method is exist in the path below:
Illuminate\Database\Eloquent\Builder.php::simplePaginate()

How to do update query on laravel fluent using db::raw

This is related to one of my question earlier where:
Update table1 field with table2 field value in join laravel fluent
But since this is a different approach now, I will just ask another question:
How do you properly do an update using DB:raw?
I want to update the favorite_contents.type with the value of contents.type, but it doesn't do anything, the static setting of 1 to favorite_contents.expired is working.
This is my code which still doesn't update the type even when the DB::raw was used:
$table = 'favorite_contents';
$contents = DB::table($table)
->join('contents', function($join) use($table){
$join->on("$table.content_id", '=', 'contents.id');
})
->whereIn("$table.content_id",$ids)
->update(array(
"$table.expired" => 1
));
DB::raw("UPDATE favorite_contents, contents SET favorite_contents.type = contents.type where favorite_contents.content_id = contents.id");
This is the first code that doesn't update before I resorted to the above code that doesn't work as well:
$table = 'favorite_contents';
$contents = DB::table($table)
->join('contents', function($join) use($table){
$join->on("$table.content_id", '=', 'contents.id');
})
->whereIn("$table.content_id",$ids)
->update(array(
"$table.expired" => 1,
"$table.type" => "contents.type"
));
P.S:
This is working when done on an sql editor:
UPDATE favorite_contents, contents SET favorite_contents.type = contents.type where favorite_contents.content_id = contents.id
code raw updates like this:
...->update( array(
'column' => DB::raw( 'column * 2' )
) );
DB::statement("UPDATE favorite_contents, contents SET favorite_contents.type = contents.type where favorite_contents.content_id = contents.id");
Try DB::statement for raw queries that does not involve outputting something (select).
Will be work such similar, simple realization in Laravel 5.2 ,
Query Builder:
DB::table('stores')
->where('id', $request)
->update(['visibility' =>DB::raw($value)]);
This response is tested real site and working properly

Resources