סניפטים מותאמים אישית ל-MODX: פתרונות PHP מהירים עם pdoTools

סnippets סטנדרטיים של MODX רצים לעיתים קרובות לאט עקב שאילתות מסד נתונים מיותרות, מה שמאט את האתר ומתסכל משתמשים. אנו מפתחים סnippets PHP מותאמים אישית באמצעות pdoTools, מייעלים כל שאילתה ומיישמים caching. הצוות שלנו מספק פתרונות turnkey—מביקורת ועד תמיכה—ומבטיח ביצועים יציבים גם בעומסים גבוהים.

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

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

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

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
סניפטים מותאמים אישית ל-MODX: פתרונות PHP מהירים עם pdoTools
בינוני
~2-3 ימים

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

שאלות נפוצות

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

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

סניפט טיפוסי הוא העתק-הדבק לא מותאם

דמיינו שקטלוג המוצרים שלכם ב-MODX נטען תוך 5 שניות, וכל לחיצה על קטגוריה מרגישה כמו נצח. הסיבה: סניפטים לא מותאמים שמבצעים עשרות שאילתות מסד נתונים. תרחיש טיפוסי: מפתח העתיק את הקוד הראשון שמצא, בלי לחשוב על קשנון (Caching). התוצאה: שאילתות N+1, ירידה בביצועים וחוויית משתמש ירודה. איך לתקן? להשתמש בתבניות נכונות.

פיתוח סניפטים ל-MODX מתחיל לעיתים קרובות בהעתקת הדוגמה הראשונה מהתיעוד. התוצאה: שאילתות N+1, ללא קשנון, ופגיעויות שהופכות משימה פשוטה לצוואר בקבוק באתר כולו. אנו משתמשים בתבניות ארכיטקטוניות מוכחות: שאילתה אחת, קשנון והקלדה קפדנית של פרמטרים. ניסיון של למעלה מ-5 שנים ויותר מ-50 פרויקטים על MODX מאפשרים לנו ליצור סניפטים שעומדים באלפי בקשות ללא אובדן ביצועים.

איך להימנע משאילתות N+1 ב-MODX?

בעיית N+1 מתרחשת כאשר אתם שולפים אוסף של משאבים ולאחר מכן עבור כל אחד מהם טוענים ערכי TV דרך getTVValue בלולאה. עם 100 משאבים, מדובר ב-101 שאילתות SQL. הפתרון: להשתמש ב-JOIN או ב-pdoFetch. ה-API המקורי של MODX מאפשר JOIN ידני, אבל pdoTools עושה זאת אוטומטית ומהירה יותר. מידע נוסף על הבעיה בבעיית שאילתות N+1.

למה קשנון סניפטים חשוב?

קשנון מפחית את העומס על מסד הנתונים ומאיץ דפים. ללא קשנון, כל קריאה לסניפט משמעותה שאילתת SQL. בפרויקט עם קטלוג של 5000 פריטים, הסניפט המקורי לקח 4 שניות. לאחר הוספת קשנון, הזמן ירד ל-0.2 שניות לבקשות הבאות. יש לפסול את הקשנון כאשר הנתונים משתנים או להגדיר TTL, למשל 30 דקות.

מבנה סניפט עם שאילתה בטוחה

שאילתה מקורית עם JOIN

<?php // Сниппет ProductList // Вызов: [[!ProductList? &category=`5` &limit=`12` &sort=`price`]] // Получить параметры (с default значениями) $categoryId = (int)($scriptProperties['category'] ?? 0); $limit = (int)($scriptProperties['limit'] ?? 10); $offset = (int)($scriptProperties['offset'] ?? 0); $sortField = $scriptProperties['sort'] ?? 'menuindex'; $sortDir = $scriptProperties['sortdir'] ?? 'ASC'; $tpl = $scriptProperties['tpl'] ?? 'productCard'; // Запрос к ресурсам через MODX API $c = $modx->newQuery('modResource'); $c->where([ 'parent' => $categoryId, 'published' => 1, 'deleted' => 0, 'class_key' => 'modDocument', ]); // Получить TV значения через Join $c->innerJoin('modTemplateVarResource', 'TVPrice', [ 'TVPrice.tmplvarid' => $modx->getObject('modTemplateVar', ['name' => 'price'])->id, 'TVPrice.contentid = modResource.id', ]); $c->select('modResource.*, TVPrice.value AS price'); $c->sortby($sortField, $sortDir); $c->limit($limit, $offset); $resources = $modx->getCollection('modResource', $c); if (empty($resources)) return ''; $output = ''; foreach ($resources as $resource) { $data = array_merge($resource->toArray(), [ 'price' => $resource->get('price'), 'link' => $modx->makeUrl($resource->id, '', '', 'full'), 'image' => $resource->getTVValue('product_image'), ]); // Чанк для вывода карточки $output .= $modx->getChunk($tpl, $data); } return $output; 

סניפט עם pdoTools

<?php // Сниппет ProductSearch с pdoTools
if (!$modx->loadClass('pdoFetch', MODX_CORE_PATH . 'components/pdotools/model/pdotools/', false, true)) {
    return 'pdoTools не установлен';
}
$pdoFetch = new pdoFetch($modx, $scriptProperties);
$pdoFetch->addWhere([
    'modResource.parent' => (int)($scriptProperties['category'] ?? 0),
    'modResource.published' => 1,
]);
// TV join
$pdoFetch->addTVs('price,product_image,short_description');
$result = $pdoFetch->run();
return $result;

קשנון תוצאות

<?php
// Кэшировать результат на 30 минут
$cacheKey = 'products_' . md5(json_encode($scriptProperties));
$cacheOptions = [
    xPDO::OPT_CACHE_KEY => 'default',
    xPDO::OPT_CACHE_EXPIRES => 1800
];
$cached = $modx->cacheManager->get($cacheKey, $cacheOptions);
if ($cached !== null) return $cached;
// ... запрос ...
$output = generateOutput($resources);
$modx->cacheManager->set($cacheKey, $output, 1800, $cacheOptions);
return $output;

אינטגרציה עם API חיצוני

<?php
// Сниппет WeatherWidget — погода из OpenWeatherMap
$city = $scriptProperties['city'] ?? 'Moscow';
$apiKey = $modx->getOption('weather_api_key');
$tpl = $scriptProperties['tpl'] ?? 'weatherWidget';
$cacheKey = 'weather_' . $city;
$cached = $modx->cacheManager->get($cacheKey, [xPDO::OPT_CACHE_EXPIRES => 1800]);
if ($cached !== null) {
    return $modx->getChunk($tpl, $cached);
}
$url = "https://api.openweathermap.org/data/2.5/weather?q={$city}&appid={$apiKey}&units=metric&lang=ru";
$response = file_get_contents($url);
if (!$response) return '';
$data = json_decode($response, true);
if (!$data || $data['cod'] !== 200) return '';
$weather = [
    'city' => $data['name'],
    'temp' => round($data['main']['temp']),
    'feels_like' => round($data['main']['feels_like']),
    'description' => $data['weather'][0]['description'],
    'icon' => "https://openweathermap.org/img/wn/{$data['weather'][0]['icon']}@2x.png",
    'humidity' => $data['main']['humidity'],
];
$modx->cacheManager->set($cacheKey, $weather, 1800);
return $modx->getChunk($tpl, $weather);

אילו פרמטרים להעביר לסניפט?

[[!ProductList? &category=`[[*id]]` &limit=`12` &tpl=`productCardTpl` &sort=`price` &sortdir=`ASC` ]] 

<?php // Сниппет ProductList // Вызов: [[!ProductList? &category=`5` &limit=`12` &sort=`price`]] // Получить параметры (с default значениями) $categoryId = (int)($scriptProperties['category'] ?? 0); $limit = (int)($scriptProperties['limit'] ?? 10); $offset = (int)($scriptProperties['offset'] ?? 0); $sortField = $scriptProperties['sort'] ?? 'menuindex'; $sortDir = $scriptProperties['sortdir'] ?? 'ASC'; $tpl = $scriptProperties['tpl'] ?? 'productCard'; // Запрос к ресурсам через MODX API $c = $modx->newQuery('modResource'); $c->where([ 'parent' => $categoryId, 'published' => 1, 'deleted' => 0, 'class_key' => 'modDocument', ]); // Получить TV значения через Join $c->innerJoin('modTemplateVarResource', 'TVPrice', [ 'TVPrice.tmplvarid' => $modx->getObject('modTemplateVar', ['name' => 'price'])->id, 'TVPrice.contentid = modResource.id', ]); $c->select('modResource.*, TVPrice.value AS price'); $c->sortby($sortField, $sortDir); $c->limit($limit, $offset); $resources = $modx->getCollection('modResource', $c); if (empty($resources)) return ''; $output = ''; foreach ($resources as $resource) { $data = array_merge($resource->toArray(), [ 'price' => $resource->get('price'), 'link' => $modx->makeUrl($resource->id, '', '', 'full'), 'image' => $resource->getTVValue('product_image'), ]); // Чанк для вывода карточки $output .= $modx->getChunk($tpl, $data); } return $output; לפני השם — קריאה לא מאוחסנת (תוכן דינמי). ללא <?php // Сниппет ProductSearch с pdoTools if (!$modx->loadClass('pdoFetch', MODX_CORE_PATH . 'components/pdotools/model/pdotools/', false, true)) { return 'pdoTools не установлен'; } $pdoFetch = new pdoFetch($modx, $scriptProperties); $pdoFetch->addWhere([ 'modResource.parent' => (int)($scriptProperties['category'] ?? 0), 'modResource.published' => 1, ]); // TV join $pdoFetch->addTVs('price,product_image,short_description'); $result = $pdoFetch->run(); return $result; — מאוחסן (בלוק סטטי, זהה לכולם).

טבלת השוואת גישות

היבט MODX מקורי pdoTools עם קשנון
מספר שאילתות SQL N+1 (אוסף + TV) 1 (JOIN יחיד) פעם אחת, ולאחר מכן מהקשנון
קלות כתיבה דורש JOIN ידני טעינת TV אוטומטית 3 שורות נוספות
ביצועים על 1000 משאבים ~2-3 שניות ~0.3-0.5 שניות ~0.01 שניות לאחר הבקשה הראשונה
תמיכה בסינון הוספת where ידנית addWhere מובנה לא מושפע

טבלת פרמטרים טיפוסית לסניפט

פרמטר סוג תיאור ברירת מחדל
category int מזהה המשאב האב 0
limit int מספר הרשומות להצגה 10
sort string שדה המיון menuindex
sortdir string כיוון המיון (ASC/DESC) ASC
tpl string שם הצ'אנק לפלט productCard

טעויות נפוצות בפיתוח סניפטים

  • שאילתות N+1: קבלת TV דרך getTVValue בלולאה. פתרון: JOIN או pdoFetch.
  • חוסר בסינון קלט: פרמטרים ללא המרת סוג (category כמחרוזת במקום int).
  • התעלמות מקשנון: כל קריאה לסניפט טוענת את מסד הנתונים, גם אם הנתונים לא השתנו.
  • מזהי משאבים מקודדים: השתמשו ב-placeholders ובפרמטרים.
רשימת בדיקה: איך להימנע מטעויות
  • [ ] השתמשו בהצהרות מוכנות (Prepared Statements)
  • [ ] המירו את כל פרמטרי הקלט לסוג הנדרש
  • [ ] הוסיפו קשנון עם מפתח ייחודי
  • [ ] השתמשו ב-pdoFetch לשאילתות מורכבות
  • [ ] תעדו פרמטרים וצ'אנקים

מה כלול בעבודה

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

תהליך פיתוח סניפטים במפתח מלא

  1. ניתוח: לימוד הדרישות, אילו נתונים להציג, מאיפה, תנאי סינון.
  2. עיצוב: קביעת מבנה השאילתה, בחירת שיטה (מקורי או pdoTools), תכנון קשנון.
  3. יישום: כתיבת קוד PHP לסניפט ותבניות צ'אנק.
  4. בדיקות: בדיקת מקרי קצה (קטגוריות ריקות, 0 רשומות), מדידת זמן ביצוע.
  5. פריסה: העלאה לשרת הייצור, הגדרת קשנון, מתן תיעוד קריאה.

לוח זמנים ועלות

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

צרו קשר כדי לדון בפרויקט שלכם. הזמינו פיתוח סניפטים עכשיו — קבלו קוד מהיר ובטוח. ניסיון של למעלה מ-5 שנים עם MODX. פנו אלינו, ונעריך את המשימה ונציע את הפתרון האופטימלי.