Querying Wordpress thumbnails - sql

I am trying to get the thumbnail meta data for the posts in my wordpress blog together with their category and some other data.
The thumbnail data is serialized and I will unserialize it later.
Here is the query I have:
SELECT wpostmeta.meta_value AS url,
wposts.post_content, wposts.post_title, wposts.post_status, wposts.post_name,
cat_terms.name AS category_name, cat_terms.term_id AS category_id,
ttable.meta_value AS thumb_data
FROM `wp_postmeta` AS wpostmeta,
`wp_posts` AS wposts
INNER JOIN wp_term_relationships AS cat_term_relationships ON (wposts.ID = cat_term_relationships.object_id)
INNER JOIN wp_term_taxonomy AS cat_term_taxonomy ON (cat_term_relationships.term_taxonomy_id = cat_term_taxonomy.term_taxonomy_id AND cat_term_taxonomy.taxonomy = 'category')
INNER JOIN wp_terms AS cat_terms ON (cat_term_taxonomy.term_id = cat_terms.term_id)
LEFT JOIN `wp_postmeta` AS ttable ON (wposts.ID = ttable.post_id AND ttable.meta_key = '_wp_attachment_metadata')
WHERE wposts.ID = wpostmeta.post_id AND wpostmeta.meta_key = 'url'
AND wposts.post_type = 'post'
Everything works except for the attachment part. 'thumb_data' is NULL.
Could you please help me fix this?

This query solved my problem:
$sql = "SELECT wposts.ID AS ID, thumbposts.ID AS thumbposts_ID,
postmeta.meta_value AS url,
wposts.post_content, wposts.post_title, wposts.post_status, wposts.post_name,
cat_terms.name AS category_name, cat_terms.term_id AS category_id,
thumb.meta_value AS thumb_data
FROM `wp_postmeta` AS postmeta,
`wp_posts` AS thumbposts,
`wp_postmeta` AS thumb,
`wp_posts` AS wposts
INNER JOIN wp_term_relationships AS cat_term_relationships ON (wposts.ID = cat_term_relationships.object_id)
INNER JOIN wp_term_taxonomy AS cat_term_taxonomy ON (cat_term_relationships.term_taxonomy_id = cat_term_taxonomy.term_taxonomy_id AND cat_term_taxonomy.taxonomy = 'category')
INNER JOIN wp_terms AS cat_terms ON (cat_term_taxonomy.term_id = cat_terms.term_id)
WHERE wposts.ID = postmeta.post_id
AND postmeta.meta_key = 'url'
AND thumbposts.post_parent = wposts.ID
AND thumbposts.post_type = 'attachment'
AND thumb.post_id = thumbposts.ID
AND thumb.meta_key = '_wp_attachment_metadata'
AND wposts.post_type = 'post'";
if($filter == 1){
$sql .= " AND cat_terms.term_id = '1'";
}
if($filter == 2){
$sql .= " AND cat_terms.term_id = '3'";
}
$sql .= " GROUP BY wposts.ID
ORDER BY wposts.post_date ASC";

Can you explain exactly what you are trying to achieve - there is no real need to go direct to the database in the vast number of situations.
For example you can use get_posts with 'post_type'=>'attachment' and 'post_mime_type'=>'image' to get image attachments and then output the metadata, and there are many functions inbuilt to deal with resizing, displaying and cropping the thumbnails, such as get_post_thumbnail() etc.

Related

Extract the list of brands associated with a category in WooCommerce

In woocommerce, I have products which are classified in one (or more) categories (product_cat), and which have a brand attribute (pa_marque), and are only in one brand.
I'm trying to extract the list of brands associated with a category ...
By doing a SQL JOIN (this may not be the best solution) on the term_relationships, term_taxonomy, terms and posts tables I get something like this:
{"post_id":"23391","term_taxonomy_id":"1217","taxonomy":"product_cat","taxonomy_parent":"0"},
{"post_id":"23391","term_taxonomy_id":"1219","taxonomy":"product_cat","taxonomy_parent":"1217"},
{"post_id":"23391","term_taxonomy_id":"1943","taxonomy":"pa_marque","taxonomy_parent":"0"}
(i.e. product 23391 has 2 product_cat and 1 pa_marque ... but that's where I don't really know how to continue ...)
Would you have a clue?
I found Get WooCommerce product categories that contain a specific product brand answer code and I got it working making some little changes to the code as follow:
// Inspired by https://stackoverflow.com/a/61624358/1256770
function get_taxovalues_in_another_taxo_from_a_product_categories($taxonomy_tofind, $taxonomy_known, $cat_term_slug)
{
global $wpdb;
$results = $wpdb->get_results("
SELECT DISTINCT
t1.*
FROM {$wpdb->prefix}terms t1
INNER JOIN {$wpdb->prefix}term_taxonomy tt1
ON t1.term_id = tt1.term_id
INNER JOIN {$wpdb->prefix}term_relationships tr1
ON tt1.term_taxonomy_id = tr1.term_taxonomy_id
INNER JOIN {$wpdb->prefix}term_relationships tr2
ON tr1.object_id = tr2.object_id
INNER JOIN {$wpdb->prefix}term_taxonomy tt2
ON tr2.term_taxonomy_id = tt2.term_taxonomy_id
INNER JOIN {$wpdb->prefix}terms t2
ON tt2.term_id = t2.term_id
WHERE
tt1.taxonomy = '$taxonomy_tofind'
AND tt2.taxonomy = '$taxonomy_known'
AND t2.slug = '$cat_term_slug'
ORDER BY t1.name
");
$return = [];
if (!empty($results)) {
$term_names = [];
foreach ($results as $result) {
$term_link = get_term_link(get_term($result->term_id, $taxonomy_tofind), $taxonomy_tofind);
$term_names[] = '<a class="' . $result->slug . '" href="' . $term_link . '">'
. $result->name . '</a>';
}
$return = $term_names;
}
return $return;
}
// searching 'pa_marque' associated to product_cat "aiguilles-et-crochets"
$brands = get_taxovalues_in_another_taxo_from_a_product_categories('pa_marque', 'product_cat', 'aiguilles-et-crochets');
print(implode(" - ", $brands));
// searching 'pa_epaisseur-laine' associated to product_cat "laines"
$brands = get_taxovalues_in_another_taxo_from_a_product_categories('pa_epaisseur-laine', 'product_cat', 'laines');
print(implode(" - ", $brands));

Convert a $_GET value in PDO

I wrote a basic function to join 3 tables regarding a similar id.
{
$id = $_GET["id"];
$product_edit_query = $this->DB->query('
SELECT * FROM products
LEFT JOIN products_ingredients
ON products_ingredients.product_id = products.product_id
LEFT JOIN products_languages
ON products_languages.product_id = products.product_id
WHERE products.product_id = 73
');
$product_edit = $product_edit_query->fetch();
$this->smarty->assign('product_edit', $product_edit);
}
In the last line I have of my request, i have WHERE products.product_id = 73. 73 is hardcoded, and should be the value of $_GET["id"], but all I tried didn't work to convert it in PDO, any help ?
Solution given by a friend:
{
$stmt = $this->DB->prepare('
SELECT * FROM products
LEFT JOIN products_ingredients
ON products_ingredients.product_id = products.product_id
LEFT JOIN products_languages
ON products_languages.product_id = products.product_id
WHERE products.product_id = :id
');
$stmt->execute([':id' => $_GET["id"]]);
$get_product_base = $stmt->fetch();
$this->smarty->assign('get_product_base', $get_product_base);
}

Increase query performance in wp_posts, via wp_get_nav_menu_items using custom sql query in wordpress

Today I ran into a problem that noticeably slows down the performance of the site. In my header, menu categories are loaded (menu name -> header_nav). I load them with a function like wp_get_nav_menu_items ($ menu-> term_id). This function returns an array of objects in which there are a lot of fields, since there are a lot of categories, there are also a lot of objects. From the whole object, I need only $ object-> title, $ object-> link, $ object-> id. I need to get this data from multilingual titles.
//$menu_items too large array of objects
$menu = wp_get_nav_menu_object( $locations[ 'menu_slug'] );
//Here my array. do foreach and creating category menu using
//$menu_item->title...and etc.
$menu_items = wp_get_nav_menu_items($menu->term_id);
And I decided to write my own request. But it returns data without multilingual
SELECT p2.ID, p2.post_title, p2.post_name, p2.guid,
p1.post_parent
FROM wp_posts p1
INNER JOIN wp_term_relationships AS TR
ON TR.object_id = p1.ID
INNER JOIN wp_postmeta AS pm
ON pm.post_id = p1.ID
INNER JOIN wp_posts AS p2
ON p2.ID = pm.meta_value
WHERE p1.post_type = 'nav_menu_item'
AND TR.term_taxonomy_id = $taxId
AND pm.meta_key = '_menu_item_object_id'
ORDER BY p1.menu_order ASC
How to return already translated titles?
SELECT * FROM wp_posts p1 INNER JOIN wp_term_relationships AS TR ON TR.object_id =
p1.ID INNER JOIN wp_postmeta AS PM ON pm.post_id = p1.ID INNER JOIN wp_posts AS p2 ON
p2.ID = PM.meta_value WHERE p1.post_type = 'nav_menu_item' AND TR.term_taxonomy_id = (
SELECT wp_terms.term_id FROM wp_terms WHERE slug = 'pedik') AND pm.meta_key =
'_menu_item_object_id' ORDER BY p1.menu_order ASC
for title
$menu_item->object_id = ! isset( $menu_item->object_id ) ? get_post_meta(
$menu_item-
>ID, '_menu_item_object_id', true ) : $menu_item->object_id;
for url
$menu_item->url = get_permalink( $menu_item->object_id );
for title
$original_title = apply_filters( 'the_title', $original_object-
>post_title,$original_object->ID );
if ( '' === $original_title ) {
/* translators: %d: ID of a post */
$original_title = sprintf( __( '#%d (no title)' ), $original_object-
>ID );
}
$menu_item->title = '' == $menu_item->post_title ? $original_title :
$menu_item->post_title;

How to do a SQL JOIN where multiple joined rows need to contain things

When someone on my site search for an image that has multiple tags I need to query and find all images that have the searched tags, but can't seem to figure out this query.
I have an Images table.
The Images table has a relation to Posts_Images.
Posts_Images would have a relation to Posts table.
Posts has a relation to Posts_Tags table.
Posts_Tags table will have the relations to Tags table.
The query I have so far:
SELECT "images".* FROM "images"
INNER JOIN "posts_images" ON posts_images.image_id = images.id
INNER JOIN "posts" ON posts.id = posts_images.post_id AND posts.state IS NULL
INNER JOIN "posts_tags" ON posts_tags.post_id = posts.id
INNER JOIN "tags" ON posts_tags.tag_id = tags.id
WHERE (("images"."order"=0) AND ("images"."has_processed"=TRUE)) AND (LOWER(tags.tag)='comic') AND ("tags"."tag" ILIKE '%Fallout%') ORDER BY "date_uploaded" DESC LIMIT 30
It gets no results, it is checking if the tags equals both values, but I want to see if any of the tags that were joined have all the values I need.
The desired result would be any Post that has a tag matching Comic and ILIKE '%Fallout%'
You seem to want something like this:
SELECT i.*
FROM images JOIN
posts_images pi
ON pi.image_id = i.id JOIN
posts p
ON p.id = pi.post_id AND p.state IS NULL JOIN
posts_tags pt
ON pt.post_id = p.id JOIN
tags t
ON pt.tag_id = t.id
WHERE i."order" = 0 AND
i.has_processed AND
(LOWER(t.tag) = 'comic') OR
(t.tag ILIKE '%Fallout%')
GROUP BY i.id
HAVING COUNT(DISTINCT tag) >= 2
ORDER BY date_uploaded DESC
LIMIT 30;
The logic is in the HAVING clause. I'm not 100% sure that this is exactly what you want for multiple matches.
In addition to gordon-linoff’s response - query can be described using ActiveQuery:
Images::find()
->alias('i')
->joinWith([
'postsImages pi',
'postsImages.posts p',
'postsImages.posts.tags t'
])
->where([
'p.state' => null,
'i.order' => 0,
'i.has_processed' => true,
])
->andWhere(
'or'
'LOWER(t.tag) = "comic"',
['like', 't.tag', 'Fallout']
])
->groupBy('id')
->having('COUNT(DISTINCT tag) >= 2')
->orderBy('date_uploaded DESC')
->limit(30)
->all()
$images = Images::find()
->innerJoin('posts_images', 'posts_images.image_id = images.id')
->innerJoin('posts', 'posts.id = posts_images.post_id AND posts.state IS NULL')
->where(['images.order' => 0, 'images.has_processed' => true]);
if (!is_null($query)) {
$tags = explode(',', $query);
$images = $images
->innerJoin('posts_tags', 'posts_tags.post_id = posts.id')
->innerJoin('tags', 'posts_tags.tag_id = tags.id');
$tagsQuery = ['OR'];
foreach ($tags as $tag) {
$tag = trim(htmlentities($tag));
if (strtolower($tag) == 'comic') {
$tagsQuery[] = ['tags.tag' => $tag];
} else {
$tagsQuery[] = [
'ILIKE',
'tags.tag', $tag
];
}
}
if (!empty($tagsQuery)) {
$images = $images->andWhere($tagsQuery)
->having('COUNT(DISTINCT tags.tag) >= ' . sizeof($tags));
}
}
$images = $images
->groupBy('images.id')
->orderBy(['date_uploaded' => SORT_DESC])
->offset($offset)
->limit($count);
return $images->all();

How to interogate a query to get all the images in wordpress from wp-posts?

I want to get the all of the images from wp-post, including : date, post content, title, url
this is my query :
SELECT p.post_parent, p.guid, p.post_title, p.post_content, p.post_date
FROM wp_posts p
WHERE ((p.post_mime_type = "image/jpeg" OR p.post_mime_type = "image/png" OR p.post_mime_type = "image/gif")
AND (p.post_parent = p.id))
If i get removed the " AND (p.post_parent = p.id))" I got the all of the result, but the post assign to it . This query return me nothing. How can I get this items ?
Finally, I manage it out : this is the wanted result :
SELECT p.post_parent, p.guid, p.post_title, wp.post_content, p.post_date
FROM wp_posts p
LEFT JOIN wp_posts wp
ON p.post_parent = wp.id
WHERE (p.post_mime_type = "image/jpeg" OR p.post_mime_type = "image/png" OR p.post_mime_type = "image/gif")