WordPress как на ладони
WordPress темы и плагины за 250 рублей wordpress jino

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

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

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

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

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

1
Гость
1.6 год назад
  • 1
    Kama5395

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

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

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

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

    Dmk17 1.6 год назад

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

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

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

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

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

    $teams = get_posts(array( '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 1.6 год назад

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

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

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

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

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

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

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

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

    Dmk17 1.6 год назад

    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 1.6 год назад
    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 1.6 год назад

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

    Dmk17 1.5 год назад

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

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

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

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

    Kama 1.5 год назад

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

    Артем 29 дней назад

    Кama, добрый день, посмотрел ваш код, все отлично для меня подошло, только вопрос, как во фронте вывести плитку с турами как тут https://skyteam.by
    вот в этом коде

    Если делать вот так, то выводит все туры полностью

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