it-swarm.com.de

Erstelle Permalinks basierend auf einem ACF-Feld

Dies ist sowohl eine Frage zur Vorgehensweise als auch zur Vorgehensweise.

Ich habe die ACF-lastige Site, auf der ich die Permalinks basierend auf einem der ACF-Felder erstellen möchte (nennen wir es foo). Wenn das Feld foo- den Wert 123 hat, möchte ich, dass der Permalink zu dieser Seite http://example.org/s123 ist (die s soll die Kollision mit Post-IDs im Permalink vermeiden). Wenn diese URL verwendet wird, sollte sie http://example.org/s123-1 und so weiter heißen.

Das ACF-Feld wird auf einen benutzerdefinierten Beitragstyp gesetzt. Und die Seite enthält einige wichtige Informationen, deshalb lasse ich diese Funktionalität lieber aus, als ein Plugin zu verwenden. Es muss also etwas sein, das in die functions.php- Datei passt.

Ist es möglich das zu machen? Und ist es unklug, sich mit der Permalink-Struktur von WordPress herumzuschlagen (außer dem, was auf der Seite mit den Permalink-Einstellungen erlaubt ist)?

Addition

Ich kann sehen, dass, wenn Sie CPTs mit "root" -Permalinks versehen, diese unterbricht die Permalinks für Posts und Seiten . : - /

... Ich wusste nicht, dass es so schwer ist, einem CPT einen Nice/Simple-Permalink zu geben.

3
Zeth

URLs aus CF

Nun, Sie können dies auf viele Arten tun ... Eine davon wäre, den parse_request-Filter zu verwenden und sein Verhalten zu ändern, aber es kann leicht etwas durcheinander bringen.

Eine andere Möglichkeit wäre, save_post action zu verwenden und die Beiträge post_name zu ändern, damit WordPress wie gewohnt funktioniert, aber der post_name wird basierend auf Ihrem benutzerdefinierten Feld und nicht basierend auf dem Titel generiert. Dies ist die Lösung, für die ich mich entscheiden würde. Warum? Denn dann können Sie mit WP Funktionen sicherstellen, dass die Links eindeutig sind ...

Also hier ist der Code:

function change_post_name_on_save($post_ID, $post, $update ) {
    global $wpdb;

    $post = get_post( $post_ID );
    $cf_post_name = wp_unique_post_slug( sanitize_title( 's' . get_post_field('foo', $post_ID), $post_ID ), $post_ID, $post->post_status, $post->post_type, $post->post_parent );

    if ( ! in_array( $post->post_status, array( 'publish', 'trash' ) ) ) {
        // no changes for post that is already published or trashed
        $wpdb->update( $wpdb->posts, array( 'post_name' => $cf_post_name ), array( 'ID' => $post_ID ) );
        clean_post_cache( $post_ID );
    } elseif ( 'publish' == $post->post_status ) {
        if ( $post->ID == $post->post_name ) {
            // it was published just now
            $wpdb->update( $wpdb->posts, array( 'post_name' => $cf_post_name ), array( 'ID' => $post_ID ) );
            clean_post_cache( $post_ID );
        }
    }
}
add_action( 'save_post', 'change_post_name_on_save', 20, 3 );

Dies ist nicht die schönste, da ACF-Felder nach dem Beitrag gespeichert werden. Sie müssen daher den post_name überschreiben, nachdem der Beitrag bereits gespeichert wurde. Aber es sollte gut funktionieren.

CPTs in root

Und da ist der zweite Teil Ihrer Frage: Wie erstelle ich CPTs-URLs ohne CPT-Slug ...

WordPress verwendet Rewrite Rules, um die Anfrage zu analysieren. Wenn die Anforderung mit einer der Regeln übereinstimmt, wird sie anhand dieser Regeln analysiert.

Die Regel für Seiten ist eine der letzten Regeln, mit denen die meisten Anfragen abgefangen werden, die nicht mit früheren Regeln übereinstimmen. Wenn Sie also Ihr CPT ohne Slug hinzufügen, wird die Seitenregel nicht ausgelöst ...

Eine Möglichkeit, dies zu beheben, besteht darin, CPT mit einem Slug zu registrieren und dann deren Links und WPs-Verhalten zu ändern. Hier ist der Code:

function register_mycpt() {
    $arguments = array(
        'label' => 'MyCPT',
        'public' => true,
        'hierarchical' => false,
        ...
        'has_archive' => false,
        'rewrite' => true
    );
    register_post_type('mycpt', $arguments);
}
add_action( 'init', 'register_mycpt' );

Jetzt sehen die URLs für diese Posts so aus:

http://example.com/mycpt/{post_name}/

Mit dem post_type_link-Filter können wir dies jedoch leicht ändern:

function change_mycpt_post_type_link( $url, $post, $leavename ) {
    if ( 'mycpt' == $post->post_type ) {
        $url = site_url('/') . $post->post_name . '/';
    }

    return $url;
}
add_filter( 'post_type_link', 'change_mycpt_post_type_link', 10, 3 );

Jetzt sind die URLs korrekt, aber ... Sie funktionieren nicht. Sie werden mithilfe der Umschreiberegel für Seiten analysiert und verursachen einen 404-Fehler (da keine Seite mit einer solchen URL vorhanden ist). Aber wir können das auch beheben:

function try_mycpt_before_page_in_parse_request( $wp ) {
    global $wpdb;

    if ( is_admin() ) return;

    if ( array_key_exists( 'name', $wp->query_vars ) ) {
        $post_name = $wp->query_vars['name'];

        $id = $wpdb->get_var( $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_name = %s ",
            'mycpt', $post_name
        ) );

        if ( $id ) {
            $wp->query_vars['mycpt'] = $post_name;
            $wp->query_vars['post_type'] = 'mycpt';
        }

    }
}
add_action( 'parse_request', 'try_mycpt_before_page_in_parse_request' );
2

Dies kann zu stark vereinfachen, was ich gerade lese, anstatt ACF-Felder zur Steuerung des Permalinks zu verwenden. Um den Permalink in der URL zu ändern, ist es am einfachsten, den Permalink auf der Bearbeitungsseite des jeweiligen Posts/der jeweiligen Seite zu bearbeiten als es programmatisch zu tun.

Wenn dies komplizierter ist, sollten Sie sich die WP_Rewrite-API ansehen und damit eine benutzerdefinierte Logik erstellen.

Außerdem können Sie die Permalink-Struktur umschreiben in die CPT-Deklaration einfügen

0
DevLime