PHP adding or subtracting elements from array - php

I have a query string. For example:
?filters=1,2,3,4
It gets turned into an array:
$filters = explode(',', $_GET['filters']);
You could push a new value on
$filters = array_push($filters, $new->filter);
Then turn it into the query string
http_build_query($filters);
Or, remove a value
$filters = array_diff($filters, [$new->filter]);
Then turn it into the query string
http_build_query($filters);
I'm looking for an elegant solution to remove the item if it already exists or to add the item if it does not exist. Alternative solutions are also welcome.
Thank you.

Hopefully I'm understanding you correctly "I'm looking for an elegant solution to remove the item if it already exists or to add the item if it does not exist.". Also, not sure if it is elegant but may spark other ideas:
$filters = in_array($new->filter, $filters) ?
array_diff($filters, [$new->filter]) :
array_merge($filters, [$new->filter]);

That's about as elegant as it gets, unless you want to use PHP's array notation "hack", e.g.
?filters[]=1&filters[]=2&filters[]=3&etc...
^^---
That'd save you the explode() stage and gives you the ability to treat $_GET['filters'] as an array directly, but at the cost of an uglier/longer URL.

Perhaps you should write 2 functions, "remove" and "add", which would each loop through the array looking for the value in question. Then the remove function could remove it, and the add function could add it. The functions themselves would not be so elegant, but using them would be simple elsewhere in your code.

Related

Check entire array for single if operation

I have this code to check some input data to be sure it fits a proper format. However input_28 is a list field that is sent as an array. Is there a shortcut to check each item in the array for the filter instead of looping through each item?
I dont care what it wrong or which line does not match. I just need to know if any line does not match the filter so I can return the form with an error.
if($_POST['input_28'] != filter_var($_POST['input_28'], FILTER_VALIDATE_REGEXP,array("options"=>array("regexp"=> "/(\d\d\d\d-\d\d\d\d)|()/" )))){
If I understand correctly, you are looking for array_search(), you can use it like this
if(array_search($value, $array)){
// Do stuff
}
Note that array_search() only works if the array is NOT multi-dimensional, you can take a look on the documentation for more references and examples
Some searching on functions that #Alfonso mentioned in his answer led me to another function: preg_grep That led to this little function which worked great.
$input_28=preg_grep("/^(\d\d\d\d-\d\d\d\d)$/", $_POST['input_28'], PREG_GREP_INVERT);
if(count($input_28) > 0){
#Do Something
}
The PREG_GREP_INVERT makes it return an array of entries that do NOT match the filter. Then we count the array, if any did not match the array will have an entry. Thus greater than 0

possible to initialize a PHP array with keys only?

I'm just looking for a MORE eloquent way of defining an array of empty error strings for a mail form then this...
$err = array('NAME'=>'', 'EMAIL'=>'', 'ADDR'=>'', 'CS_LOC'=>'', 'ZIP'=>'','PHONE'=>'', 'COMMENTS'=>'', 'FILE'=> '');
Since I have to flush these occasionally anyway, certainly anytime the form posts, I've already set up a function like the below which I call as needed, like this.
function clearFormErrors(&$ary) { // fill error array with empty strings
$keys = array_keys($ary);
$filled = array_fill_keys($keys, '');
}
Not a big deal [EDIT]:, but since I'm going to call this anyway, it would be nice if there were some nice 'wishlist' way I could just define the array **KEYS when I declare it**, like this...
$err = array('NAME', 'EMAIL, 'ADDR', 'CS_LOC, 'ZIP,'PHONE', 'COMMENTS, 'FILE');
Of course the above does NOT have that desired effect. I'm just curious if there is some simple directive or method that I've missed in the PHP docs that would just let me define the keys (with or without some default type). I'm sure there is a more complicated function that could be created to build a new array using the keys (now values) from my above 'wishlist' array, but it sounds like it wouldn't make the code any shorter or more 'eloquent', right?
If you have array of keys, array_fill_keys is the most elegant way to "reset" the array. The other way that makes sense is array_map, but for your simple task it seems like a little overhead.

Return Array Element without Creating Variable

I feel stupid for asking this cause it seems so basic but it's really bugging me.
I have a method that returns an array with a single element. I just want it to return the element not wrapped in an array. I tried this.
return $f->getValue()[0];
and it gives an error but if I save it to a variable, it works fine.
$v = $f->getValue();
return $v[0];
I can't figure it out....
It's available only since PHP 5.4: http://codepad.viper-7.com/VHOW0o
What you are trying to do, is called array dereferencing, and is only possible in PHP as of version 5.4 (if you scroll up a few lines in the documentation article I linked to, you'll see it mentioned).
Use reset().
<?php return reset( $f->getValue() ); ?>
Edit: reset() is probably superior to current() as it also makes sure that the internal pointer is reset, despite it not making much difference if the array only contains one element.
As far as I know since you are returning an array you only can get an array. You can instead save the array to a variable in the class (accessible by $f->myArray) and then return just the string portion. Or the other option is to do what your second example is and return the array and retrieve the string from it.
have you tried this
<?php
return array_shift(array_values($array));
?>
Get the first element of an array

How does php interpret the syntax $var[] = $val?

I was looking through some inherited PHP code when I found the following:
$emails=array();
foreach($usrs as $usr){
$emails[]=$usr['email'];
}
It's clear that this is trying to extract the 'email' property of each object in a list of users and hold them in an array. That's what I want it to do. Does this do that? I've never seen such a thing work this way. I replaced it with
array_push($emails, $usr['email']);
since I know that that does what I intend it to.
The two are the same, almost.
It will add an item to the end of the array, just as array_push does. The only difference is array_push returns the new number of elements in the array. The empty bracket notation does not return anything, obviously.
You should get comfortable with this notation, it's easier to type and read.
array_push on PHP docs mentions the use of this notation and covers two other differences as well.
Note: If you use array_push() to add one element to the array it's better to use $array[] = because in that way there is no overhead of calling a function.
Note: array_push() will raise a warning if the first argument is not an array. This differs from the $var[] behaviour where a new array is created.
When you want to push multiple elements to an array, then you could use array_push.
array_push($emails, $var1, $var2, $var3, ...);
Otherwise, if you only push one elements to an array, just use:
$emails[] = $var;
which saves you one function call.
Yes, it does the same thing. Assigning to $array[] is equivalent to pushing an element to $array.
Also, it looks prettier, so use it ;)

Better way to get first element of returned array

I found myself using this:
$var=(string)array_shift(array_values($item->xpath($s)));
where $s is an xpath search string and the return is an array of objects that contain strings.
It works, but I'm not sure it's the best way to get the data I want.
I could use a tempvar, but I wanted to avoid that.
Any suggestions?
Careful with array_shift, as it will remove the element from the array stack, if you simply want the first value, you can use current:
$var = (string) current($item->xpath($s));
I believe this gives the same result.
$var=array_shift($item->xpath($s));
$var = $reset($item->xpath($s));
Note that this rewinds the array's internal pointer and returns the first element. The method current returns the element at the position the pointer happens to be in - it is not guaranteed to always be the first element.

Categories