Ich möchte eine Liste aller Posts ohne Anhang erhalten und diese löschen.
Bei dieser Frage geht es darum, alle Posts zu bekommen, die einen Anhang haben, aber ich möchte das Gegenteil davon.
Der gewaltsame Weg, dies zu tun, besteht darin, alle Posts zu bekommen und sie dann einzeln durchzugehen und dann zu prüfen, ob sie Anhänge haben oder nicht. Aber ich möchte es nach Möglichkeit vermeiden.
Ich wurde neugierig auf die SQL-Methode, um alle Posts ohne Anhänge zu finden.
NOT IN
Hier ist mein erster Versuch, eine solche Abfrage zu erstellen:
global $wpdb;
$sql = "
SELECT p1.ID, p1.post_title
FROM {$wpdb->posts} p1
WHERE p1.post_type = 'post'
AND p1.post_status = 'publish'
AND p1.ID NOT IN (
SELECT DISTINCT p2.post_parent
FROM {$wpdb->posts} p2
WHERE p2.post_type = 'attachment' AND p2.post_parent > 0
)
ORDER BY p1.post_date DESC
";
// Fetch posts without attachments:
$posts_without_attachments = $wpdb->get_results( $sql );
// Display posts without attachments:
foreach( $posts_without_attachments as $post )
{
echo $post->post_title . '<br/>';
}
Dies ist der Abfrage von @ toscho sehr ähnlich, ist jedoch in der Syntax weniger rationalisiert ;-)
LEFT JOIN
mit IS NULL
Diese Abfrage scheint auch zu funktionieren:
global $wpdb;
$sql = "
SELECT p1.ID, p1.post_title
FROM {$wpdb->posts} p1
LEFT JOIN {$wpdb->posts} p2
ON ( p2.post_parent = p1.ID AND p2.post_type = 'attachment' )
WHERE p1.post_type = 'post'
AND p1.post_status = 'publish'
AND p2.post_parent IS NULL
ORDER BY p1.post_date DESC
";
// Fetch posts without attachments:
$posts_without_attachments = $wpdb->get_results( $sql );
hier verbinden wir uns mit der Tabelle posts und heben dann die Zeilen NULL
in der übergeordneten Spalte der Anhänge auf.
Wir könnten auch die WP_Query()
mit dem posts_where
-Filter ändern:
// Filter all posts without attachments:
add_filter( 'posts_where', 'wpse_no_attachments' );
// Query:
$q = new WP_Query( array( 'post_type' => 'post', 'posts_per_page' => -1 ) );
// Remove the filter:
remove_filter( 'posts_where', 'wpse_no_attachments' );
woher:
function wpse_no_attachments( $where )
{
global $wpdb;
$where .= " AND {$wpdb->posts}.ID NOT IN (
SELECT DISTINCT wpse.post_parent
FROM {$wpdb->posts} wpse
WHERE wpse.post_type = 'attachment' AND wpse.post_parent > 0 ) ";
return $where;
}
Wenn Sie mit dem vollständigen Gegenteil der verknüpften Antwort vertraut sind, können Sie mit dieser Abfrage einfach alle Posts mit einem Anhang abrufen und ihre IDs als post__not_in
-Parameter für \WP_Query
verwenden:
$attachment_args = array(
'post_type' => 'attachment',
'post_mime_type' => 'image',
'post_status' => 'inherit',
'posts_per_page' => -1,
'post_parent__not_in' => array(0),
'meta_query' => array(
array(
'key' => '_thumbnail_id',
'value' => 'x',
'compare' => 'NOT EXISTS'
)
),
'fields' => 'post_parent'
);
$atts = new WP_Query($args);
$parents = array_unique(wp_list_pluck($atts->posts,'post_parent'));
$post_args = array(
'post_type' => 'post',
'posts_per_page' => -1
'post__not_in' => $parent
'post_status' => 'any'
);
// Posts with no attachment:
$post_query = new WP_Query( $post_args );
Update Toscho hat mich darauf hingewiesen, diese eine Frage zu stellen. Und dies kann natürlich mit einer einfachen SQL-Abfrage erledigt werden:
<?php
$query = <<<SQL
SELECT p.`ID` FROM {$wpdb->posts} p
WHERE p.`post_type` = 'post'
AND p.`post_status` = 'publish'
AND p.`ID` NOT IN (
SELECT DISTINCT a.`post_parent` FROM {$wpdb->posts} a
WHERE a.`post_type` = 'attachment'
AND a.`post_parent` != 0
)
SQL;
//posts with no attachment
$results = $GLOBALS[ 'wpdb' ]->get_results( $query );
Beachten Sie, dass dies geringfügig von der Variante abweicht, die aus der angegebenen Antwort stammt, da diese Abfrage keinen Unterschied zwischen einem Bild und einem Post-Thumbnail macht und auch nach Anhängen jeder Art sucht.