תצוגות Drupal מותאמות אישית: מסננים, תוספים וייצוא REST

תצוגות סטנדרטיות ב-Drupal לא תמיד מתמודדות עם משימות לא שגרתיות: צריך פילטר טווח מחירים, נתונים ממקורות חיצוניים או פורמט שורות יוצא דופן. אנחנו בונים תוספי Views מותאמים אישית שפותרים משימות אלה במהירות וביעילות, ומגדירים גם REST export לשילוב עם מערכות חיצוניות. הצוות שלנו מוסר את הפרויקט במפתח מלא—מבדיקה ועד הטמעה—תוך הבטחת פעילות יציבה ותמיכה מתמשכת.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
תצוגות Drupal מותאמות אישית: מסננים, תוספים וייצוא REST
בינוני
מ- 1 יום עד 3 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1502
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1344
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1052
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1306
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1049
  • פיתוח אתר לחברת FIXPER
    פיתוח אתר לחברת FIXPER
    1033

מניסיוננו: לקוח רוצה מסנן טווח מחירים, אבל דרופל מציעה רק שדה טקסט. או שצריך להציג מוצרים מטבלה מותאמת אישית, אבל 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 ראה את התיעוד הרשמי של דרופל. הזמן פיתוח — קבל פתרון מוכן עם אחריות לתאימות וביצועים.