Modül iskeleti
Bir modül, cp-content/modules/<Ad>/ altında yaşayan, kendi kendine yeten bir pakettir: kendi tabloları, yetenekleri, menüleri, çevirileri ve kurulum mantığıyla gelir. Çekirdek onu adıyla bilmez; modül çekirdeğe kendini bildirir.
İlk kez modül yazıyorsanız önce İlk modülünüz (öğretici) sayfasından başlayın. Bu sayfa, öğreticide gördüklerinizin referansıdır.
php cp-core/bin/console cp:module:create Ornek
Klasör düzeni
cp-content/modules/Ornek/
module.json manifest (zorunlu)
OrnekModule.php bundle sınıfı (zorunlu, genellikle boş)
Install/ModuleInstaller.php kurulum/kaldırma (zorunlu)
Entity/ Controller/ Controller/Admin/ Service/ Settings/ Command/ Hooks/ Cron/
Resources/
config/
capabilities.yaml yetenekler
routes.yaml rota yükleyiciler
services.yaml servis tanımı
contributions.yaml çekirdeğe katkılar (aşağıda)
importmap.php JavaScript giriş noktaları
migrations/ 001_ornek.sql, 002_...
translations/ messages+intl-icu.tr.yaml messages+intl-icu.en.yaml
views/ front/ admin/
assets/ yalnızca bu modülün JS/CSS dosyaları (vendor/ altında yerel kütüphaneler)
screenshot.png mağaza görseli (isteğe bağlı)
Zorunlu üçlü: module.json, bundle sınıfı ve Install/ModuleInstaller.php. Bunlardan biri yoksa ya da bundle adı manifestle eşleşmiyorsa paket denetimi modülü etkinleştirmeyi reddeder.
module.json
{
"name": "Ornek",
"version": "1.0.0",
"description": "Kısa açıklama (mağazada görünür)",
"author": "Ben",
"bundle": "Modules\\Ornek\\OrnekModule",
"core_version": ">=2.2.52 <3",
"requires": { "Media": "^1.0" },
"conflicts": { "EskiOrnek": "*" },
"provides": ["ornek"]
}
| Alan | Anlamı |
|---|---|
name |
Modül adı; dizin adıyla aynı olmalıdır |
version |
Modülün sürümü (MAJOR.MINOR.PATCH). Yükseltmeyi bu tetikler (aşağıda) |
description, author |
Mağaza ve AACP'de görünür |
bundle |
Modules\<Dizin>\<Dizin>Module biçiminde tam sınıf adı |
core_version |
Composer sürüm aralığı: modülün çalıştığı çekirdek sürümleri |
requires |
Bağımlı olduğu diğer modüller ve sürüm aralıkları |
extends |
Bu modül başka bir modülün eklentisiyse onun dizin adı (ör. Mesajlar için "Forum"). Üst modül requires'a kendiliğinden eklenir; modül listesinde ve mağazada "Forum eklentisi" rozeti çıkar. Yönetim menüsü girdilerini üst modülün altına koymak sizin işinizdir (parent: ile) |
conflicts |
Birlikte etkin olamayacağı modüller |
provides |
Modülün sağladığı yetenek kimlikleri |
Bütün alanlar isteğe bağlı olarak okunur (eski bir manifest geçerli kalır), ama etkinleştirme requires, conflicts ve core_version matrisini etkinleştirmeden önce doğrular ve sorunu insan okunur biçimde söyler. core_version'ın alt sınırını, modülün dayandığı özelliğin geldiği çekirdek sürümüne ayarlayın: Docs modülü league/commonmark bağımlılığı 2.2.52'de geldiği için >=2.2.52 <3 ister.
Bundle sınıfı
namespace Modules\Ornek;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class OrnekModule extends Bundle
{
}
Boş kalabilir. Symfony bundle'ı olduğu için Bundle metotlarını geçersiz kılabilirsiniz, ama çoğu modülde buna gerek kalmaz: yapılandırma YAML ile yüklenir.
Kurulum sınıfı
AbstractSqlModuleInstaller'ı genişletin; moduleId() ve kaldırmada silinecek tables() listesini verin:
final class ModuleInstaller extends AbstractSqlModuleInstaller
{
protected function moduleId(): string { return 'ornek'; }
protected function tables(): array { return ['cp_ornek_items']; }
}
Taban sınıf üç kancayı sağlar:
| Kanca | Ne zaman | Varsayılan davranış |
|---|---|---|
install() |
Etkinleştirmede | Resources/migrations/*.sql dosyalarını sırayla uygular |
upgrade($ctx, $from, $to) |
module.json sürümü artınca (cp:update) |
Yeni numaralı migration dosyalarını uygular |
uninstall() |
cp:module:deactivate --purge |
tables() listesindeki tabloları siler |
Başlangıç verisi (rol yetenekleri, alan tanımları, varsayılan sözlük terimleri) için bu kancaları geçersiz kılın. Alan tanımları için FieldDefinitionSeeder::ensure() kullanın: yalnızca eksik alanı oluşturur, bir editörün ince ayar yaptığı alanı ezmez.
Kurulumcu ayrıca rol dosyalarına yetenek ekleyebilir (Portal ve Vitrin modülleri editor ve member rollerine kendi yeteneklerini böyle ekler); bu işi idempotent yazın.
Rotalar ve servisler
Resources/config/routes.yaml iki blokludur: ön yüz ve yönetim.
ornek_module_front:
resource: ../../Controller/
type: attribute
prefix: /{_locale}
requirements:
_locale: '%cpalius.locales_pattern%'
defaults:
_locale: '%cpalius.default_locale%'
exclude:
- ../../Controller/Admin/
ornek_module_admin:
resource: ../../Controller/Admin/
type: attribute
- Ön yüz denetleyicileri
/{_locale}öneki alır (/tr/ornek);%cpalius.locales_pattern%etkin dillerden üretilen kısıttır. - Yönetim denetleyicileri (
Controller/Admin/) önek almaz; kendi#[Route('/admin/ornek')]adreslerini taşırlar.
Resources/config/services.yaml:
services:
_defaults:
autowire: true
autoconfigure: true
Modules\Ornek\Controller\:
resource: '../../Controller/'
tags: ['controller.service_arguments']
Modules\Ornek\Service\:
resource: '../../Service/'
autoconfigure açıkken öznitelikle işaretlenen sınıflar (#[CpHook], #[CpCronJob], #[CpFieldType], #[CpApi]) ve SearchProviderInterface uygulayan arama sağlayıcıları otomatik toplanır. Diğer genişletme arayüzleri için modülün services.yaml dosyasında etiket verirsiniz:
services:
_instanceof:
App\Core\Queue\AsyncJobHandlerInterface:
tags: ['cp.async_job_handler']
App\Core\Search\Admin\AdminSearchProviderInterface:
tags: ['cpalius.admin_search.provider']
Etiket adlarının tam listesi: Genişletme noktaları. Modüle özgü Settings/ ve Command/ klasörlerini de aynı biçimde services.yaml'a ekleyin.
Bir hata yapılırsa (bozuk YAML, olmayan sınıf) modül etkinleşmeden önce yakalanır; bkz. Genel bakış.
contributions.yaml: çekirdeğe katkılar
Çekirdek hiçbir modülü adıyla bilmez. Modülünüz çekirdeğin hangi özelliklerine bağlanacağını Resources/config/contributions.yaml ile bildirir:
# Her içerik türü için ön yüz gösterim rotası
node_show_routes:
ornek: ornek_show
# schema.org türü
schema_types:
ornek: WebPage
# Ana sayfa modu: AACP → Ana sayfa seçeneklerine eklenir
homepage_modes:
ornek:
route: ornek_index
label: ornek.homepage.mode
priority: 20
# Düz alan indeksine yazılacak (sorgulanabilir) alanlar
queryable_fields:
ornek:
is_featured: int
# Studio kısayolları ve tür etiketleri
studio:
type_labels:
ornek: Örnek
quick_create: []
quick_links: []
# Bildirim türleri
notification_types: []
# Gelen webhook uçları
inbound_webhooks: []
| Anahtar | Ne işe yarar |
|---|---|
node_show_routes |
Bir içerik türünün ön yüz adresini bulmak (site haritası, arama, bağlantılar) |
category_show_route |
Kategori sayfası rotası |
schema_types |
İçerik türünü schema.org türüne eşlemek |
homepage_modes |
Modülün / adresini göstermesini sağlamak |
queryable_fields |
Düz alan indeksine string, int, decimal, datetime türünde alan eklemek |
studio |
Studio'da tür etiketleri, düzenle/gör rotaları, hızlı oluşturma ve kısayollar, gizli türler |
notification_types |
Bildirim türlerini tanıtmak |
portal_blocks |
Portal ana sayfası blokları |
account |
Hesap sayfası bölümleri |
inbound_webhooks |
Gelen webhook uçlarını tanıtmak |
Dosya eksik anahtar olsa da geçerlidir; yalnızca ihtiyaç duyduğunuz bölümleri yazın.
Sürümleme ve yükseltme
module.jsoniçindekiversion'ı artırın (1.1.0).- Şema değiştiyse yeni numaralı bir migration ekleyin (
002_...sql); eskisini değiştirmeyin. - Veri düzeltmesi gerekiyorsa
upgrade()ya da birUpdateHookInterfaceyazın. - Yayınlayın; sitelerde
cp:update(ya da AACP güncellemesi) bekleyen migration'ları veupgrade()kancasını çalıştırır.
Modülün kurulu sürümü cp_settings içinde saklanır; sürüm farkı varsa AACP "güncelleme gerekli" der. Anlamlı sürüm numarası verin: yalnızca düzeltme PATCH, uyumlu özellik MINOR, kırıcı değişiklik MAJOR.
Güvenlik sözleşmesi
- Modül
cp-core/ya dacp-includes/içine yazamaz ve başvuramaz. App\ad alanını bildiremez.- Kullandığı kütüphaneleri
Resources/assets/vendor/altına yerel alır; CDN çağırmaz (CSP). - Anonim isteklerde oturum başlatmaz.
- Yönetim POST'larında CSRF belirteci doğrular.
Sonraki: Veritabanı ve migration.