Filter Eloquent results Laravel 5.2 - php

I want to make a member search with some filter options.
I tried filter(), but I got this error:
Fatal error: Call to a member function filter() on array
It works when I use only one filter, because it only returns the id's.
Is their a way I can use filter() multiple times, this is my code:
$members = User::all();
if ($has_avatar) {
$members = $members->filter(function ($member) {
//Avatar is not empty, other wise false
return ($member->avatar != "") ? true : false;
});
}
if ($is_online) {
$members = $members->filter(function ($member) {
//User is now online, other wise false
return ($member->is_online == 1) ? true : false;
});
}
Or is there a other way to achieve this?

As documentation says at https://laravel.com/docs/5.2/collections#method-filter, this method returns only a plain array.
You could try:
$members->filter(function ($member) {
return ($member->avatar != "") && ($member->is_online == 1);
});

I think the issue is that in Laravel 5.2 the all() method returns an array now.
Try using:
$members = User::get();
if ($has_avatar) {
$members = $members->filter(function ($member) {
//Avatar is not empty, other wise false
return ($member->avatar != "") ? true : false;
});
}
if ($is_online) {
$members = $members->filter(function ($member) {
//User is now online, other wise false
return ($member->is_online == 1) ? true : false;
});
}

Related

PHP Check if multiple values in array are all positive or all negative or partly

I have an array with 2 possible values negative and positive. If all the values are positive my function has to return positive.
If all values are negative my function has to return negative. If the values are a mix then my function has to return partly.
My code always returns partly, unfortunately, I don't know why.
const RESULT_OF_SEARCH_POSITIVE = "positive";
const RESULT_OF_SEARCH_NEGATIVE = "negative";
const RESULT_OF_SEARCH_PARTLY = "partly";
...
private function calculateResultOfSearch(array $imagesResultArray)
{
if (array_unique($imagesResultArray) === self::RESULT_OF_SEARCH_POSITIVE) {
return self::RESULT_OF_SEARCH_POSITIVE;
} elseif(array_unique($imagesResultArray) === self::RESULT_OF_SEARCH_NEGATIVE)
{
return self::RESULT_OF_SEARCH_NEGATIVE;
} else {
return self::RESULT_OF_SEARCH_PARTLY;
}
}
As we know the count() function always returns the count of the array. So it goes to the else case in every match of the condition.
You should try something like this:
class Demo{
const RESULT_OF_SEARCH_POSITIVE = "positive";
const RESULT_OF_SEARCH_NEGATIVE = "negative";
const RESULT_OF_SEARCH_PARTLY = "partly";
function calculateResultOfSearch(array $imagesResultArray)
{
if (count(array_count_values($imagesResultArray)) == 1 && $imagesResultArray[0] === self::RESULT_OF_SEARCH_POSITIVE) {
return current($imagesResultArray);
} elseif(count(array_count_values($imagesResultArray)) == 1 && $imagesResultArray[0]== self::RESULT_OF_SEARCH_NEGATIVE) {
return self::RESULT_OF_SEARCH_NEGATIVE;
} else {
return self::RESULT_OF_SEARCH_PARTLY;
}
}
}
$demo = new Demo();
print_r($demo->calculateResultOfSearch(["positive","positive"]));
array_count_values() returns an array using the values of the array as keys and their frequency in the array as values.
Here is a simple way to check the values of an array containing the same value using array_count_values function and count if all keys are the same this should equal.
Reference
A much simplified version of the code which if array_unique just has 1 value, then return it (also I only call it once rather than repeatedly calling it which is very inefficient)...
private function calculateResultOfSearch(array $imagesResultArray)
{
$unique = array_unique($imagesResultArray);
return (count($unique) == 1 ) ? $unique[0]
: self::RESULT_OF_SEARCH_PARTLY;
}
Edit:
I am unfortuantly back after realising I've wasted 20% of the lines I wrote :( If all the items are the same, I can just return the first item of the array passed in so I don't need to store the result of array_unique() at all :-/
private function calculateResultOfSearch(array $imagesResultArray)
{
return ( count(array_unique($imagesResultArray)) == 1 ) ?
$imagesResultArray[0]: RESULT_OF_SEARCH_PARTLY;
}
Try this code :
const RESULT_OF_SEARCH_POSITIVE = "positive";
const RESULT_OF_SEARCH_NEGATIVE = "negative";
const RESULT_OF_SEARCH_PARTLY = "partly";
...
private function calculateResultOfSearch(array $imagesResultArray)
{
if (!in_array(RESULT_OF_SEARCH_NEGATIVE)) {
return self::RESULT_OF_SEARCH_POSITIVE;
} elseif(!in_array(RESULT_OF_SEARCH_POSITIVE)) {
return self::RESULT_OF_SEARCH_NEGATIVE;
} else {
return self::RESULT_OF_SEARCH_PARTLY;
}
}
You're comparing (count(array_unique($imagesResultArray)) which return an int with self::RESULT_OF_SEARCH_POSITIVE or self::RESULT_OF_SEARCH_NEGATIVE which return a string equals to either "positive" or "negative" so it's always false.
You need to change your conditions.
EDIT after OP's edit
PHP: array_unique
Takes an input array and returns a new array without duplicate values.
In your case you might want to check if the resulting array only has one element equals to "positive" or "negative".
$newArray = array_unique($imagesResultArray);
if (count($newArray) == 1 && $newArray[0] === self::RESULT_OF_SEARCH_POSITIVE) {
return self::RESULT_OF_SEARCH_POSITIVE;
} elseif(count($newArray) == 1 && $newArray[0] === self::RESULT_OF_SEARCH_NEGATIVE) {
return self::RESULT_OF_SEARCH_NEGATIVE;
} else {
return self::RESULT_OF_SEARCH_PARTLY;
}
With your guys answers I came to this "clean" solution.
private function calculateResultOfSearch(array $imagesResultArray)
{
$results = array_unique($imagesResultArray);
if(count($results) == 1 && $results[0] === self::RESULT_OF_SEARCH_NEGATIVE) {
return self::RESULT_OF_SEARCH_NEGATIVE;
}
if(count($results) == 1 && $results[0] === self::RESULT_OF_SEARCH_POSITIVE) {
return self::RESULT_OF_SEARCH_POSITIVE;
}
return self::RESULT_OF_SEARCH_PARTLY;
}

Function Return object

I was following a tutorial that I got a problem
function old($field) {
return request($field);
}
function request($field = null) {
$request = new \App\Helper\Request();
if(is_null($field))
return $request;
return $request->input($field);
}
I can't figure out why we should set $filed as null and what happens while using two return?the usage of old function is keeping true values after validation in register menu textboxes
the following source code is request class which manages the requests:
class Request
{
public function input($filed, $post = true)
{
if ($this->isPost() && $post)
return isset($_POST[$filed]) ? htmlspecialchars($_POST[$filed]) : "";
return isset($_GET[$filed]) ? htmlspecialchars($_GET[$filed]) : "";
}
public function all($post = true)
{
if ($this->isPost() && $post)
return isset($_POST) ? array_map('htmlspecialchars' , $_POST) : null;
return isset($_GET) ?array_map('htmlspecialchars' , $_GET) : null;
}
public function isPost()
{
return $_SERVER['REQUEST_METHOD'] == 'POST';
}
}
PS:if someone needs more information, please tell me I will send the complete source code.
Thank you
i can't figure out why we should set $field as null and what happens while using two return?
You are not setting $field to null but $field here is an optional argument that means, if no argument is passed to the function, null will be used as default value.
And then this:
$request = new \App\Helper\Request();
if(is_null($field))
return $request;
return $request->input($field);
simply means, if $field is null then return the result of new \App\Helper\Request() otherwise the result of $request->input($field) where $request=new \App\Helper\Request()
Even if I may have just one single line instruction inside if statement, I prefer to use parenthesis for more readability and best understanding.

Returning a single Eloquent object in Laravel

I have this function:
protected function compare_something($found_item, $saved_items)
{
foreach($saved_items as item) {
$compare_x = false;
$compare_y = false;
$compare_z = false;
$compare_x = strpos($found_item,$item->x) !== false ? true: false;
$compare_y = strpos($found_item,$item->y) !== false ? true: false;
$compare_z = strpos($found_item,$item->z) !== false ? true: false;
if($compare_x && $compare_y && $compare_z){
return $item;
}
}
return false;
}
I expect $item to be the object where $compare_x, $compare_y and $compare_z are true, however this function simply returns the entire eloquent object ($saved_items) instead of the compared one.
I am not sure why is this happening. I can always return:
$item->id
And then do Item::where("id",$item->id)->first();
But shouldn't just return $item just deliver me the chosen item?
Eloquent queries always return a collection, so you can easily use the filter function for this. After that call the first function to get the first element. If there are no elements in the collection, null will be returned.
For example:
return $saved_items->filter(function ($item) use ($found_item) {
return strpos($found_item, $item->x) !== false &&
strpos($found_item, $item->y) !== false &&
strpos($found_item, $item->z) !== false;
})->first();

php array_filter is filtering too much

Here is the code :
<?php
$a_campagnes = $this->campagne->get_campagnes_client();
foreach($a_campagnes as $o_camp){
if($o_camp->groupes){
foreach($o_camp->groupes as $o_groupe){
if($o_groupe->IDGroupe == $this->session->o_user->IDGroupe){ echo 'ok';}
}
}
}
$a_campagnes = array_filter($a_campagnes, function($o_camp){
if($o_camp->groupes){
foreach($o_camp->groupes as $o_groupe){
if($o_groupe->IDGroupe == $this->session->o_user->IDGroupe) return true;
}
}
return false;
});
$a_campagnes contains at first 10 objects
The result of the first foreach is okokokok
The result of $a_campagnes after the array_filter (which is the same code as the first foreach) is null
Where are the four objects matching my first foreach?
EDIT
Just tried that piece of code:
$i_id_groupe_user = $this->session->o_user->IDGroupe;
foreach($a_campagnes as $o_camp){
if($o_camp->groupes){
foreach($o_camp->groupes as $o_groupe){
if($o_groupe->IDGroupe == $i_id_groupe_user){ echo 'ok';}
}
}
}
$a_campagnes = array_filter($a_campagnes, function($o_camp) use ($i_id_groupe_user){
if($o_camp->groupes){
foreach($o_camp->groupes as $o_groupe){
if($o_groupe->IDGroupe == $i_id_groupe_user) return true;
}
}
return false;
});
It gives the same result as before
$this doesn't exist inside anonymous functions, and you're trying to use it as if it was inside your class scope, which would be even less logical.
If you want to use whatever $this->session is inside your array_filter() callback, you'll have to either declare a class method specifically for that, or tell the anonymous function that it can use it, like this:
$session = $this->session;
$a_campagnes = array_filter($a_campagnes, function($o_camp) use ($session) {
if ($o_camp->groupes) {
foreach($o_camp->groupes as $o_groupe) {
if ($o_groupe->IDGroupe == $session->o_user->IDGroupe) return true;
}
}
return false;
});

Function to check on variables that may or may not exist - PHP

I have a function that is meant to check if two variables match, but with different values. It's a kinda complicated idea... but here's an example of its usage:
match($set1->test,"YES",$set2->test,"ON")
It will return true if $set1->test == "YES" && $set2->test == "ON"
Here's an example of how its implemented:
function match($field1,$val1,$field2,$val2) {
if ((isset($field1) && $field1 == $val1) && (isset($field2) && $field2 == $val2))
{
return true;
}
return false;
}
So the big issue here is you CANNOT do isset inside a function with the function's arguments. It's pointless, because the error gets thrown that $set1->test does not exist when the function is called, and if it isn't an object property then the variable gets initialized in the function scope anyway. It seems that the only way to get around this is to do the isset test on $set1->test and $set2->test before passing them to the function, but I really don't want to. It feels unnecessary.
My question is how can I call match($set1->test,"YES",$set2->test,"ON") when $set1->test or $set2->test has not been set?
ANSWER
I'm going to use a variation on Tamás's answer. I will have a separate function called prop, like this:
function prop($obj, $property) {
if (property_exists($obj,$property)) {
return $obj->$property;
}
return null;
}
Then I'll call match like this:
match(prop($set1,'test'),"YES",prop($set2,'test'),"ON")
Thanks!
Try using property_exists
function match($obj1, $obj2,$property,$val1,$val2) {
if ((property_exists($obj1, $property) && $obj1->$property == $val1) && (property_exists($obj2, $property) && $obj2->$property == $val2))
{
return true;
}
return false;
}
It's not very popular, but this could be a valid use for the # modifier to disable errors:
#match($set1->test, "YES", $set2->test, "ON");
I would do something like this:
function match($field1=NULL,$val1=NULL,$field2=NULL,$val2=NULL) {
$result = false;
if (!is_null($field) && !is_null($val1) && !is_null($field2) && !is_null($val2)) {
if ($field1 == $val1 && $field2 == $val2) {
$result = true;
}
else {
$result = false;
}
}
return $result;
}

Categories