WordPress как на ладони
Очень Удобный и Быстрый Хостинг для сайтов на 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
Гость
7.5 лет назад
  • 2
    Kama9616

    Понятно, что придется делать через 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 7.5 лет назад

    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 7.5 лет назад

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

    Можно в этом случае нужно объект $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 7.5 лет назад

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

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

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

    Dmk17 7.5 лет назад

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

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

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

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

    Пробую так, не работает, я так понимаю, что причине в параметре '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 7.5 лет назад

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

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

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

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

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

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

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

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

    Dmk17 7.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 7.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 7.5 лет назад

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

    Dmk17 7.4 года назад

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

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

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

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

    Kama 7.4 года назад

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

    Alexei 2 месяца назад

    Как вывести значение metabox? И код получается странный...
    В админке открыл консоль разработчика и увидел следующее

    <label>
    				<input type="radio" name="post_parent" value="17" checked="checked"> Москва
    			</label>
    Комментировать
На вопросы могут отвечать только зарегистрированные пользователи. Вход . Регистрация