Finish tag et commencer à ajouter les template.s

This commit is contained in:
2026-04-02 19:07:08 +02:00
parent 8a173ed2c7
commit 69a5a99e15
19 changed files with 620 additions and 34 deletions

View File

@@ -157,6 +157,7 @@ nav {
border: 1px solid black;
border-radius: 10px;
width: 95%;
max-width: calc(128px*0.95);
box-shadow: 1px 1px 1px black;
}
@@ -306,25 +307,51 @@ ul {
.recette-div-info {
display: flex;
flex-direction: row;
padding: 20px;
}
.recette-div-liste-info{
padding: 50px;
padding: 30px;
margin: 10px;
width: 100%;
flex:1;
}
.recette-list-buttons {
display: flex;
flex-direction: row-reverse;
}
.recette-button {
border: 1px solid black;
border-radius: 10px;
padding : 10px;
box-shadow: 1px 1px 1px black;
background-color: blanchedalmond;
}
.recette-button:hover{
background-color: rgb(243, 215, 174);
}
.recette-liste-info-elem {
text-align: left;
padding: 4px;
padding-top: 6px;
padding-bottom: 6px;
color: #535353bd;
border-right: 1px solid #535353bd;
border-left: 1px solid #535353bd;
}
.recette-liste-info {
display: flex;
flex-direction: column;
flex-direction: row;
}
.recette-liste-tag {
display: flex;
flex-direction: row;
flex-wrap: wrap; /*trouvé à l'aide de ChatGPT car je n'arrivais pas à trouver*/
}
@@ -373,8 +400,8 @@ ul {
.formcont form .form-group input {
width: 95%;
box-sizing: border-box;
font-size:3vmin;
padding:1vmin;
font-size:3vmin;
padding:1vmin;
}
@@ -386,7 +413,7 @@ ul {
margin: 0 auto;
background: #ffa04d;
color: black;
font-size: 5vmin;
font-size: 4vmin;
border-radius: 7px;
box-shadow: 2px 2px 0px #000000;
}
@@ -400,6 +427,30 @@ ul {
box-shadow: 3px 4px 5px #8c8c8c;
}
.recette-form-div-desc {
height: 90%;
}
.recette-form {
height: 100%;
width: 100%;
margin: 10px;
padding: 10px;
}
.recette-form-group {
display: flex;
flex-direction: column;
}
#recette-form-div-desc {
height: 400px;
}
#recette-form-description {
height: 95%;
}
/*Footer et son contenue*/
footer{
padding: 25px;

View File

@@ -4,6 +4,9 @@ namespace App\Domain;
use App\Http\Route;
/**
* Classe abstraite des controllers qui vont pouvoir permettre de gérer les routes et leur retour.
*/
abstract class Controller {
/**

View File

@@ -4,15 +4,30 @@ namespace App\Domain\Ingredients;
use App\Domain\Model;
/**
* Classe qui va gérer les ingrédients.
*/
class Ingredient extends Model {
/**
* Le numéro de l'ingrédient.
* @var int
*/
public int $num_ingredient;
/**
* Le nom de l'ingrédient
* @var string
*/
public string $nom_ingredient;
/**
* Retourne le numéro de l'ingrédient.
* @return int
*/
public function getID(): int
{
return $this->num_ingredient;
}
}

View File

@@ -6,15 +6,30 @@ use App\Domain\LinkableInterface;
use App\Domain\Recettes\Recette;
use App\Domain\Repository;
use App\Domain\Model;
use App\Domain\Tags\Tag;
use App\Kernel;
/**
* Classe qui va permettre de gérer les requêtes BDD en lien avec les ingrédients.
* Les ingrédients sont liables à d'autres entités comme les Recettes.
*/
class IngredientRepository extends Repository implements LinkableInterface {
/**
* Permet d'avoir le nom de l'entité dont dépend ce repo.
* @return string
*/
public static function getEntity(): string
{
return Ingredient::class;
}
/**
* La structure de notre table dans la BDD.
* Un champ link_recettes a été ajouté pour donner le nom de la table de lien entre nos recettes.
*
* @return array
*/
public static function getStructure(): array
{
return [
@@ -27,6 +42,19 @@ class IngredientRepository extends Repository implements LinkableInterface {
}
/**
* Permet d'obtenir une liste de tous les ingrédients objet Ingreident.
*
* @return Ingredient[]|null
*/
public function getAll(): ?array {
$sqlQuery = "SELECT * FROM {$this->tableName};";
$results = $this->selectGetAll($sqlQuery);
if( $results === null )
return null;
return $results;
}
/**
* Permet d'obtenir un ingrédient spécifique par son ID.
*
@@ -49,6 +77,7 @@ class IngredientRepository extends Repository implements LinkableInterface {
* @param string $linkingField Le champ qui permet de faire la liaison des ingrédients avec une autre entité.
* @param Model $linkedEntity L'autre entité.
*
* @see LinkableInterface
* @return array|null
*/
public function getIdLinkedTo( string $linkedTo, string $linkingField, Model $linkedEntity ): ?array {
@@ -64,6 +93,17 @@ class IngredientRepository extends Repository implements LinkableInterface {
return $results;
}
/**
* Permet d'ajouter un lien entre un ingrédient et une autre entité comme Recette.
*
* @param string $linkedTo
* @param string $linkingField
* @param Model $linkedEntity
* @param Model $ingredientEntity
*
* @see LinkableInterface
* @return bool
*/
public function addLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $ingredientEntity ): bool {
$linkName = 'link_' . $linkedTo;
@@ -77,6 +117,17 @@ class IngredientRepository extends Repository implements LinkableInterface {
}
/**
* Retire un lien dans la BDD entre un ingrédient et une autre entité.
*
* @param string $linkedTo
* @param string $linkingField
* @param Model $linkedEntity
* @param Model $ingredientEntity
*
* @see LinkableInterface
* @return bool
*/
public function removeLinkBetween(string $linkedTo, string $linkingField, Model $linkedEntity, Model $ingredientEntity ): bool
{
$linkName = 'link_' . $linkedTo;
@@ -88,14 +139,35 @@ class IngredientRepository extends Repository implements LinkableInterface {
return $statement->execute();
}
/**
* Ajouter un ingrédient dans la BDD.
*
* @param Model $ingredient
*
* @return bool
*/
public function add( Model $ingredient ): bool {
return $this->addEntity( $ingredient );
}
/**
* Met à jour un ingrédient dans la BDD.
*
* @param Model $ingredient
*
* @return bool
*/
public function update( Model $ingredient ): bool {
return $this->updateEntity( $ingredient, 'num_ingredient' );
}
/**
* Supprime un ingrédient de la BDD.
*
* @param Model $ingredient
*
* @return bool
*/
public function delete( Model $ingredient ): bool {
return $this->deleteEntity( $ingredient, 'num_ingredient' );
}

View File

@@ -4,6 +4,9 @@ namespace App\Domain\Ingredients;
use App\Domain\Model;
/**
* Interface utilisée par tous les repository qui sont en lien avec les ingrédients.
*/
interface UseIngredientsInterface {
/**
@@ -12,8 +15,24 @@ interface UseIngredientsInterface {
*/
public function getAllLinkedIngredients( Model $entity ): ?array;
/**
* Permet d'ajouter un ingrédient en lien avec notre autre entité.
*
* @param Ingredient $ingredient
* @param Model $entity
*
* @return bool
*/
public function addAnIngredient( Ingredient $ingredient, Model $entity ): bool;
/**
* Permet de retirer un lien entre un ingrédient et une autre entité.
*
* @param Ingredient $ingredient
* @param Model $entity
*
* @return bool
*/
public function removeAnIngredient( Ingredient $ingredient, Model $entity ): bool;
}

View File

@@ -2,12 +2,50 @@
namespace App\Domain;
/**
* Interface pour dire qu'un objet peut avoir un lien avec un autre objet par une table.
* Il s'agit d'une interface qui s'utilise sur des repositories de meta-données (Tag, Ingrédients)
*
* Les champs de toutes les méthodes se présentent de la même façon.
* $linkedTo : Champ qui va désigner le nom de la table de liens que vous avez dans getStructure().
* $linkingField : Champ dans la BDD qui va permettre de lier l'élément courant et l'étranger.
* $linkedEntity : Une instance de l'entité étrangère que l'on veut lier.
*/
interface LinkableInterface {
/**
* Permet de récupérer tous les liens entre notre entité implémentée et notre entité étrangère.
*
* @param string $linkedTo
* @param string $linkingField
* @param Model $linkedEntity
*
* @return array|null
*/
public function getIdLinkedTo( string $linkedTo, string $linkingField, Model $linkedEntity ): ?array;
/**
* Permet d'ajouter un lien entre notre entité implémentée et notre entité étrangère.
*
* @param string $linkedTo
* @param string $linkingField
* @param Model $linkedEntity
* @param Model $entity
*
* @return bool
*/
public function addLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $entity ): bool;
/**
* Permet de retirer un lien entre notre entité implémentée et notre entité étrangère.
*
* @param string $linkedTo
* @param string $linkingField
* @param Model $linkedEntity
* @param Model $entity
*
* @return bool
*/
public function removeLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $entity ): bool;
}

View File

@@ -2,6 +2,9 @@
namespace App\Domain;
/**
* Classe abstraite pour gérer l'implémentation des entités de données.
*/
abstract class Model {
/**

View File

@@ -11,11 +11,14 @@ use App\Infrastructure\View;
*/
class PagesController extends Controller {
/**
* Définit les routes globales d'acceuil.
* @return array|\App\Http\Route[]
*/
public static function defineRoutes(): array
{
return [
self::Route( routeUrl: '/', routeName: 'home', routeAction: 'index', pageHeadTitle: "Home Page" ),
self::Route( routeUrl: '/test/{int}/', routeName: 'test', routeAction: 'test' ),
];
}
@@ -28,8 +31,4 @@ class PagesController extends Controller {
return new View( 'home', [ 'ok' => 'bla' ] );
}
public function test( string $id ): void {
echo "Coucou" . $id;
}
}

View File

@@ -2,11 +2,15 @@
namespace App\Domain\Recettes;
use App\Domain\Ingredients\Ingredient;
use App\Domain\Ingredients\IngredientRepository;
use App\Domain\Ingredients\UseIngredientsInterface;
use App\Domain\Model;
use App\Helpers\Markdown;
/**
* Classe qui va permettre de gérer tous les objets recette.
*/
class Recette extends Model {
public int $num_recette;
@@ -22,13 +26,27 @@ class Recette extends Model {
return $this->num_recette;
}
/**
* Convertit la description de Markdown à HTML.
* @return string
*/
public function getHTMLDescription(): string {
return Markdown::convertToHTML( $this->description_recette );
}
/**
* Récupère une liste de tous les ingrédients liés à la recette.
* @return Ingredient[]|null
*/
public function getAllLinkedIngredients(): ?array
{
return new RecetteRepository()->getAllLinkedIngredients( $this );
}
public function getNumberOfIngredients(): int {
$response = $this->getAllLinkedIngredients();
return $response !== null ? count( $response ) : 0;
}
}

View File

@@ -7,8 +7,15 @@ use App\Domain\Ingredients\IngredientRepository;
use App\Domain\Ingredients\UseIngredientsInterface;
use App\Domain\Model;
use App\Domain\Repository;
use App\Domain\Tags\Tag;
use App\Domain\Tags\TagRepository;
use App\Domain\Tags\UseTagsInterface;
class RecetteRepository extends Repository implements UseIngredientsInterface {
/**
* Classe qui permet de faire le lien entre la BDD et le site pour les recettes.
* Les recettes sont en lien avec les ingrédients.
*/
class RecetteRepository extends Repository implements UseIngredientsInterface, UseTagsInterface {
public static function getEntity(): string
{
@@ -26,6 +33,42 @@ class RecetteRepository extends Repository implements UseIngredientsInterface {
}
/**
* Permet d'obtenir une liste de toutes les recettes objet Recette.
*
* @return Recette[]|null
*/
public function getAll(): ?array {
$sqlQuery = "SELECT * FROM {$this->tableName};";
$results = $this->selectGetAll($sqlQuery);
if( $results === null )
return null;
return $results;
}
/**
* Permet d'obtenir toutes les recettes paginées.
* Mise par défaut dans l'ordre croissant du titre et avec une pagination de 15 éléments.
*
* @param int $page
* @param int $pagination
*
* @return array|null
*/
public function getAllRecettesBrowse( int $page = 1, int $pagination = 15 ){
if( $page <= 0 )
$page = 1;
$offset = ( $page - 1 ) * $pagination;
$sqlQuery = "SELECT * FROM {$this->tableName} ORDER BY titre_recette ASC LIMIT {$pagination} OFFSET {$offset};";
$results = $this->selectGetAll($sqlQuery);
if( $results === null )
return null;
return $results;
}
/**
* Permet d'avoir une recette par un ID.
*
@@ -72,6 +115,8 @@ class RecetteRepository extends Repository implements UseIngredientsInterface {
{
$ingredientRepo = new IngredientRepository();
$response = $ingredientRepo->getIdLinkedTo( 'recettes', 'num_recette', $entity );
if( $response === null )
return null;
return array_map( function($arr) use($ingredientRepo) {
return $ingredientRepo->getByID( $arr['num_ingredient'] );
@@ -81,13 +126,37 @@ class RecetteRepository extends Repository implements UseIngredientsInterface {
public function addAnIngredient(Ingredient $ingredient, Model $entity): bool
{
$ingredientRepo = new IngredientRepository();
return $ingredientRepo->addLinkBetween( 'recettes', 'num_recette', $ingredient, $entity );
return $ingredientRepo->addLinkBetween( 'recettes', 'num_recette', $entity, $ingredient );
}
public function removeAnIngredient(Ingredient $ingredient, Model $entity): bool
{
$ingredientRepo = new IngredientRepository();
return $ingredientRepo->removeLinkBetween( 'recettes', 'num_recette', $ingredient, $entity );
return $ingredientRepo->removeLinkBetween( 'recettes', 'num_recette', $entity, $ingredient );
}
public function getAllLinkedTags(Model $entity): ?array
{
$tagRepo = new TagRepository();
$response = $tagRepo->getIdLinkedTo( 'recettes', 'num_recette', $entity );
if( $response === null )
return null;
return array_map( function($arr) use($tagRepo) {
return $tagRepo->getByID( $arr['num_tag'] );
}, $response );
}
public function addATag(Tag $tag, Model $entity): bool
{
$tagRepo = new TagRepository();
return $tagRepo->addLinkBetween( 'recettes', 'num_recette', $entity, $tag );
}
public function removeATag(Tag $tag, Model $entity): bool
{
$tagRepo = new TagRepository();
return $tagRepo->removeLinkBetween( 'recettes', 'num_recette', $entity, $tag );
}
}

View File

@@ -3,7 +3,10 @@
namespace App\Domain\Recettes;
use App\Domain\Controller;
use App\Domain\Ingredients\IngredientRepository;
use App\Domain\Tags\TagRepository;
use App\Http\JSONResponse;
use App\Http\Request;
use App\Infrastructure\View;
class RecettesController extends Controller {
@@ -18,7 +21,16 @@ class RecettesController extends Controller {
}
public function index(): View {
return new View( 'recettes/index', [] );
$page = Request::get( 'page' );
if( $page == null )
$page = 1;
return new View( 'recettes/index', [
'tagsList' => new TagRepository()->getAll(),
'ingredientsList' => new IngredientRepository()->getAll(),
'recettesList' => new RecetteRepository()->getAllRecettesBrowse( $page ),
] );
}
}

View File

@@ -6,6 +6,9 @@ use App\Domain\Recettes\Recette;
use App\Kernel;
use PDO;
/**
* Classe abstraite avec des méthodes pour pouvoir gérer les liens entre le site et la base de données.
*/
abstract class Repository {
/**

33
src/Domain/Tags/Tag.php Normal file
View File

@@ -0,0 +1,33 @@
<?php
namespace App\Domain\Tags;
use App\Domain\Model;
/**
* Classe qui va gérer les tags.
*/
class Tag extends Model {
/**
* Le numéro du tag.
* @var int
*/
public int $num_tag;
/**
* Le nom du tag
* @var string
*/
public string $nom_tag;
/**
* Retourne le numéro du tag.
* @return int
*/
public function getID(): int
{
return $this->num_tag;
}
}

View File

@@ -0,0 +1,174 @@
<?php
namespace App\Domain\Tags;
use App\Domain\LinkableInterface;
use App\Domain\Recettes\Recette;
use App\Domain\Repository;
use App\Domain\Model;
use App\Kernel;
/**
* Classe qui va permettre de gérer les requêtes BDD en lien avec les tags.
* Les tags sont liables à d'autres entités comme les Recettes.
*/
class TagRepository extends Repository implements LinkableInterface {
/**
* Permet d'avoir le nom de l'entité dont dépend ce repo.
* @return string
*/
public static function getEntity(): string
{
return Tag::class;
}
/**
* La structure de notre table dans la BDD.
* Un champ link_recettes a été ajouté pour donner le nom de la table de lien entre nos recettes.
*
* @return array
*/
public static function getStructure(): array
{
return [
'table' => 'Tag',
'columns' => [
'num_tag', 'nom_tag'
],
'link_recettes' => 'Referencetag'
];
}
/**
* Permet d'obtenir une liste de tous les tags objet Tag.
*
* @return Tag[]|null
*/
public function getAll(): ?array {
$sqlQuery = "SELECT * FROM {$this->tableName};";
$results = $this->selectGetAll($sqlQuery);
if( $results === null )
return null;
return $results;
}
/**
* Permet d'obtenir un tag spécifique par son ID.
*
* @param int $id
*
* @return Tag|null
*/
public function getByID( int $id ): ?Tag {
$sqlQuery = "SELECT * FROM {$this->tableName} WHERE num_tag = {$id}";
$results = $this->selectGetAll($sqlQuery);
if( $results === null || count( $results ) > 1 )
return null;
return $results[0];
}
/**
* Permet d'obtenir, sous forme de liste, toutes les entrées qui lient des tags.
*
* @param string $linkedTo La table qui permet de faire la liaison des tags avec une autre entité.
* @param string $linkingField Le champ qui permet de faire la liaison des tags avec une autre entité.
* @param Model $linkedEntity L'autre entité.
*
* @see LinkableInterface
* @return array|null
*/
public function getIdLinkedTo( string $linkedTo, string $linkingField, Model $linkedEntity ): ?array {
$linkName = 'link_' . $linkedTo;
if( !isset( $this->globalStructure[$linkName]))
return null;
$sqlQuery = "SELECT * FROM {$this->globalStructure[$linkName]} WHERE {$linkingField} = {$linkedEntity->getId()};";
$results = $this->selectGetAll($sqlQuery, true);
if( $results === null )
return null;
return $results;
}
/**
* Permet d'ajouter un lien entre un tag et une autre entité comme Recette.
*
* @param string $linkedTo
* @param string $linkingField
* @param Model $linkedEntity
* @param Model $tagEntity
*
* @see LinkableInterface
* @return bool
*/
public function addLinkBetween( string $linkedTo, string $linkingField, Model $linkedEntity, Model $tagEntity ): bool {
$linkName = 'link_' . $linkedTo;
if( !isset( $this->globalStructure[$linkName]))
return false;
$query = "INSERT INTO {$this->globalStructure[$linkName]} ({$linkingField},num_tag) VALUES ({$linkedEntity->getId()}, {$tagEntity->getID()});";
$statement = Kernel::$DB->pdo->prepare( $query );
return $statement->execute();
}
/**
* Retire un lien dans la BDD entre un tag et une autre entité.
*
* @param string $linkedTo
* @param string $linkingField
* @param Model $linkedEntity
* @param Model $tagEntity
*
* @see LinkableInterface
* @return bool
*/
public function removeLinkBetween(string $linkedTo, string $linkingField, Model $linkedEntity, Model $tagEntity ): bool
{
$linkName = 'link_' . $linkedTo;
if( !isset( $this->globalStructure[$linkName]))
return false;
$query = "DELETE FROM {$this->globalStructure[$linkName]} WHERE {$linkingField} = {$linkedEntity->getId()} AND num_tag = {$tagEntity->getId()};";
$statement = Kernel::$DB->pdo->prepare( $query );
return $statement->execute();
}
/**
* Ajouter un tag dans la BDD.
*
* @param Model $ingredient
*
* @return bool
*/
public function add( Model $tag ): bool {
return $this->addEntity( $tag );
}
/**
* Met à jour un tag dans la BDD.
*
* @param Model $tag
*
* @return bool
*/
public function update( Model $tag ): bool {
return $this->updateEntity( $tag, 'num_tag' );
}
/**
* Supprime un tag de la BDD.
*
* @param Model $tag
*
* @return bool
*/
public function delete( Model $tag ): bool {
return $this->deleteEntity( $tag, 'num_tag' );
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Domain\Tags;
use App\Domain\Model;
/**
* Interface utilisée par tous les repository qui sont en lien avec les tags.
*/
interface UseTagsInterface {
/**
* Permet de récupérer tous les tags liés à ce Modèle.
* @return array|null
*/
public function getAllLinkedTags( Model $entity ): ?array;
/**
* Permet d'ajouter un tag en lien avec notre autre entité.
*
* @param Tag $tag
* @param Model $entity
*
* @return bool
*/
public function addATag( Tag $tag, Model $entity ): bool;
/**
* Permet de retirer un lien entre un tag et une autre entité.
*
* @param Tag $tag
* @param Model $entity
*
* @return bool
*/
public function removeATag( Tag $tag, Model $entity ): bool;
}

View File

@@ -48,7 +48,7 @@ final class Router {
*/
public static function routeTo(): void {
self::$clientRouteString = $_SERVER['REQUEST_URI'];
self::$clientRouteString = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
self::$controllers = self::fetchControllers();
self::$routes = self::fetchRoutes();
@@ -185,7 +185,7 @@ final class Router {
return $args[$i++] ?? "";
}, $route->routeUrl);
return rtrim( Kernel::$configs['general']['website_url'] . $routeUrl, '/' );
return rtrim( rtrim( Kernel::$configs['general']['website_url'], '/' ) . $routeUrl, '/' );
}
}

View File

@@ -16,10 +16,11 @@
</div>
<nav>
<ul class="nav-list">
<li><a id="google" class="nav-element" href="google.com">Google</a></li>
<li><a id="unTest" class="nav-element" href="bing.com">Bing</a></li>
<li><a id="google" class="nav-element" href="<?php V::routeUrl( 'home'); ?>">Acceuil</a></li>
<li><a id="unTest" class="nav-element" href="<?php V::routeUrl( 'recettes->index'); ?>">Liste des recettes</a></li>
<?php if( \App\Helpers\Authentification::isLoggedIn() ): ?>
<li><a id="login" class= "nav-element" href="<?php V::routeUrl( 'logout'); ?>">Logout</a></li>
<li><a id="addBouton" class="nav-element" href="<?php V::routeUrl( 'recettes->create'); ?>">Ajouter une Recette</a></li>
<?php else: ?>
<li><a id="login" class= "nav-element" href="<?php V::routeUrl( 'login'); ?>">Login</a></li>
<?php endif; ?>

View File

@@ -0,0 +1,39 @@
<?php use App\Infrastructure\View as V; ?>
<div class="sidebar">
<div class="tag-cont">
<h4>Tag</h4>
<div class="tag-selected-div">
<ul>
</ul>
</div>
<form class="sidebar-search" action="none">
<input type="text" class="search-form search-form-tag" name="search-tag" placeholder="Rechercher..." >
</form>
<div class="tag-unselected-div">
<ul>
<?php foreach( V::arg( 'tagsList') as $tag ): ?>
<li class="tag tag-unselected" onclick="test()"><?php echo $tag->nom_tag; ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<hr id="hr">
<div class="ingr-cont">
<h4>Ingrédient</h4>
<div class="tag-selected-div">
<ul>
</ul>
</div>
<form class="sidebar-search" action="none">
<input type="text" class="search-form search-form-tag" name="search-ingr" placeholder="Rechercher..." >
</form>
<div class="tag-unselected-div">
<ul>
<?php foreach( V::arg( 'ingredientsList') as $tag ): ?>
<li class="tag tag-unselected" onclick="test()"><?php echo $tag->nom_ingredient; ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>

View File

@@ -1,20 +1,19 @@
<?php use App\Infrastructure\View as V; ?>
<div class="sidebar"> une sidebar</div>
<?php V::partial( 'tag-sidebar' ); ?>
<div class="content">
<div class="recettes">
<a href="recette-en-dur.php">
<div class="recette-icone">
<?php if( V::arg( 'recettesList' ) != null ) foreach( V::arg( 'recettesList' ) as $recette ): ?>
<a class="recette-icone" href="<?php V::routeUrl( 'recettes->show', $recette->slug ); ?>">
<img class="recette-preview-image" src="random-recette.jpg">
</div>
</a>
<div class="recette-icone"> 2 </div>
<div class="recette-icone"> 3 </div>
<div class="recette-icone"> 4 </div>
<div class="recette-icone"> 5 </div>
<div class="recette-icone"> 6 </div>
<div class="recette-icone"> 7 </div>
<div class="recette-icone"> 8 </div>
<div class="recette-icone"> 9 </div>
<div class="recette-icone-content">
<h3><?php echo $recette->titre_recette; ?></h3>
<ul>
<li>Temps de préparation : <?php echo $recette->temps_de_preparation; ?></li>
<li>Nombre d'ingrédients : <?php echo $recette->getNumberOfIngredients(); ?></li>
</ul>
</div>
</a>
<?php endforeach; ?>
</div>
</div>