یه برنامهنویس با انگیزه که بیشتر تو https://fa.aien.me میچرخه
آشنایی با Symfony با ساختن یه وبلاگ به صورت پروژه ای
eبین تعدا زیادی از تکنولوژیهای وب که وجود دارن، پیاچپی تو طول زمانی تغییرات سریعی رو پشت سر گذاشته و الان به یک زبان بالغ تبدیل شده.
پیاچپی امروز هم برای وبسایتها و وباپلیکیشنها کوچیک و همینطور بزرگ استفاده میشه و شاید یکی از دلایل محبوبیتش، سادگیش باشه.
با توجه به اینکه هرروز پیچیدگی وباپلیکیشنها بیشتر میشه، برنامهنویسها بیشتر به استفاده از فریمورکها رو آوردن و حتی برای پروژههای کوچیکشون هم از اونا استفاده میکنن. شاید با خودتون بگید «فریمورک چیه؟». فریمورکها اساسا چیزی بجز یکسری توابع و ساختاربندیهای کلاسی نیستن که از قبل آماده شدن و قابل استفاده هستن، که مهمترین ویژگیشون اختراع نکردن چرخ از اول هست و این یعنی صرفهجویی زمان.
تقریبا تمام زبانهای برنامهنویسی برای خودشون فریمورکهایی رو دارن که هرکدوم با هدفی ساخته شدن. یسری از فریمورکهای محبوب پیاچپی، Zend Framework, Cake PHP, Smarty, Laravel و Symfony هستند، و من خودم بشخصه طرفدار سیمفونی هستم و دلایلش رو هم میگم. در نهایت سعی میکنم برای کسانی که دوست دارن با سیمفونی آشنا بشن، توضیحی از نحوه نصب و راهاندازی و کار مختصر باهاش رو توضیح بدم.
انعطافپذیری
تو خیلی از پروژههایی که کار کردم و دیدم، سیمفونی بهم ثابت کرد که خیلی زیاد انعطافپذیره و یک انتخاب خوب برای کسبوکار. با قابلیتهایی مثل Dependency Injectorها یا Event Dispatcherها کاملا قابل تنظیم و شخصیسازی شده. سیمفونی یک ساختار OOP و SOA رو به صورت حرفهای پیش برده که باعث شده برای کسایی که بخوان چه از ساختار Monolithic و چه از Micro Service بهره ببرن، گزینهی مناسبی باشه، و این یعنی توسعه سریع، افزایش مقیاس پروژه و نگهداری راحت.
برنامهنویسها نیازی ندارن تا ویژگیهای پایه و اساسی پروژه رو از اول بنویسن یا حتی بازنویسی کنن، مثل سرویس مدیرت فرم. سیمفونی برنامهنویس رو به چالش واقعی دعوت میکنه، محاسبات و مدیریت. بنظرم یکی از بهترین ویژگیهای سیمفونی داشتن Web Debug Toolbar هست که حقیقتا یه دوست واقعی برای برنامهنویسه.
ساختار تیکه تیکه! (باندل)
بنظرم یکی از ویژگیهای بسیار مثبت سیمفونی، ساختار تیکه تیکش هست. یعنی سیمفونی از اجزای کوچکتر ساخته شده که هرکدومشون جداگانه قابل استفاده هستن، یک نمونش HTTP Foundation که خیلی زیاد تو لاراول استفاده شده. در واقع خود سیمفونی، یک تیکه کوچیک از این تیکههاست که در حقیقت وظیفش جمع کردن همهی تیکهها (اسم درستشون باندل هست) و در کنار هم قراردادنشونه. برای همین سیمفونی رو میشه به دو حالت استفاده کرد:
- یک فریمورک کامل: کل ابزارهای سیمفونی و یک عالمه ابزاری که برنامهنویسهای دیگه نوشتن رو کنار هم و یکجا داشته باشید
- میکرو فریمورکها: که درواقع شما توی پروژهای که کار میکنید، بدون نصب سیمفونی، فقط از باندلهای بدرد بخورش براش خودتون استفاده کنید، مثل FormBundle
در مورد TWIG!
الان تو دنیایی هستیم که کمتر کسی علاقهای به نوشتن ظاهر سایت و HTML بصورت دستی داره، بخصوص زمانی که تعداد فایلها قراره زیاد بشن و شما مجبور بشید به ازای هر صفحه یه فایل جدید بسازید. توییگ، یه موتور ساخت قالب هست که بهتون کمک خیلی زیادی توی طراحی میکنه. مثلا شما میتونید یک فایل html بسازید و داخلش از توییگ استفاده کنید و فقط متغیرها رو بهش پاس بدید. و اون برای شما به سادگی و سریع رندر کنه.
سیمفونی به صورت پیشفرض از توییگ پشتیبانی میکنه و خیلی از زمان طراحی شما کم میکنه.
داکترین (Doctrine)
داکترین در واقع یک سری کتابخونه برای php هست که وظیفش ایجاد یک لایهی اضافی برای ارتباط برنامهنویس با دیتابیسه، در حقیقت به جای اینکه برنامهنویس مجبور بشه کدهای sql رو دستی وارد کنه، با نصب داکترین، فقط به کدهای php بسنده میکنه و داکترین تمام کارهارو براش انجام میده.
داکترین تبدیل به یک پروژه بالغ شده و بنظرم تمام امکانات مورد نیاز برنامهنویس رو در اختیارش قرار میده. خود داکترین شاخههای زیرمجموعه داره که مهمترین و پرمصرفترینش Doctrin ORM هست که وظیفش بصورت ساده و خلاصه، تبدیل کلاسهای php به مدلهای دیتابیسی هست.
سیمفونی بطور پیشفرض از Doctrine ORM پشتیبانی میکنه و نیازی نیست شما اون رو کانفیگ کنید.
تست راحت
بنظرم سیمفونی با ایدهی «تستینگ در اولویت» پیش رفته. Unit Testingها با استفاده از PHPUnit خیلی خوب از کدها جدا شدن مدیریتشون خیلی راحت شده. با یه کمک خیلی زیاد از PHPUnit این امکان برای برنامهنویس وجود داره تا به سادگی درخواستهای http رو بازسازی، آزمایش و تست کنه بدون اینکه مجبور باشه کد زیادی رو با ابزار تست بزنه.
در واقع این امکان سیمفونی حتی زمان زیادی رو هم توی تست حفظ میکنه و سرعت عمل رو بالا میبره. در مجموع اکوسیستم سیمفونی روی تستینگ و کیفیت بالای اون خیلی تمرکز داشته و موارد خوبی رو فراهم کرده.
دیباگ مثل آب خوردن
محبوبترین ویژگی سیمفونی، Web Debug Tool هست که اطلاعات کاملی و دقیقی راجع به وضعیت فعلی درخواستها، ترنسپایلرها و غیره میده و حتی امکان تست سرعت رندر هم داره. Symfony Profiler همون ابزار دیباگینگ هست که در مورد تمام اتفاقات پروژه تو هر مرحله گزارش کامل و دقیق میده.
نصب سیمفونی
حتما براتون سوال شده که چطور میشه سیمفونی رو نصب و راهاندازی کرد. برای اینکار روشهای مختلی وجود داره، اما بهترین روش که من هم ازش استفاده میکردم و راضی بودم، استفاده از نصاب خود سیمفونی هست که برای راهاندازیش میتونید به شکل زیر عمل کنید:
- دریافت فایل نصاب
برای لینوکس و مک
sudo curl -LsS https://symfony.com/installer -o /usr/bin/symfony
sudo chmod a+x /usr/bin/symfony
برای ویندوز
C:\> php -r "readfile('https://symfony.com/installer');" > symfony
- استفاده از نصاب
symfony new helloWorld lts
حتما مطمئن باشد که از PHP Phar Extension استفاده میکنید!
- نصب Composer
کامپوزر، در حقیقت یک Package Manager هست که پکیجهایی که تو ریپازیتوری کامپوزر وجود دارن رو براتون پیدا و بهترین رو از لحاظ مطابقت با ورژنهای شما نصب میکنه.
کامپوزر رو میتونید به سادگی از ریپازیتوریهای توزیع لینوکستون پیدا کنید. مثلا
sudo packman -S composer
یا
sudo apt-get install composer
- راه اندازی سرور و ادامه کد زدن
دایرکتوریتون رو به فولدر helloWorld تغییر بدبد
cd helloWorld
و سرور داخلی سیمفونی رو اجرا کنید:
app/console server:run
گام به گام با هم پیش بریم
بیاید باهم یه وبسایت ساده بنویسیم. فکر میکنم یه وبلاگ میتونه گزینه مناسبی برای شروع باشه. پس اگر هنوز نصاب سیمفونی و کامپوزر رو نصب نکردید، برگردید عقب و انجامشون بدید تا در ادامه مشکلی نداشته باشید.
قدم اول، راه اندازی پروژه
symfony new MyBlog lts
پس از اجرا، باید همچین پاسخی رو دریافت کنید:
Downloading Symfony...
5.4 MiB/5.4 MiB ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 100%
Preparing project...
Symfony 2.8.24 was successfully installed. Now you can:
* Change your current directory to ~/MyBlog
* Configure your application in app/config/parameters.yml file.
* Run your application:
1. Execute the php app/console server:start command.
2. Browse to the http://localhost:8000 URL.
* Read the documentation at http://symfony.com/doc
و در نهایت دستور composer install
رو داخل فولدر MyBlog اجرا کنید.
حالا IDE یا ادیتورتون رو باز کنید و پروژه رو داخلش بیارید بالا.
تنظیمات دیتابیس
تمام تنظیمات پروژه، داخل فولدر app/config
قرار میگیرن. فولدر app
موظف به نگهداری از تمام منابع اپلیکیشن هست، مثل قالبهای توییگ، لاگها و تنظیمات و هسته اپلیکیشن.
فایلهایی که داخل پوشه app/config
هستن، معمولا با پسوند .yml
یا .yaml
قرار میگیرن که میتونم بگم از لحاظ کاربری مشابه .json
هستن.
حالا فایل app/config/parameters.yml
رو باز کنید. با همچین ساختاری مواجه میشید:
# This file is auto-generated during the composer install
parameters:
database_host: 127.0.0.1
database_port: null
database_name: symfony
database_user: root
database_password: null
mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: null
mailer_password: null
secret: 90830183902924603f797e4b794ff7e8353e43e9
تیکه اول درواقع تنظیمات عمومی اپ برای ارتباط با دیتابیس هست. این تنظیمات رو به:
database_name: MyBlog #یا هر اسم دیگهای که برای دیتابیس دوست دارید
database_user: root #یوزرنیم که باهاش به دیتابیس وصل میشید
database_password: null #پسورد دیتابیستون...
تغییر بدید. من در حالت عادی با MySql کار میکنم، اما سیمفونی گزینههای دیگهای هم مثل MongoDb و دیتابیسهای دیگه داره و از اونا پشتیبانی میکنه.
ساخت دیتابیس
یکی از گزینههای خیلی خوب سیمفونی که من دوست دارم، کنسولش هست. که خیلی از کارهارو برای شما انجام میده. میتونید اطلاعات بیشتری راجع بهش رو صرفا با تایپ app/console
بدست بیارید.
الان فقط ساخت دیتابیس برامون کافیه تا بریم مراحل بعدی:
app/console doctrine:database:create
و پاسخش:
Created database `MyBlog` for connection named default
حالا چک کنیم که تا اینجا همهچیز خوب پیشرفته:
app/console server:run
[OK] Server running on http://127.0.0.1:8000
// Quit the server with CONTROL-C.
میتونید صفحه رو باز کنید و چک کنید. نوار سیاه پایین صفحه، همون Web Debug Tool هست که گفته بودم. بعد از اینکه مطمئن شدید اوضاع خوبه، پروسه رو قطع میکنیم و میریم گام بعدی.
ساخت یک باندل برای مدیریت وبلاگ
یک نکته مهم، از اونجایی که سیمفونی ساختار تیکه تیکه داره (Bundle) شما میتونید هر قسمتی از سایت رو بر اساس ساختار خودتون به یک باندل تبدیل کنید. مثلا فرض میکنیم که وبلاگ سایت، برای خودش یه تیکه جداست، یعنی میتونیم خیلی راحت از پروژه حذفش کنیم و دیگه کاربرا بلاگی نبینن. برای اینکار، یه باندل جدید میسازیم:
app/console generate:bundle
Welcome to the Symfony bundle generator!
Are you planning on sharing this bundle across multiple applications? [no]:
Your application code must be written in bundles. This command helps
you generate them easily.
Give your bundle a descriptive name, like BlogBundle.
Bundle name: MyBlogBundle
Bundles are usually generated into the src/ directory. Unless you're
doing something custom, hit enter to keep this default!
Target Directory [src/]:
What format do you want to use for your generated configuration?
Configuration format (annotation, yml, xml, php) [annotation]:
Bundle generation
> Generating a sample bundle skeleton into app/../src/MyBlogBundle
created ./app/../src/MyBlogBundle/
created ./app/../src/MyBlogBundle/MyBlogBundle.php
created ./app/../src/MyBlogBundle/Controller/
created ./app/../src/MyBlogBundle/Controller/DefaultController.php
created ./app/../tests/MyBlogBundle/Controller/
created ./app/../tests/MyBlogBundle/Controller/DefaultControllerTest.php
created ./app/../src/MyBlogBundle/Resources/views/Default/
created ./app/../src/MyBlogBundle/Resources/views/Default/index.html.twig
created ./app/../src/MyBlogBundle/Resources/config/
created ./app/../src/MyBlogBundle/Resources/config/services.yml
> Checking that the bundle is autoloaded
> Enabling the bundle inside app/AppKernel.php
updated ./app/AppKernel.php
> Importing the bundle's routes from the app/config/routing.yml file
updated ./app/config/routing.yml
> Importing the bundle's services.yml from the app/config/config.yml file
updated ./app/config/config.yml
Everything is OK! Now get to work :).
سوال اول اینه:
Are you planning on sharing this bundle across multiple applications? [no]
که اگر جوابتون yes
باشه، تمام فایلهای باندل، مثل قالبها، تنظیمات و غیره رو توی خود فولدر باندل میریزه که شما بتونید راحت جداش کنید. در غیر این صورت، قالبها داخل فولدر app/Resources/views
ریخته میشن. (که عملا جدا کردنشون کار سختی میشه…)
برای ادامه آموزشمون، میتونید این گزینه رو همینطور رها کنید (اینتر بزنید) و بریم سراغ سوال بعدی:
Bundle name: MyBlogBundle
این اسم، ارتباطی با اسم پروژه نداره، یهو به ذهنم رسید، شما میتونید از BlogBundle
یا HaminjuriBundle
استفاده کنید… مهم اینه که حتما کلمه Bundle
به آخرش، به صورت CamelCase اضافه بشه. سوال بعدی این خواهد بود:
Target Directory [src/]:
تمام باندلهای سایت شما (مگر زمانی که خودتون کانفیگ کنید) داخل فولدر src
ریخته میشن، درواقع شما ۹۹٪ زمانتون رو تو این فولدر صرف میکنید. ماهم این گزینه رو به حال خودش رها میکنیم.
Configuration format (annotation, yml, xml, php) [annotation]
نوع تنظیماتی که باندل قرار داشته باشه چطوره، میتونید از هر نوعی که گفته استفاده کنید ولی من annotation رو ترجیح میدم چون خیلی راحت میشه تغییرش داد و مدیریتش خیلی آسونتر هست. پس فقط اینتر رو میزنم و میرم سراغ گام بعدی!
ساخت یک مدل ساده از پست وبلاگ
خب، تا اینجا خوب پیشرفتیم. فرض میکنیم کاربرای ما، نیازی به مدلسازی پیچیدهای ندارن و در حد سادهی آموزش ما براشون کافیه. یک پست وبلاگ چه چیزاهایی احتیاج داره؟
- عنوان (title) از نوع رشتهای (string) که حتما باید وارد بشه (not nullable) و نباید تکراری باشه (unique)
- متن نوشته (content) از نوع متنی (text) که حتما باید وارد بشه (not nullable)
- تاریخ ساخت (createdAt) از نوع تاریخ (data) که حتما باید وارد بشه (not nullable)
دوباره میریم سراغ کنسول:
app/console doctrine:generate:entity
Welcome to the Doctrine2 entity generator
This command helps you generate Doctrine2 entities.
First, you need to give the entity name you want to generate.
You must use the shortcut notation like AcmeBlogBundle:Post.
The Entity shortcut name: BlogBundle:Post
اینجا بهش میگیم که این انتیتی (entity)، یا همون مدلمون، مربوط به کدوم باندل هست. اسم باندل که باهم درست کردیم دو نقطه اسم انتیتی که میشه پست…
Configuration format (yml, xml, php, or annotation) [annotation]
همچنان با انوتیشن پیش میریم. از اینجا به بعد ازتون میخواد که پراپرتیهای مدل رو مشخص کنید. زمانی که کارتون تموم شد، میتونید اینتر رو بزنید و ادامه رو به کنسول بسپارید. پس پیش میریم:
New field name (press <return> to stop adding fields): title
Field type [string]:
Field length [255]:
Is nullable [false]:
Unique [false]: true
New field name (press <return> to stop adding fields): content
Field type [string]: text
Is nullable [false]:
Unique [false]:
New field name (press <return> to stop adding fields): createdAt
Field type [string]: date
Is nullable [false]:
Unique [false]:
New field name (press <return> to stop adding fields):
Entity generation
created ./src/BlogBundle/Entity/
created ./src/BlogBundle/Entity/Post.php
> Generating entity class src/BlogBundle/Entity/Post.php: OK!
> Generating repository class src/BlogBundle/Repository/PostRepository.php: OK!
Everything is OK! Now get to work :).
حالا اگر برید داخل src/BlogBundle/Entity
متوجه میشید که فایل Post.php
براتون ساخته شده. این فایل در واقع یه کلاس ساده PHP هست که صرفا پراپرتیهای مدل رو نگهداری میکنه. در واقع این همون مدل پست ماست که میتونید بعدا خیلی راحت تغییرش بدید.
ضمنا همزمان با ساخت این مدل، یک فایل هم داخل src/BlogBundle/Repository
به نام PostRepository.php
ساخته شده، که در واقع وظیفه اصلیش اینه:
یک جاهایی از پروژه شما نیاز پیدا میکنید تا مثلا یک رکورد خاص رو از دیتابیس، با محاسبات خاصی دریافت کنید. اینجا میتونید تمام دستورات لازم رو بنویسید تا همهجا بشه به سادگی ازشون استفاده کرد.
حالا که مدل ساخته شد، اون رو به دیتابیس منتقل میکنیم تا ساختار دیتابیس با مدلهای ما یکی بشه:
app/console doctrine:schema:update --force
Updating database schema...
Database schema updated successfully! "1" queries were executed
چرا از آرگومان --force
استفاده کردیم؟ یک دلیلش اینه که مطمئن باشیم داریم درست پیش میریم. پیش میاد زمانی که احتمالا دستور رو اشتباه وارد کنیم و باعث بشیم تا دیتابیس بهم بریزه. مورد بعدی اینکه شما میتونید از آرگومان --dump-sql
هم استفاده کنید تا ببینید دقیقا چه دستوری به SQL اجرا میشه.
ساخت فرم برای مدیریت پستها
تا اینجا خوب پیشرفتیم. حالا باید این امکان رو برای کاربر فراهم کنیم، تا بتونه پستها رو کراد (CRUD = Create, Read, Update and Delete) کنه. خوبی سیمفونی اینه که تقریبا تمام این کارها رو با کنسول میشه انجام داد. پس:
app/console doctrine:generate:crud
Welcome to the Doctrine2 CRUD generator
This command helps you generate CRUD controllers and templates.
First, give the name of the existing entity for which you want to generate a CRUD
(use the shortcut notation like AcmeBlogBundle:Post)
The Entity shortcut name: BlogBundle:Post
By default, the generator creates two actions: list and show.
You can also ask it to generate "write" actions: new, update, and delete.
Do you want to generate the "write" actions [no]? yes
Determine the format to use for the generated CRUD.
Configuration format (yml, xml, php, or annotation) [annotation]:
Determine the routes prefix (all the routes will be "mounted" under this
prefix: /prefix/, /prefix/new, ...).
Routes prefix [/post]: /blog
Summary before generation
You are going to generate a CRUD controller for "BlogBundle:Post"
using the "annotation" format.
Do you confirm generation [yes]?
CRUD generation
created ./src/BlogBundle/Controller//PostController.php
created ./app/Resources/views/post/
created ./app/Resources/views/post/index.html.twig
created ./app/Resources/views/post/show.html.twig
created ./app/Resources/views/post/new.html.twig
created ./app/Resources/views/post/edit.html.twig
created ./src/BlogBundle/Tests/Controller/
created ./src/BlogBundle/Tests/Controller//PostControllerTest.php
Generating the CRUD code: OK
created ./src/BlogBundle/Form/
created ./src/BlogBundle/Form/PostType.php
Generating the Form code: OK
Updating the routing: OK
Everything is OK! Now get to work :).
بذارید مرحله به مرحله توضیح بدم. اول دستور app/console doctrine:generate:crud
رو زدم. بعد ازم پرسید که برای چه انتیتی میخوام کراد بسازم و من هم BlogBundle:Post
رو وارد کردم. بعد ازم پرسید که پیشوند مسیرم برای کاربر چیه، در واقع کاربر از چه مسیری توی سایت میتونه به این عملیاتها دسترسی داشته باشه. خودش بصورت پیشفرض، اسم انتیتی (Post) رو در نظر گرفته بود و من به /blog
تغییرش دادم. و در نهایت پرسید که آیا مطمئن هستم؟ و منم مطمئنم…
خب، حالا یه تست کنیم ببینیم تا اینجا چطور پیشرفتیم:
app/console cache:clear
app/console server:run
از این آدرس استفاده کنید تا بتونید بهتر ببینید:
http://localhost:8000/app_dev.php/blog/
app_dev.php
در واقع محیط دیباگ رو فراهم میکنه. اگر واردش نکنید، سایت اصلی بدون گزینههای دیباگ و پولیش شده جلوتون قرار میگیره.
تا اینجا عالی بود. پیشنهاد میکنم یکم با این صفحه کار کنید و چندتا پست نمونه بسازید، پاکشون کنید و تغییرشون بدید. چقدر راحت شد همهچیز.
ولی ظاهرش اصلا قشنگ نیست… قدم بعدیمون، میریم سراغ یکم طراحی…
یکم کار با قالبها
تمام قالبهای مربوط به کراد، با توجه به اینکه قرار نیست ما این باندل رو جدا کنیم، تو فولدر app/Resources/views/post
قرار گرفتن. از اسم فایلها مشخصه که هر کدوم چه وظیفهای به عهده دارن. پسوندشون هم .html.twig
هست که درواقع یک فایل توییگه که باهاش به شکل فایل html برخورد میشه.
فایل index.html.twig
اگر به فایل src/BlogBundle/Controller/PostController.php
نگاه کنید، که بعد از اجرای دستور doctrine:generate:crud
ایجاد شده، متوجه میشید که تمام عملیات کراد اینجا انجام میشه.
کنترلرها در واقع کلاسهایی هستن که وظیفشون مدیریت فعالیتهای قسمتهای مختلف باندل یا مسیرهای اوناست. اینو رو ببینید:
/**
* Lists all post entities.
*
* @Route("/", name="blog_index")
* @Method("GET")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$posts = $em->getRepository('BlogBundle:Post')->findAll();
return $this->render('post/index.html.twig', array(
'posts' => $posts,
));
}
چون تعریف کردیم که تظیمات رو با انوتیشن انجام میدیم، تمام تعاریف اکشنها (یا همون تیکههای کوچیک که وظیفه مدیریت قسمتهای مختلف باندل رو دارن وکنترلر اونارو یجا جمع کرده) بالاشون، انوتیت میشن.
مثلا اینجا به @Route
دقت کنید، آرگومان اولش /
هست، یعنی مسیرباندل/مسیر کنترلر/مسیر اکشن
که اینجا برای ما میشه /blog/
. دقت کنید که خود باندل بلاگ، مسیری رو نداره، و ما زمان ساخت فرم گفتیم که پیشوند مسیر رو از /post
به /blog
تغییر بده. اگر دوست داشتید که مسیر باندل رو هم عوض کنید، فایل app/config/routing.yml
رو باز کنید و prefix
باندل رو از /
به هرچی که دوست دارید، مثلا hello
تغییر بدید. در نتیجه این تغییر، کاربر شما برای دریافت لیست پستها باید به آدرس hello/blog/
مراجعه کنه.
خب، برمیگردیم به خود کد و اون رو مرور میکنیم. $em
درواقع انتیتی منیجر داکترین تعریف شده. وقتی ما این کلاس رو از Symfony\Bundle\FrameworkBundle\Controller\Controller
اکستند کردیم، امکاناتی مثل getDoctrine()
به $this
اضافه شده.
بعد اومده و لیست تمام رکوردهای موجود توی جدول پست رو گرفته، و در نهایت فایل app/Resources/views/post/index.html.twig
رو رندر کرده و پستها رو پاس داده بهش.
حالا بریم سراغ فایل app/Resources/views/post/index.html.twig
. تو خط اولش متوجه میشیم که {% extends 'base.html.twig'%} اجرا میشه، یعنی، این فایل ما یک بخشی از فایل اصلی base.html.twig
هست که تو پوشه app/Resources/views/base.html.twig
قرار گرفته.
شما با تغییر دادن این فایل میتونید ظاهر سایت رو عوض کنید. مثلا من بالای base.html.twig
میخوام اسم سایت رو اضافه کنم. فایلش رو باز میکنم و:
حالا بالای صفحه یه هدر دارم و پایین هم یه فوتر. یه استایل ساده رو داخل فولدر web/style.css
میذارم و اینا رو داخلش اضافه میکنم:
body {
font-family: sans;
}
.header {
margin: 15px;
background-color: #eee;
}
.footer {
margin: 15px;
border: 1px solid #ccc;
}
و در نهایت به base.html.twig
میگم که این فایل رو بیاره و تو صفحهها نمایش بده:
دستورات توییگ با { { } }
(بدون فاصله) اجرا میشن. و asset('...')
میره و هرچیزی که داخل فولدر web
بود رو برای شما با اون اسم میاره. دیگه نیازی نیست نگران آدرس فایلها باشید!
حالا میخوام جدولی که توی فایل app/Resources/views/post/index.html.twig
بود رو یکم قشنگتر کنم، یه فایل table.css
توی web
میسازم و اینارو داخل مینویسم:
table, td, th {
border: 1px solid #ddd;
text-align: left;
}
table {
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 15px;
}
و بعد، میخوام هرموقع که کاربر صفحه ایندکس پستها (indexAction
) رو باز میکنه، این استایل نمایش داده بشه. برای اینکار، فایل post/index.html.twig
رو باز میکنم و:
کارمون تموم شد. یه تست میکنیم:
app/console cache:clear
app/console server:run
حالا صفحه پستها رو باز کنید و ببینید چه اتفاقی افتاد…
خب ما باهم تونستیم یه وبسایت خیلی ساده رو درست کنیم و تقریبا هیچ کدی نزنیم. سیمفونی هنوز مونده و خیلی خیلی جا برای یادگیری داره، اما بنظرم شروع خوبی داشتیم و قطعا خودتون میتونید از اینجا به بعد رو تنهایی پیش برید.
پیشنهاد میکنم حتما سری به سایت سیمفونی، سایت آموزش داکترین و توییگ بزنید تا باهاشون بیشتر آشنا بشید.
با آرزوی موفقیت روزافزون برای شما
مطلبی دیگر از این انتشارات
تجربه های کاربری (UX) ضروری در اپلیکیشن های موبایل که به ندرت رعایت میشن
مطلبی دیگر از این انتشارات
به پیشرفت جامعه متن باز کمک کنید، تیشرت مجانی بگیرید!
مطلبی دیگر از این انتشارات
نگه داشتن فوتر در پایین صفحه مستقل از ارتفاع محتوا