3

In my Laravel project I'm building a query with some conditionals. There is one issue that I can't get my head around

I have a Query that goes as follows

$query = SocialMediaFeed::where('location_id', $location_id);

Now there are some feed items which have 'self' = true.. These should be ignored from the results at first, unless when there is a $filters array.

if(!$filters) {
    $query = $query->where('self', '<>', true);
}

Now I'm wondering, If there are filters, it should include the data that I got when self not equal to true, but also the data if it is true..

I tried the following, But that only returns the self=true posts, instead of all posts combined with self=true

$query = $query
    ->where('self', '<>', true)
    ->where('self', true)
    ->orWhereNull('self');
2
  • So if you have filters, all data should be loaded and the self column should be ignored? Then you don't need any filters on the self column. Could you give some examples for your question? Commented Aug 9, 2017 at 8:43
  • For example without the filters I would have 10 results, with the self=true it should also load in the Socialmedia that is from the owner, so that would be 15 results, but now I'm only getting 5 results back, so only the self=true instead of the 15 I need.. thanks for your answer Commented Aug 9, 2017 at 8:54

3 Answers 3

7

You can use Conditional Clauses for this:

// false: All social media feeds except where self is not true
// true: All social media feeds
$filters = false;
$query = SocialMediaFeed::where('location_id', $location_id)
->when(!$filters, function ($query) {
    return $query->where('self', '!=', true);
})->get();
Sign up to request clarification or add additional context in comments.

Comments

3

A filter can only reduce the result set, not increase it. Think about what a filter does in real life, it removes things, it never adds them.

If I understand your requirement, I would do something like this:

$query = SocialMediaFeed::where('location_id', $location_id);
if(!$filters) {
    $query = $query->where('self', '<>', true);
} else {
    $query = $query->orWhere('self', true);
}

This would return all the rows where location_id = $location_id AND self <> true when $filters isn't set and all the rows where location_id = $location_id OR self = true.

If you really need to only make one query and then filter it, reverse what you were doing, query for location_id = $location_id OR self = true and filter out self = true for when $filters is not set.

However, this code you posted doesn't really make sense:

$query = $query
   ->where('self', '<>', true)
   ->where('self', true)
   ->orWhereNull('self');

I think you should review the documentation. Multiple calls to where are joined with 'AND's so self = true AND self <> true will end up with 0 results.

So I'm not 100% sure of what you're going for. I hope I answered your question.

6 Comments

Thanks for your answer, Since I have multiple self filters (for Facebook, Instagram). I came up with the following code thanks to you, the only issue is now it's showing the self posts for facebook and/or instagram if those are included in the $filters, but the other posts are not showing... any ideas? pastebin.com/C9ecWQZL
I think a worthy change to make here is to use the when() query builder method instead of breaking the chain: $query = SocialMediaFeed::where('location_id', $location_id) -when($filters, function ($query) { return $query->where('self', '<>', true); }, function () { return $query->orWhere('self', true); }); For some reason I can't get code formatting to work in the comment, even with 4 space indentation, ugh.
@Notflip without really knowing your underlying data structure and the overall goal it's hard to say any more.
@FatBoyXPC, I don't really see why you'd do it that way. My approach is (to me) a lot more logical/clearer and I don't see that you'd gain any performance with your method. But this is why software development is more art than science. There are many paths to nirvana. :)
@MarcRunkel the main benefit to this is not breaking the chain. However, this is only "unclear" because somebody may not know of how the method works. I'm a big fan of "use the tools provided" and if your argument for saying "that's bad because people don't know it" - imo ignorance is no excuse. If you aren't constantly learning, quite frankly, I don't want you on my team.
|
0

So if you have filters, then nothing need to be done:

$query = SocialMediaFeed::where('location_id', $location_id);

if (!$filters) {
  $data= $query->where('self',true)->get();
} else {
  $data= $query->get();
}

5 Comments

Well if there is a filter I also need the self=true, but also the self=false, let's say without the filters there should be 10 results, but with the filter I need to get 15, so the 5 which are self=true need to be added.. Thank you for your response
That is exactly what this answer does. If you want both true and false, just don't filter on self.
why? the self = true, false, null or not null will be returned when there is filters, just don't do the where query. try the code above
Please update your question to include your entire code that builds the query because there's probably something wrong somewhere else.
then try do update the line with this $data= $query->where('self', != ,false)->get();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.