Знаки вопросов на черном фоне вместо русских символов

694
02 апреля 2017, 05:33

Есть сайт на WordPress. Проблем с русскими символами не было, пока я не начал переделывать вот такой функционал: на одной странице выводится английский алфавит, а ниже - списки компаний, размещенные на сайте. При нажатии на букву в алфавите - скроллится до перечня компаний с названием, начинающихся с этой буквы (этот функционал был встроен в шаблон темы). Вот код:

public function build_company_archive( $atts ) {
    global $wpdb;
    $output      = '';
    $companies   = $wpdb->get_col(
        "SELECT pm.meta_value FROM {$wpdb->postmeta} pm
         LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
         WHERE pm.meta_key = '_company_name'
         AND p.post_status = 'publish'
         AND p.post_type = 'job_listing'
         GROUP BY pm.meta_value
         ORDER BY pm.meta_value"
    );
    $_companies = array();
    foreach ( $companies as $company ) {
        $_companies[ strtoupper( $company[0] ) ][] = $company;
    }
    if ( $atts[ 'show_letters' ] ) {
        $output .= '<div class="company-letters">';
        foreach ( range( 'A', 'Z' ) as $letter ) {
            $output .= '<a href="#' . $letter . '">' . $letter . '</a>';
        }
        $output .= '</div>';
    }
    $output .= '<ul class="companies-overview">';
    foreach ( range( 'A', 'Z' ) as $letter ) {
        if ( ! isset( $_companies[ $letter ] ) )
            continue;
        $output .= '<li class="company-group"><div id="' . $letter . '" class="company-letter">' . $letter . '</div>';
        $output .= '<ul>';
        foreach ( $_companies[ $letter ] as $company_name ) {
            $count = count( get_posts( array( 'post_type' => 'job_listing', 'meta_key' => '_company_name', 'meta_value' => $company_name, 'nopaging' => true ) ) );
            $output .= '<li class="company-name"><a href="' . $this->company_url( $company_name ) . '">' . esc_attr( $company_name ) . ' (' . $count . ')</a></li>';
        }
        $output .= '</ul>';
        $output .= '</li>';
    }
    $output .= '</ul>';
    return $output;
}

Я в PHP не силен, но методом тыка я заставил отображаться кампании на русском языке, добавив в код (в двух местах) 'А-Я' вот как получилось:

public function build_company_archive( $atts ) {
    global $wpdb;
    $output      = '';
    $companies   = $wpdb->get_col(
        "SELECT pm.meta_value FROM {$wpdb->postmeta} pm
         LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
         WHERE pm.meta_key = '_company_name'
         AND p.post_status = 'publish'
         AND p.post_type = 'job_listing'
         GROUP BY pm.meta_value
         ORDER BY pm.meta_value"
    );
    $_companies = array();
    foreach ( $companies as $company ) {
        $_companies[ strtoupper( $company[0] ) ][] = $company;
    }
    if ( $atts[ 'show_letters' ] ) {
        $output .= '<div class="company-letters">';
        foreach ( range( 'A-Z', 'А-Я' ) as $letter ) {
            $output .= '<a href="#' . $letter . '">' . $letter . '</a>';
        }
        $output .= '</div>';
    }
    $output .= '<ul class="companies-overview">';
    foreach ( range( 'A_Z', 'А-Я' ) as $letter ) {
        if ( ! isset( $_companies[ $letter ] ) )
            continue;
        $output .= '<li class="company-group"><div id="' . $letter . '" class="company-letter">' . $letter . '</div>';
        $output .= '<ul>';
        foreach ( $_companies[ $letter ] as $company_name ) {
            $count = count( get_posts( array( 'post_type' => 'job_listing', 'meta_key' => '_company_name', 'meta_value' => $company_name, 'nopaging' => true ) ) );
            $output .= '<li class="company-name"><a href="' . $this->company_url( $company_name ) . '">' . esc_attr( $company_name ) . ' (' . $count . ')</a></li>';
        }
        $output .= '</ul>';
        $output .= '</li>';
    }
    $output .= '</ul>';
    return $output;
}

Также после английского алфавита дублируется еще один англ. алфавит, но уже не заглавные буквы, а прописные, так же появились символы [\]^_{|}~, и потом, как я понял, идёт русский алфавит, но он отображается вот так -�` .

Подскажите как убрать символы [\]^_{|}~` и включить нормальный русский алфавит.

Я так понял, что это все дело в кодировке, потому что компании на русском языке не показывались, пока я этот файл не перевёл в кодировку UTF 8. Пробовал менять кодировку на другие, но ничего не получалось. Читал про кодировку базы данных, но этого не хотелось бы делать, так как пишут, что могут быть проблемы потом на всем сайте.

Answer 1

Функцию php range() нельзя использовать так, как вам хочется. В описании сказано, что "Значения для последовательности знаков ограничены длиной в один символ. Если их длина больше одного, то только первый символ используется". Это означает, что выражение range('A_Z', 'А-Я') не работает.

Точнее, php интерпретирует его как range('A', 'А'), что приводит к выводу всех символов между английской A и русской А, в том числе и не имеющим отображения. Именно они, а не русские символы выводятся как знаки вопроса на черном фоне.

Попробуйте модифицировать код следующим образом:

public function build_company_archive( $atts ) {
    global $wpdb;
    $output      = '';
    $companies   = $wpdb->get_col(
        "SELECT pm.meta_value FROM {$wpdb->postmeta} pm
         LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
         WHERE pm.meta_key = '_company_name'
         AND p.post_status = 'publish'
         AND p.post_type = 'job_listing'
         GROUP BY pm.meta_value
         ORDER BY pm.meta_value"
    );
    $_companies = array();
    foreach ( $companies as $company ) {
        $_companies[ strtoupper( $company[0] ) ][] = $company;
    }
    if ( $atts[ 'show_letters' ] ) {
        $output .= '<div class="company-letters">';
        foreach ( range( 'A', 'Z' ) as $letter ) {
            $output .= '<a href="#' . $letter . '">' . $letter . '</a>';
        }
        $output .= '</div>';
        $output .= '<div class="company-letters">';
        foreach ( range( 'А', 'Я' ) as $letter ) {
            $output .= '<a href="#' . $letter . '">' . $letter . '</a>';
        }
        $output .= '</div>';
    }
    $output .= '<ul class="companies-overview">';
    foreach ( range( 'A', 'Z' ) as $letter ) {
        if ( ! isset( $_companies[ $letter ] ) )
            continue;
        $output .= '<li class="company-group"><div id="' . $letter . '" class="company-letter">' . $letter . '</div>';
        $output .= '<ul>';
        foreach ( $_companies[ $letter ] as $company_name ) {
            $count = count( get_posts( array( 'post_type' => 'job_listing', 'meta_key' => '_company_name', 'meta_value' => $company_name, 'nopaging' => true ) ) );
            $output .= '<li class="company-name"><a href="' . $this->company_url( $company_name ) . '">' . esc_attr( $company_name ) . ' (' . $count . ')</a></li>';
        }
        $output .= '</ul>';
        $output .= '</li>';
    }
    foreach ( range( 'А', 'Я' ) as $letter ) {
        if ( ! isset( $_companies[ $letter ] ) )
            continue;
        $output .= '<li class="company-group"><div id="' . $letter . '" class="company-letter">' . $letter . '</div>';
        $output .= '<ul>';
        foreach ( $_companies[ $letter ] as $company_name ) {
            $count = count( get_posts( array( 'post_type' => 'job_listing', 'meta_key' => '_company_name', 'meta_value' => $company_name, 'nopaging' => true ) ) );
            $output .= '<li class="company-name"><a href="' . $this->company_url( $company_name ) . '">' . esc_attr( $company_name ) . ' (' . $count . ')</a></li>';
        }
        $output .= '</ul>';
        $output .= '</li>';
    }

    $output .= '</ul>';
    return $output;
}
Answer 2

"Знаки вопроса на черном фоне" возникают чаще всего из-за вывода мультибайтных символов (кириллица) в однобайтной кодировке.
http://php.net/manual/ru/ref.mbstring.php

пока я этот файл не перевёл в кодировку UTF 8.

В ВП все файлы должны быть в UTF-8 и без BOM.

READ ALSO
На основе каких технологий Вы делаете систему мгновенных сообщений?

На основе каких технологий Вы делаете систему мгновенных сообщений?

Вопрос к тем, кто имеет опыт разработки систем мгновенных сообщений, чатов и аналогичных проектовНа основе какого стека технологий Вы создавали...

207
Как правильно построить отношение в Laravel

Как правильно построить отношение в Laravel

Имеется две таблицы users, check

287
Реализация многопоточности на php

Реализация многопоточности на php

Здравствуйте, есть задача реализовать перебор всех email из сайта и удалить несуществующие

334
Подключить widget без bootstrap.css

Подключить widget без bootstrap.css

Разбираюсь с Yii2Можно ли как то использовать готовый виджет (к примеру https://github

278