Запрос relationship-полей

Обзор

В этом руководстве будут рассмотрены приёмы запроса relationship-полей в обоих направлениях. В качестве примера будут использованы «Врачи» и «Локации».

Скриншоты

Чтобы сэкономить время, в этом руководстве не рассматривается процесс настройки двух типов записей и их пользовательских полей. Однако приведённые ниже скриншоты показывают данные, с которыми мы будем работать.

archive-doctor.php

Сначала мы создадим в нашей теме шаблонный файл для отображения всех врачей. Этот файл называется «archive-doctor» и его можно открыть по адресу «http://website.com/?post_type=doctor» или «http://website.com/doctor» в зависимости от структуры постоянных ссылок.

Скриншот

Код

<?php 
/**
 * Шаблон для отображения страниц архива.
 *
 * Тема: Twenty Eleven
 */

get_header(); ?>

    <section id="primary">
        <div id="content" role="main">

        <?php if ( have_posts() ) : ?>

            <header class="page-header">
                <h1 class="page-title">Врачи</h1>
            </header>

            <?php twentyeleven_content_nav( 'nav-above' ); ?>

            <?php /* Начало цикла */ ?>
            <?php while ( have_posts() ) : the_post(); ?>

                <article>
                    <header class="entry-header">
                        <?php 

                        $photo = get_field('photo');

                        ?>
                        <h1 class="entry-title">
                            <a href="<?php the_permalink(); ?>">
                                <img class="alignleft" src="<?php echo $photo['url']; ?>" alt="<?php echo $photo['alt']; ?>" width="50" />
                                <?php the_title(); ?>
                            </a>
                        </h1>
                    </header>
                </article>

            <?php endwhile; ?>

            <?php twentyeleven_content_nav( 'nav-below' ); ?>

        <?php endif; ?>

        </div><!-- #content -->
    </section><!-- #primary -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>

single-doctor.php

Далее мы создадим шаблонный файл для просмотра информации о каждом враче. На этой странице шаблона мы выведем ссылки на локации, где работает этот врач.

Скриншот

Код

<?php
/**
 * Шаблон для отображения одиночных записей.
 *
 * Тема: Twenty Eleven
 */

get_header(); ?>

    <div id="primary">
        <div id="content" role="main">

            <?php while ( have_posts() ) : the_post(); ?>

                <article>
                    <header class="entry-header">
                        <h1 class="entry-title"><?php the_title(); ?></h1>
                    </header>

                    <div class="entry-content">
                        <h2>Фото</h2>
                        <?php 

                        $photo = get_field('photo');

                        ?>
                        <img class="alignleft" src="<?php echo $photo['url']; ?>" alt="<?php echo $photo['alt']; ?>" />

                        <h2>Работает в</h2>
                        <?php 

                        $locations = get_field('location');

                        ?>
                        <?php if( $locations ): ?>
                            <ul>
                            <?php foreach( $locations as $location ): ?>
                                <li>
                                    <a href="<?php echo get_permalink( $location->ID ); ?>">
                                        <?php echo get_the_title( $location->ID ); ?>
                                    </a>
                                </li>
                            <?php endforeach; ?>
                            </ul>
                        <?php endif; ?>

                    </div>

                </article>

            <?php endwhile; // конец цикла. ?>

        </div><!-- #content -->
    </div><!-- #primary -->

<?php get_footer(); ?>

single-location.php

И наконец, мы создадим шаблонный файл для одиночной локации (поскольку теперь мы можем перейти на эту страницу из записи врача). Пока что мы создали простую двунаправленную связь между локациями и врачами. Теперь мы сделаем обратное. На каждой странице локации мы запросим базу данных WP для всех врачей, которые работают в этой локации.

Это будет реализовано с помощью функции «get_posts». Эта функция использует класс WP_Query для получения записей. См. раздел параметров в документации WP_Query для списка параметров, которые принимает эта функция.

Скриншот

Код

<?php
/**
 * Шаблон для отображения одиночных записей.
 *
 * Тема: Twenty Eleven
 */

get_header(); ?>

    <div id="primary">
        <div id="content" role="main">

            <?php while ( have_posts() ) : the_post(); ?>

                <article>
                    <header class="entry-header">
                        <h1 class="entry-title"><?php the_title(); ?></h1>
                    </header>

                    <div class="entry-content">
                        <h2>Адрес</h2>
                        <p><?php the_field('address'); ?></p>

                        <h2>Врачи, которые работают здесь</h2>
                        <?php 

                        /*
                        *  Запрос записей по значению relationship-поля.
                        *  Этот метод использует meta_query LIKE, чтобы сопоставить строку "123" со значением в базе данных a:1:{i:0;s:3:"123";} (сериализованный массив)
                        */

                        $doctors = get_posts(array(
                            'post_type' => 'doctor',
                            'meta_query' => array(
                                array(
                                    'key' => 'location', // имя пользовательского поля
                                    'value' => '"' . get_the_ID() . '"', // точно соответствует "123", а не просто 123. Это предотвращает совпадение с "1234"
                                    'compare' => 'LIKE'
                                )
                            )
                        ));

                        ?>
                        <?php if( $doctors ): ?>
                            <ul>
                            <?php foreach( $doctors as $doctor ): ?>
                                <?php 

                                $photo = get_field('photo', $doctor->ID);

                                ?>
                                <li>
                                    <a href="<?php echo get_permalink( $doctor->ID ); ?>">
                                        <img src="<?php echo $photo['url']; ?>" alt="<?php echo $photo['alt']; ?>" width="30" />
                                        <?php echo get_the_title( $doctor->ID ); ?>
                                    </a>
                                </li>
                            <?php endforeach; ?>
                            </ul>
                        <?php endif; ?>

                    </div>

                </article>

            <?php endwhile; // конец цикла. ?>

        </div><!-- #content -->
    </div><!-- #primary -->

<?php get_footer(); ?>

Понимание запроса

Приведённый выше запрос «get_posts» находит все записи типа «doctor». Затем он находит пользовательское поле «location» для каждого врача и выполняет запрос LIKE по его значению.

Relationship-поле сохраняет свои данные в виде сериализованного массива. Если вы не знакомы с этим форматом, посмотрите значение, которое хранится в вашей базе данных. Оно будет выглядеть примерно так:

  • a:2:{i:0;s:2:”35″;i:1;s:2:”33″;}

В этом сериализованном массиве два значения: первое — «35», второе — «33». Поскольку это поле «location» для «doctor», эти два числа должны быть ID типов записей локаций.

В нашем запросе значение LIKE было ‘”‘ . get_the_ID() . ‘”‘; если ID локации был 35, то значение LIKE стало бы ‘”35″‘. В этом случае запрос совпадёт со значением location у врача (сериализованный массив, показанный выше), и врач будет возвращён.

 

Обновлено: 01.06.2026