it-swarm.com.de

Ist es möglich, alle Posts abzufragen, die keinen Anhang haben?

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.

7
Sudar

Ich wurde neugierig auf die SQL-Methode, um alle Posts ohne Anhänge zu finden.

Methode 1 - Unterabfrage mit 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 ;-)

Methode 2 - 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.

Methode 3 - WP_Query mit posts_where-Filter, auch bekannt als Methode 1

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;
}
4
birgire

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.

5
David