How to get data from Wordpress database? - wordpress

I am trying to get a row out of a table (gc_test) I created in my Wordpress database. I have read the Wordpress documentation and followed it exactly and still no joy.
The $results array never seems to get populated.
$results = $wpdb->get_row("SELECT * FROM $wpdb->gc_test WHERE coupon_code = $code, ARRAY_A");
if($results['redeemable']=="true"){
$message = "Code is good!";
}
else{
$message = "Code has already been redeemed!";
}

The way you are referring to your custom table is not correct. The correct way is to global $wpdb and the prefix property. The way that you have $code embedded is also not correct for a few reasons - it is likely a string and should be surrounded by single quotes, but no matter what is likely a potential SQL injection vulnerability. Make sure to use $wpdb->prepare() to pass arguments with placeholders of %s for strings and %d for digits. You also have the double quotes in the wrong place - it is including ARRAY_A in with your SQL rather than as an argument to get_rows().
// declare $wpdb.
global $wpdb;
// sql string using $wpdb->prefix and %s placeholder
$sql = "SELECT * FROM {$wpdb->prefix}gc_test WHERE coupon_code = %s";
// pass the sql into prepare()
$query = $wpdb->prepare( $sql, $coupon_code );
// call get_row() and tell it that you want an associative array back
$row = $wpdb->get_row( $query, ARRAY_A );
if ( empty( $row ) ){
// nothing came back from the db
$message = "Code not found.";
} elseif ( isset( $row['redeemable'] ) && $row['redeemable'] == "true" ){
// we got a row and it was redeemable
$message = "Code is good!";
} else {
// something else
$message = "Code has already been redeemed!";
}

Thanks to doublesharp's post I went back and studies the $wpdb->prefix function. Apparently this is pretty important. So I changed my prefix on the table from gc_ to wp_ and then assigned the table to a variable with: {$wpdb->prefix}test and it now works like a charm. Thanks a ton!

Related

wordpress wpdb->update strange error by converting single quote to html entity

Update Julu 2018:
I find out problem is something else. The print error method will always print out a encoded html message like the one below. If the message is not showing any extra piece of information means the SQL query is fine.
Original Question:
I tried to update the invite_code by using the $wpdb->update method, but it return strange error, it seems like WordPress convert the single quote to html entity - &#39
Please help me if anyone knows why it will convert the single quote to HTML entity automatically.
I am not able to do use any WordPress built-in method to update the query because the problem seems to happen at the prepared statement which will use in every built-in method.
WordPress database error: UPDATE exhibitor_invite SET invite_code =
&#039 ;8j8mxfkkubd0kppi082p&#039 ; WHERE id = 10
function createCode() {
$length = 20;
$inviteCode = "";
$characters = "0123456789abcdefghijklmnopqrstuvwxyz";
for ($p = 0; $p < $length; $p++) {
$inviteCode .= $characters[mt_rand(0, strlen($characters))];
}
return $inviteCode;
}
function updateCode($id) {
global $wpdb;
$wpdb->show_errors();
$prefix = $wpdb->prefix;
$invite_code = createCode() ;
// I tried to esc the string, but it doesn't work
// $invite_code = $wpdb->esc_like($invite_code);
// I also tried to use normal query, but it return the same error
// $affected_rows = $wpdb->query( $wpdb->prepare(
// " UPDATE {$wpdb->prefix}exhibitor_invite SET invite_code = %s WHERE id = %d", $invite_code, $id ));
$affected_rows = $wpdb->update( $prefix.'exhibitor_invite',
array('invite_code' => $invite_code),
array('id' => $id),
'%s',
'%d' );
$wpdb->print_error();
if(!is_bool($affected_rows)) {
return $affected_rows > 0;
}
return $affected_rows;
}
Perhaps way too late, but in case not I had the exact same problem and spent hours looking for a solution.
It seems that the WordPress property 'update' of wpdb object is where the problem occurs.
One solution that I found to work is to store the entire SQL string in a variable and then before using it, pass the variable through a PHP function of mysqli_real_escape_string().
PHP manual states:
This function is used to create a legal SQL string that you can use in an SQL statement. The given string is encoded to an escaped SQL string, taking into account the current character set of the connection.
Your solution may look something like this (untested).
$sql_string =
"
UPDATE ${prefix}exhibitor_invite
SET invite_code = %s
WHERE id = %d
";
//procedural style
mysqli_real_escape_string( $your_conn_to_server, $sql_string );
//update
$wpdb->update( $wpdb->prepare(
$sql_string,
array(
$invite_code,
$id
)
), OBJECT );

Woocommerce Get the order_id from one of the item_id?

I try to get the related order (the order id) from one of the line items id.
One case for example:
When editing an order, and deleting a line item (done by Ajax) the Woocommerce only provide the hook "woocommerce_before_delete_order_item" and passes $item_id only. (The woo function performs sql and not WP enviroment). I need the "belonging" order id to make some action!
My solution so far, is to loop through all orders and compare the Items ID, and break and return order ID when the match occurs.
This is way to slow, or "bulky clumsy", when keeping 10000 orders and more alive in the current shop.
This does NOT work:
wp_get_post_parent_id ( $item_id )
But Im hoping there is a similar call, or do I need to make a DB SQL search? Any answer involving mySQL, please make it "copy and paste ready". Im great at PHP but dont handle or never write my own SQL.
Thanks for any help! Below is my solution so far:
$order_id = my_wc_get_order_from_item_id($item_id);
function my_wc_get_order_from_item_id($id) {
$orders = get_posts('post_type=shop_order&numberposts=-1&post_status=publish');
foreach($orders as $obj) {
$order = new WC_Order($obj->ID);
if ( count( $order->get_items('line_item') ) > 0 ) {
foreach($order->get_items('line_item') as $item_id => $item ) {
if($item_id == $id) $return_value = $obj->ID;
if(isset($return_value)) break;
}
}
unset($order);
if(isset($return_value)) break;
}
if(isset($return_value)) return $return_value;
else return 0;
}
Your approach didn't work because order items are not posts in the wp_posts table, so they can't have a post_parent.
However, all is not lost and this was easier than I expected considering that my SQL isn't that strong. Looking at the woocommerce_order_item table in the database you can see that order_id and order_item_id are both there:
so I borrowed a little SQL statement from WooCommerce and modified it to find the order_id given a particular order_item_id row. Let me know how that works.
function so_38286531_get_order_item_order_id( $item_id ) {
global $wpdb;
$order_id = $wpdb->get_var( $wpdb->prepare(
"SELECT order_id FROM {$wpdb->prefix}woocommerce_order_items
WHERE order_item_id = %d",
$item_id
) );
return $order_id;
}
Use the built-in woocommerce function wc_get_order_id_by_order_item_id($item_get_id) to get order ID
// define the woocommerce_before_delete_order_item callback
function my_func_before_delete_order_item( $item_get_id ) {
$order_id = wc_get_order_id_by_order_item_id($item_get_id);
// do what you need...
};
// add the action
add_action( 'woocommerce_before_delete_order_item', 'my_func_before_delete_order_item', 10, 1 );

Wordpress: How to flush cached option value

I am currently working on a plugin, and I am stuck with an issue.
I executed an SQL request on my database through PhpMyAdmin (which I implemented later through a plugin update mechanism), the request looked like this:
UPDATE `wp_options`
SET `option_value` = replace( `option_value` , 'model', 'ldp_model' )
WHERE `option_name` LIKE 'ldp_container%'
As you can see, I am updating all options value having name beginning by 'ldp_container'. Later in the code execution, when I am retrieving the option value, I am getting a value being false using:
$termId = $term->term_id;
$termMeta = get_option("ldp_container_$termId"); // $termMeta = false
I looked in this issue, and I got to the point where it seems that when I update/create this option, as I used:
update_option("ldp_container_$termID", $termMeta);
instead of
update_option("ldp_container_$termID", $termMeta, false);
The value of this option become part of the alloptions cache. So, retrieving it always return false now, and I do not know how to flush this cache.
Using a plugin update mechanism based on version number, I tried to flush the Wordpress object cache using:
$flush_cache = wp_cache_flush(); // returns true
And the Database query cache too:
$wpdb->flush();
I also tried explicitely deleting those options keys from the cache using a query then looping on results and calling wp_cache_delete:
$result = $wpdb->get_results(
"SELECT 'option_name'
FROM $wpdb->options
WHERE 'option_name' LIKE '%ldp_container_%';"
);
foreach ( $result as $current ) {
wp_cache_delete($current, 'options');
}
Still, no luck.
Does anybody have a clue for me here ?
Thanks,
EDIT:
Seems like my error is somewhere else.
After some debugging using Atom and Xdebug, it points out that the issue is with the unserialize method applied to the string retrieved from the database in the file /wp-includes/option.php as follows:
return apply_filters( 'option_' . $option, maybe_unserialize( $value ) );
maybe_unserialize do that:
if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
return unserialize( $original );
return $original;
The call to the unserialize fails, so it returns false and then the false value is cached...
Using an online unserializer it confirms that the string is not correct, but I do not get why yet.
So, as I assumed my issue was due to the modification in serialized objects I was executing directly on the database. Because of the nature of serialized objects, looking like this:
a:1:{s:9:"ldp_model";s:1651:"{...
The 1651 being the number of characters in the ldp_model string, if you change anything inside this sting, then unserializing using unserialize() will return false, because the actual number of characters is different from the one indicated.
In my case, the solution was to instead of executing a database update of this kind:
$wpdb->query(
"UPDATE $wpdb->options
SET `option_value` = replace( `option_value` , 'ldp_', '' );"
);
To use the Options API as follows:
$result = $wpdb->get_results(
"SELECT `option_name`
FROM $wpdb->options
WHERE `option_name` LIKE '%ldp_container_%';"
);
foreach ( $result as $current ) {
$option = get_option($current->option_name);
if (!empty($option) && !empty($option['ldp_model'])) {
$option['ldp_model'] = str_replace('ldp_', '', $option['ldp_model']);
update_option($current->option_name, $option, false);
}
}
So that the serialized objects stays correct, and the Options API takes care of serialization and unserialization.
Lots of learning here for me ;-)

Wordpress custom author urls

I want to implement custom author urls.
Currently the author urls are like this:
http://site.com/author/author-name/
I want to do something like
http://site.com/my-custom-url-here
For each individual user.
I have tried using author_rewrite_rules filter, using the following code, this converts the url correctly but this gives me a page not found message when i browse the url
add_filter('author_link', 'no_author_base', 1000, 3);
function no_author_base($link, $author_id) {
$link_base = trailingslashit(get_option('home'));
$link = preg_replace("|^{$link_base}author/|", '', $link);
return $link_base . $link;
}
add_filter('author_rewrite_rules', 'no_author_base_rewrite_rules');
function no_author_base_rewrite_rules($author_rewrite) {
global $wpdb;
$author_rewrite = array();
$authors = $wpdb->get_results("SELECT user_nicename AS nicename from $wpdb->users");
foreach($authors as $author) {
$author_rewrite["({$author->nicename})/page/?([0-9]+)/?$"] = 'index.php?author_name=$matches[1]&paged=$matches[2]';
$author_rewrite["({$author->nicename})/?$"] = 'index.php?author_name=$matches[1]';
}
return $author_rewrite;
}
Any help would be greatly appreciated!
Thanks.
UPDATE
Problem is solved!, basically i did not know about calling the flush_rewrite_rules function.
Solved!
Here's how i did it:
i did not need the author_link filter so i removed it, my custom urls are stored in usermeta table so i fetched them and passed them into the rewrite array, and most importantly I DID NOT KNOW ABOUT FLUSHING THE REWRITE CACHE AND THAT WAS THE REASON MY ORIGINAL CODE WAS NOT WORKING
Heres the full code:
add_filter('author_rewrite_rules', 'my_author_url_with_custom_url_rewrite_rules');
function my_author_url_with_custom_url_rewrite_rules($author_rewrite) {
global $wpdb;
$author_rewrite = array();
$authors = $wpdb->get_results("SELECT ID, user_nicename AS nicename, meta_value as profile_name
from $wpdb->users
LEFT JOIN wp_usermeta ON wp_usermeta.user_id = $wpdb->users.ID
WHERE meta_key = 'profile_name'");
foreach ($authors as $author) {
$author_rewrite["{$author->profile_name}/page/?([0-9]+)/?$"] = 'index.php?author_name=' . $author->nicename . '&paged=$matches[1]';
$author_rewrite["{$author->profile_name}/?$"] = "index.php?author_name={$author->nicename}";
}
return $author_rewrite;
}
flush_rewrite_rules(false);
dont forget to comment the flush_rewrite_rules call after you are done with rewrite rules, it is very expensive!
try this one. for get your author url.
<?php the_author_posts_link(); ?>
if post a admin or a author and want to show his/her all post in one page. so, you need to get his/her url automatic. then try this one

Reading node field values in drupal7 programmatically

I am looking for the best way to get a field value from a node id.
My actually code works however I guess there is an easier way.
$node = node_load( 1 );
$lang = $node->language;
$field = 'body';
$value = '';
if ( isset($node->{$field}[$lang]) && isset($node->{$field}[$lang][0]) )
{
$value = $node->{$field}[$lang][0]['value'];
}
echo $value;
Is there any build in drupal function that takes care of this?
Not all of it, but you should be able to simplify it a bit with http://api.drupal.org/api/drupal/modules--field--field.module/function/field_get_items/7.
You still need to check if $items[0] exists and get the 'value' of that.
Thanks #Berdir. I agree field_get_items is a better way. Here is a code example:
<?php
$body = field_get_items('node',$node, 'body');
print $body[0]['value'];
?>

Resources