מה לא בסדר בהרחבות ג'ומלה מוכנות?
תארו לעצמכם: הרחבת קטלוג סטנדרטית חסרה את הפילטר הדרוש, והתאמת הקוד שלה הופכת לסיוט. כל עדכון שובר שינויים, לקוחות מתלוננים על ביצועים איטיים, ואתם תקועים לשלם דמי מנוי עבור תכונות שאינכם משתמשים בהן. הצוות שלנו ראה זאת עשרות פעמים. לכן אנו מפתחים רכיבי ג'ומלה מותאמים אישית מאפס — המותאמים בדיוק ללוגיקה העסקית שלכם, ללא פשרות. כמפתחי ג'ומלה עם ניסיון של למעלה מעשור, אנו מתמחים ביצירת רכיבי ג'ומלה ובארכיטקטורת רכיבי ג'ומלה 5.
| קריטריון | הרחבה מוכנה | רכיב מותאם אישית |
|---|---|---|
| תכונות | רבות ומיותרות | רק מה שצריך |
| ביצועים | ממוצעים, שאילתות רבות | שאילתות אופטימליות, אינדקסים |
| אבטחה | קוד לא ידוע | נבדק ומאומת |
| מדרגיות | מוגבלת | קל להרחבה |
| תמיכה | ספק (לעיתים בתשלום) | אנו מתחזקים ומשפרים |
| עלות בעלות כוללת | גבוהה (מנויים) | נמוכה (חד-פעמית) |
בפרויקט של רשת קמעונאית, החלפנו שלוש הרחבות בתשלום ברכיב מותאם אישית אחד. מספר השאילתות SQL לעמוד ירד מ-50 ל-5, TTFB ירד ב-40%, ו-LCP ב-35%. תקציב התמיכה קוצץ בשני שלישים, וחוסך למעלה מ-8,000 דולר בשנה.
כמה עולה פיתוח רכיב ג'ומלה מותאם אישית?
התמחור שקוף ומבוסס על מורכבות. רכיב ג'ומלה CRUD פשוט עם ישות אחת מתחיל מ-2,500 דולר. פרויקט בינוני עם טבלאות מרובות, פאנל ניהול וחזית נע בין 5,000 ל-10,000 דולר. אינטגרציות מורכבות עם API של צד שלישי יכולות להגיע עד 15,000 דולר. בהשוואה לדמי מנוי שנתיים של 1,200–3,000 דולר עבור הרחבות מוכנות, רכיב מותאם אישית מחזיר את עצמו תוך שנתיים. זמן הפיתוח הוא 14 יום עד 8 שבועות, ואנו מספקים אחריות ל-3 חודשים.
תהליך הפיתוח שלנו לרכיבי ג'ומלה מותאמים אישית
אנו פועלים לפי מתודולוגיה מוכחת. היא מתחילה בבדיקת דרישות עסקיות ועיצוב סכמת מסד נתונים. לאחר מכן אנו בונים API המבוסס על ארכיטקטורת MVC של ג'ומלה. כל רכיב עובר בדיקת קוד ובדיקות עומס. אנו משתמשים ב-Namespace, PSR-4 ו-Dependency Injection — מה שהופך את התחזוקה לפשוטה. מפתחי הג'ומלה שלנו מבטיחים תאימות לג'ומלה 4 ולג'ומלה 5.
האנטומיה של רכיב ג'ומלה
רכיב הוא יחידת התפקוד העיקרית (לפי תיעוד ג'ומלה). יש לו שני חלקים: אתר וניהול. מבנה אופייני:
com_catalog/
├── catalog.xml # Манифест
├── administrator/
│ └── components/
│ └── com_catalog/
│ ├── src/
│ │ ├── Controller/ # Контроллеры
│ │ ├── Model/ # Модели
│ │ ├── View/ # Вьюхи
│ │ └── Table/ # Таблицы БД
│ ├── tmpl/ # Шаблоны
│ └── services/
│ └── provider.php # DI Provider
└── components/
└── com_catalog/
├── src/
│ ├── Controller/
│ ├── Model/
│ └── View/
└── tmpl/ מניפסט (catalog.xml)
<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="4.0">
<name>Каталог товаров</name>
<namespace path="src">MyCompany\Component\Catalog</namespace>
<version>1.0.0</version>
<files folder="components/com_catalog">
<filename>index.html</filename>
<folder>src</folder>
<folder>tmpl</folder>
</files>
<administration>
<files folder="administrator/components/com_catalog">
<filename>index.html</filename>
<folder>src</folder>
<folder>tmpl</folder>
<folder>services</folder>
</files>
<menu img="class:catalog">Каталог</menu>
</administration>
<install>
<sql>
<file driver="mysql" charset="utf8">sql/install.mysql.sql</file>
</sql>
</install>
<uninstall>
<sql>
<file driver="mysql" charset="utf8">sql/uninstall.mysql.sql</file>
</sql>
</uninstall>
</extension> מודל
// components/com_catalog/src/Model/ProductsModel.php
namespace MyCompany\Component\Catalog\Site\Model;
use Joomla\CMS\MVC\Model\ListModel;
class ProductsModel extends ListModel
{
protected function getListQuery(): \Joomla\Database\QueryInterface
{
$db = $this->getDatabase();
$query = $db->getQuery(true);
$query->select(['p.id', 'p.title', 'p.price', 'p.sku', 'p.category_id', 'c.title AS category_name'])
->from($db->quoteName('#__catalog_products', 'p'))
->join('LEFT', $db->quoteName('#__catalog_categories', 'c') . ' ON c.id = p.category_id')
->where($db->quoteName('p.published') . ' = 1');
// Фильтр по категории
$categoryId = $this->getState('filter.category_id');
if ($categoryId) {
$query->where($db->quoteName('p.category_id') . ' = ' . (int) $categoryId);
}
// Поиск
$search = $this->getState('filter.search');
if ($search) {
$query->where($db->quoteName('p.title') . ' LIKE ' . $db->quote('%' . $search . '%'));
}
$query->order($db->quoteName($this->getState('list.ordering', 'p.title')) . ' ' . $this->getState('list.direction', 'ASC'));
return $query;
}
} תצוגה
// components/com_catalog/src/View/Products/HtmlView.php
namespace MyCompany\Component\Catalog\Site\View\Products;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
use Joomla\CMS\Factory;
class HtmlView extends BaseHtmlView
{
protected array $items = [];
protected object $pagination;
protected object $state;
public function display($tpl = null): void
{
$model = $this->getModel();
$this->items = $model->getItems();
$this->pagination = $model->getPagination();
$this->state = $model->getState();
// Добавить toolbar для администраторов
if (Factory::getApplication()->isClient('administrator')) {
$this->addToolbar();
}
parent::display($tpl);
}
protected function addToolbar(): void
{
$toolbar = \Joomla\CMS\Toolbar\ToolbarHelper::class;
$toolbar::title('Каталог товаров', 'catalog');
$toolbar::addNew('product.add');
$toolbar::deleteList('', 'products.delete');
}
} מלכודות נפוצות שאנו פותרים
- שאילתות N+1: מודלי ג'ומלה לעיתים קרובות טוענים נתונים קשורים עם שאילתות נפרדות. אנו משתמשים ב-JOINs ובטעינה מוקדמת (כמו בדוגמה לעיל).
- אי-התאמת הידרציה: מטמון יכול לגרום לסכסוכי נתונים. פתרון: הפרדת מצב ברורה וטיפול נכון במטמון.
- הרשאות ACL: ACL של ג'ומלה דורש בדיקות מפורשות בקוד. אנו מוסיפים אותן בכל בקר.
מה כלול בפיתוח הרכיבים שלנו
| שלב | משך | תוצר |
|---|---|---|
| ניתוח דרישות | 2–5 ימים | מפרט טכני |
| עיצוב | 3–7 ימים | סכמת DB, מפרט API |
| פיתוח | 14 יום – 8 שבועות | קוד עובד |
| בדיקות | 3–5 ימים | דוח באגים, כיסוי >80% |
| תיעוד | 1–2 ימים | מדריכים, readme |
לוחות זמנים ותמחור
לוחות הזמנים נעים בין 14 יום ל-8 שבועות בהתאם למורכבות. אנו מספקים מחיר קבוע לאחר בדיקה, עם תשלומים מבוססי אבני דרך. צרו קשר כדי לאבחן את המקרה שלכם ולקבל הערכה. מעל 100 פרויקטים שנמסרו, חיסכון ממוצע בעלויות של 40% בהשוואה לדמי מנוי שוטפים.
אבטחת איכות
עם ניסיון של 10+ שנים בפיתוח רכיבי ג'ומלה ו-50+ פרויקטים שנמסרו, אנו מבטיחים שכל רכיב עובר בדיקת קוד ובעל כיסוי בדיקות יחידה מעל 80%. אנו משתמשים ב-Git Flow ובבדיקות CI/CD אוטומטיות. כל קוד המקור נמסר ללא תלות בצוות שלנו. תקופת אחריות מכסה בעיות לאחר ההשקה. זמן התגובה הממוצע שלנו הוא מתחת ל-200ms, ואנו משיגים זמינות של 99.9% עבור רכיבים מתארחים.
טעויות נפוצות בפיתוח רכיבי ג'ומלה עצמאי
- חסר ספק DI → הרכיב נכשל עם שגיאת 500 בהפעלה. פתרון: צרו
com_catalog/ ├── catalog.xml # Манифест ├── administrator/ │ └── components/ │ └── com_catalog/ │ ├── src/ │ │ ├── Controller/ # Контроллеры │ │ ├── Model/ # Модели │ │ ├── View/ # Вьюхи │ │ └── Table/ # Таблицы БД │ ├── tmpl/ # Шаблоны │ └── services/ │ └── provider.php # DI Provider └── components/ └── com_catalog/ ├── src/ │ ├── Controller/ │ ├── Model/ │ └── View/ └── tmpl/עם<?xml version="1.0" encoding="utf-8"?> <extension type="component" version="4.0"> <name>Каталог товаров</name> <namespace path="src">MyCompany\Component\Catalog</namespace> <version>1.0.0</version> <files folder="components/com_catalog"> <filename>index.html</filename> <folder>src</folder> <folder>tmpl</folder> </files> <administration> <files folder="administrator/components/com_catalog"> <filename>index.html</filename> <folder>src</folder> <folder>tmpl</folder> <folder>services</folder> </files> <menu img="class:catalog">Каталог</menu> </administration> <install> <sql> <file driver="mysql" charset="utf8">sql/install.mysql.sql</file> </sql> </install> <uninstall> <sql> <file driver="mysql" charset="utf8">sql/uninstall.mysql.sql</file> </sql> </uninstall> </extension>. - שאילתות SQL ישירות במקום
// components/com_catalog/src/Model/ProductsModel.php namespace MyCompany\Component\Catalog\Site\Model; use Joomla\CMS\MVC\Model\ListModel; class ProductsModel extends ListModel { protected function getListQuery(): \Joomla\Database\QueryInterface { $db = $this->getDatabase(); $query = $db->getQuery(true); $query->select(['p.id', 'p.title', 'p.price', 'p.sku', 'p.category_id', 'c.title AS category_name']) ->from($db->quoteName('#__catalog_products', 'p')) ->join('LEFT', $db->quoteName('#__catalog_categories', 'c') . ' ON c.id = p.category_id') ->where($db->quoteName('p.published') . ' = 1'); // Фильтр по категории $categoryId = $this->getState('filter.category_id'); if ($categoryId) { $query->where($db->quoteName('p.category_id') . ' = ' . (int) $categoryId); } // Поиск $search = $this->getState('filter.search'); if ($search) { $query->where($db->quoteName('p.title') . ' LIKE ' . $db->quote('%' . $search . '%')); } $query->order($db->quoteName($this->getState('list.ordering', 'p.title')) . ' ' . $this->getState('list.direction', 'ASC')); return $query; } }→ פוגע בתאימות עם מערכות DBMS שונות. השתמשו ב-// components/com_catalog/src/View/Products/HtmlView.php namespace MyCompany\Component\Catalog\Site\View\Products; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; use Joomla\CMS\Factory; class HtmlView extends BaseHtmlView { protected array $items = []; protected object $pagination; protected object $state; public function display($tpl = null): void { $model = $this->getModel(); $this->items = $model->getItems(); $this->pagination = $model->getPagination(); $this->state = $model->getState(); // Добавить toolbar для администраторов if (Factory::getApplication()->isClient('administrator')) { $this->addToolbar(); } parent::display($tpl); } protected function addToolbar(): void { $toolbar = \Joomla\CMS\Toolbar\ToolbarHelper::class; $toolbar::title('Каталог товаров', 'catalog'); $toolbar::addNew('product.add'); $toolbar::deleteList('', 'products.delete'); } }ובפרמטרים בעלי שם. - השמטת uninstall.sql → טבלאות נשארות לאחר הסרת ההתקנה. הוסיפו סקריפט SQL בקטע המניפסט
services/provider.php. - הרשאות ACL שגויות → משתמשים רואים נתונים של אחרים או לא יכולים לגשת לפאנל הניהול. בדקו
ComponentDispatcherFactoryInterfaceבכל בקר. - אין namespace במניפסט → טוען PSR-4 נכשל. ציינו
QueryInterface.
התחלה
- תארו את הדרישות שלכם — איזה נתונים הרכיב מטפל, אילו ממשקים (אתר, ניהול, או שניהם).
- בדיקה — אנו בודקים את התקנת הג'ומלה שלכם, הרחבות מותקנות וסכמה DB.
- מפרט והערכה — אנו מסכימים על תכונות, ארכיטקטורה ומחיר לפני התחלה.
- פיתוח אינקרמנטלי — אתם מקבלים תוצר עובד כל שבוע לבדיקה.
- מסירה ותמיכה — תיעוד, הדרכת צוות ותקופת אחריות של 3 חודשים.
רכיב מותאם אישית זול משמעותית משנים של מנויים להרחבות מוכנות — במיוחד כשמתחשבים בשינויים ובעדכוני ג'ומלה. המחיר קבוע בחוזה, ללא עלויות נסתרות.
צרו קשר לייעוץ — אנו נעריך את הפרויקט שלכם ונראה דוגמאות של רכיבים דומים. הזמינו פיתוח ללא סיכון עם היקף קבוע.







