How would I write the following foreach with some conditions using array_filter?
foreach ($categories as $category) {
if ($this->request->getParam('category_id')) {
if ($category->getCategoryId() == $this->request->getParam('category_id')) {
$selectedCategory = $category;
break;
}
} else {
No category id in request. Select the first one.
if (array_key_exists(0, $categoryTree) &&
$category->getCategoryId() == $categoryTree[0]['id']
) {
$selectedCategory = $category;
break;
}
}
}
First off, using array_filter isn't helpful in this case as it reduces an array instead of selecting an element. But to show its principles, you could rewrite the code to something like this.
if($this->request->getParam('category_id')){
$filteredCategories = array_filter($categories, function ($category) use ($this){
return $category->getCategoryId() == $this->request->getParam('category_id');
});
if(count($filteredCategories)>0){
return $filteredCategories[0];
}
} else {
[...]
}
I think you want an intersection function and not an array filter.
function key_compare_func($key1, $key2)
{
if ($key1 == $key2->getCategoryId()) {
return 1;
} else {
return 0;
}
}
$selectedCategory = array_intersect_ukey(
$this>request>getParam('category_id'),
$categories,
'key_compare_func'
)
For more information on the different array functions you can look at the PHP manual
Related
I have a problem code beneath this line does not work! How can I let this work? where ... orWhere orWhere does filter but cumulates the queries. where ... where does not provide any result. Can someone help me?
$artworks = Artwork::where('category_id', $category)
->where('style_id', $style)
->where('technic_id', $technic)
->where('orientation', $orientation)
->get();
Here is the full code:
if (request()->category_id) {
$category = request()->category_id;
} else {
$category = 0;
}
if (request()->style_id) {
$style = request()->style_id;
} else {
$style = 0;
}
if (request()->technic_id) {
$technic = request()->technic_id;
} else {
$technic = 0;
}
if (request()->orientation_id == 'vertical') {
$orientation = 'vertical';
} else if (request()->orientation_id == 'horizontal') {
$orientation = 'horizontal';
} else {
$orientation = 0;
}
$artists = Artist::get();
$artworks = Artwork::where('category_id', $category)
->where('style_id', $style)
->where('technic_id', $technic)
->where('orientation', $orientation)
->get();
return view('frontend.index', compact('artworks', 'artists'));
I think you want to use OR Condition and you are mistaking it with double where. Please look below to understand properly
If you want AND condition in your query then the double where are used but if you want OR condition then you have to use orWhere
Examples:
AND condition
Query::where(condition)->where(condition)->get();
OR Conditon
Query::where(condition)->orWhere(condition)->get();
If you expect all of your variables to be set
Your query variables category_id, style_id, orientation_id & technic_id are being defaulted to 0 if they are not true.
Your query is fine, but you may not have the data you think you do.
Run the following at the top of this function:
print_r($request->all());
exit;
If all of your variables are optional
very procedural, basic way to achieve this:
$artists = Artist::get();
$artworks = Artwork::where('id', '>', 0);
$category_id = request()->input('category_id');
if ($category_id != '') {
$artworks->where('category_id', request()->category_id);
}
$style_id = request()->input('style_id');
if ($style_id != '') {
$artworks->where('style_id', request()->style_id);
}
$technic_id = request()->input('technic_id');
if ($technic_id != '') {
$artworks->where('technic_id', request()->technic_id);
}
$orientation_id = request()->input('orientation_id');
if ($orientation_id != '') {
$artworks->where('orientation_id', request()->orientation_id);
}
$artworks->get();
return view('frontend.index', compact('artworks', 'artists'));
is it any way to stop this repeated data.
if ($employees_csa[0]->csa_taken == 2 && $employees_csa[1]->csa_taken == 2 && $employees_csa[2]->csa_taken == 2 && $employees_csa[3]->csa_taken == 2 && $employees_csa[4]->csa_taken == 2 && $employees_csa[5]->csa_taken == 2 && $employees_csa[6]->csa_taken == 2 && $employees_csa[7]->csa_taken == 2) {
echo "data";
}
i tried for key range(0 , 8)
like this
foreach (range(0, count($employees_csa)) as $number) {
if ($employees_csa[$number]->csa_taken == 2) {
echo "data";
}
}
i tried that way not get any succes. i any another way to write easy condition.
You can loop arrays out of the box:
$all_taken = true;
foreach ($employees_csa as $employee) {
if ($employee->csa_taken != 2) {
$all_taken = false;
break;
}
}
if ($all_taken) {
echo 'data';
}
Another approach would be array_reduce() but this doesn't abort looping when there's already an answer:
$all_taken = array_reduce($employees_csa, function ($all_taken, $employee) {
if ($employee->csa_taken != 2) {
return false;
}
return $all_taken;
}, true);
if ($all_taken) {
echo 'data';
}
Alternatively, you could do it like this using array_column to pull out all the csa_taken properties, then reducing to 1 item if they are all the same with array_unique() and then checking that the same value is the expected number 2 with reset().
$csa_taken = array_column($employees_csa, 'csa_taken');
if (reset($csa_taken) === 2 && count(array_unique($csa_taken)) === 1) {
echo 'data';
}
Reusable function version: https://3v4l.org/4kYiE
A simple for-loop could work
$condition_met=true;
for($i=0;$i<8;++$i){
if( $employees_csa[$i]->csa_taken != 2){
$condition_met=false;
break;
}
}
if($condition_met===true){
//success
}
else{
//fail
}
A simple method could be done like
foreach($employees_csa as $singleEmployee){
if($singleEmployee->csa_taken == 2){
echo "data";
}
}
I'm working with a form using the <datalist> tag, I have two input tags getting information from two different arrays. Below the form there is a Kanban board, the objective of the form is to serve as a filter, so when a user fills any of the inputs (or both) the board with fill accordingly.
Here is the problem: I had made two if staments (one for input) that work great when I use them alone but that I don't know how to put together because I don't know how to check which of the inputs has been filled (for that I believe I may have to use the issset() function), then if only one of them is used I need to use the || logical operator between them but if both are filled I need to use the && operator.
Using this condition (|| logical operator):
if (($tasksArray[$i]["responsible-party-names"] == $_POST['members'] && isset($_POST['members'])) ||
(($tasksArray[$i]['project-name'] == $_POST['projects'] && isset($_POST['projects']))))
If I fill only the members input it returns what it should.
If I fill only the projects input it returns all the projects in the array (although when using the if condition without the left part it works well).
Finally, if I fill both inputs I get the right project but all the team members.
What would be the simplest way to get it right?
Update:
This if condition it's inside the moveArray function, what comes after the if block looks like this:
{
$task = '<div id="item'.$i.'"'.'draggable="true" class="c-drag">';
$task .= '<div class="card cardTitle">'.$tasksArray[$i]['content'].'</div>';
$task .= '<div class="card cardDescription">'.$tasksArray[$i]['description'].'</div>';
$task .= '<div class="card cardProjectName">'.$tasksArray[$i]['project-name'].'</div>';
if (isset($tasksArray[$i]["responsible-party-names"])) {
$task .= '<div class="card cardProjectResponsibleName">'.$tasksArray[$i]['responsible-party-names'].'</div>';
} else {
$task .= '<div class="card cardProjectResponsibleName">'."Anyone".'</div>';
}
if ($tasksArray[$i]["due-date"] != "") {
$task .= '<div class="card cardDueDate">'.date("d/m/Y", strtotime($tasksArray[$i]["due-date"])).'</div>';
}
$task .= '</div>';
return $task;
}
Then I call the function on every part of the board (unassigned, to do, in progress, finished)
echo '<div id="board">';
echo '<div id="unassing">';
echo '<div id="unassing-bg" class="title">Unassigned</div>';
for ($i=0; $i < $tasksLenght; $i++) {
if (isset($tasksArray[$i]['boardColumn']) === false) {
echo(moveArray($i, $tasksArray));
}
}
echo '</div>';
echo '<div id="todo">';
echo '<div id="todo-bg" class="title">To Do</div>';
for ($i=0; $i < $tasksLenght; $i++) {
if (isset($tasksArray[$i]['boardColumn']) && $tasksArray[$i]['boardColumn']['id'] == "9805") {
echo(moveArray($i, $tasksArray));
}
}
echo '</div>';
echo '</div>';
And that produce sort of "a card" with data about a task in the corresponding place of the board.
You actually need the isset to come before trying to access the key on $_POST to prevent the "undefined" error.
I am assuming you have some code that looks like this:
$matchingTasks = [];
for ($i=0; $i <= count($tasksArray); $i++) {
...
}
return $matchingTasks; // or something
If that is the case, what you want is more like this:
matchingTasks = [];
foreach ($tasksArray as $task) {
// Store your search values
$members = isset($_POST['members']) ? $_POST['members'] : false;
$projects = isset($_POST['projects']) ? $_POST['projects'] : false;
// Store the search matches, only if you are searching by that key
$members_match = $members && $task["responsible-party-names"] == $members;
$projects_match = $projects && $task['project-name'] == $projects;
// if you are searching for BOTH must match BOTH
if ($members && $projects)
if ($members_match && $projects_match) {
$matchingTasks[] = $task;
}
continue;
}
// if you are searching for EITHER can match EITHER
if ($members XOR $projects) {
if ($members_match || $projects_match) {
$matchingTasks[] = $task;
}
continue;
}
// if you are not searching match ALL
$matchingTasks[] = $task;
}
return $matchingTasks;
More advanced, and would allow for more customization, is to stack these in a filter pattern like this:
$members = isset($_POST['members']) ? $_POST['members'] : false;
$projects = isset($_POST['projects']) ? $_POST['projects'] : false;
if ($members)
$tasksArray = filter_by_members($tasksArray, $members);
if ($projects)
$tasksArray = filter_by_project($tasksArray, $projects);
return $tasksArray;
//... elsewhere
function filter_by_members($tasks, $members) {
$result = [];
foreach ($tasks as $t) {
if ($task["responsible-party-names"] == $members) {
$result[] = $task;
}
}
return $tasks;
}
function filter_by_project($tasks, $project) {
$result = [];
foreach ($tasks as $t) {
if ($task["project-name"] == $project) {
$result[] = $task;
}
}
return $tasks;
}
This would let you stack new search filters, like filter_by_id or filter_by_date and by defining filter functions you can stack as many as you like without getting crazy with the logic.
I want to check if the user is using the default settings. In the example below, I'm trying to check if all "foreached" items return true. If a single foreached item doesn't return true, return false on the whole function.
private function is_using_default_settings() {
// returns a huge array with settings
$merged_preset = $this->options_merged();
foreach($merged_preset as $preset) {
if($preset[5] == 1) {
$section = 'general';
} elseif($preset[5] == 2) {
$section = 'advanced';
} elseif($preset[5] == 3) {
$section = 'technical';
}
$option = get_option($section);
if($preset[3] == $option[$preset[0]] && !is_null($preset[1])) {
return true;
}
}
return false;
}
I've been brainstorming for the past few days to get this sorted on my own, but sadly cannot get it to work. What is the best approach to this?
you can check when is false and block the full foreach then return value, if all is true return value true
try this:
private function is_using_default_settings() {
$returnValue = true;
$merged_preset = $this->options_merged();
foreach($merged_preset as $preset) {
if($preset[5] == 1) {
$section = 'general';
} elseif($preset[5] == 2) {
$section = 'advanced';
} elseif($preset[5] == 3) {
$section = 'technical';
}
$option = get_option($section);
if($preset[3] != $option[$preset[0]] || is_null($preset[1])) {
$returnValue = false;
break;
}
}
return $returnValue;
}
You should return false when any check fails in the foreach, otherwise return true.
function check()
{
foreach($arr as $v)
{
//check fails
if(fail of the check)
return false;
}
return true;
}
I am trying to get an if statement to dynamically code itself based on user input. So the if statement code is being inserted into a variable ($if_statement_variable), like this:
$if_statement_variable = "if (";
$price = trim($_GET["Price"]);
if (!empty($price)) {
$if_statement_variable .= " $Product->price < $price ";
}
$product_name = trim($_GET["Product_name"]);
if (!empty($product_name)) {
$if_statement_variable .= " && $Product->$product_name == 'product_name_string' ";
}
// plus many more if GET requests
$if_statement_variable .= ") ";
Then results from an XML file will be displayed based on user values submitted and the $if_statement_variable.
$XMLproducts = simplexml_load_file("products.xml");
foreach($XMLproducts->product as $Product) {
echo $if_statement_variable; // Here is where the problem is
{ // opening bracket for $variable_if_statement
echo $Product->$product_name; // products displayed based on if statement code in $if_statement_variable
} //closing bracket for $variable_if_statement
}
The echo $if_statement_variable above correctly displays $price from this variable string, but does NOT display $Product->price. Assuming $price had a value of 1000, the output is if ( == 1000 ). How can I get $Product->price to correctly insert itself into the $if_statement_variable so that it displays the $Product->price values from the XML file?
If you're trying to generate a boolean value dynamically, based on some complicated logic, just assign the true/false value to a variable, (say, $booleanValue) and then do if($booleanValue){}
Something like:
$price = trim($_GET['price']);
$product_name = trim($_GET['Product_name']);
if(!empty($price)){
$booleanValue = ($Product->price < $price);
}
if(!empty($productName)){
$booleanValue = ($booleanValue && $Product->$product_name == 'product_name_string')
}
if($booleanValue){
echo $Product->$product_name;
}
In other words, create a variable to hold the actual boolean value, not a string to hold an expression that will evaluate to a boolean value.
Do not build PHP source as a string. In this case callables are a better solution. A callable is a function inside a variable. In PHP this might be an function name, and array with an object and a method name, an anonymous function or an object implementing invoke.
Here is an example for anonymous functions:
function getCondition($parameters) {
$conditions = [];
if (isset($parameters['Price']) && trim($parameters['Price']) != '') {
$price = trim($parameters['price']);
$conditions[] = function($product) use ($price) {
return $product->price < $price;
}
}
if (isset($parameters['Product_name']) && trim($parameters['Product_name']) != '') {
$productName = trim($parameters['Product_name']);
$conditions[] = function($product) use ($productName) {
return $product->product_name == $productName;
}
}
return function($product) use ($conditions) {
foreach ($conditions as $condition) {
if (!$condition($product)) {
return FALSE;
}
}
return TRUE;
}
}
$condition = getConditon($_GET);
if ($condition($product)) {
...
}
It is important that each function can be called the same way. So if you call the condition function you not need to know, which condition it is. In the example above you can imagine that the getCondition() function can get really complex really fast if you add additional conditions.
If you encapsulate the conditions into classes, the usage becomes more readable:
$condition = new \YourCompany\Product\Conditions\Group(
new \YourCompany\Product\Conditions\PriceMaximum($_GET, 'Price'),
new \YourCompany\Product\Conditions\Name($_GET, 'Product_name')
);
if ($condition($product)) {
...
}
This way you separate the actual condition logic from the from the use. The source of all classes is some more then the anonymous function variant. But you you can put each class in it's own file and use them in any combination you need.
The classes need to implement __invoke().
class Group {
private $_conditions = array();
public function __construct() {
$this->_conditions = func_get_args();
}
public function __invoke($product) {
foreach ($this->_conditions as $condition) {
if (!$condition($product)) {
return FALSE;
}
}
return TRUE;
}
}
class Name {
private $_productName = NULL;
public function __construct($parameters, $name) {
if (isset($parameters[$name]) && trim($parameters[$name]) > 0) {
$this->_productName = trim($parameters[$name]);
}
}
public function __invoke($product) {
return (
NULL === $this->_productName ||
$product->product_name == $this->_productName
);
}
}
class PriceMaximum {
private $_maximum = NULL;
public function __construct($parameters, $name) {
if (isset($parameters[$name]) && trim($parameters[$name]) > 0) {
$this->_maximum = trim($parameters[$name]);
}
}
public function __invoke($product) {
return (
NULL === $this->_maximum ||
$product->price < $this->_maximum
);
}
}
This concept can even be used together with an anonymous function:
$condition = new \YourCompany\Product\Conditions\Group(
new \YourCompany\Product\Conditions\PriceMaximum($_GET, 'Price'),
new \YourCompany\Product\Conditions\Name($_GET, 'Product_name'),
function ($product) {
return $product->category == 'food';
}
);