WordPress как на ладони
wordpress jino

Метаполя (произвольные поля) для рубрик (таксономий) в WordPress — title, description, keywords…

На сайте есть замечательная статья про создание произвольных полей но вот про метаполя или произвольные поля вроде title для элементов таксономий или терминов или рубрик, меток ничего не нашел.

Подскажите, в какую сторону копать (без плагинов)

3
dmelnik5 2.5 года назад
  • 0
    Kama4697

    Как раз по теме создания таких полей в админ-панели, я описывал хук (taxonomy)_edit_form_fields. Рекомендую к прочтению.

    Шаг 2:

    Шаг 1 устарел с версии WordPress 4.4. поэтому я убрал его вниз ответа...

    Нужно вывести поля при редактировании термина. Для этого предлагаю использовать класс от Миши Рудрастых (я его немного изменил). Добавляем его в functions.php в самое начало или в плагин:

    /*
     * Бэкэнд для добавления настроек на страницу редактирования элементов таксономий
     * Взято из статьи: http://truemisha.ru/blog/wordpress/metadannyie-v-taksonomiyah.html
     * ver 1.2
     * Нужно PHP 5.3+
     */
    class trueTaxonomyMetaBox {
    	private $opt;
    	private $prefix;
    
    	function __construct( $option ) {
    		$this->opt    = (object) $option;
    		$this->prefix = $this->opt->id .'_'; // префикс настроек
    
    		foreach( $this->opt->taxonomy as $taxonomy ){
    			add_action( $taxonomy . '_edit_form_fields', array( &$this, 'fill'), 10, 2 ); // хук добавления полей
    		}
    
    		// установим таблицу в $wpdb, если её нет
    		global $wpdb;
    		if( ! isset( $wpdb->termmeta ) ) $wpdb->termmeta = $wpdb->prefix .'termmeta';
    
    		add_action('edit_term', array( &$this, 'save'), 10, 1 ); // хук сохранения значений полей
    	}
    
    	function fill( $term, $taxonomy ){
    
    		foreach( $this->opt->args as $param ){
    			$def   = array('id'=>'', 'title'=>'', 'type'=>'', 'desc'=>'', 'std'=>'', 'args'=>array() );
    			$param = (object) array_merge( $def, $param );
    
    			$meta_key   = $this->prefix . $param->id;
    			$meta_value = get_metadata('term', $term->term_id, $meta_key, true ) ?: $param->std;
    
    			echo '<tr class ="form-field">';
    				echo '<th scope="row"><label for="'. $meta_key .'">'. $param->title .'</label></th>';
    				echo '<td>';
    
    				// select
    		if( $param->type == 'wp_editor' ){
    		  wp_editor( $meta_value, $meta_key, array(
    			'wpautop' => 1,
    			'media_buttons' => false,
    			'textarea_name' => $meta_key, //нужно указывать!
    			'textarea_rows' => 10,
    			//'tabindex'      => null,
    			//'editor_css'    => '',
    			//'editor_class'  => '',
    			'teeny'         => 0,
    			'dfw'           => 0,
    			'tinymce'       => 1,
    			'quicktags'     => 1,
    			//'drag_drop_upload' => false
    		  ) );
    		}
    		// select
    				elseif( $param->type == 'select' ){
    					echo '<select name="'. $meta_key .'" id="'. $meta_key .'">
    							<option value="">...</option>';
    
    							foreach( $param->args as $val => $name ){
    								echo '<option value="'. $val .'" '. selected( $meta_value, $val, 0 ) .'>'. $name .'</option>';
    							}
    					echo '</select>';
    					if( $param->desc ) echo '<p class="description">' . $param->desc . '</p>';
    				}
    				// checkbox
    				elseif( $param->type == 'checkbox' ){
    					echo '
    						<label>
    							<input type="hidden" name="'. $meta_key .'" value="">
    							<input name="'. $meta_key .'" type="'. $param->type .'" id="'. $meta_key .'" '. checked( $meta_value, 'on', 0) .'>
    							'. $param->desc .'
    						</label>
    					';
    				}
    				// textarea
    				elseif( $param->type == 'textarea' ){
    					echo '<textarea name="'. $meta_key .'" type="'. $param->type .'" id="'. $meta_key .'" value="'. $meta_value .'" class="large-text">'. esc_html( $meta_value ) .'</textarea>';                    
    					if( $param->desc ) echo '<p class="description">' . $param->desc . '</p>';
    				}
    				// text
    				else{
    					echo '<input name="'. $meta_key .'" type="'. $param->type .'" id="'. $meta_key .'" value="'. $meta_value .'" class="regular-text">';
    
    					if( $param->desc ) echo '<p class="description">' . $param->desc . '</p>';
    				}
    				echo '</td>';
    			echo '</tr>';         
    		}
    
    	}
    
    	function save( $term_id ){
    		foreach( $this->opt->args as $field ){
    			$meta_key = $this->prefix . $field['id'];
    			if( ! isset($_POST[ $meta_key ]) ) continue;
    
    			if( $meta_value = trim($_POST[ $meta_key ]) ){
    				update_metadata('term', $term_id, $meta_key, $meta_value, '');
    			}
    			else {
    				delete_metadata('term', $term_id, $meta_key, '', false );
    			}
    		}
    	}
    
    }

    Далее используя добавленный класс, создаем поля для элементов таксономий

    add_action('init', 'register_additional_term_fields');
    function register_additional_term_fields(){ 
    	new trueTaxonomyMetaBox( array(
    		'id'       => 'txseo', // id играет роль префикса названий полей
    		'taxonomy' => array('category','post_tag'), // названия таксономий, для которых нужно добавить ниже перечисленные поля
    		'args'     => array(
    			array(
    				'id'    => 'seo_title', // атрибуты name и id без префикса, получится "txseo_seo_title"
    				'title' => 'SEO Заголовок',
    				'type'  => 'text',
    				'desc'  => 'Укажите альтернативное название термина для SEO.',
    				'std'   => '', // по умолчанию
    			),
    			array(
    				'id'    => 'seo_description',
    				'title' => 'SEO Описание',
    				'type'  => 'text',
    				'desc'  => 'meta тег description.',
    				'std'   => '', // по умолчанию
    			)
    		)
    	) );
    }

    И вот что получиться должно:

    Шаг 3:

    Выводим имеющиеся поля в заголовки рубрик и в head часть документа.

    add_action('wp_head', 'add_taxseo_head_meta_fields');
    function add_taxseo_head_meta_fields(){
    	if( ! is_tax() && ! is_category() && ! is_tag() ) return; // выходим если не таксы
    
    	$term = get_queried_object();
    
    	echo '<meta name="description" content="'. get_metadata('term', $term->term_id, 'txseo_seo_description', 1 ) .'">'. "\n";
    }
    
    //apply_filters( 'wp_title', $title, $sep, $seplocation );
    add_filter('wp_title', 'add_taxseo_wp_title', 20, 3);
    function add_taxseo_wp_title( $title, $sep, $seplocation ){
    	if( ! is_tax() && ! is_category() && ! is_tag() ) return $title; // выходим если не таксы
    
    	$term = get_queried_object();
    	$title = get_metadata('term', $term->term_id, 'txseo_seo_title', 1 );
    
    	return esc_html( $title );
    }

    Можно делать без хуков, а напрямую, тут уже от имеющихся плагинов зависит...

    Главное тут мы получаем метаполя с помощью get_metadata()

    $description = get_metadata('term', $term->term_id, 'txseo_seo_description', 1 )
    $title = get_metadata('term', $term->term_id, 'txseo_seo_title', 1 );
    
    // с версии WP 4.4 можно использовать встроенные функции 
    $description = get_term_meta( $term->term_id, 'txseo_seo_description', 1 );
    $title = get_term_meta( $term->term_id, 'txseo_seo_title', 1 );

    Шаг 1: (с версии WP 4.4 не нужен)

    Тут главная проблема, что некуда записывать данные. Во многих источниках данные пишут в опции, а это плохо. Хорошо если создать специальную таблицу метаданных для таксономий.

    Этот шаг не нужен с версии 4.4. В этой версии, наконец, была создана таблица метаполей для элементов таксономий! Поэтому если у вас WP 4.4 и выше, переходите сразу к шагу 2.

    Запускаете один раз эту функцию, потом код можно удалить. Для запуска можно в functions.php сунуть:

    ## Функция создания таблицы метаданных таксономий, вешается на register_activation_hook()
    # register_activation_hook( __FILE__, 'create_termmeta_table');
    function create_termmeta_table(){
    	global $wpdb;
    
    	$charset_collate = '';  
    	if ( ! empty($wpdb->charset) )
    		$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
    	if ( ! empty($wpdb->collate) )
    		$charset_collate .= " COLLATE $wpdb->collate";
    
    	/*
    	 * Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
    	 * As of 4.2, however, we moved to utf8mb4, which uses 4 bytes per character. This means that an index which
    	 * used to have room for floor(767/3) = 255 characters, now only has room for floor(767/4) = 191 characters.
    	 */
    	$max_index_length = 191;
    
    	$tables = $wpdb->get_results("show tables like '{$wpdb->prefix}termmeta'");
    	if (!count($tables)){
    		$wpdb->query("CREATE TABLE {$wpdb->prefix}termmeta (
    			meta_id bigint(20) unsigned NOT NULL auto_increment,
    			term_id bigint(20) unsigned NOT NULL default '0',
    			meta_key varchar(255) default NULL,
    			meta_value longtext,
    			PRIMARY KEY (meta_id),
    			KEY term_id (term_id),
    			KEY meta_key (meta_key($max_index_length))
    		) $charset_collate;");
    	}
    }
    
    // запуск
    create_termmeta_table();

    Эта функцию создаст новую таблицу в БД, termmeta - термины для таксономий.

    Подробнее в этой статье: http://wp-kama.ru/id_5150/taxonomy-metadata-metadannyie-dlya-taksonomiy.html

    Теперь у нас есть куда записывать данные таксономий.

    dmelnik 2.5 года назад

    в теории все понятно, как раз то, что было нужно.

    Но вот на практике - не работает. Данные не сохраняются.

    В этой статье: также было упомянуто про создание поля для картинки в рубриках, было бы здорово реализовать еще и это. Сейчас потыкаю на тестовом варианте, может что и получится.

    сейчас вывод title для записей и страниц происходит вот так:

    <?php if ( get_post_meta($post->ID, 'title', true) ) :
    	echo get_post_meta($post->ID, 'title', true);
    else :
    	wp_title('-', true, 'right'); ?><?php bloginfo('name');
    endif; ?>

    также, в header.php вывод мета для страниц и записей

    <meta name="description" content="<?php echo get_post_meta($post->ID, 'description', true); ?>" />
    <meta name="keywords" content="<?php echo get_post_meta($post->ID, 'keywords', true); ?>" />

    Как возможно подставить вывод сюда, с прописанием условий для категорий? а то запутался

    Kama 2.5 года назад

    >> Но вот на практике - не работает. Данные не сохраняются.

    Как это не сохраняются, я проверял код у меня все работало...

    Что касается вывода, то созданные метаполя выводятся так:

    <?php echo get_metadata('term', $term->term_id, 'term_seo_description', 1 ); ?>

    Это вывод для поля seo_description

    И т.д. по аналогии. Выводите где нужно и как нужно. Перед выводом проверьте что вы находитесь на странице рубрики. В общем этот код есть в ответе, изучайте...

    dmelnik 2.5 года назад

    Таблица wp_termmeta создалась, тут все ок, поля в таблице: meta_id, term_id, meta_key, meta_value. Доп. поля в рубрике тоже создались, все как на картинке, выложенной Вами. Но вот при редактировании рубрики, таблица остается пустой т.е.: вбиваем в соответствующие поля в рубрике что-либо, кликаем "сохранить", заходим в рубрику заново, и видим эти поля пустыми. В бд данные также не заносятся

    Kama 2.5 года назад

    Ой, извиняюсь! Я же забыл зарегистрировать название таблицы. Обновил класс trueTaxonomyMetaBox до версии v1.1, там строки добавил:

    // установим таблицу в $wpdb, если её нет
    		global $wpdb;
    		if( ! isset( $wpdb->termmeta ) ) $wpdb->termmeta = $wpdb->prefix .'termmeta';
    dmelnik 2.5 года назад

    здорово, работает. Только Вы ошиблись: поле в таблице по выше написанному коду не "term_seo_description", а "txseo_seo_description". Получилось что-то вроде вот этого:

    <meta name="description" content="<?php if( ! is_tax() && ! is_category() && ! is_tag() ) return; // выходим если не таксы
    
    	$term = get_queried_object(); echo get_metadata('term', $term->term_id, 'txseo_seo_description', 1 ); ?>" />

    Осталось дописать вывод в else стандартного сценария вывода доп полей. Спасибо большое!

    dmelnik 2.4 года назад

    ага, все вместе получилось так:

    <meta name="description" content="<?php
    	if( is_tax() || is_category() || is_tag() ) { //выводим, если страница архива, категории или страница меток
    		$term = get_queried_object(); // магия
    		echo get_metadata('term', $term->term_id, 'txseo_seo_description', true ); // собственно, сам вывод
    	}
    	else { // если что-то другое (страница или запись)
    		echo get_post_meta($post->ID, 'description', true);
    	}
    ?>" />
    speker 11 месяцев назад

    Для тех кто использует All in One Seo Pack третий шаг нужно изменить

    add_action('init', 'register_additional_term_fields');
    function register_additional_term_fields(){ 
    	new trueTaxonomyMetaBox( array(
    		'id'       => 'txseo', // id играет роль префикса названий полей
    		'taxonomy' => array('category','post_tag'), // названия таксономий, для которых нужно добавить ниже перечисленные поля
    		'args'     => array(
    			array(
    				'id'    => 'seo_title', // атрибуты name и id без префикса, получится "txseo_seo_title"
    				'title' => 'SEO Заголовок',
    				'type'  => 'text',
    				'desc'  => 'Укажите альтернативное название термина для SEO.',
    				'std'   => '', // по умолчанию
    			),
    			array(
    				'id'    => 'seo_description',
    				'title' => 'SEO Описание',
    				'type'  => 'text',
    				'desc'  => 'meta тег description.',
    				'std'   => '', // по умолчанию
    			)
    		)
    	) );
    }
    
    add_filter('aioseop_description', 'add_taxseo_head_meta_fields');
    function add_taxseo_head_meta_fields($descr){
    	if( ! is_tax() && ! is_category() && ! is_tag() ) return $descr; // выходим если не таксы
    
    	$term = get_queried_object();
    	$descr = get_metadata('term', $term->term_id, 'txseo_seo_description', 1 );
    
    	return $descr;
    }
    
    //apply_filters( 'wp_title', $title, $sep, $seplocation );
    add_filter('aioseop_title', 'add_taxseo_wp_title', 5, 3);
    function add_taxseo_wp_title( $title, $sep, $seplocation ){
    	if( ! is_tax() && ! is_category() && ! is_tag() ) return $title; // выходим если не таксы
    
    	$term = get_queried_object();
    	$title = get_metadata('term', $term->term_id, 'txseo_seo_title', 1 );
    
    	return esc_html( $title );
    }
    Василий 4 месяца назад

    Доброго времени суток!

    Подскажите, пожалуйста, тема еще жива?

    Возникли некоторые трудности, точнее, недопонимания в выводе поля с данными на странице. В админке есть, а вот на сайте уже нет данных...

    Kama 4 месяца назад

    Жива, жива...

    Василий 3 месяца назад

    Доброго времени суток!

    А можете подсказать, почему поля в админке работают, а на сайте данные не выводятся? если делать через var_dump то там где должны быть значения поля выводится bool(false). Никак не пойму, где и что я делаю не так?!

    Поле нужно для категорий woocommerce. вывод поля есть, а данных нет sad

    Kama 3 месяца назад

    Название поля правильно передаешь? Не должно быть так, что-то не так делаешь...

    vasily-2208 3 месяца назад

    Мне код здесь указать или как правильнее?

    В целом я ничего не менял, за исключением того, что добавил 'product_cat' в код, для отображения полей

    vasily-2208 3 месяца назад

    В общем мои попытки вывести значения в поле, так и не увенчались успехом sad

    Я все делал, как указано в статье выше, шаг №1 не трогал.

    В коде

    // Создаем поля для custom fields
    add_action('init', 'register_additional_term_fields');
    function register_additional_term_fields(){
    	new trueTaxonomyMetaBox( array(
    		'id'       => 'txseo', // id играет роль префикса названий полей
    		'taxonomy' => array('product_cat','category','post_tag'), // названия таксономий, для которых нужно добавить ниже перечисленные поля
    		'args'     => array(
    			array(
    				'id'    => 'seo_title', // атрибуты name и id без префикса, получится "txseo_seo_title"
    				'title' => 'SEO Заголовок',
    				'type'  => 'text',
    				'desc'  => 'Укажите альтернативное название термина для SEO.',
    				'std'   => '', // по умолчанию
    			),
    			array(
    				'id'    => 'seo_description',
    				'title' => 'SEO Описание',
    				'type'  => 'text',
    				'desc'  => 'meta тег description.',
    				'std'   => '', // по умолчанию
    			)
    		)
    	) );
    }

    добавил 'product_cat', чтобы в админке появились поля.

    больше ничего не менял.

    Вывод в нужном месте делаю вот так

    function woocommerce_template_loop_category_title( $category ) {
    	?>
    			<h2 class="woocommerce-loop-category__title">
    				<?php
    					echo $category->name;
    
    					if ( $category->count > 0 ) {
    						echo apply_filters( 'woocommerce_subcategory_count_html', ' <mark class="count">(' . $category->count . ')</mark>', $category );
    					}
    				?>
    // Мое поле
    <title><?php echo get_term_meta( $term->term_id, 'txseo_seo_title', 1 ) ; ?></title>
    			</h2>
    		<?php
    	}

    Где же я косячу?!

    vasily-2208 3 месяца назад

    Доброго времени суток!

    Подскажите, пожалуйста, а все шаги нужно прописывать в function.php, за исключением вывода созданных полей?!

    Василий 2 месяца назад

    Доброго времени суток!
    А за темой еще кто-то следит?

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

    Да вроде, что за тема? smile

    Василий 2 месяца назад

    Которая описана выше )))

    Теперь я не понимаю вообще ничего. На другом шаблоне вообще ничего не выводится на сайте. Если на старом шаблоне ошибку выдавало, то теперь вообще нет ничего. Хотя в админке в нужном месте поля есть и данные в них сохраняются.

    Как быть и куда копать, понять не могу...

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

    Я этот код не использую, возможно что-то отвалилось, как время будет гляну. Но по идее должно работать все.

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

    Уважаемые WordPresserы, подскажите, только у меня PHP ругается "Parse error: syntax error, unexpected ':'" на тернарный оператор "?:" в "Шаг 2:" строка

    $meta_value = get_metadata('term', $term->term_id, $meta_key, true ) ?: $param->std;

    WordPress Версия 4.6.1 (первый шаг пропускаю, начинаю со второго...)

    Пробовал:

    $meta_value = get_metadata('term', $term->term_id, $meta_key, true ) ? '' : $param->std;
    $meta_value = $param->std;

    Оба варианта не работают, когда открываю для редактирования терм таксономии через админку, мета-боксы не появляются...

    Kama год назад

    PHP версия какая? Тут 5,3+ надо...

    Замену написал неправильно! Надо так:

    $meta_value = ($var=get_metadata('term', $term->term_id, $meta_key, true )) ? $var : $param->std;
    Stepan год назад

    Я не писал замену, просто хотел проверить код на работоспособность без этого тернарного оператора... может слишком по-дилетантскии)

    Спасибо автору проекта за труды, очень полезный ресурс!

    Комментировать
  • 0
    seo-frog cайт: seo-frog.com @

    Парни, подскажите, как к этим полям вывести редактор?
    И ещё, что порекомендуете - использовать миниатюры для вывода картинки или использовать прямую ссылку?

    Kama 4 месяца назад

    Смотри wp_editor(). Юзай лучше миниатюру, а сохраняй ID вложения а не ссылку...

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