Почему появляются ошибки "undefined_index" и как их исправить?
Я буквально бьюсь головой об стену. Уверен, что это что-то очень простое, но я постоянно получаю ошибки undefined index для всех этих переменных.
function meta_genus_species() {
global $post;
if (isset($post)) {
$custom = get_post_custom($post->ID);
}
if (isset($custom)) {
$genus = $custom["genus"][0]; // Получаем значение рода
$species = $custom["species"][0]; // Получаем значение вида
$etymology = $custom["etymology"][0]; // Получаем этимологию
$family = $custom["family"][0]; // Получаем семейство
$common_names = $custom["common_names"][0]; // Получаем распространенные названия
}
?>
<label>Род:</label>
<input name="genus" value="<?php if(isset($genus)) { echo $genus; } ?>" />
<label>Вид:</label>
<input name="species" value="<?php if(isset($species)) { echo $species; } ?>" />
<p><label>Этимология:</label><br />
<textarea cols="50" rows="5" name="etymology"><?php if(isset($etymology)) { echo $etymology; } ?></textarea></p>
<label>Семейство:</label>
<input name="family" value="<?php if(isset($family)) { echo $family; } ?>" />
<label>Распространенные названия:</label>
<input name="common_names" value="<?php if(isset($common_names)) { echo $common_names; } ?>" />
<?php
}
Я получаю эту ошибку для каждой переменной:
Notice: Undefined index: genus в [...]sf-species-profiles.php на строке 207
Есть идеи?

Это распространённая ошибка в PHP, которая возникает при попытке обратиться к несуществующему ключу массива:
$array = array( 'hello' => 'world' );
echo $array['foobar']; // неопределённый индекс
Сначала следует проверить наличие ключа с помощью isset( $array['foobar'] );
ОБНОВЛЕНИЕ: В данном случае я бы использовал цикл, который автоматически устанавливает переменные, проверяя индексы в процессе:
foreach ( array( 'genus', 'species', 'etymology', 'family', 'common_names' ) as $var )
$$var = isset( $custom[ $var ][0] ) ? $custom[ $var ][0] : '';
echo $genus; // выводит значение $custom['genus'][0], если оно существует, иначе пустую строку

Вы предлагаете использовать isset на каждой строке, например (псевдокод) isset($custom[genus]) > $genus=$custom[genus]? Неужели это чертовски долгий способ делать вещи? Я был под впечатлением (и это первый раз, когда я столкнулся с этой проблемой), что использование isset на $post, а затем и на $custom означало бы, что эти переменные не установлены/не существуют, если в $post нет данных?

Вы уже вызываете isset() каждый раз при выводе данных на экран.
Почему бы просто не пропустить эту часть:
if (isset($custom)) {
$genus = $custom["genus"][0];
$species = $custom["species"][0];
$etymology = $custom["etymology"][0];
$family = $custom["family"][0];
$common_names = $custom["common_names"][0];
}
и делать так при выводе в поле ввода:
<label>Род:</label>
<input name="genus" value="<?php if( isset( $custom["genus"][0] ) ) { print $custom["genus"][0]; } ?>" />
Дополнительные присваивания переменных не нужны и вызывают появление уведомлений здесь.
Кстати...
Вам нужно экранировать вывод перед тем, как он будет отображен в форме:
<label>Род:</label>
<input name="genus" value="<?php if(isset($genus)) { echo esc_attr( $genus ); } ?>" />
<label>Вид:</label>
<input name="species" value="<?php if(isset($species)) { echo esc_attr( $species ); } ?>" />
<p><label>Этимология:</label><br />
<textarea cols="50" rows="5" name="etymology"><?php if(isset($etymology)) { echo esc_textarea( $etymology ); } ?></textarea></p>
<label>Семейство:</label>
<input name="family" value="<?php if(isset($family)) { echo esc_attr( $family ); } ?>" />
<label>Общие названия:</label>
<input name="common_names" value="<?php if(isset($common_names)) { echo esc_attr( $common_names ); } ?>" />

Да, я не заморачиваюсь с экранированием, пока код не заработает.. :) Я действительно думал сделать так, как вы предложили, но я немного фанатею за эстетику кода и, Боже мой, как же это ужасно выглядит! Спасибо.

Видимо, мы разные... Я не вывожу ничего на экран, пока данные не экранированы, и никогда не добавляю ненужной сложности, чтобы код выглядел "красиво".

ЛОЛ! По моему скромному мнению, взломанные сайты с фармацевтическими ссылками в футере выглядят куда ужаснее этого кода. ;)

Не зацикливайтесь на том, что $custom["genus"][0]
выглядит "менее красиво", чем $genus
. Код @mfields в остальном абсолютно идентичен вашему, но при этом не вызовет ошибку. Пишите столько кода, сколько необходимо для решения задачи, не больше и не меньше.

Альтернативный вариант, который появился в обсуждении этого поста в Twitter, заключается в изменении способа получения данных. Функция get_post_custom()
возвращает массив массивов, что и вызывает у вас сложности. Вместо неё я рекомендую использовать get_post_custom_values()
:
function meta_genus_species() {
global $post;
$genus = get_post_custom_values( 'genus', $post->ID );
$species = get_post_custom_values( 'species', $post->ID );
$etymology = get_post_custom_values( 'etymology', $post->ID );
$family = get_post_custom_values( 'family', $post->ID );
$common_names = get_post_custom_values( 'common_names', $post->ID );
?>
<label>Род:</label>
<input name="genus" value="<?php if(isset($genus[0])) { echo esc_attr( $genus[0] ); } ?>" />
<label>Вид:</label>
<input name="species" value="<?php if(isset($species[0])) { echo esc_attr( $species ); } ?>" />
<p><label>Этимология:</label><br />
<textarea cols="50" rows="5" name="etymology"><?php if(isset($etymology[0])) { echo esc_attr( $etymology ); } ?></textarea></p>
<label>Семейство:</label>
<input name="family" value="<?php if(isset($family[0])) { echo esc_attr( $family ); } ?>" />
<label>Обычные названия:</label>
<input name="common_names" value="<?php if(isset($common_names[0])) { echo esc_attr( $common_names ); } ?>" />
<?php
}
Более удачной альтернативой для получения пользовательских значений может быть использование пользовательских метаполей. Вы можете определить их как уникальные, и тогда при извлечении из базы данных вы получите одно значение вместо индексированного массива с единственным элементом. Это стоит учитывать.
