Skip to content

YetAnotherFactsEnjoyer/RecipeBook

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🍳 RecipeBook

A modern Symfony recipe management application

PHP Symfony Doctrine PostgreSQL Twig


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.


✨ Features

  • 🍽️ 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

🧠 What It Does

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

πŸ› οΈ Tech Stack

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

πŸ“ Project Structure

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.lock

πŸš€ Getting Started

1. Clone the repository

git clone <your-repository-url>
cd RecipeBook-main

2. Install PHP dependencies

composer install

3. Start the database

The project includes Docker Compose configuration for PostgreSQL.

docker compose up -d

This starts a PostgreSQL database using the settings from compose.yaml.

Default database values:

POSTGRES_DB=app
POSTGRES_USER=app
POSTGRES_PASSWORD=!ChangeMe!

4. Configure environment variables

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:1025

5. Run database migrations

php bin/console doctrine:migrations:migrate

6. Start the Symfony server

symfony server:start

Or with PHP’s built-in server:

php -S localhost:8000 -t public

Then open:

http://localhost:8000

🧭 Main Routes

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

🍽️ Recipe Management

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'))

🏷️ Category Management

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.


πŸ“¬ Contact Form

The application includes a contact page powered by:

  • ContactController
  • ContactDTO
  • ContactType
  • Symfony Mailer
  • TemplatedEmail

The form collects:

Field Description
service Selected recipient service
name Sender name
email Sender email
message Message content

Available services:

Label Email
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.


βœ… Validation

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 1440 minutes

🚫 Custom Validator

Recipe titles use a custom BanWords validator.

By default, it blocks titles containing:

spam
macron

The validator lives in:

src/Validator/BanWords.php
src/Validator/BanWordsValidator.php

πŸ§ͺ Running Tests

Run the test suite with:

php bin/phpunit

Or:

vendor/bin/phpunit

🧰 Useful Commands

Clear Symfony cache

php bin/console cache:clear

Create a new migration

php bin/console make:migration

Run migrations

php bin/console doctrine:migrations:migrate

Check routes

php bin/console debug:router

Check services

php bin/console debug:container

Validate Doctrine schema

php bin/console doctrine:schema:validate

🎨 Interface

RecipeBook 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

🧱 Database

The application uses Doctrine ORM with PostgreSQL.

Main entities:

Recipe
Category
Duration

Relationship overview:

Category 1 ──── * Recipe

A category can have many recipes. A recipe can belong to one category.


🐳 Docker Services

The project includes Docker Compose services for local development.

PostgreSQL

Configured in:

compose.yaml

Mailpit

Configured in:

compose.override.yaml

Mailpit is useful for testing contact form emails without sending real emails.


πŸ“Œ Development Notes

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

🚧 Possible Improvements

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 DELETE method support
  • Add automated functional tests

Built with Symfony, Twig, Doctrine, and a love for good recipes. 🍝✨

About

Symfony RecipeBook Website

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors