Post meta values order in WordPress - php

i'm using custom fields in wordpress to store meta values. some custom fields have multiple values. i'm retrieving the array with "get post meta" which returns an array, as expected. but it seems the different items are ordered without any logic. some show up in the order they were entered, other's in opposite order, some total chaos.. what could i be missing?
i can't change the way the items are stored anymore.. there is too many entries in the database and the values show up perfect in the editing area but are stored in different order within the array.

This may or may not be possible. Wordpress is a bit like free energy machines - it violates a few useful concepts.
All your metadata is stored in the postmeta table. This table has a few fields: meta ID, post ID, meta key, value. Every time you add a meta, you add a row to this table. Every time you update a meta, however, you do not change the row order.
get_post_meta usually returns rows in the same order, so I am guessing you are doing some sort of sorting somewhere. Could we see some code? If it's always in ascending or descending but never as a random mix, you have a sort() lost somewhere.

I just recently had this same issue, here's what I found:
When you use get_post_meta(), WordPress checks if the meta data for the given object (post) has alreadby been loaded; if it has, then it's on the object cache (volatile, apc, memcached, etc) and load it's from there.
If the meta data it's not on the object cache, then it loads all the meta data for that object through update_meta_cache(), which queries the database without an ORDER BY
If your storage engine it's MyISAM, the results will be returned on a random order every time you update the meta data, but when using InnoDB the order in which the results are returned seems to be consistent (at least on my tests)

Related

Reorder pictures in a webgallery

I have a webgallery (made with laravel) and would like to add the possibility to reorder the images... Now, I have thought of several approaches but for every aproach i find that there should be a better way of doing it.
the gallery does not use javascript, so ones changes have been made it needs to be sumbitted and reloaded to reflect the changes
The main difficulties are:
how to store the order in the database? an additional Integer column?
how to add a picture "between" two others?
how to handle it at a frontend level?
So far the best ideas I had are these:
a column with integers, order by clause on this column. Frontend: a move up and a move down button.
problems of this solution: it needs a refresh after each single movement. it needs to identify the previous/next picture and swap the number with that one. To move a single pic from the end of the gallery to the top it takes forever.
a column with integers, automatically prefilled in steps of 100, order by this column + upload time in case of same numbers, Frontend: a textbox where the user can specify the integers for each picture and a submit button.
problems of this solution: does not look very professional. solves all the problems of the previous solution
same as previous solution but with double values to be able to insert pictures without limits.
They all dont seem the real deal.. Any sugestion on how to do it properly is welcome. thanks
I have done that kind of sorting in OpenCart products list (custom backend design)
Sort order was additional column order INT(11) in database
We had 3 input fields: up/down/custom
Where custom was dropdown of all indexes from 1 to max-items.
All inputs does the same:
Take new order value and shift all elements except itself. Up or down shift depends if you move element to front or to back of current position
UPDATE order FROM products SET order = :newOrder WHERE id = :currentItemId
if ($newOrder > $oldOrder)
UPDATE order FROM products SET order + 1 WHERE order >= :newOrder AND id != :currentItemId
else
UPDATE order FROM products SET order - 1 WHERE order <= :newOrder AND id != :currentItemId
Inserting does the same update, just first query becomes INSERT INTO
To get rid of ugly refresh of page on every action we do Ajax requests and re-sorted DOM with jQuery

MySQL editable sort index in CakePHP

I am trying to implement a way to sort elements in a list based on the order they were added from oldest to newest. This would be easy to do in MySQL using an ORDER BY on a created DATETIME. The problem is I then want to be able to move elements up and down the list and have that order saved in the database, but also make sure that new elements get put on the end of the list.
I have thought of using an INT index and just increment that for each new item that is added to the list. Then when an existing item is moved up or down in the list, swap the index numbers. Does this sound like the best way to achieve this result? If not, would anyone be able to provide some insight of a better way. Thanks
So I ended up solving this by using an INT field in the MySQL table called order. When new items are added, the order field is just incremented from the previous largest order in the table. When items are moved up or down in order, all other items orders are shifted up or down accordingly so that the order numbers are always continuous. On delete, orders are also shifted down.

Insert an object into MySQL database field

i'm developing a web platform in codeigniter (first time with CI) to calculate quotes for a growing number of different products.
The problem i'm facing is that each of my products have different sets of 10+ options but I want to save this data to just one table in my database. I have previously used a different table for each product allowing the table structure to represent the different sets of options however this isn't very scalable with our growing product range.
After some research it appears one solution would be using the 'serialize' function to store all of my post data (from the quote form) for each product in one column and then unserialize when I want to use this data...
Is serializing the data the best approach and would anyone be able to provide a simple example to show how to handle the insert from a form submission / retrieving the data?
Thanks very much in advance
EDIT: Searching will only ever on a product type or unique id. My thoughts were to have a table like 'id, product_type, product_options' with the product_options containing the serialized data?
EDIT 2: Taking an EAV approach seems like a good shout. I'm used to querying and returning a single result object to be passed into the view ($query->quote_ref, $query->quote_date for example). Could anyone point me in the right direction on how to use the single quote's data when the query would return multiple rows, one for each attribute?
As you mention you would not need to search on the serialized data, then yes this approach will be fine. I would opt for json_encode as the data is more human readable in this form.
Then code will depend on your DAL but a basic example would be:
$productOptions=array($_POST['option1'], $_POST['option2']);//etc will need to validate data
$databaseMapper->product_type='product type';
//your product_options column is suitable sized varchar
$databaseMapper->product_options=json_encode($productOptions);
$databaseMapper->save();
To retrieve:
$databaseMapper->loadById(20);
//$productOptions is a standard php array
$productOptions = json_decode($databaseMapper->product_options, true);
EDIT re displaying in your view.
This is codeignitor specific (whereas the above is not).
Based on code from here: http://ellislab.com/codeigniter/user-guide/general/views.html
In your controller:
//code similar to above to retrieve product options data, ideally contained within a model
$data['productOptions']=$productOptions;
$this->load->view('content', $data);
in your view:
<ul>
<?php foreach ($productOptions as $option):?>
<li><?php echo $option;?></li>
<?php endforeach;?>
</ul>

Magento attribute values saved in admin disappear

I had set up the catalog to sort on these values, which I saved through the admin last night. For most of a full day they were there. Now, like ghosts they have disappeared.
I suspect the problem could be tied to values saved through the admin rather than imported.
Can anyone point me to the source of this problem and the solution in the code?
Between the last time I saw the values working on the frontend (a few hours ago) and now, I did several things:
1.) Added 2 new attributes and some test values (unrelated to problem attribute), reindexed.
2.) Tried to import unrelated values for 60,000 products. Import hanged, so
3.) Imported values for 20,000 products at a time, no errors.
4.) reindexed.
Now all values saved manually are gone. Again, how can this happen? If they were saved to the DB, then shouldn't it take an delete call from the code to the DB to do this? How/why would such a call be made when I did not execute any such command in code or through admin? How can I fix this and avaoid in future?
TO AXEL (clarifying):
Thanks for your reply, #Axel.
1.) I created a text attribute called "sort_order" and entered some integer values through the admin.
2.) Then I did a full db backup with mysqldump.
3.) Then, I created two new attributes, "random_order" (price type) and "random_order_1" (text type). The purpose was to experiment with two solutions for shuffling the products in the catalog pages.
4.) Through phpMyAdmin I did a simple query to give me all products in random order:
SELECT `sku`
FROM `catalog_product_entity`
WHERE 1
ORDER BY RAND( )
and exported the result to csv. I simply used excel to number the items from 1-60,000, creating an import csv file with columns: sku, random_order (price type), random_order_1 (text type), with both attributes having same integer values.
5.) I used standard import method (replace existing complex data) in admin, 20k products at a time. After import, values for previously set and seemingly totally unrelated "random_order" have been deleted.
Before reindexing, every item's sort_order is now reset to default (=1), but it still appears in proper order on the frontend (so value still exists in product flat table), while the random_order and random_order_1 attributes have their imported values.
After reindex, all trace of sort_order is wiped out. That would make sense if I was actually importing that attribute, but I'm not. No other attribute appears to have been affected.
I restored db from mysqldump, tried whole process again. Same result.

Take snapshot of DB table row?

I want to take a snap shot of a row in a MySQL table.
The reason being, if someone buys a product. I want to take a snapshot of that product to store for the order.
It needs to be a snapshot to maintain data integrity. If I just assign the product to the order, if the product changes in the future the order will show those changes. For example if the price changes, the order will now load the new data and say that it sold the product at its new price rather than what the price was when the order was placed. So a snapshot needs to be assigned to the order instead.
The way I did this in the past was having 2 tables, one for products, and one for snapshots of products. The snapshot had every column as the regular table plus extra colums like order_id
I had a script to take a snapshot that automatically looked at the fields in the regular table and tried to do an insert into the same fields into the snapshot table.
The biggest problem with that approach is that, if I added a column to the regular table and forgot to add the same column to the snapshot table; the script would try to insert data into a non existent field and fail.
I also disliked the idea of having 2 tables that were nearly identical. I think maybe figuring out a way to use one table for both purposes might be better.
So I am wondering if there is a known method I am unaware of to solve this issue?
My previous project used no framework but my next one will be using CakePHP if that matters.
I think the best way of handling this would be to roll the "snapshot" information into an orders_products table. So if you have an order, store the total price, tax, etc. information in a single row on the orders table and reference that order_id on your orders_products table. On your orders_products table, you can have order_id, product_id, price, quantity, discount and whatever else you need.
Seems like your previous is fine. But that you just need to do more testing to ensure that you don't forget to add the new fields to the snapshot table. Seems like a basic test that would be easy to do. The other alternative is to just use a big text field, and store the snapshot as XML. This will let you store the snapshot regardless of if the schema changes. Depending on how much you want to query this data, it may or may not work for you.
Also you may not want to store every field, as it may just take up extra space. For instance, if you have the location of the image file of the item, you may not want to store that, as it may not be important at a later date. You could try querying information_schema to query which fields are in the snapshot table, and only copy the available fields.

Categories