השקתם חנות מסחר אלקטרוני על ProcessWire, אבל עמודים נטענים תוך 3 שניות ו-LCP בשמיים? ערכת הנושא ברירת המחדל מוסיפה המון סקריפטים שאינם בשימוש, והסימון לא ניתן להתאמה לנתונים שלכם. תבנית מותאמת אישית פותרת את זה – אתם מקבלים בדיוק את מה שצריך, בלי נפח מיותר. עם 8 שנות ניסיון ב-ProcessWire, אנחנו מבטיחים פתרון אמין. מעבר לתבניות מותאמות אישית מפחית את TTFB פי 2-3 על ידי הסרת מודולים שאינם בשימוש.
איך לפתח תבנית ProcessWire מותאמת אישית?
תבנית ב-ProcessWire היא קובץ PHP ב-/site/templates/, ששמו תואם לשם התבנית במסד הנתונים. הקובץ מקבל את אובייקט $page עם נתוני העמוד הנוכחיים וגישה מלאה ל-$pages, $config, $user, ושאר ה-API. PHP טהור – ללא מנוע ברירת מחדל, אם כי אפשר לשלב Twig דרך מודול TemplateEngineTwig. לסביבת ייצור אנחנו ממליצים על PHP טהור: זה מהיר יותר ומוסיף שכבת הפשטה נוספת.
למה תבנית מותאמת אישית עדיפה על ערכת נושא סטנדרטית?
ערכות נושא סטנדרטיות לרוב עמוסות בסקריפטים וסגנונות שאינם בשימוש, מה שמגדיל את LCP ו-CLS. תבנית מותאמת אישית מציגה רק את הנתונים הדרושים, משתמשת בעיבוד צד שרת לרכיבים כבדים, ומיישמת טעינה עצלה לתמונות. באחד הפרויקטים שלנו – חנות ProcessWire עם 5000+ מוצרים – מעבר לתבניות מותאמות אישית הפחית את צריכת הזיכרון ב-60% והאיץ את יצירת העמוד פי 2. בנוסף, צמצמנו את שאילתות מסד הנתונים מ-50 ל-3 לעמוד.
ארכיטקטורת תבניות: אפשרויות חלוקה
אפשרות 1: _init.php + _main.php
הגישה הנפוצה ביותר. ProcessWire כולל אוטומטית את _init.php לפני כל תבנית ואת _main.php אחריה, אם האפשרות "Prepend/Append template file" מופעלת בהגדרות התבנית:
// _init.php и _main.php — единый поток
$baseUrl = $config->urls->root;
$homePage = $pages->get("/");
$mainNav = $pages->find("parent=/,template!=error404,sort=sort");
?><!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>אפשרות 2: 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"),
]; השוואת גישות
| תכונה | init/main | controller+view |
|---|---|---|
| מורכבות | נמוכה | בינונית |
| יכולת תחזוקה | פשוטה | גמישה |
| יכולת בדיקה | נמוכה | גבוהה |
| ביצועים | גבוהים | גבוהים |
| המלצה | פרויקטים קטנים | פרויקטים מורכבים |
עבודה עם תמונות
ProcessWire מעבד תמונות תוך כדי תנועה דרך מתודת // _init.php и _main.php — единый поток $baseUrl = $config->urls->root; $homePage = $pages->get("/"); $mainNav = $pages->find("parent=/,template!=error404,sort=sort"); ?><!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> . דוגמה עם WebP:
$img = $page->images->first();
if ($img) {
$thumb = $img->size(800, 600, ['cropping' => 'center', 'quality' => 85]);
echo "<img src='{$thumb->url}' alt='{$img->description}' loading='lazy'>";
$webp = $img->size(800, 600, ['suffix' => 'webp', 'webpAdd' => true]);
} 404 מותאם אישית והפניות
if ($page->redirect_url) {
$session->redirect($page->redirect_url, 301);
}
if (!$user->isLoggedin() && $page->requires_login) {
throw new Wire404Exception();
} איך לייעל תמונות: שלב אחר שלב
- בחרו תמונה מגלריית העמוד.
- קראו ל-
// 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"), ];עם הפרמטרים הרצויים. - ציינו
size()ו-$img = $page->images->first(); if ($img) { $thumb = $img->size(800, 600, ['cropping' => 'center', 'quality' => 85]); echo "<img src='{$thumb->url}' alt='{$img->description}' loading='lazy'>"; $webp = $img->size(800, 600, ['suffix' => 'webp', 'webpAdd' => true]); }כדי ליצור WebP. - הוסיפו את המאפיין
if ($page->redirect_url) { $session->redirect($page->redirect_url, 301); } if (!$user->isLoggedin() && $page->requires_login) { throw new Wire404Exception(); }לטעינה דחויה. - השתמשו ב-
$img->size()להמרה בכמות גדולה באתרים עם תעבורה גבוהה.
ביצועים: טעינה עצלה של קשרים
כברירת מחדל, suffix: 'webp' טוען אובייקטים קשורים בעת גישה. לרשימות גדולות, השתמשו ב-webpAdd: true – עיבוד זורם ללא טעינת הכל לזיכרון:
foreach ($pages->findMany("template=product, sort=title") as $product) {
echo $product->title . "\n";
} פרטים על findMany()
findMany() מעבד עמודים אחד אחד, מבלי לאחסן אותם בזיכרון. זה חשוב במיוחד בעמודים עם אלפי מוצרים. זה עובד כגנרטור: כל איטרציה טוענת רק את העמוד הנוכחי.לוחות זמנים אופייניים לפיתוח תבניות
| משימה | הערכה |
|---|---|
| תבנית בסיסית (פריסה + ניווט + פוטר) | 4–8 שעות |
| תבנית רשימה עם דפדוף וסינון | 8–16 שעות |
| עמוד מפורט עם קשרים | 4–10 שעות |
| מערכת תבניות ל-10+ סוגי תוכן | 3–6 ימים |
| שילוב Twig + גישת רכיבים | 2–4 ימים |
מה כלול בפיתוח?
- ארכיטקטורת תבניות (init/main או controller+view)
- הגדרת קבצי prepend/append
- סימון לכל העמודים האופייניים (רשימה, פרטים, 404)
- אופטימיזציה של תמונות (גודל, WebP, טעינה עצלה)
- סימון SEO בסיסי (meta title, description, og:image)
- תיעוד תבניות וגישה
- הדרכה לצוות הלקוח (שעה אונליין)
- אחריות לקוד ל-3 חודשים
הדרכה ותיעוד הם פריטים נפרדים: אנחנו מעבירים ידע כדי שתוכלו לתחזק את הפרויקט באופן עצמאי.
בעיות ופתרונות אופייניים
אי שימוש ב-output buffering עם prepend/append מוביל לכותרות כפולות. פתרון – תמיד הפעילו prepend/append או השתמשו בתבנית controller. טעינת כל העמודים הקשורים בבת אחת – לסטים מעל 100 רשומות השתמשו ב-loading='lazy'. התעלמות ממטמון תמונות – ProcessWire שומר גרסאות, אבל אם התוכן משתנה לעתים קרובות, נקו את המטמון ב-$pages->findMany(). עמוד 404 הוא חובה: תמיד זרקו FieldtypePage עבור אזורים מוגנים.
צרו קשר לייעוץ – נדון בפרויקט שלכם. הזמינו פיתוח תבנית ProcessWire מותאמת אישית וקבלו גמישות וביצועים.
מדריך MDN לטעינה עצלה – עוד על מאפיין loading. ויקיפדיה Core Web Vitals – מדדי ביצועים.







