Към съдържанието
PN Scripts

Разработка

Laravel CMS с приставки и теми като в WordPress: инсталиране и първа приставка

  • PN Scripts
  • 10 мин четене

WordPress направи една идея позната на всеки, който поддържа сайт: сайтът върши основното, а приставките и темите добавят останалото, инсталират се от zip и се включват и изключват от администрацията. Разработчиците на Laravel обикновено получават обратното: чиста рамка и много свобода, но всяка функция, която клиентът поиска, става промяна в самото приложение. PN Scripts Press е нашата CMS с отворен код, която пренася модела на WordPress в Laravel: страници от блокове, блог, менюта, медия, SEO полета и версии в администрация на Filament, разширявани с приставки и теми, които са папки с манифест. Тук я инсталираме, пишем малка приставка и тема и обясняваме докъде стига моделът.

#Инсталиране

Трябват ви PHP 8.4, Composer, Node.js и npm. Пакетът е в Packagist, така че една команда създава нов сайт, копира примерния файл със средата, задава ключа на приложението, създава база SQLite и пуска миграциите:

composer create-project pnscripts/pn-press my-site
cd my-site
php artisan db:seed
npm ci
npm run build
php artisan serve

Seeder-ът добавя демонстрационен сайт: начална страница, страници „За нас“ и „Контакти“, две менюта, темата Folio и двете примерни приставки, Contact Form и SEO Sitemap. Пропуснете го за празен сайт. Изграждането на интерфейса е нужно, защото пакетът не носи компилирани стилове. Отворете http://127.0.0.1:8000 за сайта и /admin за администрацията; създаденият администраторски профил е описан в README, а имейлът и паролата му трябва да се сменят веднага.

Преди сайтът да стане публичен, сменете две настройки в .env. Новият проект е проект за разработка: APP_ENV=local и APP_DEBUG=true показват подробни грешки и лента за отстраняване на грешки на всяка страница. Задайте APP_ENV=production и APP_DEBUG=false и ползвайте MySQL или PostgreSQL, ако няколко редактори ще работят едновременно.

#Какво е приставка

Приставката е папка в plugins/ с файл plugin.json. Манифестът дава името на приставката, версията ѝ, версията на Press, която ѝ трябва, пространство от имена, което Press зарежда автоматично от собствената папка на приставката (без стъпка с Composer), и доставчик на услуги (service provider) на Laravel, в който приставката върши работата си. Незадължителни са миграции, изгледи, файл с маршрути и екрани в администрацията. Приставката минава през пет състояния: инсталирана (разархивирана, нищо не работи), активна (доставчикът и миграциите ѝ се пускат), обновена (нова версия заменя папката и новите миграции се пускат веднъж), деактивирана (спира да се зарежда, данните ѝ остават) и деинсталирана (миграциите ѝ се връщат назад, а папката и настройките ѝ се изтриват).

Приставките променят сайта чрез действия и филтри, както в WordPress: add_action и do_action, за да изпълнят код в определена точка, и add_filter и apply_filters, за да променят стойност по пътя ѝ към страницата. Press дава точки за заглавната част и тялото на страницата, блоковете на страниците, съдържанието на публикациите, менютата, шаблоните на страници, екрана с настройки и картата на сайта.

#Да напишем приставка: списък на разделите

Дългите публикации се четат по-лесно с кратък списък на разделите им най-отгоре. Press няма такъв, затова е добра първа приставка. Трябват ѝ два файла. Манифестът:

{
    "slug": "contents",
    "name": "Contents",
    "version": "1.0.0",
    "description": "A list of a post's sections above its text, with links to each heading.",
    "author": "You",
    "requires": { "press": ">=1.0" },
    "provider": "Acme\\Contents\\ContentsServiceProvider",
    "autoload": { "psr-4": { "Acme\\Contents\\": "src/" } }
}

И доставчикът на услуги в src/ContentsServiceProvider.php:

<?php

namespace Acme\Contents;

use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;

class ContentsServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        add_filter('post.content', function (string $html): string {
            $items = [];
            $html = preg_replace_callback('#<h2>(.*?)</h2>#s', function (array $m) use (&$items): string {
                $text = html_entity_decode(trim(strip_tags($m[1])), ENT_QUOTES | ENT_HTML5, 'UTF-8');
                $id = (Str::slug($text) ?: 'section').'-'.(count($items) + 1);
                $items[] = '<li><a href="#'.e($id).'">'.e($text).'</a></li>';

                return '<h2 id="'.e($id).'">'.$m[1].'</h2>';
            }, $html);

            // The post body is printed as HTML: escape everything you add to it.
            if (count($items) < (int) press_setting('plugin.contents.min_sections', 3)) {
                return $html;
            }

            return '<nav aria-label="Contents"><p class="press-eyebrow">Contents</p><ol>'
                .implode('', $items).'</ol></nav>'.$html;
        });

        add_filter('settings.sections', function (array $sections): array {
            $sections[] = Section::make('Contents')->schema([
                TextInput::make('plugin.contents.min_sections')
                    ->label('Show the list from this many sections')->numeric()->minValue(1)->default(3),
            ]);

            return $sections;
        });
    }
}

Филтърът post.content получава HTML на публикацията. Приставката дава id на всяко заглавие от второ ниво, събира заглавията в списък с връзки и слага списъка над текста, когато разделите са поне три. Вторият филтър добавя раздел в екрана Settings на администрацията, за да може редакторът да промени това число, без да пипа код; press_setting() го чете. Две подробности си струва да се копират във всяка приставка. Тялото на публикацията се отпечатва като HTML, затова всичко, което приставката добавя, се екранира с e(). А знаци като &amp; се декодират преди екранирането, иначе „Q&A“ ще се покаже с видимо &amp;, както стана в първата ни версия.

Архивирайте папката и я инсталирайте от командния ред в папката на сайта или качете zip файла от Extend, Plugins в администрацията (тя е на английски):

zip -r contents.zip contents
php artisan press:plugin install contents.zip
php artisan press:plugin activate contents

В публикация със заглавия „Как да планирате седмицата“, „Q&A“ и „Done“ приставката добавя този списък и тези id; Laravel превръща заглавието на кирилица в id с латиница:

<nav aria-label="Contents"><p class="press-eyebrow">Contents</p><ol><li><a href="#kak-da-planirate-sedmicata-1">Как да планирате седмицата</a></li><li><a href="#qa-2">Q&amp;A</a></li><li><a href="#done-3">Done</a></li></ol></nav>
<h2 id="kak-da-planirate-sedmicata-1">
<h2 id="qa-2">
<h2 id="done-3">

За да промените приставката по-късно, вдигнете версията ѝ, архивирайте я отново и я инсталирайте с --replace; тя остава активна, а ако има нови миграции, те се пускат при следващата заявка.

#Повече от филтри

Същият доставчик може да регистрира блокове, които редакторите добавят в редактора на страници, файл с маршрути за публични страници (зарежда се с маршрутите на сайта, така че php artisan route:cache работи, а маршрутите на деактивирана приставка отговарят с 404 дори от стар кеш) и клас-приставка на Filament, който добавя екрани в администрацията. Примерът Contact Form показва всичко това: блок, маршрут с ограничение на заявките и капан за ботове, собствена таблица, раздел в настройките и входяща кутия за съобщенията с експорт в CSV.

#Тема с настройки

Темата е папка в themes/ с файл theme.json. Всеки Blade изглед в папката ѝ views/ заменя изгледа по подразбиране със същия път, а изгледите, които не копирате, продължават да работят. Настройките, описани в манифеста, се появяват под Customize в екрана Themes, проверяват се според типа си и стигат до страницата като CSS променливи (цвят с име accent става --press-accent) и атрибути на страницата. Минимална тема с цвят за акцент, бележка във футъра и собствен файл със стилове:

{
    "slug": "plain-ink",
    "name": "Plain Ink",
    "version": "1.0.0",
    "description": "Black on white with one accent colour.",
    "author": "You",
    "requires": { "press": ">=1.0" },
    "stylesheet": "assets/theme.css",
    "settings": [
        { "key": "accent", "label": "Accent colour", "type": "color", "default": "#b4232a" },
        { "key": "footer_note", "label": "Footer note", "type": "text", "default": "Printed on the web." }
    ]
}

Копирайте resources/views/press/partials/footer.blade.php на същия път в папката views/ на темата и сменете реда с авторските права, за да отпечатва настройката:

<p>&copy; {{ now()->year }} {{ $siteName }}. {{ app(\App\Press\Themes\ThemeManager::class)->setting('footer_note') }}</p>

Инсталирайте я и я активирайте с php artisan press:theme или я качете от Appearance, Themes, където Preview показва сайта с новата тема само на вас, преди Activate да я включи за всички. Едно ограничение е важно тук: тема, качена на работещ сайт, не минава през изграждането на интерфейса, затова стиловете ѝ трябва да са в собствения ѝ файл или да ползва класовете, които ядрото вече компилира.

#Сигурност: приставката е код

Приставката работи като PHP с пълен достъп до сайта и базата му, точно като приставка за WordPress, затова инсталирайте само код, на който вярвате, и оставете правото да се инсталират приставки и теми на администраторите. Press проверява всяко качване, преди да запише каквото и да е: размер на архива, брой файлове, размер след разархивиране и степен на компресия; без абсолютни пътища, .., обратни наклонени черти, символни връзки или скрити файлове като .env и .htaccess; само позволени типове файлове. Темата може да съдържа PHP само като Blade изгледи; когато добавихме обикновен .php файл в тема, инсталирането беше отказано. На сайтове, на които никой не бива да качва код от браузъра, задайте PRESS_PACKAGE_UPLOADS=false и инсталирайте през SSH.

#Докъде стига моделът

Press няма каталог с приставки и теми, автоматични обновления и отдалечено инсталиране, и това е нарочно: код стига до сайта само когато някой го сложи там. Няма коментари, многоезично съдържание и поддръжка на много сайтове. Приставките се пишат на PHP за Laravel и Filament, така че авторът трябва да познава и двете; приставки за WordPress не работят в нея.

#Откъде да я вземете

PN Scripts Press е безплатна и с отворен код под лиценз MIT, в GitHub и Packagist. Изградена е с Laravel 13, Filament 5, Livewire 4, Spatie Permission и Tailwind CSS 4 и идва с темите Folio и Nocturne, двете примерни приставки и ръководства за писане на приставки и теми.

#Често задавани въпроси

Работят ли приставки за WordPress в PN Scripts Press?

Не. Моделът е същият, папки с манифест, действия и филтри, активиране от администрацията, но приставките се пишат за Laravel и Filament.

Как да инсталирам приставка без администрацията?

Пуснете php artisan press:plugin install със zip файла или папката, после php artisan press:plugin activate с краткото име на приставката.

Безопасно ли е да се качват приставки от браузъра?

Качванията се проверяват за размер, пътища, скрити файлове и типове файлове, но приставката пак е PHP с пълен достъп до сайта. Инсталирайте само код, на който вярвате, или изключете качването с PRESS_PACKAGE_UPLOADS=false.

Какво трябва да сменя, преди сайтът да стане публичен?

Имейла и паролата на създадения администратор, APP_ENV=production и APP_DEBUG=false в .env и обикновено MySQL или PostgreSQL вместо SQLite.

#Източници

Коментари

Коментари

Напишете първия коментар.

Оставете коментар

Следваща стъпка

pnscripts.com/bg/contact

Пишете на екипа

Попитайте за статия или ни разкажете за проект, който искате да изградим. Отговаряме до един работен ден.

Пишете ни

Семейството PN Scripts

Другите сайтове на PN Scripts

Хостингът, игрите и блогът имат свои сайтове, поддържани от същата компания.

  • pnscripts.com

    PN Scripts

    Софтуерно инженерство

    Уеб и мобилни приложения, API и игри по поръчка, плюс нашите продукти и плъгини с отворен код.

  • games.pnscripts.com

    Игри

    Игри и игрови сървъри

    Домът на игрите на PN Scripts: безплатни браузърни игри, които се играят веднага, а игровите сървъри предстоят.

  • hosting.pnscripts.com

    Хостинг

    Хостинг и инфраструктура

    Споделен хостинг, KVM VPS, самостоятелни сървъри и домейни от същата компания, която изработва проекта ви.

  • blog.pnscripts.com

    Блог

    Статии и бележки

    Практични статии за разработка на софтуер, хостинг, отворен код и игри, писани от хората, които ги създават.

    Вие сте тук