Статьи

Как создать WordPress тему с нуля: основы

В этом руководстве мы подробно рассмотрим структуру файлов тем WordPress и узнаем, как создать базовую тему WordPress с нуля.

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

Создание голой минимальной темы

Первое, что мы сделаем, это установим плагин, который позволит нам создавать записи WordPress и другой контент. Таким образом, мы сможем быстро заполнить наш веб-сайт разработки, не теряя слишком много времени. Одним из плагинов, который служит для этой цели, является FakerPress от Gustavo Bordoni , доступный в хранилище плагинов WordPress.

Мы быстро устанавливаем и активируем плагин через WP-CLI.

Теперь, когда мы войдем в панель администратора, мы увидим, что FakerPress установлен, и мы можем создавать все виды контента в пакетном режиме, включая любые пользовательские типы записей, которые у нас есть.

FakerPress установлен

Теперь, используя этот плагин, мы создадим фальшивый контент. Это результат использования темы WordPress TwentySeventeen по умолчанию:

Тема TwentySeventeen с наполнением

Теперь мы быстро style.css и style.css минимальную тему, состоящую из файла catch-all index.php и style.css , которые нужны системе шаблонов WordPress для распознавания темы:

  

Это style.css , который style.css состоит только из мета-CSS комментариев. Эти комментарии обязательны.

Это файл index.php . Он будет ловить все запросы на данный момент:

 <?php /** * * @package Botega_Scratch_Theme */ ?> <!DOCTYPE html> <html <?php language_attributes(); ?>> <head> <title><?php bloginfo('name'); ?></title> <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>"> <?php wp_head(); ?> </head> <body> <header> <h1><?php bloginfo('name'); ?></h1> <h3><?php bloginfo('description'); ?></h3> </header> <?php if ( have_posts() ) : /* Start the Loop */ while ( have_posts() ) : the_post(); endwhile; endif; ?> </body> 

Теперь мы загружаем и активируем минимальную тему, которая у нас есть. Я активирую его с помощью WP-CLI:

Тема теперь видна WordPress и активна:

Тема активирована

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

Если мы сейчас посетим наш сайт в браузере, это то, что мы увидим:

Текущая домашняя страница

Очевидно, у нас есть работа.

Если мы посмотрим на исходный код домашней страницы, то увидим, что wp_head() множество тегов WordPress по умолчанию в <head> , таких как CSS, JavaScript, link и meta теги.

Функция bloginfo() используется для вывода информации о сайте .

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

На странице Кодекса о Цикле подробно рассказывается об этом. Типичная структура цикла - которая основана на PHP, а структура управления - выглядит следующим образом:

 <?php if ( have_posts() ) { while ( have_posts() ) { the_post(); // // Post Content here // } // end while } // end if ?> 

Нам нужно заполнить этот цикл while содержимым или тегами WordPress, выводящими содержимое.

Если мы изменим наш цикл, добавив the_title() , the_excerpt() и добавим HTML-разметку и the_ID() , чтобы они выглядели так:

  <?php if ( have_posts() ) : while ( have_posts() ): the_post(); ?> <div id="post-<?php the_ID(); ?>"> <h2><?php the_title(); ?></h2> <div class="post-excerpt"><?php the_excerpt(); ?></div> </div> <?php endwhile; endif; ?> 

Теперь мы получим список постов на нашей домашней странице без применения стиля:

Нестандартный вывод

WordPress по умолчанию показывает страницу блога - страницу архива для всех сообщений блога.

Если мы сейчас посетим URL-адрес одного сообщения - что-то вроде http://my-website.com/2018/11/14/sapiente-ad-facilis-quo-repellat-quos/ - мы увидим что-то вроде этого:

Наш текущий макет одного поста

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

Структурирование нашей темы в файлы и применение разметки начальной загрузки

Теперь мы реализуем партиалы , такие как header.php и footer.php а также различные специализированные шаблоны, все с использованием разметки Twitter Bootstrap , чтобы нам было проще их стилизовать.

Начиная с index.php , мы заменяем весь контент до и после цикла на функции get_header() и get_footer() :

 <?php /** * * @package Botega_Scratch_Theme */ get_header(); ?> <?php if ( have_posts() ) : while ( have_posts() ): the_post(); ?> <div id="post-<?php the_ID(); ?>"> <h2><?php the_title(); ?></h2> <div class="post-excerpt"><?php the_excerpt(); ?></div> </div> <?php endwhile; endif; ?> <?php get_footer(); ?> 

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

В соответствии с тем, что мы сказали - мы будем использовать тему Twitter Bootstrap - наш файл header.php будет выглядеть так:

 <?php /** * The header for our theme. * * @package Botega_Scratch_Theme * */ ?> <!DOCTYPE html> <html> <head> <meta charset="<?php bloginfo( 'charset' ); ?>"> <meta name="viewport" content="width=device-width, initial-scale=1"> <?php wp_head(); ?> </head> <body <?php body_class(); ?>> <nav class="navbar navbar-default navbar-custom navbar-fixed-top"> <div class="container-fluid"> <div class="navbar-header page-scroll"> <a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home" class="navbar-brand"><?php bloginfo( 'name' ); ?></a> </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav navbar-right"> <?php wp_nav_menu( array( 'theme_location' => 'primary', 'items_wrap' => '%3$s' ) ); ?> </ul> </div> </div> </nav> <div class="container"> <div class="row"> 

Наш файл footer.php будет выглядеть так:

 <?php /** * Footer template partial * * @package Botega_Scratch_Theme * */ ?> </div> <!-- /.row --> </div> <!-- /.container --> <!-- Footer --> <footer> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> </div> </div><!-- /.row --> </div><!-- /.container --> </footer><!-- /footer --> <?php wp_footer(); ?> </body> </html> 

Мы используем классы Bootstrap в наших тегах HTML, а wp_head () и wp_footer () wp_head wp_footer действий wp_head и wp_footer .

Следующее, что мы сделаем, это включим CSS и JavaScript из чистого шаблона начальной загрузки от startbootstrap.com, который поставляется с лицензией MIT, поэтому мы можем свободно использовать его. Таким образом, наша тема будет иметь предопределенные стили, отзывчивость, и мы все равно сможем ее стилизовать дальше.

functions.php

functions.php это файл, который поставляется с любой серьезной темой WordPress. Это файл, который действует как архив плагинов для бедного человека. Это позволяет нам включать любые пользовательские функции в нашу тему.

Сначала мы будем использовать этот файл для включения Bootstrap и стилей и сценариев нашей темы начальной загрузки:

 function bsimple_scripts() { wp_enqueue_style( 'bsimple-style', get_stylesheet_uri() ); wp_enqueue_style( 'bsimple-clean', get_template_directory_uri() . '/css/clean-blog.min.css' ); wp_enqueue_style( 'bsimple-bootstrap', get_template_directory_uri() . '/css/bootstrap.min.css' ); wp_enqueue_style( 'bsimple-fontawesome', get_template_directory_uri() . '/css/fa-all.min.css' ); wp_enqueue_style( 'bsimple-font1', "https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic" ); wp_enqueue_style( 'bsimple-font2', "https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" ); wp_enqueue_script( 'bsimple-jq', get_template_directory_uri() . '/js/jquery.min.js'); wp_enqueue_script( 'bsimple-bootstrap', get_template_directory_uri() . '/js/bootstrap.bundle.min.js'); wp_enqueue_script( 'bsimple-clean', get_template_directory_uri() . '/js/clean-blog.min.js'); } add_action( 'wp_enqueue_scripts', 'bsimple_scripts' ); 

Это WordPress-идиоматический способ включения скриптов и стилей в тему. Это позволяет нам указать, что положение сценариев будет помещено в очередь (заголовок или нижний колонтитул) и приоритет постановки в очередь. Мы даже можем указать зависимость каждого конкретного ресурса от другого. Это обеспечит загрузку ресурсов в правильном порядке.

Мы используем здесь wp_enqueue_scripts действия wp_enqueue_scripts . Мы можем узнать больше об этом в Кодексе . (Мы рассмотрели хуки действий в предыдущей статье .)

Внутри нашей пользовательской функции bsimple_scripts() которую мы подключаем к wp_enqueue_scripts действий wp_enqueue_scripts мы используем две функции WordPress для загрузки наших скриптов и стилей - wp_enqueue_script () и wp_enqueue_style () . Аргументы для этих функций - как указано в ссылочных ссылочных страницах - позволяют нам в полной мере использовать упомянутую нами гибкость.

Мы видим, что мы загружаем стили из Интернета (шрифты Google) и из папки нашей темы. Поэтому мы создаем webfonts css , js и webfonts в нашей папке темы и копируем CSS, файлы JavaScript и файлы шрифтов FontAwesome нашей темы Bootstrap.

Мы также копируем наш файл index.php файлы archive.php , page.php и single.php , которые мы single.php .

Теперь структура нашего файла темы будет выглядеть примерно так:

Наша текущая структура файла темы

Регулировка разметки

Если мы сейчас посетим нашу домашнюю страницу, то увидим меню сверху - хотя оно и страница все еще в беспорядке - потому что следующая строка в нашем заголовке по-прежнему выводит меню, заключенное в div и собственные теги ul , поэтому это не зависит от наших стилей начальной загрузки:

 <?php wp_nav_menu( array( 'theme_location' => 'primary', 'items_wrap' => '%3$s' ) ); ?> 

Чтобы решить эту проблему, нам сначала нужно перейти на нашу панель управления wp-admin и создать - в настройщике - новое меню. мы назовем это Top Menu .

После того, как мы это сделаем, мы перейдем в наш файл header.php удалим эти строки:

 <ul class="nav navbar-nav navbar-right"> <?php wp_nav_menu( array( 'theme_location' => 'primary', 'items_wrap' => '%3$s' ) ); ?> </ul> 

На их место мы ставим следующие строки:

 <ul class="navbar-nav ml-auto"> <?php wp_nav_menu(array( 'menu' => 'Top Menu', 'items_wrap'=>'%3$s', 'container' => false, )); ?> </ul> 

Это удалит тег div и дублирование тега ul для нас, но нам все еще нужно применить nav-item и nav-link к нашим пунктам меню (соответственно, к li и тегам). Как мы пойдем об этом? wp_nav_menu не предоставляет аргументов для этого . Мы будем использовать nav_menu_link_attributes фильтра nav_menu_link_attributes и nav_menu_css_class . Мы помещаем это в наш файл functions.php :

 function add_menu_link_class( $atts, $item, $args ) { if($args->link_class) { $atts['class'] = $args->link_class; } return $atts; } add_filter( 'nav_menu_link_attributes', 'add_menu_link_class', 1, 3 ); function add_menu_list_item_class($classes, $item, $args) { if($args->list_item_class) { $classes[] = $args->list_item_class; } return $classes; } add_filter('nav_menu_css_class', 'add_menu_list_item_class', 1, 3); 

Теперь мы можем указать новые атрибуты в нашем wp_nav_menu в нашем header.php :

 <ul class="navbar-nav ml-auto"> <?php wp_nav_menu(array( 'menu' => 'Top Menu', 'items_wrap'=>'%3$s', 'container' => false, 'list_item_class' => "nav-item", 'link_class' => "nav-link", )); ?> </ul> 

Теперь наши ссылки в верхнем меню могут использовать стили, уже определенные в CSS нашей темы Bootstrap.

Динамический заголовок

Чтобы иметь возможность использовать динамический заголовок - то есть другой заголовок для главной страницы, для других выбранных страниц или для архивов - мы определим функцию dynamic_header() в нашем файле functions.php , куда мы выведем разметка нашего заголовка зависит от страницы, которую загружает посетитель.

Так что теперь наш файл header.php закончится так:

 </nav> <?php dynamic_header(); ?> <div class="container"> <div class="row"> 

Мы также определим эту функцию следующим образом:

 if(!function_exists('dynamic_header')){ function dynamic_header(){ global $post; ?> <?php if (is_front_page()){ ?> <header class="masthead" style="background:#ccc;"> <div class="overlay"></div> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> <div class="site-heading"> <h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1> <span class="subheading"><?php get_bloginfo( 'description', 'display' );?></span> </div> </div> </div> </div> </header> <?php } else if (is_home()){ ?> <header class="masthead" style="background:#ccc;"> <div class="overlay"></div> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> <div class="site-heading"> <h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1> <span class="subheading"><?php get_bloginfo( 'description', 'display' );?></span> </div> </div> </div> </div> </header> <?php } else if (is_page()){ ?> <header class="masthead" style="background:#ccc;"> <div class="overlay"></div> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> <div class="site-heading"> <h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1> <span class="subheading"><?php get_bloginfo( 'description', 'display' );?></span> </div> </div> </div> </div> </header> <?php } else if (is_single()){ ?> <header class="masthead" style="background:#ccc;"> <div class="overlay"></div> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> <div class="site-heading"> <h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1> <span class="subheading"><?php get_bloginfo( 'description', 'display' );?></span> </div> </div> </div> </div> </header> <?php } else { ?> <header class="masthead" style="background:#ccc;"> <div class="overlay"></div> <div class="container"> <div class="row"> <div class="col-lg-8 col-md-10 mx-auto"> <div class="site-heading"> <h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1> <span class="subheading"><?php get_bloginfo( 'description', 'display' );?></span> </div> </div> </div> </div> </header> <?php } } } 

Чтобы иметь возможность использовать все текущие URL или данные публикации - как в цикле - мы объявляем переменную $post global . Затем мы просто заполняем другую страницу или запрашиваем случаи с заголовком заполнителя HTML, который мы закончим позже. Это закладывает основу для действительно динамического заголовка.

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

Мы добавим это в наш style.css :

 body.logged-in.admin-bar #mainNav { margin-top: 32px; } @media screen and (max-width: 782px) { body.logged-in.admin-bar #mainNav { margin-top: 46px; } } 

Это гарантирует, что #mainNav - наш контейнер меню - имеет достаточное смещение от вершины, поэтому он не покрывается при #mainNav пользователя в систему. WordPress добавляет классы logged-in и admin-bar в body в этих случаях, поэтому мы можем легко цель это.

Мы видим, что мы обращаемся к двум случаям в нашем CSS - один по умолчанию, а другой для небольших экранов. Это связано с тем, что WordPress выводит более широкую панель администратора на мобильные устройства, поэтому нам необходимо обеспечить смещение в 46 пикселей.

На мобильном устройстве у нас теперь должно быть отзывчивое раскрывающееся меню на основе JavaScript:

Наш выпадающий на мобильном

Вывод

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

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

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


В этой серии есть три статьи по созданию темы WordPress с нуля: