Why doesn't this WordPress $wpdb query work? - wordpress

I am doing the following:
$type = 'attachment';
$images = $wpdb->get_results($wpdb->prepare('
SELECT p.*
FROM wp_%d_posts p
WHERE p.post_parent =%d
AND p.post_type = "%s"
', $blog_id, $page->ID, $type),OBJECT);
var_dump($images);
If I remove the line 'AND p.post_type = "%s"' then I get results returned, otherwise I get an empty array returned. If I run the query direct against the DB in a mysql client, I get results.
There is no error, just an empty result set. I am doing similar queries throughout my file and they are working so I'm not looking for "don't do it like that" style replies. I just need to understand why this isn't working and fix it.
PHP 5.3, MYSQL 5.1. WordPress MU 2.9.2

Do not Quote "%s". From the WordPress site, "Notice that you do not have to worry about quoting strings. Instead of passing the variables directly into the SQL query, use a %s placeholder for strings and a %d placedolder for integers."
Example:
$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_title = %s WHERE ID = %d", $var, $id ) );

Related

Count number of posts have particular meta key or value?

What I want to achieve is display the number of posts which have particular meta key or value I am getting a list of posts and meta key and value but don't know how to display them I'm storing data using repeatable fields. Storing work properly.
Now, for example, I have age meta value in two posts so how can I count no of a post with age. Age = No of post 2.
My Code :
global $wpdb;
$query = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}postmeta WHERE (meta_key = 'repeatable_fields') ");
$array = wp_json_encode($query);
print_r($array);
Outout :
[{"meta_id":"312","post_id":"108","meta_key":"repeatable_fields","meta_value":"a:2:{i:0;a:2:{s:4:\"name\";s:6:\"Zaheer\";s:5:\"phone\";s:3:\"123\";}i:1;a:2:{s:4:\"name\";s:6:\"Sageer\";s:5:\"phone\";s:11:\"09190219218\";}}"},{"meta_id":"323","post_id":"121","meta_key":"repeatable_fields","meta_value":"a:2:{i:0;a:2:{s:9:\"iif_label\";s:4:\"City\";s:11:\"iif_details\";s:7:\"karachi\";}i:1;a:2:{s:9:\"iif_label\";s:3:\"Age\";s:11:\"iif_details\";s:2:\"12\";}}"},{"meta_id":"329","post_id":"126","meta_key":"repeatable_fields","meta_value":"a:1:{i:0;a:2:{s:9:\"iif_label\";s:3:\"Age\";s:11:\"iif_details\";s:2:\"12\";}}"},{"meta_id":"332","post_id":"128","meta_key":"repeatable_fields","meta_value":"a:3:{i:0;a:2:{s:9:\"iif_label\";s:7:\"Country\";s:11:\"iif_details\";s:8:\"Pakistan\";}i:1;a:2:{s:9:\"iif_label\";s:4:\"City\";s:11:\"iif_details\";s:9:\"Islamabad\";}i:2;a:2:{s:9:\"iif_label\";s:3:\"Age\";s:11:\"iif_details\";s:2:\"12\";}}"}]
You could try something like this:
$count_age = $wpdb->get_col( $wpdb->prepare(
"
SELECT count(meta_id)
FROM {$wpdb->prefix}postmeta
WHERE meta_value LIKE '%%%s%%'
",
'Age'
));
More about get_col() here: https://codex.wordpress.org/Class_Reference/wpdb#SELECT_a_Column

Woocommerce Vendors Set Selling Locations and Manipulate Product Query Loop

I want to only list products that can be shipped to a customer based on their location set in billing/shipping address. (All my users are logged in)
Each of my vendors may ship to certain countries only so I don't want to show products to a user that cannot be shipped to them.
To tackle this problem I have added an extra field in the edit vendor page which saves the countries (via multi select box) they can ship to as a separate term meta.
update_term_meta($term_id, 'vendor_data_shipping_countries', $selected_shipping_countries);
etc...
All that data saves fine and is outputted as follows when I call get_term_meta($term->term_id, 'vendor_data_shipping_countries')[0].
Array
(
[0] => FR
[1] => GB
)
What I am having trouble with now is filtering the product loop query to only show products that can be shipped to the user with the action 'woocommerce_product_query'.
function ac_vendor_show_deliverable_products($query)
{
// magical query filter here...
// if users location matches any of the vendor products ship to countries then output the product to the user
// $query->set(); ... something...
}
add_action('woocommerce_product_query','ac_vendor_show_deliverable_products');
This is where my skill level fails me. I am fairly new to WC and not good at manipulating the query with actions. Better at just writing the full SQL but feel I would mess lots of other things up and filtering is the best way to go.
I expect someone's kunfu is way stronger than mine! Can anyone figure this out?
Hope someone can help.
UPDATE:
I have managed to write exactly what I want to happen in SQL
SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts
LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
LEFT JOIN wp_term_taxonomy ON (wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id)
LEFT JOIN wp_termmeta ON (wp_termmeta.term_id = wp_term_taxonomy.term_id)
WHERE wp_termmeta.meta_key = 'vendor_data_shipping_countries'
AND wp_termmeta.meta_value LIKE '%"GB"%'
AND wp_posts.post_type = 'product'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
GROUP BY wp_posts.ID
ORDER BY wp_posts.menu_order ASC, wp_posts.post_title ASC LIMIT 0, 12
This only lists products that have added GB as a country they can ship to.
Note the meta_value is stored as a serialized array so the easiest way to match was to perform a LIKE as values are stored as a:2:{i:0;s:2:"FR";i:1;s:2:"GB";} for example.
If anyone can figure out how to put that SQL into the woocommerce_product_query hook then that would be amazing. But I can't for the life of me figure out how this is possible...
Everything on https://codex.wordpress.org/Class_Reference/WP_Query just adds SQL for wp_postmeta not wp_termmeta from what I can see.
Cheers
I managed to get this to work by using the posts_join and posts_where filters instead.
I hope this helps someone else down the line.
/*
* Add the needed term tables
*/
function ac_vendor_sql_join_term_meta($join)
{
global $wp_query, $wpdb;
//only do this is WC product query
if(isset($wp_query->query_vars['wc_query']) && $wp_query->query_vars['wc_query'] == 'product_query')
{
$join .= ' LEFT JOIN '. $wpdb->term_relationships .' tr1 ON (tr1.object_id = '. $wpdb->posts .'.ID)';
$join .= ' LEFT JOIN '. $wpdb->term_taxonomy .' tt1 ON (tt1.term_taxonomy_id = tr1.term_taxonomy_id)';
$join .= ' LEFT JOIN '. $wpdb->termmeta .' tm1 ON (tm1.term_id = tt1.term_id)';
}
return $join;
}
add_filter('posts_join', 'ac_vendor_sql_join_term_meta');
/*
* Add the needed where statements
*/
function ac_vendor_sql_filter_shipping_where($where, $wp_query)
{
//only do this is WC product query
if(isset($wp_query->query_vars['wc_query']) && $wp_query->query_vars['wc_query'] == 'product_query')
{
//get the users billing country code.
if(is_user_logged_in())
{
$billing_country = get_user_meta(get_current_user_id(), 'billing_country', TRUE);
}
else //default to IP location
{
$geo_locate = WC_Geolocation::geolocate_ip($_SERVER['REMOTE_ADDR']);
$billing_country = $geo_locate['country'];
}
$where .= " AND tm1.meta_key = 'vendor_data_shipping_countries'";
$where .= " AND tm1.meta_value LIKE '%\"". $billing_country ."\"%'";
}
return $where;
}
add_filter('posts_where', 'ac_vendor_sql_filter_shipping_where', 10, 2);

Query to copy data of multiple columns from one table to another in sqlite3? [duplicate]

I want to read query string from URL and save them into a sqlite database
I face with these Error message:
PHP Warning: SQLite3::exec(): near ",": syntax error
But I don't the problems:
$Tel = $_REQUEST["from"];
$Content = $_REQUEST["text"];
echo $Tel = strip_tags($Tel);
echo $Content = strip_tags($Content);
$sql =<<<EOF
INSERT INTO foodordering(Fullname, Tel, RecievingTime, Content)
VALUES ("Ehsan", $Tel, date('now'), $Content);
EOF;
$ret = $db->exec($sql);
As mentioned by #HassanAhmed, this is what happens when inputs are not properly handled; you're seeing the same issue as if someone was using SQL injection against you. The quick fix is to wrap the fields in quotation marks:
VALUES ("Ehsan", "$Tel", date('now'), "$Content");
What you should be doing is binding the parameters:
$sql =<<<EOF
INSERT INTO foodordering(Fullname, Tel, RecievingTime, Content)
VALUES ("Ehsan", :tel, date('now'), :content);
EOF;
$stmt = $db->prepare($sql);
$stmt->bindValue(':tel', $_REQUEST['from']);
$stmt->bindValue(':content', $_REQUEST['text']);
$ret = $stmt->execute();

Query with join not work

i am doing a query in my controller like this:
$aviso = $em->getRepository("FabricacionBundle:Aviso")->findBy(array("fecha" => $fecha));
$dql = "SELECT a FROM PedidosBundle:Articulo a WHERE a.aviso = :aviso";
if(isset($_GET['filterField']) && isset($_GET['filterValue'])){
$dql = "SELECT a FROM PedidosBundle:Articulo a JOIN ProductosBundle:Producto p WHERE a.aviso = :aviso";
$dql .= " AND " . $_GET['filterField'] . " LIKE '%" . $_GET['filterValue'] . "%'";
}
$query = $em->createQuery($dql)
->setParameter("aviso", $aviso[0]->getId());
//dump($query);die();
$paginator = $this->get('knp_paginator');
$articulos = $paginator->paginate(
$query,
$request->query->get('page', 1),
25
);
When i dont use the filter, this work, but when i use the filter i get the next error:
Cannot count query which selects two FROM components, cannot make distinction
Where is the problem? Thanks!
What SQL engine are you running ?
Note, that it's usually a very bad practice to insert anything directly from your $_GET variable into your SQL query, as this can lead to SQL injection.
Imagine, that someone sends \'; DROP TABLE something; -- in your $_GET['filterField'] - everything is gone.
From the top of my head, there is a lacking JOINing condition.

WordPress database error: [Query was empty]

I'm using $wpdb to connect to a different database than my wordpress one like this:
$newdb = new wpdb(DB_NEW_USER, DB_NEW_PASSWORD, DB_NEW_NAME, DB_NEW_HOST);
I need to insert multiple rows into the database.
I used the code from this answer: Wordpress $wpdb. Insert Multiple Records.
To run the query, I use this line:
$newdb->query( $newdb->prepare("$query", $values));
When I do echo $query, this is the result: (there are more than 3 columns, but I shortened if for times sake)
INSERT INTO table (column1, column2, column3) VALUES ('%s', '%s', '%s')
When I var_dump($values), it returns an array with the same amout of strings as I have columns.
When I run the query, I get the following error:
WordPress database error: [Query was empty]
I tried selecting from the database in a similar fashion and it did work, so my connected to the db is working.
What am I doing wrong?
If anyone can help me I would really appreciate it.
Are you sure your query look like this?
$metakey = "Harriet's Adages";
$metavalue = "WordPress' database interface is like Sunday Morning: Easy.";
$wpdb->query( $wpdb->prepare(
"
INSERT INTO $wpdb->postmeta
( post_id, meta_key, meta_value )
VALUES ( %d, %s, %s )
",
array(
10,
$metakey,
$metavalue
)
) );

Resources