در مقاله قبل در رابطه با نصب و شروع کار با فریمورک Symfony صحبت کردیم در این مقاله قصد دارم نگاهی به ساختار این فریمورک بندازیم و مقدمات اولیه آن را با هم یاد بگیریم.

فولدر web در واقع مسیر public ما در فریمورک Symfony است و همه فایلهای style, javascript , images و… در این مسیر قرار میگیرند. همچنین کنترلرهای سمت فرانت اند نیز ریسپانسهایی که به کاربر نمایش میدهند را از طریق این مسیر نمایش میدهند.

همانطور که میدانیم وقتی پروژهای راه اندازی میشود وبسرور فایلی با نام index را به عنوان فایل اصلی اولیه که لود میشود شناسایی میکند مگر اینکه در فایل .htaccess آن را تغییر دهیم که اینکار در Symfony انجام شده و فایل app.php به عنوان فایل اصلی تنظیم شده است.

// web/app.php
require_once __DIR__.'/../var/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';
use Symfony\Component\HttpFoundation\Request;
$kernel = new AppKernel('prod', false);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
The controller first bootstraps the application using a kernel class (AppKernel
in this case). Then, it creates the Request
object using the PHP’s global variables and passes it to the kernel. The last step is to send the response contents returned by the kernel back to the user.
app / Directory
کلاس AppKernel نقطه شروع پروژه و از مهمترین فایلهای پروژه است که داخل فولدر app قرار دارد. مهمترین توابع آن registerBundles و registerContainerConfiguration ( که از Kernel اصلی پروژه implement شدهاند ) هستند.
- registerBundles آرایه ای از Bundleهایی که برای اجرای پروژه نیاز است را لود میکند.
- registerContainerConfiguration تنظیمات پرژه را لود میکند.

Bundle System
یکی از قدرتمندترین ویژگیها و امکانات Symfony بخش bundle System آن است.
یک bundle در فریمورک Symfony شبیه پلاگین یا افزونهها در سایر سیستمها هستند. در این فریمورک همه چیز بر اساس bundle کار میکنید از ویژگیهای core سیستم گرفته تا کدی که شما مینویسید به صورت یک bundle تعریف میشود.
تمام کدهایی که شما مینویسید داخل یک bundle سازماندهی میشوند. در واقع یک bundle همه ساختارها و فایلها که برای پیاده سازی یک ویژگی ( مثلا بلاگ ) را شامل میشود که میتوان bundle مورد نظر را با بقیه نیز به اشتراک گذاشت.
Bundleها از مهمترین بخشها فریمورک سیمفونی هستند که ویژگیهای با انعطاف پذیری زیادی را به فریمورک شما میبخشد مثلا شما میتوانید مشخص کنید کدام bundleها در اپلیکیشن شما فعال یا غیرفعال باشد و به صورت جداگانه آنها را بهبود ببخشید و در نهایت به راحتی روی سیستم شما قرار میگیرد.
فریمورک سیمفونی به صورت پیشفرض یک Appbundle دارد که شما میتوانید کنترلرهای خود را داخل آن ایجاد کنید و یا بر اساس ویژگیهایی که برای اپلیکیشن خود دارید Bundleهای اختصاصی خود را ایجاد کنید.
ایجاد Bundle جدید
وقتی ما بر اساس ویژگیهای اپلیکیشن خود bundleهای اختصاصی خود را میسازیم در واقع باید آن را داخل متد registerBundles درون فایل AppKernel معرفی کنیم. در واقع هر bundle کلاسی دارد که معرف آن bundle است.

در تصویر فوق اگر دقت کنید بخشهایی از فریمورک Symfony که جزو اپلیکیشن هستند در این متد فعال شده اند bundleهایی همچون FrameworkBundle, DoctrineBundle ،TwigBundle ،SwiftmailerBundle و AsseticBundle.
Configuring a Bundle
تنظیمات هر bundle را میتوانیم در فایل کانفیگ آن که به صورت Yaml, Xml و PHP نوشته شده اند به صورت موردنیاز ست کنیم. در مسیر app > config > config.yml تنظیمات پیشفرض را با هم میبینیم.

با توجه به محیط پروژه تنظیمات bundleها میتوانند تغییر داده شوند برای مثال اگر پروژه در حالت توسعه باشد ( یعنی روی حالت dev قرار داشته باشد ) نام فایل کانفیگ آن به صورت config_dev.yml است که میتواند تنظیمات پیشفرض را override کند.
Extending a Bundle
یکی دیگر از ویژگیهای جذاب Bundleها ارثبری کردن از یکدیگر است. در واقع ارثبری در bundle ها به شما این امکان را میدهد که برای هر bundle همه بخشهای کنترلرها و قالبها و هر فایلی که وجود دارد را override کنید.
وقتی میخواهید به یک bundle اشاره و فراخوانی کنیم از این ساختار باید استفاده کنیم : @BUNDLE_NAME/path/to/file
; در این صورت Symfony با استفاده از @BUNDLE_NAME در واقع resolve میکنه و مسیردهی را انجام میدهد.
برای نمونه وقتی مینویسیم @AppBundle/Controller/DefaultController.php مسیردهی به این صورت تبدیل میشود: src/AppBundle/Controller/DefaultController.php
برای کنترلرها ما از این ساختار برای اشاره به تابع/متد استفاده میکنیم:
BUNDLE_NAME:CONTROLLER_NAME:ACTION_NAME
# Example
AppBundle:Default:index
که در مثال ذکر شده متد indexAction در کلاس DefaultController در مسیر AppBundle\Controller\DefaultController فراخوانی میشود.
نکته مهم: اگر مطابق قرارداد سیمفونی عمل کنیم و از bundle inheritance برای override کردن فایلها، کنترلرها و تمپلتها استفاده کنیم میتوانیم تمام قسمتهایی که لازم داریم را مطابق bundle جدید پیاده سازی کنیم بدون آنکه در سایر bundleها تغییری ایجاد کنیم. به این صورت که مثلا NewBundle را ایجاد میکنیم و مشخص میکنیم که AppBundle را override کند. زمانی که سیمفونی کنترلر AppBundle:Default:index را لود میکند ابتدا کنترلر DefaultController در NewBundle را چک میکند اگر متدی به نام indexAction وجود داشت از آن استفاده میکند در غیر اینصورت از متد indexAction در AppBundle استفاده میکند.
Vendors Directory
این دایرکتوری منحصرا توسط Composer مدیریت و بروزرسانی میشود و ما هیچ تغییری را در آن ایجاد نمیکنیم. در این بخش کتابخانه bundle های سیمفونی و همچنین bundleهایی که نصب میکنیم وجود دارد. کتابخانههایی همچون SwiftMailer، Doctrine ORM، Twig templating system و …
Cache and Logs
سیمفونی چندین فایل کانفیگ با فرمتهای مختلفی همچون yml, xml , php ,… دارد، به جای اینکه با هر رکوست این فایلها دوباره لود شوند سیمفونی از سیستم Cache استفاده میکند و آنها را در دایرکتوری var/cache قرار میدهد و در رکوستهای بعدی برای افزایش سرعت از کش استفاده میکند. در واقع در رکوست اول ابتدا همه فایلها فراخوانی میشوند و در فایلهای php در مسیر var/cache ذخیره میشوند.
وقتی که شما در حالت توسعه هستید ( development environment ) سیمفونی هوشمند عمل میکند و با تغییر هر فایل دوباره کش را بروزرسانی میکند ولی در حالت نهایی production environment برای افزایش سرعت از کش استفاده میشود که در صورت تغییرات فایلها باید کش سیستم را با کامند زیر بروزرسانی کنیم
php bin/console cache:clear --env=prod
زمانی که در حال توسعه و برنامهنویسی هستید و خطایی رخ میدهد در مسیر var/logs میتوانید خطاهایی که رخ داده است را مشاهده کنید و برای رفع آن اقدام کنید.
دانلود Symfony Best Practice
سیمفونی یک پروژه demo به صورت best practice منتشر کرده که پیشنهاد میکنم آن را دانلود کنید و ساختار کدهای آن را مشاهده کنید خیلی دید خوبی بهتون میده که چگونه کدهایی بنویسید تا best practice باشند. برای نصب نسخه demo سیمفونی کد زیر را اجرا کنید تا پروژه با ورژن installer شما دانلود شود.
symfony demo