RecipeBook is a Symfony web application for creating, organizing, and managing recipes and categories.
It includes a clean Bootstrap interface, Doctrine entities, admin CRUD pages, recipe validation, automatic slug generation, and a contact form powered by Symfony Mailer.
- π½οΈ Recipe listing and management
- π·οΈ Category management
- βοΈ Create, edit, and delete recipes
- π§Ύ Create, edit, and delete categories
- π Automatic slug generation
- β±οΈ Recipe duration tracking
- β Symfony form validation
- π« Custom banned-word validator
- π¬ Contact form with email sending
- π¨ Responsive Bootstrap UI
- ποΈ PostgreSQL database support with Docker
- π§± Doctrine ORM entities and repositories
- π§ͺ PHPUnit test setup included
RecipeBook lets users manage a small collection of cooking recipes.
The application has a public homepage that highlights quick recipes and an admin area where recipes and categories can be created, edited, and removed.
User
β
β visits homepage / contact page
βΌ
Symfony Controllers
β
βββ HomeController
βββ ContactController
βββ Admin Controllers
βββ RecipesController
βββ CategoryController
β
βΌ
Forms + Validation
β
βββ RecipeType
βββ CategoryType
βββ ContactType
βββ BanWords Validator
β
βΌ
Doctrine ORM
β
βββ Recipe
βββ Category
βββ Duration
β
βΌ
PostgreSQL Database| Tool | Purpose |
|---|---|
| PHP 8.1+ | Backend language |
| Symfony 6.4 | Main web framework |
| Doctrine ORM | Database mapping |
| PostgreSQL 16 | Database |
| Twig | HTML templating |
| Bootstrap 5 | UI styling |
| Symfony Forms | Form handling |
| Symfony Validator | Data validation |
| Symfony Mailer | Contact email sending |
| Docker Compose | Local database and mail services |
| PHPUnit | Testing setup |
RecipeBook-main/
βββ assets/
β βββ app.js
β βββ bootstrap.js
β βββ controllers.json
β
βββ bin/
β βββ console
β βββ phpunit
β
βββ config/
β βββ bundles.php
β βββ routes.yaml
β βββ services.yaml
β
βββ migrations/
β βββ Version20251002142557.php
β βββ Version20251002143247.php
β βββ Version20251013124122.php
β βββ Version20251014084721.php
β
βββ public/
β βββ .htaccess
β βββ index.php
β
βββ src/
β βββ Controller/
β β βββ ContactController.php
β β βββ HomeController.php
β β βββ Admin/
β β βββ CategoryController.php
β β βββ RecipesController.php
β β
β βββ DTO/
β β βββ ContactDTO.php
β β
β βββ Entity/
β β βββ Category.php
β β βββ Duration.php
β β βββ Recipe.php
β β
β βββ Form/
β β βββ CategoryType.php
β β βββ ContactType.php
β β βββ FormListenerFactory.php
β β βββ RecipeType.php
β β
β βββ Repository/
β β βββ CategoryRepository.php
β β βββ DurationRepository.php
β β βββ RecipeRepository.php
β β
β βββ Validator/
β β βββ BanWords.php
β β βββ BanWordsValidator.php
β β
β βββ Kernel.php
β
βββ templates/
β βββ base.html.twig
β βββ admin/
β β βββ admin.html.twig
β β βββ category/
β β βββ recipe/
β βββ contact/
β βββ emails/
β βββ home/
β βββ partials/
β
βββ tests/
βββ translations/
βββ compose.yaml
βββ compose.override.yaml
βββ composer.json
βββ importmap.php
βββ phpunit.dist.xml
βββ symfony.lockgit clone <your-repository-url>
cd RecipeBook-maincomposer installThe project includes Docker Compose configuration for PostgreSQL.
docker compose up -dThis starts a PostgreSQL database using the settings from compose.yaml.
Default database values:
POSTGRES_DB=app
POSTGRES_USER=app
POSTGRES_PASSWORD=!ChangeMe!Create or update your .env.local file:
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
MAILER_DSN=smtp://localhost:1025php bin/console doctrine:migrations:migratesymfony server:startOr with PHPβs built-in server:
php -S localhost:8000 -t publicThen open:
http://localhost:8000| Route | Name | Description |
|---|---|---|
/ |
home |
Homepage with featured recipes |
/contact |
contact |
Contact form |
/admin/recipe/ |
admin.recipe.index |
List all recipes |
/admin/recipe/create |
admin.recipe.create |
Create a recipe |
/admin/recipe/{id}/edit |
admin.recipe.edit |
Edit a recipe |
/admin/recipe/{id}/delete |
admin.recipe.remove |
Delete a recipe |
/admin/category/ |
admin.category.index |
List all categories |
/admin/category/create |
admin.category.create |
Create a category |
/admin/category/{id}/edit |
admin.category.edit |
Edit a category |
/admin/category/{id}/delete |
admin.category.remove |
Delete a category |
Recipes are represented by the Recipe entity.
A recipe contains:
| Field | Description |
|---|---|
id |
Unique recipe identifier |
title |
Recipe title |
slug |
URL-friendly recipe slug |
content |
Recipe description or instructions |
duration |
Cooking duration in minutes |
category |
Related category |
createdAt |
Creation date |
updatedAt |
Last update date |
The recipe form supports automatic slug creation using the recipe title.
->addEventListener(FormEvents::PRE_SUBMIT, $this->factory->autoSlug('title'))Categories are represented by the Category entity.
A category contains:
| Field | Description |
|---|---|
id |
Unique category identifier |
name |
Category name |
slug |
URL-friendly category slug |
createdAt |
Creation date |
updatedAt |
Last update date |
recipes |
Recipes linked to the category |
Each category can contain multiple recipes through a Doctrine OneToMany relationship.
The application includes a contact page powered by:
ContactControllerContactDTOContactTypeSymfony MailerTemplatedEmail
The form collects:
| Field | Description |
|---|---|
service |
Selected recipient service |
name |
Sender name |
email |
Sender email |
message |
Message content |
Available services:
| Label | |
|---|---|
| Accounting | accounting@demo.fr |
| Support | support@demo.fr |
| Marketing | marketing@demo.fr |
For local development, the Docker setup includes Mailpit.
Open the Mailpit interface at the port exposed by Docker to preview outgoing emails.
The project uses Symfony validation constraints on entities and DTOs.
Examples include:
- Required contact fields
- Valid email address
- Minimum title length
- Unique recipe titles
- Unique recipe slugs
- Unique category names
- Unique category slugs
- Slug format validation
- Maximum recipe duration of
1440minutes
Recipe titles use a custom BanWords validator.
By default, it blocks titles containing:
spam
macronThe validator lives in:
src/Validator/BanWords.php
src/Validator/BanWordsValidator.phpRun the test suite with:
php bin/phpunitOr:
vendor/bin/phpunitphp bin/console cache:clearphp bin/console make:migrationphp bin/console doctrine:migrations:migratephp bin/console debug:routerphp bin/console debug:containerphp bin/console doctrine:schema:validateRecipeBook uses Twig templates and Bootstrap to provide a clean, responsive interface.
Main UI pages include:
| Template | Purpose |
|---|---|
templates/base.html.twig |
Main layout with navbar and styling |
templates/home/index.html.twig |
Homepage |
templates/admin/recipe/index.html.twig |
Recipe list |
templates/admin/recipe/create.html.twig |
Recipe creation |
templates/admin/recipe/edit.html.twig |
Recipe edition |
templates/admin/category/index.html.twig |
Category list |
templates/admin/category/create.html.twig |
Category creation |
templates/admin/category/edit.html.twig |
Category edition |
templates/contact/contact.html.twig |
Contact page |
templates/emails/contact.html.twig |
Contact email template |
The application uses Doctrine ORM with PostgreSQL.
Main entities:
Recipe
Category
DurationRelationship overview:
Category 1 ββββ * RecipeA category can have many recipes. A recipe can belong to one category.
The project includes Docker Compose services for local development.
Configured in:
compose.yamlConfigured in:
compose.override.yamlMailpit is useful for testing contact form emails without sending real emails.
This project is a practical Symfony application focused on:
- MVC architecture
- Doctrine entity relationships
- Symfony forms
- Form event listeners
- Custom validation
- Twig templating
- Bootstrap UI
- Mail handling
- Database migrations
Ideas for future improvements:
- Add user authentication
- Protect admin routes
- Add recipe detail pages
- Upload recipe images
- Add recipe search and filters
- Add pagination
- Add fixtures for demo data
- Add API endpoints
- Improve category timestamps with lifecycle callbacks
- Add CSRF handling for delete routes with real
DELETEmethod support - Add automated functional tests
Built with Symfony, Twig, Doctrine, and a love for good recipes. πβ¨