Adding items to a php array without replacing the previous items - php

Am building a shopping cart and would like to append new items to a wishlist by adding them to a session but they shouldnt replace the existing items
This is what i have tried but returns an error of
[] operator not supported for strings
This is the code:
public function addItem($value, (int)$id){
if(isset($_SESSION[$value])){
$_SESSION[$value][] = array();
array_push($_SESSION[$value],array(
'id'=>$id
));
return true;
}
}
The values of $value is a string
I have also followed on This yii link and also on This link but still am getting the same error
By doing it this way
public function addItem($value, $id){
if(isset($_SESSION[$value])){
$_SESSION[$value] = array();
array_push($_SESSION[$value],array(
'id'=>$id
));
return true;
}
}
Adds the items but replaces whatever i had previously
WHAT DO I NEED TO CHANGE FOR IT TO WORK

You get this error when attempting to use the short array push syntax on a string. demo here.
$_SESSION[$value] is a string. so you cannot use something like $_SESSION[$value][]= 's'
So when the first time you use the $_SESSION[$value], make it an array. Not a string. Then you can use as $_SESSION[$value][]= 's';

Related

How do I work with an array object in PHP?

I have a Laravel site I am modifying, but there are some parts of the PHP code I don't quite understand, which are "array objects" or "object arrays". You see, I don't even know what to call them and so can't find a tutorial or basic data on it. Below is the code that I am dealing with:
private function parseMetric($result, $view)
{
$data = collect([]);
$result->each(function($item) use ($data, $view) {
if (isset($item->metric->{$view})) {
$data->push((object)[
'label' => $item->metric->{$view},
'value' => $item->metric->count
]);
}
});
...
From what I can tell, this creates an object out of $result. If I json_encode this and echo it out I get this:
[{"label":"1k-25k","value":14229},
{"label":"1mm+","value":1281},
{"label":"25k-50k","value":398},
{"label":"50k-75k","value":493},
{"label":"75k-100k","value":3848},
{"label":"100k-150k","value":9921},
{"label":"150k-200k","value":4949},
{"label":"200k-250k","value":3883},
{"label":"250k-300k","value":2685},
{"label":"300k-350k","value":2744},
{"label":"350k-500k","value":4526},
{"label":"500k-1mm","value":8690}]
Now this is obviously an array of arrays... or is it? Is it an array of objects? Or is it an object containing arrays? But the most important question is, how do I access and move or change the individual objects/arrays in this object? For example, I want to take the second object/array, which is:
{"label":"1mm+","value":1281}
and move it to the end. How do I do that? How do I find it? I used the following piece of code to find it which is pretty clunky:
$pos = strpos(json_encode($result), '1mm+');
if($pos){
Log::debug('Enrich 73, I found it!!!!!!!!!!!!!!!!!!!!!!!!!!!');
}
And once I find it, how do I move that array/object to the end of the whole object?
And finally, where can I find some kind of tutorial, or documentation, that describes this construct and how to work with it?
There is no need to json_encode the data. Since the data is an instance of Laravel Collection, you can manipulate it like so
$item = $data->firstWhere('label', '1mm+'); // get the item
$data = $data->filter(fn($value, $key) => $value->label !== '1mm+') // remove $item from $data
->push($item); // move $item to the end of data
Acording to Laravel documnentation for Collections, you can try something like this :
To find index of element with name = "1mm+" :
$index = $datas->search(function ($item, $key) {
return $item['name'] == "1mm+";
});
to get an element at a given index :
$element = $datas->get($index);
to Move element at index 3 to the end :
$index = 3
$elementToMove = $data->splice($index, 1);
$datas->push($elementToMove);
Here is a link to the document used : https://laravel.com/docs/8.x/collections

Best way to use multiple URL paramemetrs for advacned filtering with PHP?

I wonder if there is a "simple" PHP solution to create multiple URL parameters. Until now I am able to create a "one click" filter like this:
$url_param = ($_GET["sort"]);
Sort by this
and then:
if($url_param == 'rank-chipset') {do this}
This works great as a "one click" URL parameter for filtering! I like this simple solution to do things with URL parameters, but can't figure out how to do something similar so i can give the option to users to select multiple parameters, like brand1, brand2, year 2021 and more.
I would prefer this to work like this: If users clicks brand1 filter then instantly reload page and show brand1 products, after if also clicks brand2 then show also brand1 and brand2 products. If users clicks again brand1 remove brand1 from filtering.
Make the filter parameter a comma-delimited list of filters. Then combine the existing value of $_GET['filter'] with the filter for that link.
function add_or_remove_filter($new, $filters) {
$pos = array_search($new, $filters);
if ($pos === false) {
// add if not found
$filters[] = $new;
} else {
/remove if found
unset($filters[$pos]);
}
return implode(',', $filters);
}
$filters = explode(',', $_GET['filter'] ?? '');
?>
Brand 1
Brand 2
Year 2021
If you are going to design a solution that writes the navigation history directly in the url, then set up the storage with the goal of easy/swift data mutation.
Code: (untested)
function toggleItem($item, $cache) {
$cache[$item] = isset($cache[$item]) ? null : 1;
return $cache;
}
// show array_keys($_GET) as you wish
$allItems = ['a', 'b', 'c', 'd'];
foreach ($allItems as $item) {
printf(
'%s',
http_build_query(toggleItem($item, $_GET)),
$item
);
}
The advantage in this is that the values are always stored as array keys. This means checking for their existence is optimized for speed and http_build_query() will ensure that a valid querystring is generated.
A special (perhaps unexpected for the unknowing developer) behavior of http_build_query() ensures that an element with a null value will be stripped from its output (the key will not be represented at all). This acts as if unset() was used on the array.
If you want keep these item values in a specific subarray of $_GET, you can adjust the snippet for that too. You would set this up with $_GET['nav'] ?? [] and access array_keys($_GET['nav'] ?? []). One caveat to this performance boost is that PHP's array keys may not be floats -- they get automatically converted to integers. (I don't know the variability of your items.)

The in_array doesn't compare my converted objects as it is supposed to

I'm developping a website, where if a user changes some data, it should be stored on the background, to see who did last change and what etc... . I have 1 object called Event, but the data onscreen is devided into 2 tabs (Client and Event). After the submit, I get all the fields and put the data in the object. I have this self made function to compare the values in the new boject with the values of the old object:
function createArrayReturnDiff($obj1, $obj2) {
$helpArray1 = (array) $obj1; //convert object to array
$helpArray2 = (array) $obj2; //convert object to array
$help = array_diff_assoc($helpArray2, $helpArray1); //Computes the difference of arrays with additional index check
return $help;
}
Now this works all fine, I get an array returned with names of the field and the new value.
But here comes the tricky part. After the return of this array, I loop trough it I want to check which tab the value was on in order to give beter user feedback later. So if the value is on Cleint or Event tab. Now I made 2 arrays where I describe all the fields in each tab.
$tabKlant = array('Evenementfirmanaam', 'Evenementaanspreking', 'Evenementcontactpersoon', 'Evenementcontactpersoonstraat', 'Evenementcontactpersoongemeente', 'Evenementcontactpersoonland', 'Evenementcontactpersoonmail', 'Evenementcontactpersoontel', 'Evenementgeldigheidsdatum', 'Evenementfacturatiegegevens', 'Evenementfactuur_mededeling', 'Evenementbestelbon', 'Evenementreferentie');
$tabEvenement = array('Evenementstartdatum', 'Evenementeinddatum', 'Evenementnaam', 'Evenementfeestlocatie', 'Evenementcontactfeestlocatie', 'Evenementaantal', 'Evenementact_speeches_opm', 'Evenementdj', 'Evenementinleiding');
Now my code to check:
foreach ($help as $key => $value) {
if (in_array($key, $tabEvent)) {
$tab = "Event";
} else if (in_array($key, $tabClient)) {
$tab = "Client";
} else {
$tab = "";
}
}
Now what I tried to change was Evenementfirmanaam, so the $help array contains values with key = Evenementfirmanaam and value = 'xxxx'. Everything looks like it is supposed to work. But for some reason, it can't find the value in the in_array of my foreach.
After I tried to write away data to the database. I used a mysqli_real_escape_string on the $key of my help array (firmanaam in this case) and I found out it is creating the string like: '\0Evenement\0firmanaam' . I have no idea why the \0 are added, but I have a feeling this is the reason why the in_array function won't compare my values properly. Does anyone have an idea what the problem might be?
The problem is that the firmanaam property of your Evenement class (which $obj1 and $obj2 look like to be instances of) is private, which results in the cast to array creating special keys:
If an object is converted to an array, the result is an array whose
elements are the object's properties. The keys are the member variable
names, with a few notable exceptions: integer properties are
unaccessible; private variables have the class name prepended to the
variable name; protected variables have a '*' prepended to the
variable name. These prepended values have null bytes on either side.
This can result in some unexpected behaviour.
In essence, you are being punished for violating the logical design of your class: if $firmanaam is private the outside world should not have any access to its value. The cast to array does allow you to get the value but you really should not do this.
Since you are using Evenement to encapsulate and hide data members, do it all the way. If you want access to those members, provide for and use a getter. If you want to compare two instances with specific semantics, add a comparison method to the class.

Handling Single Array Values

This is using WordPress lingo - but is more of a core PHP based question. I have an option in my site backend that I am storing a specific Location (a WordPress custom post type) as the "headquarters". I am storing the value as such:
function options_headquarters() {
foreach(get_field('option_headquarters','options') as $post_object) {
$options_headquarters = $post_object->ID;
return $options_headquarters;
}
}
What I am fuzzy on is - since my option is only allowed to grab one value (option is configured to just be a single dropdown) -- is there an alternative to using a foreach statement (to grab just a specific array value) and still applying it to the post_object?
Thanks!
function options_headquarters() {
$options = get_field('option_headquarters','options');
$options_hq = isset($options[0]) ? $options[0]->ID : NULL;
return $options_hq;
}
Just get the array and access the first element:
$post_object = array_pop(get_field('option_headquarters','options'));
Reference: array_pop

html form arrays how to store into php array not including null elements

Storing an array submitted from forms stores elements with null values. Is there a way to store only non null fields into the php array?
$_SESSION['items'] = $_POST['items'];
is my current code.
You should take a look at array_filter(). I think it is exactly what you are looking for.
$_SESSION['items'] = array_filter($_POST['items']);
# Cycle through each item in our array
foreach ($_POST['items'] as $key => $value) {
# If the item is NOT empty
if (!empty($value))
# Add our item into our SESSION array
$_SESSION['items'][$key] = $value;
}
Like #Till Theis says, array_filter is definitely the way to go. You can either use it directly, like so:
$_SESSION['items'] = array_filter($_POST['items']);
Which will give you all elements of the array which does not evaluate to false. I.E. you'll filter out both NULL, 0, false etc.
You can also pass a callback function to create custom filtering, like so:
abstract class Util {
public static function filterNull ($value) {
return isset($value);
}
}
$_SESSION['items'] = array_filter($_POST['items'], array('Util', 'filterNull'));
This will call the filterNull-method of the Util class for each element in the items-array, and if they are set (see language construct isset()), then they are kept in the resulting array.

Categories