מניסיוננו: לקוח רוצה מסנן טווח מחירים, אבל דרופל מציעה רק שדה טקסט. או שצריך להציג מוצרים מטבלה מותאמת אישית, אבל Views עובד רק עם ישויות. במקרים כאלה אנו מפתחים תוספים מותאמים אישית — וזה מהיר יותר ממה שזה נראה. עם ניסיון של למעלה מ-8 שנים בדרופל, אנו יכולים ליישם משימות כאלה במפתח מלא תוך 2–3 ימים. הביצועים של פתרון מותאם אישית גבוהים פי 3 מפתרונות דומים באמצעות Preprocess או פריצות תבנית. ואם יש צורך ב-REST API למערכות חיצוניות — Views מספק ייצוא JSON מוכן עם הגדרת CORS תוך חצי שעה.
למה Views דורש התאמה אישית?
Views סטנדרטי מכסה 80% מהמשימות — מסננים, מיון, דפדוף, ייצוא. ה-20% הנותרים הם לוגיקה מותאמת אישית: סינון לפי ישויות קשורות עם אגרגציה, הצגת נתונים מ-API חיצוני, פורמט שורות לא סטנדרטי. ללא קוד, משימות אלה אינן פתירות או דורשות פריצות תבנית שפוגעות בביצועים. תוסף מותאם אישית עובד פי 3 מהר יותר מפתרון דומה באמצעות Preprocess. לדוגמה, בעיה אופיינית היא INP (Interaction to Next Paint) מעל 200 אלפיות השנייה בעת הצגת רשימה מורכבת. תוסף שורות תקין עם מטמון תגי צומת מפחית את ה-INP ל-50 אלפיות השנייה.
איך ליצור מסנן מותאם אישית בחצי יום?
הדרך המהירה ביותר היא hook_views_query_alter(). נניח שצריך לסנן מוצרים לפי מחיר מ-ועד. העבר פרמטרים של GET price_from ו-price_to, הוסף תנאים לשאילתה. זה לא דורש יצירת תוסף, אבל הלוגיקה נשארת במודול. לשימוש חוזר אנו כותבים תוסף מסנן עם הערת @ViewsFilter. גישה זו מבטיחה ארכיטקטורה נקייה ויכולת לבדוק את המסנן בנפרד. אנו משתמשים ב-PHP 8.3+ עם טיפוסים וטיפוסים קפדניים — זה מפחית באגים בשלב הביקורת.
מה אם Views סטנדרטי לא עובד עם טבלה מותאמת אישית?
אם הנתונים שלך מאוחסנים בטבלה נפרדת (לדוגמה, product_stats), Views לא יראה אותה כברירת מחדל. יש לרשום את הטבלה באמצעות hook_views_data(): ציין שדה בסיס, קשרים ל-node_field_data, וסוגי נתונים לכל עמודה. לאחר מכן הטבלה הופכת לזמינה בממשק המשתמש. לאחר מכן כתוב תוספי מסנן ומיון אם סוג הנתונים אינו סטנדרטי. בפרויקט אחד חיברנו טבלה מותאמת אישית עם מלאי והנחות בדיוק בדרך זו — זה לקח 4 שעות כולל בדיקות.
איך אנחנו עושים את זה: ערימת טכנולוגיה ומקרה בוחן
אנו משתמשים ב-Drupal 10/11, PHP 8.3+, Drush לייצוא הגדרות. דוגמה מהפרקטיקה שלנו: חנות מקוונת הייתה זקוקה לבלוק מותאם אישית "מוצרים מוזלים" עם מסנן לפי אחוז הנחה ומיון לפי כמות מלאי. Views סטנדרטי לא יכול לעבוד עם טבלה מותאמת אישית product_stats. רשמנו את הטבלה באמצעות hook_views_data(), כתבנו תוסף מסנן לאחוז הנחה ותוסף מיון למלאי. תוצאה: הבלוק נטען תוך 40 אלפיות השנייה, עם מטמון תגי צומת.
הגדרת View כזה ב-YAML:
# views.view.discount_products.yml
id: discount_products
label: 'Товары со скидкой'
module: views
description: ''
base_table: product_stats
base_field: id
display:
default:
display_options:
fields:
title:
id: title
table: node_field_data
field: title
relationship: nid
price:
id: price
table: node__field_price
field: field_price_value
discount_percent:
id: discount_percent
table: product_stats
field: discount_percent
stock:
id: stock
table: product_stats
field: stock_quantity
filters:
status:
value: '1'
discount_percent:
id: discount_percent
table: product_stats
field: discount_percent
operator: '>=,'
value: { min: '', max: '' }
expose:
operator: 'discount_percent_op'
identifier: discount
sorts:
stock_quantity:
order: ASC
pager:
type: some
options: { items_per_page: 10 }
relationships:
nid:
id: nid
table: product_stats
field: node_id
relationship: node_field_data
required: true
style:
type: html_list
row:
type: fields
block_1:
display_plugin: block
Hook למסנן מותאם אישית:
<?php
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\query\QueryPluginBase;
function my_module_views_query_alter(ViewExecutable $view, QueryPluginBase $query): void {
if ($view->id() !== 'discount_products') {
return;
}
$discount = \Drupal::request()->query->get('discount');
if (!empty($discount['min'])) {
$query->addWhereExpression(0, 'product_stats.discount_percent >= :min', [':min' => (float) $discount['min']]);
}
if (!empty($discount['max'])) {
$query->addWhereExpression(0, 'product_stats.discount_percent <= :max', [':max' => (float) $discount['max']]);
}
}תוסף שורות לכרטיס מוצר:
<?php
namespace Drupal\my_module\Plugin\views\row;
use Drupal\views\Plugin\views\row\RowPluginBase;
use Drupal\views\ResultRow;
/**
* @ViewsRow(
* id = "product_card",
* title = @Translation("Product card"),
* help = @Translation("Renders products as cards"),
* display_types = {"normal"},
* )
*/
class ProductCardRow extends RowPluginBase {
public function render(ResultRow $row): array {
$node = $row->_entity;
$view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
return [
'#theme' => 'product_card',
'#node' => $node,
'#title' => $node->getTitle(),
'#price' => $node->get('field_price')->value,
'#discount' => $row->discount_percent,
'#stock' => $row->stock_quantity,
'#url' => $node->toUrl()->toString(),
'#cache' => [
'tags' => $node->getCacheTags(),
'contexts' => ['user.roles'],
],
];
}
}שימוש פרוגרמטי ב-View:
<?php
use Drupal\views\Views;
$view = Views::getView('discount_products');
$view->setDisplay('block_1');
$view->setExposedInput(['discount' => ['min' => 20, 'max' => 50]]);
$view->execute();
$results = $view->result;
foreach ($results as $row) {
$node = $row->_entity;
// render
}
רישום טבלה מותאמת אישית עבור Views:
<?php
function my_module_views_data(): array {
$data = [];
$data['product_stats']['table']['group'] = t('Product Stats');
$data['product_stats']['table']['base'] = [
'field' => 'id',
'title' => t('Product statistics'),
'help' => t('Custom table with discount and stock'),
];
$data['product_stats']['node_id'] = [
'title' => t('Node ID'),
'relationship' => [
'base' => 'node_field_data',
'base field' => 'nid',
'id' => 'standard',
'label' => t('Node'),
],
'filter' => ['id' => 'numeric'],
'sort' => ['id' => 'standard'],
'field' => ['id' => 'numeric'],
];
$data['product_stats']['discount_percent'] = [
'title' => t('Discount percent'),
'filter' => ['id' => 'numeric'],
'sort' => ['id' => 'standard'],
'field' => ['id' => 'numeric'],
];
$data['product_stats']['stock_quantity'] = [
'title' => t('Stock quantity'),
'filter' => ['id' => 'numeric'],
'sort' => ['id' => 'standard'],
'field' => ['id' => 'numeric'],
];
return $data;
} השוואת גישות: hook מול תוסף
| קריטריון | hook_views_query_alter | תוסף מסנן |
|---|---|---|
| מהירות פיתוח | 30 דקות | 2–4 שעות |
| שימוש חוזר | לא | כן |
| יכולת בדיקה | נמוכה | גבוהה |
| מטמון | ברירת מחדל | תגי מטמון מותאמים אישית |
תהליך עבודה: מניתוח לפריסה
| שלב | משך | תוצאה |
|---|---|---|
| ניתוח | 0.5–1 יום | מפרט טכני עם תיאור אלמנטים מותאמים אישית |
| עיצוב | 0.5 יום | סכמת נתונים, אבות טיפוס של מסננים |
| יישום | 1–3 ימים | תוספים, הגדרות, נקודות קצה של REST |
| בדיקות | 0.5 יום | בדיקות עומס, תאימות ל-Drupal 10/11 |
| פריסה | 0.5 יום | ייצוא הגדרות, תיעוד |
מה כלול בפיתוח Views מותאם אישית
- תוספים מותאמים אישית למסננים, מיון, שדות ושורות
- תצוגת REST Export עם הגדרת CORS
- אינטגרציה עם טבלאות מסד נתונים מותאמות אישית
- תיעוד על שימוש והתאמה אישית נוספת
- אחריות לתאימות עם גרסאות דרופל העדכניות
לוח זמנים ועלות
לוח הזמנים תלוי במורכבות: מסנן מותאם אישית פשוט — מחצי יום, פרויקט מורכב עם טבלה מותאמת אישית ו-REST — 2–3 ימים. העלות מחושבת באופן אישי. בממוצע, התאמות אישיות כאלה חוסכות עד 60% מהתקציב בהשוואה לפריצות תבנית. צור קשר — נבחן את הפרויקט שלך. קבל ייעוץ על ארכיטקטורה ואופטימיזציה.
לפרטים נוספים על Views API ראה את התיעוד הרשמי של דרופל. הזמן פיתוח — קבל פתרון מוכן עם אחריות לתאימות וביצועים.







