I have list of items that need to be processed and printed to the user.
Each item on the list needs to have a unique set of calculations to it.
The only thing is, the user also supplies me with the order of how items will be printed & handled first - for example: item4,item2,item1,item3
How can one approach this in PHP?
I thought of running a for loop against the user submitted ordered list and tackle each calculation and print it to the user, the problem is that this will be hard to maintain because the user will have to edit the for loop each time he will want to add a new item or calculation.
Given a list of 1-n items:
$items['item1'] = $item1;
With a co-related list of 1-n functions:
$functions['item1'] = function($item) {return ...;};
You can sort items according to the user-input:
$subset = orderAndFilterItems($items, $userInput);
and then iterate:
foreach($subset as $key => $item)
{
$function = $functions[$key];
$value = $function($item);
}
Naturally you can encapsulate this further on, but it should give you the idea.
Related
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.)
I am using a json api to bring data in a wordpress function, this is for a sports related website and the purpose of this particular call is to create a list of fixtures for the current competition. I need the data to be grouped by match date with the most recent date first, My first step has been to create a new array that groups the data by matchdate as a $key
<?php
$matchLists = json_decode(json_encode($fixture_data), True);
$newlist = array();
foreach ($matchLists as $key => $matchitem) {
if (array_key_exists('matchDate', $matchitem)) {
$newlist[$matchitem['matchDate']][$key] = ($matchitem);
}
}
?>
This returns a new array grouped as I expected - but the problem I am having is how to then use the matchDate converted to datetime to act as the heading for each fixture grouping as now each item in the $newlist contains a matchDate. an example of the $newlist
in attached picture
My first thought was to create a variable the used the 'match date' labels of the newly created arrays but when I tried this It said the label did not exist.
I then thought to try using [] to go down levels of the array and again this did not return the desired results
Can anybody help?
I am writing some code to supply the Google certified shop data which I have nearly finished. I only need to supply the ship and delivery dates. I have written code to supply this information at the product level. However when there is more than one product in an order I need to select the largest ship date.
For example;
Order has two products.
Producta with $ship_date = 2 and porductb with $ship_date = 5
I need to collect all the $ship_dates (2 and 5) and return the highest one (5).
My question is simply how do I write the php to collect all the $ship_dates correctly - should I create an array and if so how?
Put all the required variables into an array, then use max.
$ship_date1 = 2;
$ship_date2 = 5;
$shipDates = [$ship_date1, $ship_date2];
// other dates as needed
// OR, a much cleaner solution, append to the array
$shipDates = [];
$shipDates[] = 2;
$shipDates[] = 5;
//No matter how you fill up the array, this is how you get its maximum value
$maxShipDate = max($shipDates);
max actually accepts individual variables instead (eg. max($ship_date1, $ship_date2);) but the array solution is easier to maintain.
OK before my foreach product loop I added this;
$deliverydatearray = array();
which creates a new (empty) array which I called $deliverydatearray
Within my foreach product loop I added this;
$deliverydatearray[] = $delivery_datep;
which adds my product specific delivery date ($delivery_datep) to my array.
After the foreach product loop has closed I can access the variables in my array. For example just printing the contents of the array is done like this;
print_r($deliverydatearray);
which looks like this;
Array
(
[0] => 2017-01-28
[1] => 2017-01-23
)
I have a SESSION['cart'] with ID numbers only. I have a form passing the ID with a remove button. Once passed to my controller, I cannot figure out how to write the code that uses the ID ($_POST['id']) to delete the item from the SESSION['cart'].
I can loop through and display the array contents, but I cannot figure out how to delete based on ID passed from the form.
How do I loop through the SESSION['cart'] array to find a match with the ID passed from my delete form, and then delete that ID? I know that unset($_SESSION['cart'][X] deletes the ID at index X, but I cannot figure out how to loop through all the elements to find a match.
I have read a number of related issues in this forum but have been unable to apply any of those solutions to resolve this challenge. Any assistance is appreciated.
The way you have your values ($products = array(3,7,99,152)) isn't a very good method. Every time you want to perform an action, you have to loop through the array, you don't want that. Apart from that, how do you store quantity? Or variations like e.g. size or color?
if your structure is $array[ ID_OF_PRODUCT ], you can simply do this:
unset( $_SESSION['cart'][$_POST['id']] ); // Instant access via the key!
This should be the method to use. This allows you to create an array like this, with advanced info, but with easy access (42/63 are example id's)
$_SESSION['cart']['products'][42] = array(
'quantity' = 11,
'size' = 'large',
'color' = 'blue'
);
$_SESSION['cart']['products'][63] = array(
'quantity' = 9,
'size' = 'small',
'color' = 'red'
);
This way you can access a lot of info with the product ID, and now also see which size and color (both just examples) the user selected. You may not have need for this now, but you will further down the road :)
As you might see, you can easily do stuff with the item:
isset($_SESSION['cart'][$_POST['id']]); // check if the product exists
unset($_SESSION['cart'][$_POST['id']]); // remove the product
echo $_SESSION['cart'][$_POST['id']]['quantity']; // get the quantity.
Not a loop in the code. You should only use loops when you have to, try to somewhat avoid them because often their slow. Say you have an extreme case of 1000 items in your shop, and you need to delete no999... That'll take a noticable moment.
Here is the code to do it right:
$id = $_POST['id'];
$items = $_SESSION["cart"];
if(($key = array_search($id, $items)) !== false) {
unset($items[$key]);
}
$_SESSION["cart"] = array_values($items);
Advice
Beside item ID, you can also sve item count in SESSION array because user can add several times same item into cart. In that case your $_SESSION["card"] should be structured like:
array(
'1'=>12,//Item with ID=1 is added 12 times in shopping cart
'17'=>2,//Item with ID=17 is added 2 times in shopping cart etc.
'32'=>12,
)
I'm looking for the best way to create a complex navigation element on the fly. I have all of the elements in a database (title, id, parentId) and I want to efficiently take them out of the DB and display them correctly. I also want to collapse all of the navigation elements that aren't active. So if I was browsing through "Sofas" I wouldn't see "Chandeliers" or any of the categories under lighting but I would see "Lighting".
This is what I want the final product to look like:
Furniture
Living Room
Sofas
Chairs
Ottomans
Bedroom
Beds
Nightstands
Lighting
Chandeliers
Floor Lamps
Sconces
Rugs & Textiles
Contemporary
Vintage
My current method is
write one SQL query that pulls down all of the category names, ids, and parent ids
Iterate through the categories and put into a sorted multi-dimensional array with child categories stored under their parents.
Iterate through the new array and add another entry to mark the appropriate categories as open (all categories are closed by default)
iterate through the array and write HTML
I'm trying to to this with as few interations as possible and I'm sure the code I have right now is inefficient. Especially step 2 I iterate through the array several times. There has to be a general solution to this (common?) problem.
Consider adding a new field to your database table: level.
Main-categories will have level 0.
Sub-categories will have level 1.
Sub-sub-categories will have level 2.
etc.
This trick will help you to know which sub-categories to disable without 2nd iteration of the array.
I believe this is the perfect place to generate your html code using recursion.
I used this function a while ago. It is working with a multi-dimensional array (tree)
function buildMenu($menu_array, $is_sub=FALSE) {
$attr = (!$is_sub) ? 'id="menu"' : 'class="submenu"';
$menu = "<ul $attr>\n";
foreach($menu_array as $id => $elements) {
foreach($elements as $key => $val) {
if(is_array($val)) {
$sub = buildMenu($val, TRUE);
}
else {
$sub = NULL;
$$key = $val;
}
}
if(!isset($url)) {
$url = $id;
}
$menu .= "<li>$display$sub</li>\n";
unset($url, $display, $sub);
}
return $menu . "</ul>\n";
}
echo buildMenu($menu_array);
This adds css properties too. If you wish to mark the currently active page you can use the strpos() function to find your current url. If you need some more functionality you can easily add them to buildMenu()
Using level as mentioned in the answer above will help too. If you were using the nested set model in your database I could also help you with my query which is a single select returning the whole menu data.