Najpopularniejszymi na świecie systemami do zarządzania treścią są: WordPress, Drupal, Joomla. Tego typu systemy CMS pozwalają zarządzać frontendem bez znajomości języków programowania (czasami wymagana jest minimalna wiedza techniczna). Jeśli potrzebujesz platformy sprzedażowej, wystarczy zainstalować e-commerce Magento. Oczywiście, może okazać się, że żaden „gotowiec” nie sprosta specyfikacji technicznej projektu, ze względu na jego uniwersalność. Czasami też łatwiej i szybciej jest zakodować coś od nowa, niż burzyć i przebudowywać stare. Do każdego konceptu należy podejść indywidualnie. Załóżmy, że masz za zadanie zbudować prostą stronę typu Landing Page. W tym przypadku instalacja WordPressa może nie mieć sensu, bo wystarczy zakodować ją w zwykłym HTMLu i CSS, dołączając odpowiednie biblioteki JavaScript do mechanizmów typu paralaksa, slider itp.
Standardem stają się aplikacje fontendowe typu SPA (ang. Single Page Application), które mogą działać niezależnie od backendu – dzięki udostępnianiu architektury REST API. Takie rozwiązania pozwalają budować aplikacje przenośne pomiędzy platformami i urządzeniami mobilnymi. W odpowiedzi na tego typu rozwiązania zaczęły powstawać jak grzyby po deszczu API CMSy, np: api-platform.com. Po co zamykać się w archaicznych monolitach, kiedy można tworzyć bez barier. Tak elastyczne podejście wymaga oczywiście więcej wkładu pracy i czasu, ale poziom satysfakcji jest dużo większy 🙂 .
Jeżeli tworzysz „od zera” (moduły, biblioteki lub całą aplikację), ważne jest aby trzymać się pewnych standardów programowania opartych o wzorce projektowe. Nie rób nic po swojemu, bo i tak to spierdolisz. Zapomnij. Stracisz cenny czas na łatanie błędów, albo przepisywanie kodu od nowa. W końcu i tak „skończysz jak każdy” – wybierzesz jakiś framework. To najlepsze wyjście!
Symfony i jego nowe dziecko Webpack Encore to idealny zestaw do budowy aplikacji i stron internetowych. Jeśli chcesz zrozumieć dlaczego, to podążaj za mną w głąb króliczej nory …
I. SYMFONY FLEX
Symfony odrodził się niczym „Feniks z popiołów” jako Flex. Wersja „odchudzona” składa się z komponentów, które dobierasz do projektu wedle potrzeb. Nie ma sensu instalowanie modułów, z których nie będziesz korzystał, jak to było w poprzednich wersjach silnika.
CHARAKTERYSTYKA ŚRODOWISKA SYMFONY
Do budowy szablonów podpięty jest system Twig, który jest bezpieczny i rozszerzalny (można dodawać własne filtry i funkcje). Komunikacja z bazą danych opiera się o Doktrynę ORM, ale można wybrać też inne mapowanie np.: Propel ORM. Symfony nie zmusza do niczego, nawet jeśli chodzi o konfigurację, którą można trzymać w plikach php, xml lub yaml. Komponent Console pozwala pisać własne pomocne komendy. Z tego spektrum jest oczywiście możliwość generowania plików tłumaczeń, klas modelu Entity, Kontrolerów i CRUD. Pod ręką (w dolnym pasku przeglądarki) jest umieszczony rozbudowany Debugger. Na pokłon zasługuje również szybki Routing oraz moduł Security. Do tego jest pełna dokumentacja, społeczność i setki gotowych do użycia modułów. To wszystko czyni Symfony technologią, którą warto rozważyć przy budowie małych, średnich jak i rozbudowanych projektów korporacyjnych.
CMS + API
EasyAdmin i Sonata to systemy CMS, które można śmiało podpinać do projektów opartych o Symfony. Oba bazują na tym frameworku 🙂 . Podobnie jak inne wspaniałe narzędzie: API Platform Admin – „framework PHP do budowy nowoczesnych webowych API”. Wspominałem o tym na wstępie.
WŁASNY FRAMEWORK Z KOMPONENTÓW SYMFONY
Wertując runy kodu zawarte w dokumentacji „Ojców Założycieli SensioLabs” natknąłem się niegdyś na ciekawy wątek dotyczący budowy własnego frameworka z komponentów Symfony. To właśnie dzięki temu odnalazłem drogę do Zionu. Heretycy kodu rzekną: „A po cóż na nowo wynajdować koło?”. Właśnie po to żeby zrozumieć czym jest MATRIX!
Jeśli nie wiesz o co mi chodzi to zażyj niebieską pigułkę i wróć do WordPressa.
Z dobrodziejstw Symfony korzysta wiele popularnych rozwiązań. To też o czymś świadczy. Poniżej lista niektórych z nich:
INSTALACJA FRAMEWORKA SYMFONY
Najlepiej użyć narzędzia composer. Do wyboru mamy dwa rodzaje instalacji:
- tradycyjna aplikacja internetowa:
1 |
$ composer create-project symfony/website-skeleton my_project |
- mikroserwis, aplikacja konsolowa lub API:
1 |
$ composer create-project symfony/skeleton my_project |
Nazwa my_project to katalog (nazwa projektu), w którym zostanie zainstalowany framework. Jeśli katalog nie istnieje to zostanie utworzony.
Skupmy się na tej pierwszej instalacji, bo o niej mowa w tym artykule. Jeśli wszystko poszło bezboleśnie to uruchom w przeglądarce adres strony: http://localhost/my_project/public/index.php/ lub bez my_project, w zależności od konfiguracji serwera i/lub wpisów w VirtualHost.
I wuala 🙂 . Pierwsze koty za płoty.

II. WEBPACK ENCORE
Webpack Encore jest dzieckiem Symfony ale może być użyty również w innych aplikacjach PHP lub językach programowania działających po stronie serwera. Webpack zwiększa wydajność aplikacji internetowych, optymalizuje skrypty JavaScript, kaskadowe arkusze CSS, Sass, LESS oraz grafiki. W prosty sposób można dodawać do aplikacji kolejne składniki typu: jQuery, ReactJS, Bootstrap itd. Webpack Encore pozwala tworzyć zależności oraz zarządzać pakietami w sposób modułowy. Zasoby kompilowane są do jednego zminifikowanego pliku *.js.
Wyobraź sobie Webpack Encore jako „przybornik narzędziowy”, dzięki któremu wszystko masz pod ręką.
INSTALACJA WEBPACK ENCORE
Za pomocą wiersza poleceń przejdź do katalogu projektu, a następnie zainstaluj pakiet symfony/webpack-encore-bundle:
1 2 |
$ cd my_project/ $ composer require symfony/webpack-encore-bundle |
Dodatkowo zainstaluj yarn – menedżer pakietów dla JavaScript. Jest potrzebny do kompilowania zasobów, dodawania nowych pakietów itp.
1 |
$ yarn install |
Po poprawnej instalacji, Webpack Encore doda do projektu kilka „rzeczy”. Katalog node_modules oraz assets. W tym drugim przechowywane są zasoby, czyli pliki: css, js, grafika itp. Skompilowana zawartość zasobów kopiowana jest do katalogu public/build. Konfiguracja projektu mieści się w pliku webpack.config.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
var Encore = require('@symfony/webpack-encore'); // Manually configure the runtime environment if not already configured yet by the "encore" command. // It's useful when you use tools that rely on webpack.config.js file. if (!Encore.isRuntimeEnvironmentConfigured()) { Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev'); } Encore // directory where compiled assets will be stored .setOutputPath('public/build/') // public path used by the web server to access the output path .setPublicPath('/build') // only needed for CDN's or sub-directory deploy //.setManifestKeyPrefix('build/') /* * ENTRY CONFIG * * Add 1 entry for each "page" of your app * (including one that's included on every page - e.g. "app") * * Each entry will result in one JavaScript file (e.g. app.js) * and one CSS file (e.g. app.css) if your JavaScript imports CSS. */ .addEntry('app', './assets/js/app.js') //.addEntry('page1', './assets/js/page1.js') //.addEntry('page2', './assets/js/page2.js') // When enabled, Webpack "splits" your files into smaller pieces for greater optimization. .splitEntryChunks() // will require an extra script tag for runtime.js // but, you probably want this, unless you're building a single-page app .enableSingleRuntimeChunk() /* * FEATURE CONFIG * * Enable & configure other features below. For a full * list of features, see: * https://symfony.com/doc/current/frontend.html#adding-more-features */ .cleanupOutputBeforeBuild() .enableBuildNotifications() .enableSourceMaps(!Encore.isProduction()) // enables hashed filenames (e.g. app.abc123.css) .enableVersioning(Encore.isProduction()) // enables @babel/preset-env polyfills .configureBabelPresetEnv((config) => { config.useBuiltIns = 'usage'; config.corejs = 3; }) // enables Sass/SCSS support //.enableSassLoader() // uncomment if you use TypeScript //.enableTypeScriptLoader() // uncomment to get integrity="..." attributes on your script & link tags // requires WebpackEncoreBundle 1.4 or higher //.enableIntegrityHashes(Encore.isProduction()) // uncomment if you're having problems with a jQuery plugin //.autoProvidejQuery() // uncomment if you use API Platform Admin (composer require api-admin) //.enableReactPreset() //.addEntry('admin', './assets/js/admin.js') ; module.exports = Encore.getWebpackConfig(); |
III. TECHNOLOGIE FRONTENDOWE
Symfony korzysta z systemu szablonów Twig, co nie znaczy, że musimy kurczowo trzymać się tylko tego rozwiązania. Moje propozycje:
1. REACT JS
React (reactjs.org) to biblioteka języka JavaScript stworzona przez pracowników Facebooka i przeznaczona do budowy dynamicznych interfejsów użytkownika (ang. User Interface, w skrócie UI). Projektowanie w React opiera się o tzw. komponenty wielokrotnego użytku. Wyobraź sobie komponent jako niezależny, odizolowany element, którym może być na przykład: menu, okienko popup, baner, stopka itd. Komponenty posiadają konkretne funkcjonalności, reagują na zdarzenia (np: onClick), mogą pobierać dane i utrzymywać ich wewnętrzny stan poza drzewem DOM. Interakcja z użytkownikiem odbywa się w czasie rzeczywistym, zmiany w obrębie interfejsu są aktualizowane natychmiast, bez przeładowania całej strony. Komponenty są elastyczne, skalowalne i przenośne, bez problemu komunikują się z innymi bibliotekami i frameworkami. Dzięki React Native, możemy również pisać aplikacje na urządzenia mobilne! Po co marnować czas i uczyć się kilku różnych technologii, jak wystarczy jedna uniwersalna 🙂
„Naucz się raz, pisz na wszystkie platformy!”
Ta maksyma świetnie oddaje możliwości Reacta 🙂 . Więcej na temat biblioteki React znajdziesz tutaj.
Aby dodać React do naszego projektu, wystarczy użyć prostej komendy – yarn add:
1 2 |
$ yarn add @babel/preset-react --dev $ yarn add react react-dom prop-types |
Następnie musimy włączyć go w pliku webpack.config.js, inaczej nie będzie widoczny w projekcie:
1 2 3 4 |
Encore // ... .enableReactPreset() ; |
2. SASS
Sass (sass-lang.com) to kolejna technologia, którą warto ogarnąć. Sass to preprocesor CSS i rozszerza możliwości kaskadowych arkuszy stylów – CSS, które służą do formatowania wyglądu stron internetowych. CSSy (jak zapewne wiesz) posiadają pewne ograniczenia. Wyobraź sobie sytuację, w której musisz zmienić w całym dokumencie krój i kolor czcionki. Musisz przeszukać plik lub pliki .css „linia po linii” i aktualizować każdy wpis. Korzystając z dobrodziejstw Sass, wystarczy zrobić to w jednym miejscu, bo możesz użyć zmiennych (podobnie jak w językach programowania).
1 2 3 4 5 6 7 |
$font-stack: Helvetica, sans-serif; $primary-color: #333; body { font-family: $font-stack; color: $primary-color; } |
Oczywiście jest tego więcej 🙂 . Dzięki Sass można m.in.: zagnieżdżać selektory, tworzyć własne funkcje, instrukcje warunkowe, pętle, domieszki. To wszystko zresztą znajdziesz w dokumentacji.
Aby dodać Sass do projektu uruchom polecenie:
1 |
$ yarn add sass-loader@^7.0.1 node-sass --dev |
a następnie zaktualizuj plik webpack.config.js:
1 2 3 4 |
Encore // ... .enableSassLoader() ; |
3. BOOTSTRAP
Bootstrap (getbootstrap.com) to biblioteka ułatwiająca tworzenie interfejsów graficznych aplikacji i stron internetowych. Korzysta z HTML, CSS, Sass, Less i JavaScript. Bootstrap zawiera szereg narzędzi i rozwiązań, których nie musisz kodować. Są to na przykład gotowe szablony stron, komponenty typu: akordeony, przyciski, menu, alerty, okienka popup, formularze itd. W dodatku wszystkie elementy są z góry responsywne 🙂 – czyli dostosowują się do różnych rozdzielczości ekranu.
REACT-BOOTSTRAP
Istnieje również wersja komponentów Bootstrapa przełożona na komponenty Reacta. Tak więc możemy upiec dwie pieczenie przy jednym ogniu! Mowa o React-Bootstrap (react-bootstrap.github.io). Nic dodać, nic ująć 🙂 .
Aby dodać Bootstrap do projektu uruchom polecenie:
1 |
$ yarn add bootstrap --dev |
Bootstrap JavaScript wymaga dwóch bibliotek: jQuery i popper.js dlatego musimy je także doinstalować:
1 |
$ yarn add jquery popper.js --dev |
IV. PRZYKŁAD
W poniższym przykładzie zrobimy pojedynczą stronę internetową ze standardowym powitaniem Hello World 🙂 . Przykład jest oczywiście błahy i ma jedynie na celu wprowadzenie Cię w rozwiązania, o których pisałem w tym artykule.
Zakładam, że omawiane w tym artykule technologie masz już zainstalowane. Jeśli nie, to wróć do poprzednich punktów i postępuj według wytycznych.
W pierwszej kolejności wygeneruj kontroler o nazwie HomeController:
1 |
$ php bin/console make:controller |
Polecenie stworzy plik HomeController.php (w lokalizacji /src/Controller/HomeController.php) oraz dwa szablony: base.html.twig (templates/base.html.twig ) i index.html.twig (templates/home/index.html.twig).
Wygenerowana zawartość kontrolera:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; class HomeController extends AbstractController { /** * @Route("/home", name="home") */ public function index() { return $this->render('home/index.html.twig', [ 'controller_name' => 'HomeController', ]); } } |
Nową podstronkę możesz odpalić pod adresem: /public/index.php/home (zgodnie z routingiem). Kod kontrolera jest banalny. Funkcja index renderuje szablon strony ($this->render(’home/index.html.twig’)) i przekazuje do niego nazwę kontrolera (’controller_name’ => 'HomeController’). Aczkolwiek parametr ten jest zbędny, bo zaraz nadpiszemy przykładową zawartość wygenerowaną przez Symfony w pliku index.html.twig:
1 2 3 4 5 |
{% extends 'base.html.twig' %} {% block body %} <div id="root"></div> {% endblock %} |
Do bloku <div id=”root”></div> wczytany zostanie komponent Reacta 🙂 . Ale o tym za chwilę.
Do layoutu bazowego (templates/base.html.twig) musimy dodać funkcje inkludujące zasoby Encore’a: encore_entry_link_tags(’app’) i encore_entry_script_tags(’app’):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>{% block title %}{% endblock %}</title> {% block stylesheets %} {{ encore_entry_link_tags('app') }} {% endblock %} </head> <body> {% block body %}{% endblock %} {% block javascripts %} {{ encore_entry_script_tags('app') }} {% endblock %} </body> </html> |
W związku z tym, że chcemy korzystać z SASS a nie standardowych stylów CSS, zmień rozszerzenie pliku app.css na app.scss (assets/css/app.scss). Zaktualizuj ten zamiar również w pliku: app.js (assets/js/app.js):
1 |
import '../css/app.scss'; |
Plik app.js to główny plik przechowujący skrypty i biblioteki do strony. Plik ten jest zdefiniowany w konfiguracji webpack.config.js. Dla przypomnienia:
1 2 3 |
Encore // ... .addEntry('app', './assets/js/app.js') |
Zaktualizuj zawartość app.scss dodając własne style oraz polecenie importujące style Bootstrapa:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@import "~bootstrap/scss/bootstrap"; $bg-color: #efefef; $base-font-size: 14px; $base-font-color: #555; body { background-color: $bg-color; font-size: $base-font-size; } h1.title { font-size: $base-font-size * 3; color: $base-font-color; } |
Ponownie wyedytuj plik app.js dołączając JavaScript Bootstrap:
1 2 3 4 |
require('../css/app.scss'); const $ = require('jquery'); require('bootstrap'); |
Teraz dodamy komponent Reacta. Będzie to nagłówek <h1></h1>, którego treść będzie można modyfikować dynamicznie. W tym celu utwórz plik: Hello.js (assets/js/components/Hello.js):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import React, {Component} from 'react'; class Hello extends Component { render() { return ( <div> <h1 classname="title">{this.props.title}</h1> </div> ) } } export default Hello; |
Budowa komponentu nie jest skomplikowana. Na początku importujemy biblioteki Reacta. Jak widać komponent Hello to klasa obiektu, która dziedziczy (extends) po wbudowanej klasie Component. Wewnątrz klasy Hello znajduje się funkcja render(), która zwraca nagłówek H1 z argumentem (props) title. Wartość ta będzie mogła być modyfikowana. Więcej samouczków znajdziesz w artykule: „WPROWADZENIE DO REACT”.
Aby komponent był dostępny musisz dodać go w pliku app.js. Końcowa zawartość pliku będzie miała taką oto postać:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import React from 'react'; import ReactDOM from 'react-dom'; require('../css/app.scss'); const $ = require('jquery'); require('bootstrap'); import Hello from './components/Hello'; ReactDOM.render( <hello title="Hello World!"></hello>, document.getElementById('root') ); |
Jak widać, musimy zaimportować biblioteki Reacta oraz komponent Hello. ReactDOM zarządza wyświetlaniem elementów DOM. Metoda render odpowiada za wyrenderowanie komponentu na stronie i przyjmuje dwa parametry:
- <Hello /> – nazwa klasy (komponentu) z atrybutem title, którego wartość możemy zmieniać,
- document.getElementById(‚root’) – wskazuje id selektora na stronie, do którego wczytany zostanie komponent, czyli do root (<div id=”root”></div> – w szablonie: index.html.twig).
KOMPILACJA ZASOBÓW
Na koniec musimy skompilować zasoby, aby zmiany były widoczne na stronie po jej odświeżeniu. Spakowane w jedną całość pliki zasobów kopiowane są do katalogu /public/build. WebPack Encore udostępnia trzy metody budowania zasobów:
- pojedyncza kompilacja:
1 |
yarn encore dev |
- automatyczna kompilacja, kiedy plik/i ulegną zmieniane (są modyfikowane):
1 |
yarn encore dev --watch |
- kompilacja do wersji produkcyjnej:
1 |
yarn encore production |
Naturalnie, w trakcie prac nad projektem użyj pierwszej lub drugiej opcji.
V. PODSUMOWANIE
Dzięki Symfony Flex i Webpack Encore możesz budować szybkie, bezpieczne i skalowalne aplikacje internetowe na różne platformy i urządzenia mobilne. Składniki interfejsu typu: React, Sass i Bootstrap wspaniale uzupełniają ten zestaw. Pracując z frameworkami uczysz się dobrych praktyk i rozwijasz kunszt programowania. Nie zamykaj się w monolitycznych rozwiązaniach bo wypłaszczysz sobie mózg.