תוסף Statamic מותאם אישית: מהרעיון לפרסום
כאשר תגי Antlers סטנדרטיים או שדות מובנים אינם מספיקים ליישום לוגיקה עסקית ספציפית, תוסף Statamic מותאם אישית הוא הדרך היחידה. תרחיש טיפוסי: לקוח צריך ליצור דינמית קישורים למדיה חברתית עם תגי UTM — תגים מובנים אינם מאפשרים עיצוב גמיש. פיתחנו תג social_share שפתר את הבעיה תוך כמה שעות, והפחית את זמן יצירת הקישורים ב-40%. לדוגמה, חנות מסחר אלקטרוני נדרשה להציג מוצרים מוזלים בקרוסלה עם מיון ייחודי — תגי Statamic סטנדרטיים לא תמכו בכך. תג featured_products המותאם אישית פתר את המשימה תוך יום אחד, ומהירות טעינת העמוד עלתה ב-30%, בעוד החיסכון ברישיונות תוספים מוכנים הגיע ל-40%.
עם ניסיון של למעלה מ-5 שנים, יישמנו יותר מ-20 תוספים עבור Statamic — ממודיפיקטורים פשוטים ועד חבילות מקיפות עם שדות ווידג'טים של CP. כל תוסף הוא חבילת Laravel שמרחיבה את ה-CMS דרך ה-API הרשמי: תגי Antlers מותאמים, שדות, מודיפיקטורים, ווידג'טים ופקודות קונסול. הפתרון יכול להיות מופץ דרך Packagist או לשמש כחבילה מקומית.
אילו בעיות פותרים תוספים מותאמים אישית?
תגים מותאמים אישית — כאשר המובנים אינם מכסים את הלוגיקה. לדוגמה, יצירה דינמית של קישורים למדיה חברתית עם פרמטרים. תג social_share שלנו יוצר קישורים עבור Twitter, Telegram, VK ופלטפורמות אחרות, ומקבל פרמטרים של url, title ו-platform. שימוש ב-Antlers: {{ social_share:buttons url="{url}" title="{title}" }}.
// src/Tags/SocialShare.php
namespace Vendor\MyAddon\Tags;
use Statamic\Tags\Tags;
class SocialShare extends Tags
{
protected static $handle = 'social_share';
/**
* {{ social_share url="{url}" title="{title}" platform="twitter" }}
*/
public function index(): string
{
$url = urlencode($this->params->get('url', request()->url()));
$title = urlencode($this->params->get('title', ''));
$platform = $this->params->get('platform', 'all');
return match ($platform) {
'twitter' => "https://twitter.com/intent/tweet?url={$url}&text={$title}",
'telegram' => "https://t.me/share/url?url={$url}&text={$title}",
'vk' => "https://vk.com/share.php?url={$url}&title={$title}",
default => $this->renderAllButtons($url, $title),
};
}
/**
* {{ social_share:buttons url="{url}" }}
* Рендерит view с кнопками
*/
public function buttons(): string
{
return view('my-addon::social-share', [
'url' => urlencode($this->params->get('url', request()->url())),
'title' => urlencode($this->params->get('title', '')),
])->render();
}
}שדות לא סטנדרטיים — כאשר יש צורך בבורר צבעים ויזואלי, עורך מותאם או שדה מורכב. שדה ColorSwatch שלנו הוא פתרון מוכן לפלטות צבעים עם רכיב Vue ב-CP.
// src/Fieldtypes/ColorSwatchFieldtype.php
namespace Vendor\MyAddon\Fieldtypes;
use Statamic\Fields\Fieldtype;
class ColorSwatchFieldtype extends Fieldtype
{
protected static $handle = 'color_swatch';
public static function title(): string
{
return 'Color Swatch';
}
public function configFieldItems(): array
{
return [
'swatches' => [
'display' => 'Color Swatches',
'type' => 'array',
'value_header' => 'HEX Value',
'key_header' => 'Name',
],
];
}
public function preload(): array
{
return [
'swatches' => $this->config('swatches', []),
];
}
public function preProcess(mixed $data): mixed
{
return $data ?? null;
}
public function process(mixed $data): mixed
{
return $data;
}
}רכיב Vue עבור CP (// src/Tags/SocialShare.php namespace Vendor\MyAddon\Tags; use Statamic\Tags\Tags; class SocialShare extends Tags { protected static $handle = 'social_share'; /** * {{ social_share url="{url}" title="{title}" platform="twitter" }} */ public function index(): string { $url = urlencode($this->params->get('url', request()->url())); $title = urlencode($this->params->get('title', '')); $platform = $this->params->get('platform', 'all'); return match ($platform) { 'twitter' => "https://twitter.com/intent/tweet?url={$url}&text={$title}", 'telegram' => "https://t.me/share/url?url={$url}&text={$title}", 'vk' => "https://vk.com/share.php?url={$url}&title={$title}", default => $this->renderAllButtons($url, $title), }; } /** * {{ social_share:buttons url="{url}" }} * Рендерит view с кнопками */ public function buttons(): string { return view('my-addon::social-share', [ 'url' => urlencode($this->params->get('url', request()->url())), 'title' => urlencode($this->params->get('title', '')), ])->render(); } } ):
<template>
<div class="color-swatches">
<div
v-for="(hex, name) in meta.swatches"
:key="name"
class="swatch"
:class="{ selected: value === hex }"
:style="{ backgroundColor: hex }"
:title="name"
@click="$emit('input', hex)"
/>
<div v-if="value" class="selected-color">
{{ value }}
<button @click="$emit('input', null)">×</button>
</div>
</div>
</template>מודיפיקטורים ממוקדים — לדוגמה, חישוב זמן קריאה. המודיפיקטור // src/Fieldtypes/ColorSwatchFieldtype.php namespace Vendor\MyAddon\Fieldtypes; use Statamic\Fields\Fieldtype; class ColorSwatchFieldtype extends Fieldtype { protected static $handle = 'color_swatch'; public static function title(): string { return 'Color Swatch'; } public function configFieldItems(): array { return [ 'swatches' => [ 'display' => 'Color Swatches', 'type' => 'array', 'value_header' => 'HEX Value', 'key_header' => 'Name', ], ]; } public function preload(): array { return [ 'swatches' => $this->config('swatches', []), ]; } public function preProcess(mixed $data): mixed { return $data ?? null; } public function process(mixed $data): mixed { return $data; } } סופר מילים ומציג "N דקות קריאה".
ווידג'טים של CP ופקודות קונסול — עבור לוח הניהול ואוטומציה. פקודות קונסול מבצעות אוטומציה של משימות שגרתיות כמו ייבוא תוכן מ-CSV או ניקוי מטמון בלוח זמנים. יצרנו את הפקודה resources/js/components/fieldtypes/ColorSwatchFieldtype.vue שמעבדת 10,000 רשומות ב-15 דקות. הכל נרשם דרך ServiceProvider:
// src/ServiceProvider.php
namespace Vendor\MyAddon;
use Statamic\Providers\AddonServiceProvider;
use Statamic\Facades\Fieldtype;
use Statamic\Facades\Modifier;
class ServiceProvider extends AddonServiceProvider
{
protected $tags = [
\Vendor\MyAddon\Tags\SocialShare::class,
\Vendor\MyAddon\Tags\RelatedContent::class,
];
protected $fieldtypes = [
\Vendor\MyAddon\Fieldtypes\ColorSwatchFieldtype::class,
];
protected $modifiers = [
\Vendor\MyAddon\Modifiers\ReadingTime::class,
\Vendor\MyAddon\Modifiers\Truncate::class,
];
protected $widgets = [
\Vendor\MyAddon\Widgets\RecentEditsWidget::class,
];
protected $commands = [
\Vendor\MyAddon\Console\Commands\ImportContent::class,
];
public function boot(): void
{
parent::boot();
$this->mergeConfigFrom(__DIR__.'/../config/my-addon.php', 'my-addon');
$this->publishes([
__DIR__.'/../config/my-addon.php' => config_path('my-addon.php'),
], 'my-addon-config');
$this->loadViewsFrom(__DIR__.'/../resources/views', 'my-addon');
}
} איך לפתח תוסף: תהליך שלב-אחר-שלב
- יצירת שלד — דרך
<template> <div class="color-swatches"> <div v-for="(hex, name) in meta.swatches" :key="name" class="swatch" :class="{ selected: value === hex }" :style="{ backgroundColor: hex }" :title="name" @click="$emit('input', hex)" /> <div v-if="value" class="selected-color"> {{ value }} <button @click="$emit('input', null)">×</button> </div> </div> </template>. יוצר מבנה ב-reading_time. - הגדרת composer.json — הגדרת סוג
import:content, תלויות וטעינה אוטומטית.
{
"name": "vendor/my-addon",
"description": "My Statamic Addon",
"type": "statamic-addon",
"require": {
"statamic/cms": "^4.0"
},
"extra": {
"statamic": {
"name": "My Addon",
"slug": "my-addon"
}
},
"autoload": {
"psr-4": {
"Vendor\\MyAddon\\": "src/"
}
}
} - חיבור בפרויקט — הוספת המאגר ל-
// src/ServiceProvider.php namespace Vendor\MyAddon; use Statamic\Providers\AddonServiceProvider; use Statamic\Facades\Fieldtype; use Statamic\Facades\Modifier; class ServiceProvider extends AddonServiceProvider { protected $tags = [ \Vendor\MyAddon\Tags\SocialShare::class, \Vendor\MyAddon\Tags\RelatedContent::class, ]; protected $fieldtypes = [ \Vendor\MyAddon\Fieldtypes\ColorSwatchFieldtype::class, ]; protected $modifiers = [ \Vendor\MyAddon\Modifiers\ReadingTime::class, \Vendor\MyAddon\Modifiers\Truncate::class, ]; protected $widgets = [ \Vendor\MyAddon\Widgets\RecentEditsWidget::class, ]; protected $commands = [ \Vendor\MyAddon\Console\Commands\ImportContent::class, ]; public function boot(): void { parent::boot(); $this->mergeConfigFrom(__DIR__.'/../config/my-addon.php', 'my-addon'); $this->publishes([ __DIR__.'/../config/my-addon.php' => config_path('my-addon.php'), ], 'my-addon-config'); $this->loadViewsFrom(__DIR__.'/../resources/views', 'my-addon'); } }של הפרויקט. - בדיקות — כיסוי בבדיקות יחידה באמצעות Pest/PHPUnit. הבטחת כיסוי של לפחות 80%.
- פרסום — אם נדרש, שחרור ב-Packagist או ב-Statamic Marketplace.
איך לפרסם תוסף ב-Marketplace?
כדי לפרסם ב-Statamic Marketplace, צור חשבון מפתח, מלא את התיאור, הגדר מחיר (אם פרימיום), ועבור אישור. בדרך כלל זה לוקח 1-2 ימים לאחר ההעלאה.לוחות זמנים ומה כלול
| סוג תוסף | זמן |
|---|---|
| 2–3 תגי Antlers | 1–2 ימים |
| שדה עם רכיב Vue | 2–4 ימים |
| ווידג'ט CP | 1–2 ימים |
| תוסף מלא (תגים + שדה + הגדרות) | 1–2 שבועות |
| הכנה לפרסום ב-Marketplace | +1–2 ימים |
מה כלול:
- קוד מקור עם רישיון MIT.
- תיעוד (README עם דוגמאות שימוש).
- גישה למאגר פרטי (GitHub/GitLab) במהלך הפיתוח.
- בדיקות יחידה (כיסוי של לפחות 80%).
- תמיכה חינמית למשך 30 יום לאחר המסירה.
השוואה: תוסף מוכן מול תוסף מותאם אישית
| קריטריון | תוסף מוכן | תוסף מותאם אישית |
|---|---|---|
| מהירות יישום | כמה דקות | יום עד שבועיים |
| התאמה לדרישות | לעיתים רחוקות 100% | מותאם בדיוק |
| ביצועים | ממוצע | מותאם לתרחיש (עד פי 2 מהיר יותר) |
| תועלת כלכלית | רישיון עד $200 | חיסכון של עד 50% בשימוש ארוך טווח |
| תמיכה | תלוי במפתח | האחריות שלנו ל-30 יום |
לדוגמה, בפרויקט אחד, החלפת תוסף מוכן בתוסף מותאם אישית הפחיתה את זמן העיבוד מ-2.5 ל-0.8 שניות — שיפור של פי 3, ועלויות הרישיון ירדו ב-40%.
למה להזמין פיתוח תוספים מאיתנו?
ניסיון עם Laravel ו-Statamic — 5+ שנים. למעלה מ-20 תוספים מוצלחים, כולל כאלה שפורסמו ב-Marketplace. אחריות על הקוד — אנו מתקנים באגים בחינם בחודש הראשון. תהליך שקוף — אתה רואה את ההתקדמות ב-Trello או Jira.
בניגוד לפתרונות סטנדרטיים, תוסף מותאם אישית פועל עד פי 3 מהר יותר בזכות אופטימיזציה למשימה הספציפית. אנו עוקבים אחר התיעוד הרשמי של תוספי Statamic.
צור קשר להערכת פרויקט — קבל ייעוץ והצעה מסחרית תוך יום. הזמן פיתוח תוסף מותאם אישית וקבל חבילה מוכנה עם תיעוד ובדיקות.







