Jak mogę zaufać switch_to_blog ()?

18

Kiedy dzwonię switch_to_blog()z identyfikatorem bloga, nie wiem, czy ten blog rzeczywiście istnieje. Funkcja zawsze zwraca TRUE.

Przypadek testowy:

switch_to_blog( PHP_INT_MAX );
$post = get_post( 1 );
restore_current_blog();

Spowoduje to błędy bazy danych, które zostaną ujawnione użytkownikowi. Jak mogę temu zapobiec?

Przypadek użycia w świecie rzeczywistym

Byłem głównym programistą Multilingual Press . Gdy użytkownik tłumaczy post, dostaje taki ekran:

wprowadź opis zdjęcia tutaj

Teraz mogą się zdarzyć:

  1. Zapisuje post z powodzeniem i kontynuuje jego tłumaczenie.
  2. Inny użytkownik, administrator sieci, usuwa niemiecki blog podczas pisania.
  3. Uderza ponownie zapisz i dostaje błędy bazy danych.

Chcę uniknąć tego scenariusza. Jak mogę szybko sprawdzić, czy blog docelowy istnieje? Dzwonię switch_to_blog()bardzo często w wielu różnych klasach, więc musi być szybko.

fuxia
źródło
Co powiesz $wpdb->blogid;na hak wp_insert_post_data?
JMau
@JMau get_post()to tylko czytanie. Pomiędzy ostatnim zapisaniem a ponownym załadowaniem ekranu edycji może być długa przerwa.
fuxia
5
Zapytanie SQL buforowane na żądanie dla id_bloga w tabeli wp_blogs (gdzie usunięte = 0)?
gmazzap
1
@GMSELECT blog_id FROM {$wpdb->blogs} WHERE site_id = %d AND public = '1' AND archived = '0' AND spam = '0' AND deleted = '0'
kaiser
@toscho Myślenie głośno ... Jest wp_cache_switch_to_blog(), ale pomaga tylko przy trwałej pamięci podręcznej, a nie domyślnej stronie WP. W każdym razie, dla mnie nie jest do końca jasne, gdzie chcesz sprawdzić istnienie bloga: Kiedy ktoś usuwa blog lub gdy ktoś próbuje napisać przetłumaczony post wskazujący na innego bloga (zasilający tę samą treść w innym języku)?
kaiser

Odpowiedzi:

10

Pomysł @ GM na buforowanie czeku doprowadził mnie do następującej funkcji pomocnika. Umieściłem go w globalnej przestrzeni nazw, aby był dostępny wszędzie.

Ta funkcja nie mówi nic o stanie bloga, tylko jeśli istnieje i nie jest oznaczona jako usunięta. Zapytanie do bazy danych jest bardzo szybkie (0,0001 sekundy) i uruchamia tylko jedno zapytanie na identyfikator witryny, bez względu na to, jak często funkcja jest wywoływana.

if ( ! function_exists( 'blog_exists' ) ) {

    /**
     * Checks if a blog exists and is not marked as deleted.
     *
     * @link   http://wordpress.stackexchange.com/q/138300/73
     * @param  int $blog_id
     * @param  int $site_id
     * @return bool
     */
    function blog_exists( $blog_id, $site_id = 0 ) {

        global $wpdb;
        static $cache = array ();

        $site_id = (int) $site_id;

        if ( 0 === $site_id )
            $site_id = get_current_site()->id;

        if ( empty ( $cache ) or empty ( $cache[ $site_id ] ) ) {

            if ( wp_is_large_network() ) // we do not test large sites.
                return TRUE;

            $query = "SELECT `blog_id` FROM $wpdb->blogs
                    WHERE site_id = $site_id AND deleted = 0";

            $result = $wpdb->get_col( $query );

            // Make sure the array is always filled with something.
            if ( empty ( $result ) )
                $cache[ $site_id ] = array ( 'do not check again' );
            else
                $cache[ $site_id ] = $result;
        }

        return in_array( $blog_id, $cache[ $site_id ] );
    }
}

Stosowanie

if ( ! blog_exists( $blog_id ) )
    return new WP_Error( '410', "The blog with the id $blog_id has vanished." );
fuxia
źródło
dlaczego $wpdb->get_results+ wp_list_pluckzamiast tylko (int) $wpdb->get_var? jednak +1 i myślę, że coś podobnego powinno być w rdzeniu switch_to_blog ...
gmazzap
@GM get_var()zwraca tylko jeden wynik. Użyłem get_col()teraz i upewniłem się, że pusty wynik nie zostanie ponownie pobrany.
fuxia
Ach, ok ... Lepiej przeczytam teraz zapytanie, dostajesz wszystkie identyfikatory blogów dla konkretnego identyfikatora witryny, na początku czytam Myślę, że dostajesz tylko jeden identyfikator blogu na raz (ten przekazany do funkcji) ... pewnie tablica droga jest lepsza. Przepraszam, nie jest możliwe +1 ponownie :)
gmazzap