Как я могу доверять switch_to_blog ()?

18

Когда я звоню switch_to_blog()с идентификатором блога, я не знаю, существует ли этот блог на самом деле. Функция возвращает всегда TRUE.

Прецедент:

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

Это приведет к ошибкам в базе данных, которые выставляются пользователю. Как я могу предотвратить это?

Реальный пример использования

Я был ведущим разработчиком Multilingual Press . Когда пользователь переводит сообщение, он получает такой экран:

введите описание изображения здесь

Теперь может произойти следующее:

  1. Она успешно сохраняет сообщение и продолжает переводить сообщение.
  2. Другой пользователь, сетевой администратор, удаляет немецкий блог, пока она пишет.
  3. Она снова нажимает сохранить и получает ошибки базы данных.

Я хочу избежать этого сценария. Как я могу быстро проверить, существует ли целевой блог? Я звоню switch_to_blog()очень часто в разных классах, поэтому это должно быть быстро.

Фуксия
источник
Как насчет $wpdb->blogid;и крюк wp_insert_post_data?
JMau
@JMau get_post()- это просто чтение. Между последним сохранением и следующей перезагрузкой экрана редактирования может быть долгая пауза.
Fuxia
5
Кэшированный SQL-запрос по запросу для blog_id в таблице wp_blogs (где удалено = 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 Мысли вслух ... Есть wp_cache_switch_to_blog(), но это помогает только с постоянным кешем, а не по умолчанию на странице WP. В любом случае, для меня не совсем понятно, где вы хотите проверить существование блога: когда кто-то удаляет блог или кто-то пытается написать переведенный пост, указывающий на другой блог (включающий тот же контент на другом языке)?
Кайзер

Ответы:

10

Идея @ GM кешировать чек привела меня к следующей вспомогательной функции. Я поместил его в глобальное пространство имен, чтобы он был доступен везде.

Функция ничего не говорит о статусе блога, только если он существует и не помечен как удаленный. Запрос к базе данных очень быстрый (0,0001 секунды) и выполняет только один запрос на каждый идентификатор сайта, независимо от того, как часто вызывается функция.

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 ] );
    }
}

использование

if ( ! blog_exists( $blog_id ) )
    return new WP_Error( '410', "The blog with the id $blog_id has vanished." );
Фуксия
источник
почему $wpdb->get_results+ wp_list_pluckвместо только (int) $wpdb->get_var? однако +1, и я думаю, что нечто подобное должно быть в ядре switch_to_blog ...
gmazzap
@GM get_var()возвращает только один результат. Я использовал get_col()сейчас, и я убедился, что пустой результат снова не получен.
fuxia
Ах, хорошо ... Я лучше прочитал запрос сейчас, вы получаете все идентификаторы блогов для определенного идентификатора сайта, сначала прочитайте, я думаю, вы получаете только один идентификатор блога за раз (тот, который передан в функцию) ... уверен, массив путь лучше. Я извиняюсь, невозможно снова +1 :)
gmazzap