Разработка кастомного шаблона ProcessWire

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

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка кастомного шаблона ProcessWire
Средняя
~5 рабочих дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Разработка кастомного шаблона ProcessWire

Шаблон в ProcessWire — это PHP-файл в /site/templates/, имя которого совпадает с именем шаблона в базе. Файл получает объект $page с данными текущей страницы и полный доступ к $pages, $config, $user и остальному API. Никакого движка шаблонов по умолчанию — чистый PHP, хотя можно подключить Twig через модуль TemplateEngineTwig.

Архитектура шаблонов: варианты разделения

Вариант 1: _init.php + _main.php

Самый распространённый подход. ProcessWire автоматически включает _init.php перед каждым шаблоном и _main.php после, если включена опция «Prepend/Append template file» в настройках шаблона.

// _init.php — глобальные переменные, хелперы
$baseUrl  = $config->urls->root;
$homePage = $pages->get("/");
$mainNav  = $pages->find("parent=/,template!=error404,sort=sort");

function formatDate(int $ts): string {
    return date("d.m.Y", $ts);
}
// _main.php — layout-обёртка
?><!DOCTYPE html>
<html lang="<?= $user->language->name ?>">
<head>
    <meta charset="utf-8">
    <title><?= $page->title ?> | <?= $homePage->title ?></title>
    <link rel="stylesheet" href="<?= $config->urls->templates ?>css/main.css">
</head>
<body>
<?php include("partials/nav.php"); ?>
<main><?= $content ?></main>
<?php include("partials/footer.php"); ?>
</body>
</html>

В шаблоне страницы $content накапливается через буферизацию вывода:

// services.php — ProcessWire автоматически буферизует вывод
$items = $pages->find("template=service, parent={$page}, sort=sort");
foreach ($items as $item) {
    echo "<article>";
    echo "<h2><a href='{$item->url}'>{$item->title}</a></h2>";
    echo "<p>{$item->summary}</p>";
    echo "</article>";
}

Вариант 2: контроллер + вид

Для сложных шаблонов логику выносят в отдельный файл-контроллер:

templates/
  controllers/
    services.php     # только логика, без echo
  views/
    services.view.php # только разметка
  services.php         # точка входа, связывает controller+view
// templates/services.php
require __DIR__ . '/controllers/services.php';
extract($viewData); // переменные из контроллера
require __DIR__ . '/views/services.view.php';
// templates/controllers/services.php
$viewData = [
    'items'      => $pages->find("template=service, sort=sort, limit=12"),
    'categories' => $pages->find("template=service-category, sort=sort"),
    'pagination' => $modules->get("MarkupPagerNav"),
];

Работа с изображениями

ProcessWire обрабатывает изображения на лету через метод size():

// Основное изображение страницы
$img = $page->images->first();
if ($img) {
    // Ресайз с кадрированием 800×600
    $thumb = $img->size(800, 600, ['cropping' => 'center', 'quality' => 85]);
    echo "<img src='{$thumb->url}' alt='{$img->description}' loading='lazy'>";

    // WebP через опцию suffix
    $webp = $img->size(800, 600, ['suffix' => 'webp', 'webpAdd' => true]);
}

Вариантные размеры кэшируются в /site/assets/files/{id}/. Повторный запрос возвращает уже готовый файл.

Повторно используемые частичные шаблоны

// partials/card.php — принимает $item из include
?>
<div class="card">
    <?php if ($item->image): ?>
        <img src="<?= $item->image->size(400,300)->url ?>" alt="<?= $item->title ?>">
    <?php endif; ?>
    <h3><?= $item->title ?></h3>
    <p><?= $item->summary ?></p>
    <a href="<?= $item->url ?>">Подробнее</a>
</div>
// Использование в services.php
foreach ($items as $item) {
    include("./partials/card.php");
}

Мета-данные и SEO

SEO-поля обычно добавляют на уровне шаблона через отдельный fieldset:

// В _main.php
$metaTitle       = $page->meta_title ?: $page->title;
$metaDescription = $page->meta_description ?: $page->summary;
$ogImage         = $page->og_image ? $page->og_image->size(1200, 630)->httpUrl : '';
?>
<title><?= htmlspecialchars($metaTitle) ?></title>
<meta name="description" content="<?= htmlspecialchars($metaDescription) ?>">
<meta property="og:image" content="<?= $ogImage ?>">

Кастомные 404 и редиректы

// templates/basic-page.php
// Редирект устаревшего URL
if ($page->redirect_url) {
    $session->redirect($page->redirect_url, 301);
}

// Принудительный 404
if (!$user->isLoggedin() && $page->requires_login) {
    throw new Wire404Exception();
}

Производительность: ленивая загрузка связей

По умолчанию FieldtypePage загружает связанные объекты при обращении. При больших списках используют $pages->findMany() — потоковая обработка без загрузки всего в память:

// findMany() для больших наборов (1000+ страниц)
foreach ($pages->findMany("template=product, sort=title") as $product) {
    echo $product->title . "\n";
    // ProcessWire автоматически освобождает память
}

Типовые сроки разработки шаблонов

Задача Оценка
Базовый шаблон (layout + nav + footer) 4–8 ч
Шаблон списка с пагинацией и фильтром 8–16 ч
Детальная страница со связями 4–10 ч
Система шаблонов для 10+ типов контента 3–6 дней
Интеграция Twig + компонентный подход 2–4 дня