how to update an array using a function, php - php

Hey I have return a function that takes some orders and subtracts them from an array of inventory...however when am running the function it is only updating the inventory within the function and the original inventory doesn't change..I know this is something to do with scope but I don't know how to do it exactly..
How can I do this ? can you help?
function updateInventory ($inv) {
foreach($_SESSION["inventory"] as $bookDetails) {
foreach($_POST['orders'] as $k => $v) {
if($bookDetails['title'] == $k && $v == "hardcover") {
$bookDetails['hc-quantity']=intval($bookDetails['hc-quatinty'])-1;
}
}
}
}

When you assign an array to a variable, it gets a copy of the array, so changes to that variable don't affect the original array. You can use a reference to prevent copying.
function updateInventory ($inv) {
foreach($_SESSION["inventory"] as &$bookDetails) {
foreach($_POST['orders'] as $k => $v) {
if($bookDetails['title'] == $k && $v == "hardcover") {
$bookDetails['hc-quantity']--;
}
}
}
}

Related

How to retrieve the complete array element or index from the multi-dimensional array when its some of the key and values are known

I have an array which consists of arrays. So, now suppose I want to retrieve the sku and price whose
key value is 2=>5 and 3=>7 so it should return price=>13 and sku=>bc i.e. that array whose index is at 1 in the array.
Hi I would probably try the following (Same as Riziers comment)
foreach($array as $key => $item) {
if($item[2] == 5 && $item[3] == 7) {
// return price
return $item;
}
}
There is a function array_search, which does what you want but for simple values. You can define your own function that will take not $needle, but callable predicate:
function array_search_callback(callable $predicate, array $array)
{
foreach ($array as $key => $item) {
if ($predicate($item)) {
return $key;
}
}
return false;
}
Having this function your example can be done like this:
$key = array_search_callback(function ($item) {
return $item[2] === '5' && $item[3] === '7';
}, $array);
$result = $key === false ? null : $array[$key];
I could simply return an item from the search function. But to be consistent with the original search function, I am returning the index.
As array_search_callback takes callable as an argument you can provide any criteria you want without the need of modifying the function itself.
Here is working demo.

Next element in array

I create such function for find next element from my array
protected function getProject($array, $slug, $next = 999)
{
foreach($array as $key => $project)
{
if($project->getSlug() == $slug) {
return $this->getNextProject($array, $slug, $key + 1);
}
}
}
But in result i have error "Maximum function nesting level of '100' reached, aborting". I know that there is a getSlug() isset. Please, help me solve this problem
I think the best way it's create new function, witch look like this:
public function yourAction($array, $key)
{
foreach($array as $index => $project) {
if($index == $key) {
return $project->getProduct();
}
}
}
And then usa like
if($project->getProduct() == $slug) {
$nextProduct = $this->yourAction($array, $key + 1)
return $nextProject;
}
Increase the limit of xdebug in php.ini
For example, making nesting level limit to 300:
xdebug.max_nesting_level=300
You can also comment out this line in php.ini to remove limiting constrain:
";xdebug.max_nesting_level"
You have an infinite loop/infinite recursion going on here.
foreach($array as $key => $project)
{
if($project->getSlug() == $slug) {
return $this->getNextProject($array, $slug, $key + 1);
}
// ...
}
If there are any $array elements that match the condition $project->getSlug() == $slug, it will call getNextProject() again, which will run this foreach again thus calling getNextProject() again... and so on.
You need to reorder/re-think your logic here. You can try to move the if($next != 999) { to the top of the foreach.
Try this:
protected function getNextProject($array, $slug, $next = 999)
{
foreach($array as $key => $project)
{
if($next != 999 && $next == $key) {
return $project->getSlug();
}
if($project->getSlug() == $slug) {
return $this->getNextProject($array, $slug, $key + 1);
}
}
}
Or better yet, you can just do this with one loop and no recursion:
protected function getNextProject($array, $slug)
{
foreach($array as $key => $project)
{
if($project->getSlug() == $slug && isset($array[$key+1])){
return $array[$key+1]->getSlug();
}
}
}
Just find the 1st element that matches the $slug, then get the next one and return its slug.

Caching large arrays

I have following function:
function f($idx, $arr) {
static $a;
if ($a == NULL) {
foreach ($arr as $v) {
$key = $v['key'];
if (!isset($a[$key])) {
$a[$key] = array();
}
$a[$key][] = $v;
}
}
return $a[$idx];
}
And the initial conditions are:
function f() is called many-many times in 1 request
$arr is always very large
$arr may differ in different function calls (low cardinality)
$idx differs almost in every function call (high cardinality)
And now I need to know, if $arr is already cached and if not, then create this "cached version", but keep also all previous arrays.
According to 2. I'm not able to use md5(serialize($arr)) to use it as identifier, so I need another way to determine that. Do you have any idea how to achieve such hight-performance caching functionality (let's say I'm not able to do any changes outside this function)?
If it's not imperative that $arr not be modified, then I'd just add your optimized key access directly to it:
// note the argument has been changed to &$arr - we're passing by reference
function f($idx, &$arr) {
if (empty($arr['___cached'])) {
$arr['___cached'] = array();
foreach ($arr as $k => $v) {
if ($k === '___cached') continue;
if (!isset($arr['___cached'][$v['key']])) {
$arr['___cached'][$v['key']] = array();
}
$arr['___cached'][$v['key']][] = $v;
}
}
return $arr['___cached'][$idx];
}

foreach over array of objects with matching attribute

I have an array of objects I'm using to create a menu, and each object has the properties id, video_id and chapter_id.
I'd like to make a for each loop such as
foreach($menu_objects as $object WHERE $object->chapter == $variable)
Is there a way of doing this?
PHP doesn't offer syntax like that, however, you could always make it an if-statement as the first line in the loop:
foreach ($menu_objects as $object) {
if ($object->chapter != $variable) continue;
... process as normal ...
just nest an if in your loop:
foreach($menu_objects as $object){
if($object->chapter == $variable){
// do something here
}
}
Few ways
foreach(array_filter($menu_objects, function($o) { return $o->chapter == $variable}) as $object)
Or
foreach($menu_objects as $o)
{
if ($o->chapter == $variable)
{
//Code here
}
}
Just add an if?
foreach($menu_objects as $object) {
if ($object->chapter == $variable) {
// Do Something?
}
}

PHP: How do i remove an element from a multidemision array?

I have this code to add new elements to a multidimension array:
$this->shopcart[] = array(productID => $productID, items => $items);
So how do i remove an element from this array? I tried this code, but its not working:
public function RemoveItem($item)
{
foreach($this->shopcart as $key)
{
if($key['productID'] == $item)
{
unset($this->shopcart[$key]);
}
}
}
I get this error:
Warning: Illegal offset type in unset in C:\xampplite\htdocs\katrinelund\classes\TillRepository.php on line 50
public function RemoveItem($item)
{
foreach($this->shopcart as $i => $key)
{
if($key['productID'] == $item)
{
unset($this->shopcart[$i]);
break;
}
}
}
That should do the trick.
Update
There is also an alternative way:
if ( false !== $key = array_search($item, $this->shopcart) )
{
unset($this->shopcart[$key];
}
You're not enumerating over indices, but values there, to unset an array index, you have to unset it by index, not by value.
Also, If your array index is actually the productID you can eliminate the loop altogether:
public function RemoveItem($productID)
{
if (isset($this->shopcart[$productID]))
{
unset($this->shopcart[$productID]);
}
}
Your example doesn't show how you are adding items to $this->shopcart, but this may or may not be an option for you depending on the needs of your project. (i.e. not if you need to have seperate instances of the same productid in the cart).

Categories