I would like some help iterating through an object that is stored in the meta_value column of my wp_postmeta table.
I have ID's stored in the column and I would like to use those ID's in an inner SELECT that will go and get the Page Title that is associated with each ID.
Here is my SQL:
SELECT p.ID, p.post_title, p.post_status, p.post_type, pm.meta_key, pm.meta_value
FROM wp_posts p, wp_postmeta pm
WHERE p.ID = pm.post_id
AND pm.meta_key = topic_related_topics
AND pm.meta_value != ''
ORDER BY p.post_title, p.post_type desc
Here is an example of what is brought back:
1313,ADIPIC ACID,draft,post,topic_related_topics,
a:5:
{i:0;s:3:"961";
i:1;s:4:"1313";
i:2;s:3:"975";i:
Basically I need to know the title that is associated with ID 961. The title resides in the wp_posts table.
The value you are seeing in the database is an array that has been serialized to a string by PHP. The i stands for "integer" and the s stands for "string", with the number following the s indicating how long the string is. In this case, even though "961" is an integer, it is being stored as a string in the first place of a an array with 5 elements (it looks like you chopped the last 2 off).
There isn't a good way to unserialize the data in SQL, so you will need to do it in PHP and then make a second query to get the title. You can use the WordPress function maybe_unserialize() to convert it back into an array.
global $wpdb;
$sql = "your sql....";
$rows = $wpdb->get_results( $wpdb->prepare( $sql, $your_args ) );
foreach( $rows as $row ){
// convert to an array
$ids = maybe_unserialize( $row->meta_value );
// loop through the array
foreach( $ids as $id ){
// fetch the titles
$sql = "SELECT post_title FROM $wpdb->posts WHERE ID = %d";
$title = $wpdb->get_var( $wpdb->prepare( $sql, $id ) );
}
}
A more standard way of doing it would be to just use get_post_meta() to fetch the array, and have WordPress handle the serialization internally. The other big advantage here is that if you are using caching, support for it is already built into these functions.
Lastly if you do want to be able to fetch it all in a single SQL query, you will need some additional logic, likely hooked to the saving of the meta value. In addition to having it save as an array, you can grab the single value you want to JOIN on and save it in its own meta_key. With a single value you can then join the posts table to the postmeta to accomplish what you are looking for.
Related
I have a function that works fine when I say
$results = $wpdb->get_results(
"SELECT meta_value
FROM wp_woocommerce_order_itemmeta
WHERE order_item_id = '21'
AND meta_key = '_qty"
);
This function returns 4, which is the correct number I would be looking for in my database.
Unfortunately, this code is returning an empty array to get_results(). There is something wrong in my code with passing a variable to $wpdb, does anyone have an idea?
$results = $wpdb->get_results(
"SELECT meta_value
FROM wp_woocommerce_order_itemmeta
WHERE order_item_id =" .$order_item_id.
"AND meta_key = '_qty'"
);
In this specific case I think it is a simple issue of missing white-space in your string concatenation. However there may be a more suitable way to prepare your statement that would have prevented this by making it easier to spot, and follows other good query building practices
Wordpress Prepared Statments
By using $wpdb->prepare() you can use (most of) the sprintf () syntax to help you build your query.
$query = $wpdb->prepare("SELECT meta_value
FROM wp_woocommerce_order_itemmeta
WHERE order_item_id = %d
AND meta_key = '_qty'", $order_item_id);
$results = $wpdb->get_results($query);
More info available at the wordpress codex and on prepared statements in general
So I'm trying to integrate a bit of Wordpress with a backend. Their MySQL schema isn't too great, especially when you add in Woocommerce.
I've come up with the following query:
SELECT wp.*
FROM wp_postmeta wp
INNER JOIN (SELECT post_id
FROM wp_postmeta
WHERE ( `meta_key` = '_shipping_method'
AND `meta_value` = 'free_shipping' )
OR ( `meta_key` = '_order_items'
AND `meta_value` LIKE '%search%' )) a
ON a.post_id = wp.post_id
ORDER BY wp.post_id DESC
To be run on this table http://i.imgur.com/YBaGq.jpg to select the right things for certain people.
Now when I var_dump this in PHP it comes out like so (truncated) - http://pastebin.com/WR3byT8k
Is there any way I can map this properly to an array so that I can use something simple like:
echo $content['_billing_first_name'];
echo $content['_billing_last_name'];
Which would output:
John
Citizen
Keep in mind all the content is dynamic, so I can't just use row numbers.
If you have a fixed set of meta keys you need to retrieve (not necessarily a fixed order), you can do it in the query itself by using a technique similar to a pivot table.
SELECT
post_id,
MAX(CASE WHEN meta_key = '_billing_first_name' THEN meta_value ELSE NULL END) AS _billing_first_name,
MAX(CASE WHEN meta_key = '_billing_last_name' THEN meta_value ELSE NULL END) AS _billing_last_name,
MAX(CASE WHEN meta_key = '_some_other_attribute' THEN meta_value ELSE NULL END) AS _some_other_attribute,
MAX(CASE WHEN meta_key = '_another_attribute' THEN meta_value ELSE NULL END) AS _another_attribute,
...
...
FROM wp_post_meta
GROUP BY post_id
The CASE statements determine which parameter you are pulling and assign it to a column. They are wrapped in MAX() aggregates simply to eliminate the NULLs which result when the keys don't match, collapsing it down to a single row with columns for each attribute rather than multiple rows with mostly NULL values.
Failing this (if your set of attributes is varies unexpectedly), you would need to iterate in code. That would be messy though.
In PHP:
Using PHP, if you have an array of the meta post keys you want to retrieve, you can loop over all rows and if the meta_key is one you want, store the meta_value onto an array:
// Assumes your WP query results are already stored into the array $your_db_rows
// Will hold your final processed results
$output = array();
// If you want only a specific set of meta_key names rather than all meta_key names
$keys_you_want = array('_billing_first_name','_billing_last_name','_some_other_attribute');
// Loops over the result set
foreach ($your_db_rows_array as $row) {
// If the current row holds one of the meta_key you are looking for
if (in_array($row['meta_key'], $keys_you_want)) {
// Put it onto the output array using the meta_key as the array key
$output[$row['meta_key'] = $row['meta_value'];
}
// Otherwise do nothing...
}
var_dump($output);
To get all meta_key, just leave out the in_array() test and the $keys_you_want array. That will store every meta_key encountered onto $output.
// Loops over the result set for all values of meta_key, not a specific set
foreach ($your_db_rows_array as $row) {
// Put it onto the output array using the meta_key as the array key
$output[$row['meta_key'] = $row['meta_value'];
}
var_dump($output);
I'm trying to query the WordPress database to get the post tags for a specific post type.
So far I have this, which is giving me all the tags, but I'm not sure how to limit this to a specific post type, or if that is possible.
$query = "SELECT name FROM wp_terms";
$myrows = $wpdb->get_results( $query );
foreach ( $myrows as $myrow )
{
print_r($myrow);
}
In order to limit your queries, you can use the WHERE clause, i.e.
$query = "SELECT name FROM wp_terms WHERE *post_type*=*typeyouwant*";
It's also possible to use the LIKE clause, but that results in very slow queries.
I am trying to show the sum of meta_value (which is numeric) for all the instances where post_id is the same in table postmeta. From looking at other replies the following seems to be what should do this but I just get nothing returned
<?php
global $wpdb;
$data = $wpdb->query("
SELECT SUM(meta_value)
FROM $wpdb->postmeta
WHERE `post_id` = $post_id
");
echo $data;
?>
I can't figure out what is wrong with this when compared to other answers. Any pointers?
Thanks
Well... Are you connected to the database? And when you're including object properties inside a string, it's good form to encase them in braces, like so:
$data = $wpdb->query("SELECT SUM(meta_value)
FROM {$wpdb->postmeta}
WHERE `post_id` = $post_id
");
Encapsulate your php variables if they are complex, so:
FROM {$wpdb->postmeta}
For SELECTing, you should use $wpdb->get_results() instead of $wpdb->query().
$wpdb->query() "… returns an integer corresponding to the number of rows affected/selected."
http://codex.wordpress.org/Class_Reference/wpdb#SELECT_Generic_Results
OK, I have changed the code to reflect the above including he encapsulation and using get_results instead of query but now just get 'Array' as the returned result.
global $wpdb;
$data = $wpdb->get_results("
SELECT SUM($wpdb->postmeta.meta_value)
FROM {$wpdb->postmeta}
WHERE `post_id` = the_id()
");
echo $data;
Do I need to use a foreach() loop to cycle the resultant array? I have also checked there is data and also that the_id() is valid
I have a table (wp_postmeta), which contains four columns (meta_id, post_id, meta_key, meta_value). meta_key contains a field called neighborhood_value and the values for neighborhood_value are stored under the meta_value column. How do I retrieve the contents of neighborhood_value from my table and use them as a variable? Any support is appreciated
Ok, as everything is meta, thecode will also be "meta" :)
UPDATE - now when I know what you use to connect to DB I can change my answer to be more specific.
global $wpdb;
$sql = "SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=XXX";
$retMeta = array();
$results = $wpdb->get_results($sql);
foreach ($results as $resultRow)
{
if (!isset($retMeta[$resultRow['meta_key']]))
{
$retMeta[$resultRow['meta_key']] = array();
}
$retMeta[$resultRow['meta_key']][] = $resultRow['meta_value'];
}
The resulting $retMeta will be two dimensional array, and then you will be able to access your neighbourhood value by using $retMeta['neighbourhood_value'][0] (of course first you have to check if this is set - isset($retMeta['neighbourhood_value'])).
UPDATE2
For script imporing data, it'll look like that:
$sql = "SELECT meta_key, meta_value FROM wp_postmeta WHERE post_id=XXX";
$retMeta = array();
$result = mysql_query($sql);
while ($resultRow= mysql_fetch_assoc($result))
{
if (!isset($retMeta[$resultRow['meta_key']]))
{
$retMeta[$resultRow['meta_key']] = array();
}
$retMeta[$resultRow['meta_key']][] = $resultRow['meta_value'];
}
mysql_free_result($result);
But you should use WP_Query anyway, to maintain portability (the wp_postmeta doesn't have to be named that way, it can be wp2_postmeta etc).
If I understand correctly, you want to key a list of keys from meta_value?
I would do this in php: (assuming you are using some sort of framework that supports this construct. This example works with the codeigniter framework))
$sql = "SELECT distinct meta_value FROM wp_postmeta"
$result = $db->query($sql)
foreach ($result->reult() as $row) {
$mydata[] = $row->meta_value;
}
$mydata is now array containing all of your meta_value values.
I was doing same as the following.
<?php foreach($values as $value)
{
$myVarname[$value[valuefield]]=$value[valuefield];
}
$myVarname[field1]="Cow";
$myVarname[field2]="dog";
?>
If you're working with Wordpress template files such as loop.php etc., just use the handy get_post_meta() function.
You don't specify what language you want to use for your variables - but if it happens to be SQL in MySQL, here's how you "Retrieve Value From MySQL Table and Save in Variable":
select #var_name := column_name from table_name where other_column = 5;
This does the select, and as a side-effect assigns the value of the user variable #var_name to the value of column_name.
or
select #var_name := count(*) from other_table where other_column > 5;
which sets #var_name to the number of records that matched the condition.