First of all, I'm really disappointed after all googling and getting nothing!
I have an Arraydataprovider called
$data = [
400 => [
'name' => 'x',
'lesson_1' => '10',
'lesson_2' => '9',
...
],
389 => ...
]
It's generated in a for loop.
I want the values to be shown in a text box :
foreach($lessons as $lid => $name) {
$attrs[] = [
'attribute' => 'lesson_' . $lid,
'label' => $name['name'],
'format' => 'raw',
'value' => function($model, $key, $index) use($lid, &$data) {
return '<input class="txt" data-lid="'.$lid.'" type="text" value="'.$data[$key]['lesson_'.$lid].'"/>';
}
];
}
It gives me error : Undefined index: lesson_49
But I'm sure that $data provider, has the key lesson_49 (proved by var_dump);
what is the problem? :-(
You should check for value is empty or not using isset() or empty():
Use isset() inside value function to check for empty value.
For example,
(isset($data[$key]['lesson_'.$lid]) ? $data[$key]['lesson_'.$lid] : '-';
You can also use var_dump($data).
Try to use var_dump($data) in your value function when !isset($data[$key]['lesson_'.$lid]) and check what's wrong with your data
Related
Is there any solution in PHP to make an array destructuring assignment with associative keys can extract optional values/default values (like the example below)?
Because when I tried, I always get undefined index 'age' (it's because it is not set).
See example:
// implementation
function myFunction(array $params = ['name' => 'user-name', 'age' => 15]){
['name' => $name, 'age' => $age ] = $params;
echo $name.' '.$age;
}
// Execution:
// normal case
myFunction(['name' => 'user', 'age' => 100]);
// Output: user 100
// Wanted case to be released
myFunction(['name' => 'user']);
// Output: user 15 <== i want to get this default age value if i don't set it in the given associative array params.
What about defining an array with default values?
function myFunc(array $params, array $defaults = [ 'name' => 'Marcel', 'age' => 40 ]): string
{
$data = array_merge($defaults, $params);
[
'name' => $name,
'age' => $age
] = $data;
return $name . $age;
}
The array merge overwrites the default values with the given param values. So the return will always be a complete mixture of both values. If you send a name only, the name will be mixed up with the default age. If you give an age only, the age will be mixed up with the default value.
myFunc([ 'name' => 'sohaieb', 'age' => 15 ]); // => sohaieb15
myFunc([ 'name' => 'yadda' ]); // => yadda40
The second parameter $defaults can be changed, if the defaults change in the future. A possible scenario: You set the default values in a config. With this solution the function can take the default settings from the config and don 't has to be touched in the future.
Well, since you pass in a parameter, it will always take that instead of the default one. However, you can use the union operator + to merge it with default values if not present in the originally supplied value during function call.
<?php
function myFunction(array $params = []){
$params = $params + ['name' => 'user-name', 'age' => 15];
['name' => $name, 'age' => $age ] = $params;
echo $name.' '.$age;
}
myFunction(['name' => 'user']);
Because $params is an array, so it overrides the default values even if you pass in an empty array.
One way to do this is to check the value inside your function body.
function myFunction(array $params){
$name = $params['name'] ?? 'user-name';
$age = $params['age'] ?? 15;
echo $name.' '.$age;
}
// Execution:
// normal case
myFunction(['name' => 'user', 'age' => 100]);
// Output: user 100
// Wanted case to be released
myFunction(['name' => 'user']);
Reference
https://wiki.php.net/rfc/isset_ternary
I need to sum the price values of all rows where the optional check element exists.
Sample data:
[
6254 => [
'check' => 'on',
'quantity' => 2,
'name' => 'Testing product_special One Size',
'total' => 15.9,
'price' => 33.0000,
'totalken' => 33075.9,
],
6255 => [
'quantity' => 1,
'name' => 'Testing card',
'total' => 113.85,
'price' => 33.0000,
'totalken' => 16537.95,
],
6256 => [
'check' => 'on',
'quantity' => 1,
'name' => 'Testing food',
'total' => 113.85,
'price' => 33.0000,
'totalken' => 16537.95,
],
]
I tried array_sum(array_column($value, 'price')) but this sums all price values regardless of the check value.
Expected result: 66
I would use array_reduce in this case.
array_reduce loops through the array and uses a callback function to reduce array to a single value.
<?php
$totalPrice = array_reduce($myArray, function ($accumulator, $item) {
// I'm checking 'check' key only here, you can test for 'on' value if needed
if (isset($item['check'])) {
$accumulator += $item['price'];
}
return $accumulator;
});
You can simply filter the array based on condition by using array_filter() function of php.
You can see the usage of array_filter() here.
Here is my solution for you if you want to use condition.
$filteredByCheck = array_filter($value, function ($val){
return isset($val['check']);
});
$total = array_sum(array_column($filteredByCheck, 'price'));
The quickest method would be just to loop over the array and maintain a sum, use ?? '' to default it to blank if not set...
$total = 0;
foreach ($value as $element ) {
if ( ($element['check'] ?? '') == "on" ) {
$total += $element['price'];
}
}
#aliirfaan's implementation of array_reduce() can be modernized and compacted as the following snippet.
Code: (Demo)
echo array_reduce(
$array,
fn($result, $row) =>
$result + isset($row['check']) * $row['price']
);
The above uses arrow function syntax which is available since PHP7.4. The mathematics in the return value of the custom function multiplies the price value by the true/false evaluation of isset() on the check column. The boolean value is coerced to an integer automatically when used with arithmetic -- false is zero and true is one. If the coercion is not to your liking, you can explicitly cast the boolean value using (int) immediately before isset().
I cannot for the life of me figure out how to search through a multidimensional array for a key => value pair, and then either A) Return the array it belongs to or a different specific key => value pair that exists in the same array.
My array is:
$pages = array(
array(
'pageId' => 10,
'title' => 'Welcome',
'theme' => 'basic'
),
array(
'pageId' => 11,
'title' => 'Home',
'theme' => 'basic'
),
array(
'pageId' => 12,
'title' => 'Login',
'theme' => 'basic'
)
);
I've tried
$theme = array_search(10, array_column($search, 'pageId'));
but it keeps returning an int and not the value basic as I am wanting.
I would like either just the value or an array with the key => value pair or the whole array it belongs to.
Try this simplest one, hope this will be helpful. Here we are using array_column
Try this code snippet here
$result=array_column($pages,"theme" ,'pageId');
if(isset($result[$toSearch]))
{
echo $result[$toSearch];
}
You can use array_filter, live demo.
array_filter($array, function($v) use($searchKey, $searchValue) {
return $v[$searchKey] == $searchValue;
});
Is there a way to define a default value (or to force the callback to be called everytime) when using filter_var_array and FILTER_CALLBACK ?
Example data:
{
"name": "John"
}
Example usage:
$params = filter_var_array($datas_from_above, [
'name' => FILTER_SANITIZE_STRING,
'age' => [
'filter' => FILTER_CALLBACK,
'options' => function ($data) {
// I was thinking $data would be null here
// but this function is not called if the
// param is not present in the input array.
die('stop?');
}
]
], true); // Add missing keys as NULL to the return value
When using other filters, there's the default option. So it shouldn't be supernatural to have a default value for callback filters. Am I missing something obvious?
Thanks
ok so after some comments and digging, filters in php only process what the input array contains.
So if you want to guarantee that a custom callback is always called, even if the input array doesn't contain the key => value pair, you can do:
$partial_input = ["name" => "John"]; // E.g. from a GET request
$defaults = ["name" => null, "age" => null];
$input = array_merge($defaults, $partial_input);
$parsed = filter_var_array($input, [
"name" => FILTER_SANITIZE_STRING,
"age" => [
"filter" => FILTER_CALLBACK,
"options" => function ($data) {
// do something special if $data === null
}
]
]);
I'm trying to fill an array and I want to add some logic in it so it won't give me back errors...
Here is the code:
$entries_mixes = array();
foreach ($entries_query->result_array() as $entry) {
$entries_mixes[] = array('title' => $entry['title'],
'body' => $entry['body'],
'author' => $entry['author'],
'date_time' => $entry['date_time'],
'id' => $entry['id'],
'mix_name' => $mix['name'],
'photo_name' =>$photo['name']
);
}
what I want to do is to be able to check if some of the variables exist before I put them into the array....
so for example if(isset($mix['name'])) then insert to array or else do nothing
The point is not having undeclared variables trying to be inserted to my array cause it gives back errors...thanks!
You can use the ? : ternary operator:
$entries_mixes[] = array(
'title' => (isset($entry['title']) ? $entry['title'] : null),
'author' => (isset($entry['author']) ? $entry['author'] : null),
...
alternatively, use empty() for the check
You could use the ternary operator so that if the variables don't exist, NULL is used as the value. But you actually want to omit certain keys from the array altogether in that case. So just set each key separately:
$entry[] = array();
...
if (isset($mix['name'])) {
$entry['mix_name'] = $mix['name'];
}
...
$entries_mixes[] = $entry;
The following will check if title doesn't exists in the entry array or if it's blank. If so, it'll skip the entry completely and continue to the next element in the loop.
$entries_mixes = array();
foreach ($entries_query->result_array() as $entry) {
if (empty($entry['title'])) {
continue;
}
$entries_mixes[] = array('title' => $entry['title'],
'body' => $entry['body'],
'author' => $entry['author'],
'date_time' => $entry['date_time'],
'id' => $entry['id'],
'mix_name' => $mix['name'],
'photo_name' =>$photo['name']
);
}