Here is the situation, I am getting data from a WordPress plugin database. I need to grab that "products" from the database, find the "name" value, remove some charafters from it and then finally sort it by "name" length. Here is what is going on
//The plug in queries the database
$products = $product->getModelsNames($where="", $orderBy='order by name', $limit=null);
//I added this to take that query and make changes to the 'name' field
foreach ($products as $p) {
//Characters I need removed
$characters = array("a", "b", "c", "d", ".", "-");
$p->name = str_replace($characters, "", $p->name);
//Re sort by name now without characters and save back to $products. not sure what to do here
}
//now start the loop for the products
<?php foreach($products as $p): ?>
The main issue is I have products with names like: 8.2-1, 8.2-2, 8.2-2-A, 8.2-10 and so on and I can not get them to sort right. I figure the only way is to remove all the characters to just have the numbers and then sort by length or else I get my products listed like 8.2-1, 8.2-10, 8.2-2, 8.2-2-A or 8.2-1, 8.2-2, 8.2-10, 8.2-2-A. On top of that I need to echo the names in the second loop as they were before I removed the characters. At a real loss on how to get this done. Seemed simple enough since products often go by number and character but can not get them sorted right.
What you are looking for is called natural ordering. PHP has a function for this:
$products = array(
'8.2-10',
'8.2-2',
'8.2-1',
'8.2-2-A'
);
natsort($products);
foreach ($products as $product) {
echo $product . "<BR>";
}
Output:
8.2-1
8.2-2
8.2-2-A
8.2-10
EDIT! missed the fact that $products was actually an array of objects. You can use a different technique using strnatcmp:
usort($products, function($a, $b) {
return strnatcmp($a->name, $b->name);
});
Note that if you wanted to keep the same keys for some reason, just change it to uasort instead.
Related
I have a json file with this content :
[
{
"id": "apple",
"symbol": "app",
"name": "Apple",
},
]
I Want To Search In This Json File In id Or symbol Or name Columns,
I Write This Code :
$nameOrIDOrSymbol="apple"; // user types id or symbol or name.
$names= json_decode(file_get_contents("file.json", true), true);
$name_key1 = array_search($nameOrIDOrSymbol,array_column($names, 'id')
$name_key2 = array_search($nameOrIDOrSymbol,array_column($names, 'name');
$name_key3 = array_search($nameOrIDOrSymbol,array_column($names, 'symbol');
if($name_key1){
var_dump($name_key1);
}elseif($name_key2){
var_dump($name_key2);
}elseif($name_key3){
var_dump($name_key3);
}
How Can I Search In This Three 3 Array Columns Only Once With array_search Or Another Function? For example search like this :
$name_key = array_search($nameOrIDOrSymbol,array_column($names, 'id','name','symbol')
Currently you search first in the 'id' column, then in the 'name' column, and finally in the 'symbol' column. If, at any stage, you encounter a match you return the array key. If you want to keep this functionality you have to look through the columns in that order.
You could combine the three columns into one array, juggle a bit with the keys, and do a single search that way, but I don't think that's very efficient.
Why not restructure you code a bit? For instance like this:
$query = 'apple';
$columns = ['id', 'name', 'symbol'];
$data = json_decode(file_get_contents('file.json', true), true);
foreach ($columns as $column) {
$key = array_search($query, array_column($data, $column);
if ($key !== false) break;
}
var_dump($key);
Now you've only used array_search() once, in a way.
This code is more efficient than yours because it stops searching as soon as it has found 'apple' in a column. Your code always searches through all columns.
Note that I actually check that array_search() returns false, unlike what you did, which would not have responded when this functions returned key zero.
Also note that, if ever the need arises, you can now easily add more columns without having to add more repeating lines of code.
I am constructing a function that is making a call with API to db and returns me JSON data. The json contains orders and I have already decoded them in php array. Every order has properties such as "product_id" and "quantity". I want to temporarily store the "quantity" property somewhere because I need to sum all the products with the same product_id. Any suggestion how to do this?
I'm in a bit of a hurry, but wanted to see if I could help you out.
$quantities = [];
//Loop through all the orders
foreach ($orders as $order) {
//Loop through the orderrows
foreach ($order->getOrderRows() as $orderRow) {
if (array_key_exists($orderRow->getProductName(), $quantities)) {
//The product is already in the quantities array, so the quantity of this orderrow is added to the total
$quantities[$orderRow->getProductName()] =
($quantities[$orderRow->getProductName()] + (int) $orderRow->getItemQuantity());
} else {
//If this is the first time the product is encountered add the product and its quantity to the quantities array
$quantities[$orderRow->getProductName()] = (int) $orderRow->getItemQuantity();
}
}
}
This is going to have the following result, showing you the product names along with their quantities:
$quantities = [
'foo' => 12,
'bar' => 3,
];
You may use the session variable to store these values.
I'm trying to merge 2 arrays in PHP and then sort them.
I'm pulling data from WordPress database ( tags and categories ) and I need to merge them and sort them properly.
Code looks similar to this:
$categories = [
'<a>WordPress Tips</a>',
'<a>SEO Tips'</a>,
'<a>Development Tips</a>'
];
$tags = [
'<a>WordPress</a>',
'<a>SEO'</a>,
'<a>Development</a>'
];
$taxonomies = array_merge($categories, $tags);
sort($taxonomies);
Since I need to loop through $taxonomies array and print them with anchors included ( every one of those must have a valid URL to itself ), I don't get a proper sorting result. However, as soon as I 'strip out' all the tags around these items, sorting works as it should, but I don't get URLs that I need, only string / text.
Could someone suggest a better sorting algorithm which would sort these items properly with html elements included around them? Thanks!
You need to do custom comaprision to make it work using usort() and strip_tags()
<?php
$taxonomies = array_merge($categories, $tags);
print_r($taxonomies);
function cmp($a, $b){
$data1 = strip_tags($a);
$data2 = strip_tags($b);
return ($data1 < $data2) ? -1 : 1;
}
usort($taxonomies, "cmp");
print_r($taxonomies);
Output:-https://eval.in/934071
Since you mentioned that the tags stripped version works, a simple way might be to use them as the keys in the sort. Something like this, for instance :
$taxonomies = array_merge( $categories, $tags );
$toSort = [];
foreach($taxonomies as $tax) {
$toSort[strip_tags($tax)] = $tax;
}
ksort( $toSort );
print_r( $toSort );
Which will give the sorted array and you can just use the values in there. Maybe there's better options but this comes to mind off the top of my head..
EDIT : uasort with a comparision function that actually compares the stripped versions might be better, after looking at other answers here.
Not sure how to title this properly but here's the issue I am running into currently. I built a cart and checkout system and it loads all the data into a database when it finalized the order. To save some space, I stored just the item IDs originally but then I ran into the issue of if I deleted the item from the database (because it was discontinued or whatever) then it wouldn't return the info I needed. And if they ordered more then 1 item the database record would be wrong. So I stored the data like so:
Itemid:Quantity:Price:name, itemid2:quantity2:price2:name2
OR
1:3:20.00:Flower Hat, 2:1:17.75:diamonds
The issue I have right now that I need help with is this. I need to seperate the four values into variables like $price, $item, $id, $ammount so I can display them on the order history page and I need to loop through all items on the array so I can print a row for each item with all four fields respective to that item.
I use strpos already to get the shipping info from the same database field which is formatted as METHOD:Price but since I have 3 :'s on my string I'm not sure how to go through each one. Thanks.
Here's a function
function parseItems($dbjunk){
$cart = array();
$items = explode(",",$dbjunk);
foreach($items as $i){
$chunks = explode(":", $i);
$cart[] = array(
"ItemID" => $chunks[0] ,
"Quantity" => $chunks[1] ,
"Price" => $chunks[2] ,
"name" => $chunks[3]
);
}
return $cart;
}
Example usage:
$dbjunk = "Itemid:Quantity:Price:name, itemid2:quantity2:price2:name2";
$parsed = parseItems($dbjunk);
print_r($parsed);
See: https://3v4l.org/rBkXF
If you need variables instead of an array you can use list(), like this..
$dbjunk = "Itemid:Quantity:Price:name, itemid2:quantity2:price2:name2";
$parsed = parseItems($dbjunk);
foreach($parsed as $p){
list($itemID, $Quantity, $Price, $name) = array_values($p);
var_dump($itemID, $Quantity, $Price, $name);
}
see: https://3v4l.org/l4vsn
You should not physically delete items from your database. Instead, put a new column named 'is_active' or something like that to indicate whether the product is active/non-deleted.
Answering your question, here is my suggestion:
$orderString = '1:3:20.00:Flower Hat, 2:1:17.75:diamonds';
$items = array();
foreach(explode(', ', $orderString) as $itemString) {
$itemData = explode(':', $itemString);
$items[] = array(
'id' => $itemData[0],
'amount' => $itemData[1],
'value' => $itemData[2],
'description' => $itemData[3]
);
}
with this code, you will obtain an array with the data of all the items in the string, no matter how much items are in the string
try something like
$data = 1:3:20.00:Flower Hat, 2:1:17.75:diamonds
list($price, $item, $uid, $id, $ammount) = explode(":", $data);
echo $user;
echo $item;
Read about First Normal Form. Basically, you want to store one value in one field. So, instead of this:
shipping = "method:price"
You want something like this:
shipping_method = "method"
shipping_price = "price"
Don't concern yourself with space -- it's essentially free nowadays.
Regarding your deleted items dilemma, your initial implementation was the way to go:
I stored just the item IDs originally
In addition to reverting to this technique, I would recommend two things:
Add a boolean field to your item table to represent if the item is currently available or not. This gives you the additional feature of being able to toggle items on/off without having to delete/insert records and change ids.
Before deleting an item, check to see if it's ever been ordered. If not, it's ok to delete. If so, instead just deactivate it.
I added a code that allows me to sort WordPress posts by custom fields. I'm trying to sort the posts by prices, but it's sorting by the first number and not the value:
$116.99
$12.95
$149.00
$15.99
Instead of:
$12.95
$15.99
$116.99
$149.00
How can I get it to sort properly?
Here's the code: http://pastebin.com/Pe5yfvrE
I took it from this discussion, but it was left unresolved there..
http://wordpress.org/support/topic/sort-posts-by-custom-field-in-backend
If you would like to do it manually (though the answers referencing WP_Query are better options), a reasonably nice treatment might use array_multisort:
$arr = array(
'$116.99',
'$12.95',
'$149.00',
'$15.99'
);
$keys = array();
foreach ($arr as $value) {
$keys[] = floatval(substr($value, 1));
}
array_multisort($keys, SORT_ASC, $arr);
Use the WP_Query class and the orderby=meta_value_num parameter to sort numerically. Also, make sure you store the price in the custom field as a number without the "$" prepended.
$query = new WP_Query( array ( 'orderby' => 'meta_value_num', 'meta_key' => 'price' ) );
$query then contains rows of posts sorted numerically by price.
I haven't had a look at your code but you this has to do with the numbers being strings in your case. If you sort a string it is sorted like you describe. In order to sort it by it's value you need to remove the $ sign and cast it to a number.
Did you see this technique? - adding zero to the meta value of the to force it to be treated as an integer. The post has been updated various times over the years too so it might help you;
http://wordpress.org/support/topic/order-by-meta_key-where-meta_value-is-number?replies=11
function order($a, $b) {return intval($b) - intval($a);}
uasort($array, 'order');
I wonder that can help you ;)