Как избежать распространенных ошибок при работе с WordPress

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

1. Не изобретайте велосипед

Будьте осторожны, когда создаете функцию, которая выполняет почти то же самое, что и другая функция. Чем более изощренный код вы добавляете, тем сложнее его поддерживать.

Я ошибался, думая, что пишу DRY-код. Например, я создавал функцию с именем get_portfolio_part($name, $slug). Это оболочка, которая избавляет меня от написания часто повторяющейся get_template_part(“portfolio/$name”, $slug). Это почти то же самое, что и оригинал, однако это усложняет базу кода.

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

2. Перестаньте предсказывать будущее

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

function has_social_icon($icon) {
$icons = get_post_meta(get_the_ID(), 'post_social_icons', true);
// делаем то, что нам нужно сделать с $icons
return true;
}

Но что, если когда-нибудь в будущем я захочу использовать эту функцию за пределами цикла? Для этого пришлось изменить код примерно так:

function has_social_icon($icon, $post_id = 0) {
if( ! $post_id ) {
$post_id = get_the_ID();
}
$icons = get_post_meta($post_id, 'post_social_icons', true);
// делаем то, что нам нужно сделать с $icons
return true;
}

Мы создали абсолютно ненужный раздутый код во имя несуществующего будущего. Не делай этого! Осуществляйте рефакторинг, исходя из реальных потребностей, а не гипотетических сценариев.

3. Преждевременная оптимизация — это корень всех зол

Вы когда-нибудь делали что-то наподобие этого?

<?php
$post_id = get_the_ID(); // смотрите - я повторно использую ID, экономя 1 вызов функции!
$thumb = get_the_post_thumbnail( $post_id, 'large'); // смотрите - я экономлю еще один вызов функции! Ура!
?>
<div id="post-<?php echo $post_id ?>"
<?php if( $thumb ): ?>
<div class="thumbnail">
<?php echo $thumb ?>
</div>
<?php endif; ?>
</div>

Присвоение значения переменной, поскольку вы используете это значение дважды, сэкономит 0.000002 мс и 0 мс, когда этот запрос будет кэширован. А это произойдет в подавляющем большинстве случаев при оптимизации производительности.

Вот более простой способ реализации:

<div id="post-<?php the_ID() ?>"
<?php if( has_post_thumbnail() ): ?>
<div class="thumbnail">
<?php the_post_thumbnail('large') ?>
</div>
<?php endif; ?>
</div>

Да, это связано с двумя дополнительными вызовами функций. Но производительность кода при этом сильно не пострадает.

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

4. Избегайте использования переменных в файлах шаблонов

Попытайтесь полностью избегать использования переменных в файлах шаблонов. Вот простой пример.

<?php
$logo_url = false;
$thumbnail_url = wp_get_attachment_image_src( get_theme_mod( 'hypthetical_theme_logo' ), 'full' );
if( $thumbnail_url ) {
$logo_url = $thumbnail_url[0];
}
?>
<?php if( $logo_url ): ?>
<a href="<?php echo esc_url( home_url() ); ?>" title="<?php bloginfo( 'name' ); ?>" class="custom-logo">
<img src="<?php echo $logo_url; ?>" />
</a>
<?php endif; ?>

Этот код находится где-то внутри файла header.php. Он выглядит грязным, особенно когда обернут в несколько блоков div с отступами. Тем более что файлы шаблонов должны просто отображать контент, а не извлекать или анализировать его.

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

<?php if( hypotheme_has_logo() ): ?>
<a href="<?php echo esc_url( home_url() ); ?>" title="<?php bloginfo( 'name' ); ?>" class="custom-logo">
<img src="<?php hypotheme_the_logo_url() ?>" />
</a>
<?php endif; ?>

Это намного проще читать, и мы избегаем ненужного беспорядка. Если кто-то хочет знать, откуда берется логотип, он может посмотреть файл функций. Теперь логика отделена от представления.

Вот еще один пример:

<?php
/**
* page.php
*/
?>
<?php get_header(); ?>
<?php
$hypotheme_sidebar      = hypotheme_get_option( 'hypotheme_sidebar' );
$hypotheme_sidebar_size = hypotheme_get_option( 'hypotheme_sidebar_size' );
?>
<?php while ( have_posts() ) : the_post(); ?>
<div class="row two-columns">
<?php if ( $hypotheme_sidebar == 1 ): ?>
<div class="main-column <?php if ( $hypotheme_sidebar_size == 0 ) { ?> col-md-6 <?php } else { ?> col-md-7 <?php } ?>">
<?php else: ?>
<div class="main-column col-md-12">
<?php endif; ?>
<div id="page-<?php the_ID(); ?>" <?php post_class( 'entry-page' ); ?>>
<h1 class="entry-title"><?php the_title(); ?></h1>
<div class="entry-content"><?php the_content(); ?></div>
</div>
<?php if ( comments_open() ) : ?>
<?php comments_template(); ?>
<?php endif; ?>
</div>
<?php if ( $hypotheme_sidebar == 1 ) {
get_sidebar();
} ?>
</div>
<?php endwhile; ?>
<?php get_footer(); ?>

Шаблон, вероятно, не является единственным шаблоном в этой теме с боковой панелью. Поэтому эти переменные присутствуют во всех файлах шаблонов, в которых есть боковая панель.

Здесь логика не только смешивается с представлением, но и повторяется во всех файлах шаблонов (page.php, single.php, index.php и т. д.). Это большой объем кода, который можно удалить:

<?php
/**
* page.php
*/
?>
<?php get_header(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<div class="row two-columns">
<div class="main-column <?php echo hypotheme_container_width_class() ?>">
<div id="page-<?php the_ID(); ?>" <?php post_class( 'entry-page' ); ?>>
<h1 class="entry-title"><?php the_title(); ?></h1>
<div class="entry-content"><?php the_content(); ?></div>
</div>
<?php if ( comments_open() ) : ?>
<?php comments_template(); ?>
<?php endif; ?>
</div>
<?php get_sidebar(); ?>
</div>
<?php endwhile; ?>
<?php get_footer(); ?>

Это проще для чтения и понимания. Функции помогают сделать код легко читаемым и расширяемым, если они используются в сочетании с шаблонами WordPress Hooks.

Не бойтесь создавать несколько файлов, в которых можно хранить все функции шаблона. Не сваливайте все в файл functions.php.

5. Будьте в курсе последних тенденций

WordPress постоянно развивается. Будьте в курсе актуальных практик.

Я лично видел темы, представленные в этом году на WordPress.org, которые все еще используют wp_print_styles вместо wp_enqueue_scripts. Хотя wp_print_styles устарел, начиная с версии WordPress 3.3.

6. Используйте оригинальные функции WordPress, когда это возможно

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

Если будете в курсе последних новшеств WordPress, то сможете обнаружить, что пример для «Ошибки №4» можно полностью заменить оригинальными функциями WordPress, начиная с версии WordPress 4.5. Так как WordPress теперь изначально поддерживает функционал пользовательского логотипа.

<?php if( has_custom_logo() ): ?>
<a href="<?php echo esc_url( home_url() ); ?>" title="<?php bloginfo( 'name' ); ?>" class="custom-logo">
<img src="<?php the_custom_logo() ?>" />
</a>
<?php endif; ?>

Вот еще один пример.

При разработке навигации по записям я воспользовался функцией get_next_post и скопировал что-то подобное в свою тему:

<?php
$next_post = get_next_post();
if (!get_next_post()): ?>
<a href="<?php echo esc_url( get_permalink( $next_post->ID ) ); ?>"><?php echo esc_attr( $next_post->post_title ); ?></a>
<?php endif; ?>

И что не так? Прежде всего, если вы не до конца уверены в том, что делаете, не обращайтесь к свойствам объекта. В этом случае лучше использовать функцию get_the_title(). С ее помощью вы корректно извлечете заголовок, расширите «Private / Protected» и примените фильтр the_title.

// сделайте это:
echo get_the_title( $next_post )
// вместо этого:
echo $next_post->post_title

Есть функция WordPress next post link, и вы можете заменить весь приведенный выше код простым вызовом функции:

<?php next_post_link() ?>

7. Не создавайте собственный фреймворк

Я против создания «фреймворка для себя», а не фреймворков в принципе. Существуют хорошо поддерживаемые фреймворки, такие как тема Genesis или Sage by Roots.

Ниже я опишу несколько проблем и побочных эффектов построения фреймворка для себя:

Проблемы обслуживания

Создание «фреймворка» добавляет дополнительную базу кода, которую нужно обслуживать. Если среда размещается в каталоге /inc/me-framework, вам придется обновлять все свои темы, использующие этот фреймворк, когда выпускается обновление для него.

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

Территория плагинов

Темы должны задавать красивые макеты и определять их стили. Файлы тем должны заполняться настройками, прикрепляться к хукам и использовать теги шаблонов, которые предоставляют либо плагины, либо ядро ​​WordPress. Если почувствуете необходимость использования PHP-классов, вы зайдете на территорию плагинов.

Создайте плагин, сделайте его легко настраиваемым и задайте для него стили в своей теме. Таким образом, вы не только избежите создания фреймворка, но и сможете внести свой вклад в развитие open-source сообщества!

Заключение

WordPress имеет собственные стандарты написания кода и создания тем. Поэтому лучше придерживаться «способа WordPress», даже если это не самый оптимальный вариант.

Не повторяйте моих ошибок. Я надеюсь, что эта статья поможет вам создавать отличные WordPress-темы!

 

Перевод статьи «How To Prevent Common WordPress Theme Mistakes»  был подготовлен дружной командой проекта Сайтостроение от А до Я