Функциональный файл functions.php в теме WordPress

Раздел: Разработка на PHP -> Разработка на WordPress

Файл functions.php: центральный элемент пользовательских функций

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

Для безопасного внесения изменений следует всегда использовать дочернюю тему. Тогда обновление родительской темы не затронет ваших доработок. Рассмотрим базовую структуру: файл начинается с открывающего тега PHP (<?php), затем можно определять функции, подключать скрипты и стили, регистрировать поддержку возможностей темы. Вот минимальный пример добавления поддержки миниатюр и меню:


<?php
// Дочерняя тема: functions.php

// Поддержка миниатюр записей
add_action( 'after_setup_theme', function() {
    add_theme_support( 'post-thumbnails' );
} );

// Регистрация навигационного меню
add_action( 'after_setup_theme', function() {
    register_nav_menu( 'primary', __( 'Primary Menu', 'textdomain' ) );
} );

файл functions php (файл functions.php (wordpress))

Каждый шаг:

  • add_action( 'after_setup_theme', ... ) - добавляет функцию на хук, срабатывающий после инициализации темы.
  • add_theme_support( 'post-thumbnails' ) - включает поддержку изображений записей.
  • register_nav_menu() - регистрирует область для меню.

Как добавить собственные стили и скрипты через functions.php?

Подключение ресурсов выполняется с помощью функций wp_enqueue_style() и wp_enqueue_script() внутри хука wp_enqueue_scripts. Пример:


function my_theme_assets() {
    // Подключаем основной стиль
    wp_enqueue_style( 'my-style', get_stylesheet_uri(), array(), '1.0' );
    
    // Подключаем скрипт с зависимостью от jQuery и в футере
    wp_enqueue_script( 'my-script', get_template_directory_uri() . '/js/custom.js', array( 'jquery' ), '1.0', true );
}
add_action( 'wp_enqueue_scripts', 'my_theme_assets' );

Wordpress версии php (версия php для wordpress)

get_stylesheet_uri() возвращает URL основного файла стилей (style.css). Параметр true в wp_enqueue_script помещает скрипт перед закрывающим тегом </body>.

Типичная ошибка: вызов wp_enqueue_style() или wp_enqueue_script() без хука приводит к нарушению порядка загрузки ресурсов и может вызвать конфликты. Решение: всегда оборачивать подключение в функцию, привязанную к правильному хуку.

Другая проблема - белый экран после добавления кода. Она возникает из-за синтаксической ошибки в PHP. Рекомендуется перед сохранением проверять код локально или использовать FTP для восстановления резервной копии файла.

Как избежать потери кода при обновлении темы?

Лучший метод - создание дочерней темы, как показано выше. Альтернатива: использование специального плагина для пользовательских функций (например, Code Snippets). Плагин хранит сниппеты в базе данных и не зависит от темы, что удобно при смене оформления. Однако плагин добавляет дополнительную нагрузку и потенциальные точки отказа.

Как организовать код в большом проекте?

При разрастании functions.php рекомендуется разбивать логику на отдельные include-файлы. Например, создать папку /inc/ и подключать файлы по функциональности:


// functions.php
require_once get_template_directory() . '/inc/custom-post-types.php';
require_once get_template_directory() . '/inc/widgets.php';
require_once get_template_directory() . '/inc/shortcodes.php';

Wp include php (wordpress: включение файлов)

Это упрощает поддержку и поиск ошибок. Важно проверять существование файла через file_exists(), чтобы избежать фатальных ошибок.

Как предотвратить конфликты функций при включении плагинов?

Перед объявлением новой функции следует проверять её существование с помощью function_exists():


if ( ! function_exists( 'my_custom_function' ) ) {
    function my_custom_function() {
        // код
    }
}

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

Ошибка: попытка переопределить встроенную функцию WordPress без проверки приведёт к фатальной ошибке. Решение: всегда используйте function_exists() для пользовательских функций, а для изменения стандартного поведения применяйте фильтры и хуки.

Расширенные возможности: шорткоды и фильтры

Шорткоды добавляются через add_shortcode(). Пример создания шорткода [greeting name='Мир']:


function greeting_shortcode( $atts ) {
    $atts = shortcode_atts( array( 'name' => 'гость' ), $atts );
    return 'Привет, ' . esc_html( $atts['name'] ) . '!';
}
add_shortcode( 'greeting', 'greeting_shortcode' );

Фильтры позволяют изменять данные перед выводом. Например, изменение длины excerpt:


function custom_excerpt_length( $length ) {
    return 40;
}
add_filter( 'excerpt_length', 'custom_excerpt_length' );

Расширенные примеры кода для functions.php

1. Создание произвольного типа записи (Custom Post Type) и таксономии

Пример

// Добавление типа записи 'Книга' с поддержкой категорий
function create_book_post_type() {
    register_post_type( 'book',
        array(
            'labels' => array(
                'name' => __('Книги'),
                'singular_name' => __('Книга')
            ),
            'public' => true,
            'has_archive' => true,
            'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
            'menu_icon' => 'dashicons-book'
        )
    );

    // Регистрация таксономии 'Жанр'
    register_taxonomy( 'genre', 'book', array(
        'label' => __('Жанры'),
        'rewrite' => array( 'slug' => 'genre' ),
        'hierarchical' => true
    ) );
}
add_action( 'init', 'create_book_post_type' );

Результат: в админ-панели появляется новый пункт меню "Книги" с возможностью создавать записи и назначать им жанры.

// После добавления кода необходимо пересохранить постоянные ссылки (Настройки -> Постоянные ссылки -> Сохранить)

2. Автоматическое подключение стилей родительской темы в дочерней

Пример

function child_enqueue_parent_styles() {
    // Сначала подключаем style.css родительской темы
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
    // Затем свой style.css (может переопределять стили)
    wp_enqueue_style( 'child-style', get_stylesheet_uri(), array( 'parent-style' ), wp_get_theme()->get('Version') );
}
add_action( 'wp_enqueue_scripts', 'child_enqueue_parent_styles' );

Результат: стили родительской темы загружаются первыми, а дочерние - вторыми, что позволяет аккуратно переопределять CSS-правила.

3. Добавление произвольного поля (метабокса) для записей

Пример

function add_custom_meta_box() {
    add_meta_box(
        'my_meta_box',
        'Дополнительная информация',
        'display_my_meta_box',
        'post',
        'side',
        'default'
    );
}
function display_my_meta_box( $post ) {
    $value = get_post_meta( $post->ID, '_my_meta_key', true );
    ?>
    <label for="my_meta_field">Введите текст:</label>
    <input type="text" id="my_meta_field" name="my_meta_field" value="<?php echo esc_attr( $value ); ?>" size="25" />
    <?php
}
function save_my_meta_box_data( $post_id ) {
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
    if ( ! current_user_can( 'edit_post', $post_id ) ) return;
    if ( isset( $_POST['my_meta_field'] ) ) {
        update_post_meta( $post_id, '_my_meta_key', sanitize_text_field( $_POST['my_meta_field'] ) );
    }
}
add_action( 'add_meta_boxes', 'add_custom_meta_box' );
add_action( 'save_post', 'save_my_meta_box_data' );

Результат: в редакторе записей появляется блок "Дополнительная информация" с текстовым полем. Введённое значение сохраняется в мета-поле _my_meta_key.

4. Использование AJAX в WordPress для неавторизованных и авторизованных пользователей

Пример

// Обработчик AJAX-запроса
function my_ajax_handler() {
    $data = sanitize_text_field( $_POST['data'] );
    // Логика обработки
    $response = 'Вы отправили: ' . $data;
    wp_send_json_success( $response );
}

// Зарегистрируем для авторизованных и неавторизованных
add_action( 'wp_ajax_my_action', 'my_ajax_handler' );
add_action( 'wp_ajax_nopriv_my_action', 'my_ajax_handler' );

// JavaScript для отправки запроса (добавить через wp_enqueue_script в functions.php)
Пример

// Пример JS-кода (должен быть в отдельном файле)
jQuery(document).ready(function($) {
    $('#my-button').on('click', function() {
        $.post(ajaxurl, {
            action: 'my_action',
            data: 'тест'
        }, function(response) {
            console.log(response.data);
        });
    });
});

Результат: нажатие кнопки отправляет AJAX-запрос, сервер возвращает JSON с полем data.

5. Добавление пользовательского лога для отладки

Пример

if ( ! function_exists( 'write_log' ) ) {
    function write_log( $log ) {
        if ( true === WP_DEBUG ) {
            if ( is_array( $log ) || is_object( $log ) ) {
                error_log( print_r( $log, true ) );
            } else {
                error_log( $log );
            }
        }
    }
}

// Пример использования
write_log( 'Пользователь залогинился: ' . $user_login );

Результат: в файл wp-content/debug.log (если включён WP_DEBUG_LOG) записывается отладочная информация.

6. Переопределение частей шаблона через фильтры (для advanced)

Пример

function custom_breadcrumb_output( $breadcrumb ) {
    // Добавляем дополнительный элемент в начало
    $home = '<a href="' . home_url() . '">Домой</a>';
    return $home . ' > ' . $breadcrumb;
}
add_filter( 'woocommerce_breadcrumb_defaults', function($defaults) {
    $defaults['delimiter'] = ' > ';
    return $defaults;
});

Результат: хлебные крошки WooCommerce начинаются с ссылки "Домой" и используют разделитель " > ".

Файл functions.php (WordPress) - comments

En
файл functions php (php)