WordPress как на ладони
Недорогой хостинг для сайтов на WordPress: wordpress.jino.ru Авторские Темы для WordPress

Как связать посты из двух произвольных типов записей?

Есть два кастомных типа записей WordPress:

  1. Команда
  2. Члены команды

т.е. отдельно формируются посты для команды и для каждого ее члена.

Когда захожу в пост одной команды, то я хочу видеть в одном из табов (в single-team.php) состав ее членов (выборка постов определенных игроков из общего массива постов во втором типе записей с игроками).

Не могу понять как мне теперь сделать увязку?

Как вариант вижу такой выход: сделал таксономию "Команды" со списком всех команд, вывел эту таксономию в оба типа записей (в 1й и во 2й), в постах нужных членов команды выбрал элемент таксономии с нужной командой, например: "Команда 1". Так же в посте "Команда 1" в записи 1 выбрал элемент таксономии "Команда 1". Т.е. и там и там прочекал нужный элемент таксономии.

Но! Я не знаю как теперь мне задать условие, что если данный элемент таксономии выбран одновременно в постах кастомных типов записей 1 (у команды) и 2(членов команды), то вывести посты членов команды в цикле в single-team.php для команды.

Понятно, что придется делать через query_posts. Записи ниже пробовал, работают, но только, если для каждой команды будет свой кастомный тип записей, а так будет выводиться только для одной команды (я так понимаю),а команд ооочень много, поэтому нужна универсальная общая увязка.

$args = array(
	'post_type' => 'team',
	'teams' => 'team1'
);
query_posts( $args );

или

$args = array(
	'tax_query' => array(
		array(
			'taxonomy' => 'teams',
			'field' => 'slug',
			'terms' => 'team1'
		)
	)
);
query_posts( $args );

Может что подскажете мне на этот счет?
Наверняка есть более простое решение.

Заранее благодарю за помощь!

2
Гость
4.6 лет назад
  • 2
    Kama8254

    Понятно, что придется делать через query_posts. Записи ниже пробовал, работают, но только, если для каждой команды будет свой кастомный тип записей

    Это не понял...

    Решение

    Тут их целых 3: через таксономии как ты начал делать; через метаполя; и через поле таблицы записей post_parent

    Я бы сделал через поле post_parent, потому что у нас уже есть и команды и игроки и их просто нужно связать между собой. Причем связь односторонняя - игроки прикрепляются к командам и не наоборот, и у игрока может быть только одна команда. Такая связь просто копия связи записи и её вложений...

    Поэтому предлагаю сделать именно так - это ужасно простой способ получится, без всяких таксономий и метаполей - ничего лишнего. Более того в таблице wp_posts поле post_parent индексное, а значит потом выборка будет очень быстрая...

    Итак, погнали...

    Имеется: тип записи team - команды и типа записи player - игроки. Оба не древовидные.

    // Добавим метабокс выбора команды к игроку
    add_action('add_meta_boxes', function () {
    	add_meta_box( 'palyer_team', 'Команда игрока', 'player_team_metabox', 'player', 'side', 'low'  );
    }, 1);
    
    // метабокс с селектом команд
    function player_team_metabox( $post ){
    	$teams = get_posts(array( 'post_type'=>'team', 'posts_per_page'=>-1, 'orderby'=>'post_title', 'order'=>'ASC' ));
    
    	if( $teams ){
    		// чтобы портянка пряталась под скролл...
    		echo '
    		<div style="max-height:200px; overflow-y:auto;">
    			<ul>
    		';
    
    		foreach( $teams as $team ){
    			echo '
    			<li><label>
    				<input type="radio" name="post_parent" value="'. $team->ID .'" '. checked($team->ID, $post->post_parent, 0) .'> '. esc_html($team->post_title) .'
    			</label></li>
    			';
    		}
    
    		echo '
    			</ul>
    		</div>';
    	}
    	else
    		echo 'Команд нет...';
    }

    Вот и все, готово! smile

    Получим такой метабокс, уже рабочий!

    Рабочий потому что параметр запроса name="post_parent" WodPress обрабатывает автоматом, поэтому дополнительного кода обработки не нужно.

    Вывод

    Теперь, все что остается вывести где нужно игроков команды.

    Для демонстрации вывода, ниже код второго метабокса, но уже для команд. У них будет выводится список её игроков. В лицевой части сайта аналогично выводишь список, оформляешь его как нужно...

    // проверка подключения игрока
    add_action('add_meta_boxes', function(){
    	add_meta_box( 'players', 'Игроки команды', 'team_players_metabox', 'team', 'side', 'low'  );
    }, 1);
    
    function team_players_metabox( $post ){
    	$players = get_posts(array( 'post_type'=>'player', 'post_parent'=>$post->ID, 'posts_per_page'=>-1, 'orderby'=>'post_title', 'order'=>'ASC' ));
    
    	if( $players ){
    		foreach( $players as $player ){
    			echo $player->post_title .'<br>';
    		}
    	}
    	else
    		echo 'Игроков нет...';
    }
    

    У команд получим такой бокс:

    П.С. код писал не просто так, а с проверкой на тестовом сайте, скрины от туда же...

    Dmk17 4.6 лет назад

    Kama, я удивляюсь Вашему уровню компетенции! Искренне благодарен Вам.

    Код работает прекрасно.
    Список игроков выводится правильно.

    В single-team.php (там где вывод поста команды и списка игроков) сделал ссылки на каждый профиль игрока, чтобы можно было перейти в шаблон поста игрока за доп. информацией:

    <a href="<?php the_permalink($player); ?>"><?php echo $player->post_title; ?> </a>

    Пробовал там же вывести вместо ссылок сами посты игроков:

    <?php get_template_part( 'template-parts/content-player', get_post_format() ); ?>

    Но видимо из-за того, что шаблон поста команды и поста игрока имеют много перекрестных моментов, как, например,the_title(), то на посте игрока происходит замена названий от игрока названиями от команды.

    С этим как-то можно справиться?

    Причем связь односторонняя - игроки прикрепляются к командам и не наоборот, и у игрока может быть только одна команда. Такая связь просто копия связи записи и её вложений...

    Возможно ли в моем случае сделать возможность игроку играть в разных командах (это очень часто бывает, команда от города, от работы)?

    Замена радио кнопки на чекбоксы в списке команд не помогла, не сохраняется чекбокс и не выводится второе значение.

    Kama 4.6 лет назад

    С этим как-то можно справиться?

    Можно в этом случае нужно объект $player опредеделить как глобавльную переменную $post

    $players = get_posts(array( 'post_type'=>'player', 'post_parent'=>$post->ID, 'posts_per_page'=>-1, 'orderby'=>'post_title', 'order'=>'ASC' ));
    
    if( $players ){
    	global $post;
    
    	foreach( $players as $post ){
    		setup_postdata($post);
    
    		the_title(); // выводим имя игрока
    	}
    
    	// вернем $post Обратно
    	wp_reset_postdata();
    }

    Возможно ли в моем случае сделать возможность игроку играть в разных командах

    C таким подходом невозможно. Если это нужно очень, то придется переделывать связь на таксономии или метаполя. Тут наверное лучше в метаполя... Сорри время нет писать код этот...

    Логика такая: через метабоксы у игрока также выводим все команды, но теперь чекбоксами. Затем при сохранении сохраняем данные выбранных чеков в метаполе каждой выбранной команды и в метаполе текущего игрока - у команд добавляем ID игрока, у игрока ID команды - все это должно храниться в виде массивов разумеется, нам же по несколько значений нужно сохранять.

    А вывод будет простой, у команды берем метаполе с ID игроков и получаем их по ID с помощью get_posts(). Тоже самое и для игроков.

    Dmk17 4.6 лет назад

    Kama, еще раз Вас благодарю!

    Посты вывелись как нужно.

    За описание шагов так же отдельное спасибо, буду пытаться воспроизвести в коде.

    Dmk17 4.6 лет назад

    Кама, подскажите пожалуйста по возможности.

    Сейчас благодаря вашему коду установлена связь между записями.
    В записи "Команда" идет вывод постов с каждым членом команды (на отдельном табе).

    По аналогии с командой и игроками пробую вывести в посте Игрока пост с Командой, к которой он прикреплен (так же со своим шаблоном).

    Но не получается, видимо из-за направления односторонней связи.

    Пробую так, не работает, я так понимаю, что причине в параметре 'post_parent'=>$post->ID ?

    $teams = get_posts( [
    	'post_type'      => 'team',
    	'post_parent'    => $post->ID,
    	'posts_per_page' => -1,
    	'orderby'        => 'post_title',
    	'order'          => 'ASC',
    ] );
    
    if( $teams ){
    	global $post;
    
    	foreach( $teams as $team ){
    		setup_postdata($post);
    
    		// the_title(); // выводим название команды
    		get_template_part( 'template-parts/content-team', get_post_format() );
    	}
    
    	// вернем $post Обратно
    	wp_reset_postdata();
    }
    Kama 4.6 лет назад

    Блин, тут же ваще просто... ID команды находится в самом объекте игрока!

    На странице игрока:

    // выводим команду у игрока
    $team = get_post( $post->post_parent );
    
    echo esc_html( $team->post_title );
    
    Dmk17 4.6 лет назад

    Спасибо, название команды по вашему коду выводится правильно.

    А почему не срабатывает вывод поста по шаблону?

    Добавление строки ниже не выводит пост команды, а выводит игрока с рваным шаблоном.

    get_template_part( 'template-parts/content-team', get_post_format() );

    Пробовал через цикл, делал глобальной $team, по аналогии как ранее вы писали, выводится уже пост команды по шаблону , но он опять рваный и за ним идут другие посты, тоже с рваным шаблоном.

    Dmk17 4.5 лет назад

    Kama, у меня вся надежда только на Вас)

    Я все хочу вывести в посте игрока его команду тоже в виде поста.

    Код ниже выводит все посты команды по их шаблону, а не его единственную.

    Посмотрите пожалуйста)

    $args = array('post_type'=>'team', $post->post_parent, 'posts_per_page'=>-1, 'orderby'=>'post_title', 'order'=>'ASC' );
    
    $teams = get_posts( $args );
    	if( $teams ){
    		global $post;
    
    		foreach( $teams as $post ){                             
    			setup_postdata($post);
    
    get_template_part( 'template-parts/content-team', get_post_format() );                  
    			}
    			wp_reset_postdata();
    	}
    Kama 4.5 лет назад
    global $post;
    
    // получим команду у игрока
    $post = get_post( $post->post_parent );
    
    // теперь $post это команда игрока
    
    setup_postdata($post); // установим данные
    
    // выводим данные 
    get_template_part( 'template-parts/content-team', get_post_format() );  
    
    wp_reset_postdata(); // вернем $post обратно
    Dmk17 4.5 лет назад

    Kama, просто нет слов, большое спасибо!

    Dmk17 4.5 лет назад

    наткнулся на такую проблему:

    если нужно связать 3 типа записи: например, сейчас связаны команда и игрок (у игрока идет выбор команды).

    А если я сделаю все аналогично и свяжу игрока с 3-ей записью тренер (у игрока идет выбор тренера через радио кнопку также), то радиокнопки у двух метабоксов становятся сквозными, т.е. выбираются и сохраняются только в одном метабоксе.

    Получается, что post_parent дает возможность связать только 2 типа записи?

    Kama 4.5 лет назад

    Ну да... Это же одно поле и туда может быть записать только один ID или команда или тренер. Любое расширение требует другого подхода!

    eLDeR 2.6 лет назад

    Есть 2 типа записей Объекты и Города
    Сопряжение (связь) этих 2х произвольных типов выполнил.. все работает хорошо...
    Подскажите, как обновить информацию поста Объекты на другую ( выбрав из списка город )

    update_post_meta() - обновляет данные метополей
    wp_set_object_terms() - присваивает пост к таксе
    А вот как присвоить город (произвольный тип записи) к Объекту ( Через форму ) я не знаю

    WorldWebs 1.5 года назад

    Спасибо огромное!
    Есть решение как отцепить игрока от команды?
    Сейчас получается, что если выбрал команду, то исключить уже нельзя.

    kudanoff год назад

    Тимур, спасибо за готовый и полезный код!)
    Есть 1 совсем небольшой нюанс, выводится только 1 запись. Я из radio переделал в chekbox, выбрал несколько и у меня выводится лишь 1 последний выбор чекбоксом. Как можно пофиксить?

    Комментировать
  • 0

    Статья очень познавательная и самое главное пример рабочий. Спасибо за материал. smile

    Я не очень люблю использовать сторонние плагины и из-за этого приходится постоянно изобретать велосипед.

    Уважаемые господа, помогите реализовать подобный пример, где:

    • новые типы записи: 2 шт., древовидные
    • новый тип записи: 1 шт., не древовидная
    • связи: многие ко многим для всех 3-ех новых типов записей

    Спасибо!

    vladymyrlem 1 месяц назад

    Спасибо за статью! Вышло вывести, но немного не так как нужно. У меня выходит принцып - Компания имеет акции, и по этому в ней я чекбоксами вместо радио вывожу акции, и в акциях я вижу компании каким они пренадлежат, и в посте самой акции ввыводится перечень компаний. Мне же нужно вывести в каждой компании которой пренадлежит эта акция саму акцию.

    Комментировать
На вопросы могут отвечать только зарегистрированные пользователи. Вход . Регистрация