Tema şablonları Twig ile yazılır. Bu sayfa ana şablonun anatomisini, kullanabileceğiniz yardımcıları ve sık yapılan hataları anlatır.
Ana şablon: layout.html.twig#
Her sayfa layout.html.twig'i genişletir. Aşağıdaki iskelet, varsayılan temadan sadeleştirilmiş, çalışan bir ana şablondur:
<!DOCTYPE html>
<html lang="{{ app.request.locale }}">
<head>
<meta charset="UTF-8">
{{ cp_consent_mode() }}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% block seo %}
{% set seo_title %}{% block title %}{% endblock %}{% endset %}
{% set seo_description %}{% block meta_description %}{% endblock %}{% endset %}
{% set seo_robots %}{% block meta_robots %}index, follow{% endblock %}{% endset %}
{{ cp_seo_head({ title: seo_title, description: seo_description, robots: seo_robots }) }}
{% endblock %}
<link rel="icon" type="image/png" href="{{ cp_appearance().favicon }}">
<link rel="stylesheet" href="{{ cp_theme_url('dist/style.css') }}">
{% set cpFonts = cp_font_stylesheet() %}
{% if cpFonts %}<link rel="stylesheet" href="{{ cpFonts }}">{% endif %}
<style{{ csp_nonce_attr() }}>{{ cp_appearance_css() }}</style>
{% block stylesheets %}{% endblock %}
{{ cp_hook('theme.head.end', {}) }}
</head>
<body class="{% block body_class %}{% endblock %}">
<a class="skip-link" href="#main">{{ 'website.skip_to_content'|trans }}</a>
{% include '@Theme/partials/header.html.twig' %}
<main id="main">
{% block content %}{% endblock %}
</main>
{{ cp_hook('theme.footer.before', {}) }}
{% include '@Theme/partials/footer.html.twig' %}
{{ cp_cookie_consent() }}
<script{{ csp_nonce_attr() }} src="{{ cp_theme_url('dist/main.js') }}"></script>
{% block javascripts %}{% endblock %}
</body>
</html>
Modüllerin doldurduğu bloklar#
Modül şablonları {% extends '@Theme/layout.html.twig' %} ile bu ana şablonu genişletir ve şu blokları doldurur. Ana şablonunuz bu blokları tanımlamak zorundadır, yoksa modüller içeriğini yerleştiremez:
| Blok |
Modülün koyduğu |
title, meta_description, meta_robots, meta_keywords |
SEO başlığı, açıklaması, robots değeri |
stylesheets |
Sayfaya özel CSS |
body_class |
<body> sınıfı |
content |
Sayfanın asıl içeriği |
javascripts |
Sayfaya özel betik |
Temanın sunması gereken iki kanca#
{{ cp_hook('theme.head.end', {}) }} {# </head> öncesi: analitik sayaçları vb. #}
{{ cp_hook('theme.footer.before', {}) }} {# alt bilgi öncesi: modüllerin kartları #}
Bu iki satır yoksa istatistik modülleri ve forum özet kartları gibi katkılar görünmez. Başka tema kancaları: theme.header.alerts, theme.header.user_badge.
Şablonları geçersiz kılmak#
Modül sayfaları @Theme/... yoluyla çağrılır. Bir sayfanın görünümünü değiştirmek için temanıza aynı yoldaki şablonu koyun:
Resources/views/blog/show.html.twig blog yazısı
Resources/views/blog/archive.html.twig blog arşivi
Resources/views/page/show.html.twig sayfa
Resources/views/forum/topics.html.twig forum konuları
Resources/views/search/index.html.twig arama sonuçları
Resources/views/partials/header.html.twig
Resources/views/partials/footer.html.twig
Yol, varsayılan temadaki yolla birebir aynı olmalıdır. Şablonlarınızı varsayılan temanın aynı dosyasını kopyalayıp değiştirerek başlatın: değişken adlarını ve blokları ondan görürsünüz.
Oturumu başlatmayan yardımcılar#
Ön yüzde `app.user` kullanmayın
Twig'in standart app.user, is_granted() ve app.flashes ifadeleri anonim ziyaretçide bile oturum başlatır. Oturumlu yanıt herkese ortak önbelleğe alınamaz; sitenin önbelleği çöker. CPalius bunlar için oturum güvenli karşılıklar sunar:
| Standart |
Ön yüzde kullanın |
Davranış |
app.user |
cp_user() |
Oturum çerezi yoksa null |
is_granted('x') |
cp_is_granted('x') |
Oturum çerezi yoksa false |
app.flashes |
cp_flashes() |
Oturum çerezi yoksa boş |
{% set me = cp_user() %}
{% if me %}
<a href="/hesap">{{ me.username }}</a>
{% else %}
<a href="/login">{{ 'website.login'|trans }}</a>
{% endif %}
Yönetim ekranlarında (Studio, AACP) oturum her zaman vardır; standart ifadeler orada serbesttir.
Yardımcı referansı#
Adres ve varlık#
| Yardımcı |
Ne yapar |
cp_theme_url('dist/style.css') |
Temanın bir dosyasının sürümlü adresi (önbellek kırma); dosya public/themes/<tema>/ altına ilk kullanımda kopyalanır |
cp_asset('yol') |
AssetMapper ile derlenmiş çekirdek varlığının adresi |
cp_path_if_exists('rota_adı', {…}) |
Rota yoksa boş dize döner; modül kapalıyken menü bağlantısını kırmaz |
csp_nonce_attr() |
Satır içi <script>/<style> için nonce özniteliği |
asset|cp_thumb(400, 300) |
Yüklenmiş görselin küçük resmi (ikinci ve üçüncü parametre boyut; 'fit' sığdırma) |
Menü ve alanlar#
| Yardımcı |
Ne yapar |
cp_menu_location('main_header') |
Konuma atanan menüyü hazır işaretlemeyle yazdırır |
cp_menu_location_items('main_header') |
Kendi işaretlemeniz için öğe ağacını verir |
cp_menu('ad') |
Adlandırılmış menünün öğe ağacını (label, url, openInNewTab, children) dizi olarak verir |
cp_widget_area('sidebar') |
Bir widget alanını çizer |
cp_field(node, 'alan') |
Bir alanı biçimlendirerek yazdırır |
cp_field_value(node, 'alan') |
Alanın ham değeri |
cp_fields(node, 'grup') |
Bir alan grubunu yazdırır |
cp_has_field(node, 'alan') |
Alan dolu mu |
cp_fields_preload(nodes) |
Listedeki referansları toplu yükler |
cp_entity_view(node, 'teaser') |
Varlığı bir görüntüleme modunda çizer |
Dil#
| Yardımcı |
Ne yapar |
cp_locales() |
Etkin diller listesi |
cp_locale_switcher('buttons') ya da 'dropdown' |
Hazır dil değiştirici |
cp_locale_links() |
Mevcut sayfanın diğer dillerdeki adresleri |
cp_locale_url('en') |
Mevcut sayfanın belirli dildeki adresi |
cp_hreflang_links() |
<link rel="alternate" hreflang> etiketleri (<head> içine) |
'anahtar'|trans |
Çeviri |
SEO#
| Yardımcı |
Ne yapar |
cp_seo_head({…}) |
Başlık, açıklama, canonical, Open Graph etiketleri (Seo modülü yoksa temel etiketler) |
cp_schema_org(node) |
schema.org JSON-LD |
Görünüm ve tercihler#
| Yardımcı |
Ne yapar |
cp_appearance() |
Yöneticinin seçtiği marka verisi (logo, favicon, renkler) |
cp_appearance_css() |
Seçilen renk/ölçülerin :root CSS değişkenleri |
cp_font_stylesheet() |
Yazı tipi ayarlarından üretilen CSS adresi (yoksa boş) |
cp_consent_mode() |
Google Consent Mode v2 varsayılanları (<head> içinde) |
cp_cookie_consent() |
Çerez onayı çubuğu (gövde sonunda) |
Kullanıcı ve yetki#
| Yardımcı |
Ne yapar |
cp_user(), cp_is_granted('x'), cp_flashes() |
Oturum güvenli kullanıcı, yetki ve flash mesajlar |
cp_current_user_avatar_url() |
Oturumdaki kullanıcının avatar adresi |
cp_notification_unread_count(), cp_recent_notifications() |
Bildirim sayacı ve son bildirimler |
Metin#
| Yardımcı |
Ne yapar |
text|text_format('basic_html') |
Metni bir metin biçiminden geçirip güvenli HTML verir |
text|reading_time |
Tahmini okuma süresi |
date|cp_date / date|cp_date(true) |
Dile uygun tarih (ikinci biçim saatle birlikte) |
Sistem#
| Yardımcı |
Ne yapar |
cp_version() |
Çekirdek sürümü |
cp_hook('nokta', {…}) |
Hook noktasını çizer |
Modüller kendi yardımcılarını da ekler (ör. Vitrin: cp_showcase_items; Mesajlar: cp_messages_unread). Bunlar yalnızca modül etkinken vardır; temanızda kullanıyorsanız cp_path_if_exists gibi korumalarla ya da modülün etkinliğini kontrol ederek yazın.
Sık yapılan hatalar#
for ... if söz dizimi Twig 3'te yoktur. Süzgeç kullanın: {% for x in items|filter(i => i.active) %}.
- Makro görünürlüğü: bir alt şablonun üstünde içe aktarılan makro, o şablonun
block içinde görünmez. Makroyu bloğun içinde içe aktarın.
- Kaçışlama: kullanıcı verisini
|raw ile basmayın. Zengin metin için text_format süzgecini kullanın.
- Dış kaynak:
<script src="https://cdn..."> CSP tarafından engellenir. Kütüphaneyi temanın dist/ klasörüne alın.
- Satır içi betik: nonce yoksa çalışmaz:
<script{{ csp_nonce_attr() }}>.
- Çeviri anahtarı yok:
'anahtar'|trans anahtarı olduğu gibi yazar. TR ve EN dosyalarına ekleyin.