My code here is working fine but I need it to be short. I'm using if statement so Select if I will use user_id or Guest_ip.
But I get a long code, any help?
if (Auth::guest()) {
$Task = Enrollee::with('path.ProgrammingField')->with(['path.pathtags' => function ($q) use ($TagArray)
{
$q->with(['Tasks' => function ($q) use ($TagArray)
{$q->has('tasktags', '=', 2)->orderBy('id', 'ASC') ->whereDoesntHave('tasktags',
function ($query) use ($TagArray) {
$query->whereNotIn('name', $TagArray);
}
)
->with('tasktags');
}]
)->orderBy('id', 'ASC');
}])
->where( 'user_id' , '=' , Auth::user()->id )
->where('Path_id', $Path->id) ->get();
$Tasks = $Task[0]->path;
$Subs = Enrollee::where( 'user_id' , '=' , Auth::user()->id )->where('Path_id', $Path->id)->get();
$AllSubs = [];
foreach($Subs as $sub){
$AllSubs[] = $sub->task_id;
}
$AllSubTasks = implode(" ",$AllSubs);
$SubTasks = explode(",", ($AllSubTasks));
}
else {
$Task = Enrollee::
with('path.ProgrammingField')
->with(['path.pathtags' => function ($q) use ($TagArray)
{
$q->with(['Tasks' => function ($q) use ($TagArray)
{$q->has('tasktags', '=', 2)->orderBy('id', 'ASC')
->whereDoesntHave('tasktags',
function ($query) use ($TagArray) {
$query->whereNotIn('name', $TagArray);
}
)
->with('tasktags');
}]
)->orderBy('id', 'ASC');
}])
->where( 'guest_ip' , '=' , '127.0.0.1' )
->where('Path_id', $Path->id) ->get();
$Tasks = $Task[0]->path;
$Subs = Enrollee::where( 'guest_ip' , '=' ,'127.0.0.1') ->where('Path_id', $Path->id)->get();
$AllSubs = [];
foreach($Subs as $sub){
$AllSubs[] = $sub->task_id;
}
$AllSubTasks = implode(" ",$AllSubs);
$SubTasks = explode(",", ($AllSubTasks));
}
Can I Use
if (Auth::guest()) {
->where( 'guest_ip' , '=' , '127.0.0.1' )
}
I need to be one code and change if I use guest_ip or user id Using if statement
Hope this will help you.
$ObjTask = Enrollee::with('path.ProgrammingField')
->with(['path.pathtags' => function ($q) use ($TagArray) {
$q->with(['Tasks' => function ($q) use ($TagArray) {
$q->has('tasktags', '=', 2)->orderBy('id', 'ASC')
->whereDoesntHave('tasktags', function ($query) use ($TagArray) {
$query->whereNotIn('name', $TagArray);
}
)
->with('tasktags');
}]
)->orderBy('id', 'ASC');
}])
->where('Path_id', $Path->id);
$Subs = null;
if (Auth::guest()) {
$Task = $ObjTask->where('user_id', '=', Auth::user()->id)->get();
$Subs = Enrollee::where('user_id', '=', Auth::user()->id)->where('Path_id', $Path->id)->get();
}
else {
$Task = $ObjTask->where('guest_ip', '=', '127.0.0.1')->get();
$Subs = Enrollee::where('guest_ip', '=', '127.0.0.1')->where('Path_id', $Path->id)->get();
}
$Tasks = $Task[0]->path ?? null;
$AllSubs = [];
$AllSubTasks = $SubTasks = null;
if (!empty($Subs)) {
foreach ($Subs as $sub) {
$AllSubs[] = $sub->task_id;
}
$AllSubTasks = implode(" ", $AllSubs);
$SubTasks = explode(",", ($AllSubTasks));
}
After properly indenting the code (like #castis correctly advised) , you can start extracting the bits within the statements into methods. That's called refactoring.
From wikipedia:
Code refactoring is the process of restructuring existing computer code—changing the factoring—without changing its external behavior.
It will look something like this:
if(true) {
doWhateverNeedsToBeDone();
} else {
doTheOtherThing();
}
And you copy all code and paste into the body of these new methods.
Related
I am trying to extend one app to use my new Laravel app. In this scenario I am getting an unknown number of filters and I would like to forward them all to where() clause.
I have made something like this:
private function filterConverter($filter)
{
$f = [];
foreach ($filter as $singleFilter) {
$operator = $this->filterValues[$singleFilter['operator']];
$value = $operator == 'like' ? '%' . $singleFilter['value'] . '%' : $singleFilter['value'];
$f[] = $singleFilter['field'] . ',' . $operator . ',' . $value;
}
return $f;
}
The thing is that I am getting operators like EQUALS and CONTAINS so I need to convert them to = and LIKE.
With this code I am trying to do this:
return response(MyModel::where($filter)->get());
But it doesn't work. Is there any elegant way to resolve this?
EDIT/SOLUTION
Sorry to #HCK as I couldn't quite accept the answer since it doesn't answer my question, but it pointed me on the right track. The solution was to use key, operator, value keys in the array instead of what I had "keyless".
private function filterConverter($filters)
{
$filter = [];
foreach ($filters as $singleFilter) {
$operator = $this->filterMap[$singleFilter['operator']];
$value = $operator == 'LIKE' ? '%' . $singleFilter['value'] . '%' : $singleFilter['value'];
$filter[] = [
'key' => $singleFilter['field'],
'operator' => $operator,
'value' => $value
];
}
return $filter;
}
Not the nicest way to solve it, but this should work:
private function filterConverter($filters)
{
return collect($filters)->map(function ($filter) { // <---
if($filter['operator'] == 'CONTAINS')
{
$filter['value'] = '%' . $filter['value'] . '%';
$filter['operator'] = 'LIKE';
}
else if ($filter['operator'] == 'EQUALS')
{
$filter['operator'] = '=';
}
return collect($filter)->flatten(); // <---
})->toArray(); // <---
}
Here I'm using the Map() function of the Collection class. there is a lot of useful methods provided by this class.
You may follow this way
DB::table('users')
->where(function($query) use ($filter)
{
// You able to access $filter here
// You may able to to generate this block by loop
$query->where('votes', '>', 100)
->where('title', '<>', 'Admin');
})
->get();
Laravel Doc | Advanced Wheres
Exp-1
$filters = [
['key' => 'votes', 'operator' => '>', 'value' => 100]
];
DB::table('users')
->where(function ($query) use ($filters) {
foreach ($filters as $filter) {
if (#$filter['key'] && #$filter['operator'] && #$filter['value']) {
$query->where($filter['key'], $filter['operator'], $filter['value']);
}
}
})->get();
Exp-2
$filters = [
['key' => 'votes', 'operator' => '>', 'value' => 100]
];
DB::table('users')
->where(function ($query) use ($filters) {
foreach ($filters as $filter) {
if (#$filter['key'] && #$filter['operator'] && #$filter['value']) {
$query->whereRaw("{$filter['key']} {$filter['operator']} '{$filter['value']}'");
}
}
})->get();
You may also use scope function Ref
Exp-3 Laravel Scope
class User extends Model
{
public function scopeFilter($query, $filters)
{
foreach ($filters as $filter) {
if (#$filter['key'] && #$filter['value']) {
$query->where($filter['key'], #$filter['operator']?:"=", $filter['value']);
}
}
return $query;
}
}
// Use
User::filter($filters)->get();
I need the same query for two different user roles. Difference is only in one whereNotIn condition.
So for the Basic user it would be:
$chart2 = DB::connection('mysql2')->table('tv')
->select('*')
->join('epgdata_channel', 'cid', '=', 'channelid')
->where('ReferenceDescription', $campaign->spotid)
->whereNotIn('ChannelName', $sky)
->get();
And for Premium:
$chart2 = DB::connection('mysql2')->table('tv')
->select('*')
->join('epgdata_channel', 'cid', '=', 'channelid')
->where('ReferenceDescription', $campaign->spotid)
->get();
I know I can do it with simple if statement:
if($user->userRole == "Basic"){
//first $chart2
}
else{
//second $chart2}
but I have a lots of queries where I need just to add or remove this whereNotin condition and rewriting the queries (using if statement) is not a nice solution.
Try scope.
In your TVModel.php:
public function scopeConditionalWhereNotIn($query, $doesUse, $col, $val) {
if($doesUse)
$query->whereNotIn($col, $val);
}
Usage:
$condi = true;//or false.
$chart2 = TVModel::select('*')
->join('epgdata_channel', 'cid', '=', 'channelid')
->where('ReferenceDescription', $campaign->spotid)
->conditionalWhereNotIn($condi, 'ChannelName', $sky)
->get();
Inside your model add this:
public function scopeBasicUser($query,$channel){
return $query->whereNotIn('ChannelName', $channel);
}
and in your controller:
$query = DB::connection('mysql2')->table('tv')
->select('*')
->join('epgdata_channel', 'cid', '=', 'channelid')
->where('ReferenceDescription', $campaign->spotid);
if($user->userRole == "Basic")
$query = $query->basicUser($channel);
return $query->get();
$userRole = $user->userRole;
$chart2 = DB::connection('mysql2')->table('tv')
->select('*')
->join('epgdata_channel', 'cid', '=', 'channelid')
->where('ReferenceDescription', $campaign->spotid)
->where(function ($query) use ($userRole){
if($userRole == "Basic"){
$query->whereNotIn('ChannelName', $sky)
}
})
->get();
This code worked for me.
I am doing the following request to extract some data from my database. The expected result is wrong because some parenthesis is not well placed in the SQL generated request:
$data = Ov::with([
'masters' => function ($query) use ($devicesArrayOnlyLKUAToZero) {
$query->whereIn('macAddress', $devicesArrayOnlyLKUAToZero)
->orWhere('lastKnownUpAt','<>', '0');
}
])->where('ovId', '=', $ovId)->get();
The dedicated sql generated by Laravel is: (see with Laravel debugbar):
select * from `masterequipments` where `masterequipments`.`id_ov_foreign_key` in ('38') and `macAddress` in ('e8:e7:32:c1:e6:48', 'e8:e7:32:bc:b0:94', 'e8:e7:32:e4:8e:68', 'e8:e7:32:bc:a7:70', '00:e0:b1:fe:ef:a5', 'e8:e7:32:bc:a7:a4', '2c:fa:a2:10:79:74', 'e8:e7:32:b9:6d:1d', '00:e0:b1:ee:58:2d', '00:e0:b1:9d:2c:44', '00:e0:b1:b5:e6:00', '00:e0:b1:72:34:86', '00:e0:b1:fe:ee:8d', '00:e0:b1:79:53:52', '00:e0:b1:fe:f0:bd', '00:e0:b1:75:fa:8a', 'e8:e7:32:98:80:22', '00:e0:b1:75:00:8a') or `lastKnownUpAt` <> '0'
This is wrong because 2 () are missed. I would like to have:
select * from `masterequipments` where `masterequipments`.`id_ov_foreign_key` in ('38') and (`macAddress` in ('e8:e7:32:c1:e6:48', 'e8:e7:32:bc:b0:94', 'e8:e7:32:e4:8e:68', 'e8:e7:32:bc:a7:70', '00:e0:b1:fe:ef:a5', 'e8:e7:32:bc:a7:a4', '2c:fa:a2:10:79:74', 'e8:e7:32:b9:6d:1d', '00:e0:b1:ee:58:2d', '00:e0:b1:9d:2c:44', '00:e0:b1:b5:e6:00', '00:e0:b1:72:34:86', '00:e0:b1:fe:ee:8d', '00:e0:b1:79:53:52', '00:e0:b1:fe:f0:bd', '00:e0:b1:75:fa:8a', 'e8:e7:32:98:80:22', '00:e0:b1:75:00:8a') or `lastKnownUpAt` <> '0')
Use advanced where clauses to accomplish it.
$data = Ov::with([
'masters' => function ($query) use ($devicesArrayOnlyLKUAToZero) {
$query->where(function ($query) use ($devicesArrayOnlyLKUAToZero) {
$query->whereIn('macAddress', $devicesArrayOnlyLKUAToZero);
})
->orWhere(function($query) {
$query->where('lastKnownUpAt','<>', '0');
});
}
])->where('ovId', '=', $ovId)->get();
UPDATE
$data = Ov::with([
'masters' => function ($query) use ($devicesArrayOnlyLKUAToZero) {
$query->where(function ($query) use ($devicesArrayOnlyLKUAToZero) {
$query->whereIn('macAddress', $devicesArrayOnlyLKUAToZero);
})
->orWhere('lastKnownUpAt','<>', '0');
}
])->where('ovId', '=', $ovId)->get();
Yo need to do something like this:
$data = Ov::with([
'masters' => function ($query) use ($devicesArrayOnlyLKUAToZero) {
$query->where(function ($query) use ($devicesArrayOnlyLKUAToZero) {
$query->whereIn('macAddress', $devicesArrayOnlyLKUAToZero);
})
->orWhere(function($query) {
$query->where('lastKnownUpAt','<>', '0');
});
}
])->where('ovId', '=', $ovId)->get();
This article explain it well http://laraveldaily.com/and-or-and-brackets-with-eloquent/
I want to make a filter with different parameters. One of parameter is $article_title. But it can be empty . My problem is even if its not empty i get null in return $comments. That is because this part of code:
$q->where('language_id', $default_language_id)->where('title','like',$article_title);
This is my function
public function getResultCommentsWithArticle($comment,$user_firstname,$article_title,$orderBy){
$default_language = Languages::where('default',1)->first();
$default_language_id = $default_language->id;
$comments = ArticleComments::orderBy($orderBy,'desc')
->with(['user', 'article', 'article.translations' => function($q) use($default_language_id,$article_title) {
$q->where('language_id', $default_language_id)->where('title','like',$article_title);
}])->paginate(10);
return $comments;
}
EDIT:
I also tried like this:
$comments = ArticleComments::orderBy($orderBy,'desc')
->with(['user', 'article', 'article.translations' => function($q) use($default_language_id,$article_title) {
$q->where([
['language_id', '=', $default_language_id],
['title', 'like', '%'. $article_title .'%'],
]);
}])->paginate(10);
But i get all comments and not comments with title="something"
$comments = ArticleComments::orderBy($orderBy,'desc')
->with(['user', 'article'])
->whereHas('article.translations', function($q)
use($default_language_id,$article_title) {
$q->where('language_id', $default_language_id)
->where('title','like',$article_title);
})->paginate(10);
Try this:
$comments = ArticleComments::orderBy($orderBy, 'desc')
->with(['user', 'article' => function ($q) use($default_language_id, $article_title) {
$q->with('translations')
->whereHas('translations', function ($q) use($default_language_id, $article_title) {
$q->where('language_id', $default_language_id)->where('title','like',$article_title);
});
}])->paginate();
This will select all comments and it will attach to it articles that match the translation.title and default language id.
In case you want to filter the comments instead of articles you would do this:
$comments = ArticleComments::orderBy($orderBy, 'desc')
->with(['user', 'article.translation'])
->whereHas('article', function ($q) use($default_language_id, $article_title) {
$q->whereHas('translations', function ($q) use($default_language_id, $article_title) {
$q->where('language_id', $default_language_id)->where('title','like',$article_title);
});
})->paginate();
return $comments;
I'm trying to make an advanced search form with Laravel 4, and this is the query:
$result = DB::table('users_ads')
->join('ads', 'users_ads.ad_id', '=', 'ads.id')
->orderBy($column, $method)
->where('status', TRUE)
->where(function($query) use ($input)
{
$query->where('short_description', $input['search'])
->where('category', $input['category'])
->where('product', $input['product']);
})
->join('users', 'users_ads.user_id', '=', 'users.id')
->select('ads.id', 'ads.img1', 'ads.short_description', 'ads.category', 'ads.product', 'ads.price', 'users.city')
->get();
return $result;
The problem is that the user might not use all the input fields. So i want to include some if conditions in this part:
$query->where('short_description', $input['search'])
->where('category', $input['category'])
->where('product', $input['product']);
.. so if the input is empty, to remove the "where" condition.
You could wrap each where in an if statement.
$query = DB::table('user_ads')
->join('ads', 'users_ads.ad_id', '=', 'ads.id')
->orderBy($column, $method);
if ($input['search']) {
$query->where('short_description', $input['search']);
}
if ($input['category']) {
$query->where('category', $input['category']);
}
$query->join('users', 'users_ads.user_id', '=', 'users.id')
->select('ads.id', 'ads.img1', 'ads.short_description', 'ads.category', 'ads.product', 'ads.price', 'users.city')
$result= $query->get();
return $result;
Something along those lines would work I believe.
$filters = [
'short_description' => 'search',
'category' => 'category',
'product' => 'product',
];
.....
->where(function($query) use ($input, $filters)
{
foreach ( $filters as $column => $key )
{
$value = array_get($input, $key);
if ( ! is_null($value)) $query->where($column, $value);
}
});
Newer version of Laravel have a when method that makes this much easier:
->where(function ($query) use ($input, $filters) {
foreach ($filters as $column => $key) {
$query->when(array_get($input, $key), function ($query, $value) use ($column) {
$query->where($column, $value);
});
}
});
$role = $request->input('role');
$users = DB::table('users')
->when($role, function ($query) use ($role) {
return $query->where('role_id', $role);
})
->get();