====== Registro de comidas ====== Registro diario de las comidas. ===== Funcionalidades ===== * Registro de comidas * Día * Tipo (desayuno, comida, cena, picoteo) * Asociación de comidas a categorías (Postres, Carnes, Pescados, Frutas...) * Asociación de comidas a etiquetas * Detalle de comida por ingredientes ===== Estructura de base de datos ===== ==== Tipos de comida ==== * id * nombre * slug * descripción ==== Comidas ==== * id * usuario_id (opcional) * nombre * descripcion (opcional) * fecha * calorias * tipo (desayuno, comida, cena, tentempié) * id_categoria (opcional) * lugar (casa, fuera) ==== Ingredientes ==== * id * nombre * id_categoria * calorias_por_100g ==== Comida_Ingrediente ==== Tabla que relaciona comidas e ingredientes. * id_comida * id_ingrediente * cantidad (gramos) ==== Categorías ==== * id * nombre * color? ==== Etiquetas ==== * id * nombre * slug ==== Comida_Etiqueta ==== Tabla que relaciona comidas y etiquetas * id_comida * id_tag ===== Herramientas empleadas ===== * Framework [[informatica:programacion:php:frameworks:laravel|Laravel]] (PHP) ===== Base de datos ===== Diagrama entidad-relación. ===== Tipos de comida ===== Según el momento del día: * Desayuno * Comida * Cena * Tentempié / picoteo / snack ==== Migración ==== php artisan make:migration create_meal_types_table Contenido del fichero ''database/migrations/2025_03_30_164255_create_meal_types_table.php'': id(); $table->string('name'); $table->string('slug')->unique(); $table->text('description')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('meal_types'); } }; ==== Modelo ==== Lo creamos con: php artisan make:model MealType Contenido del fichero generado ''app/Models/MealType.php'': ===== Categorías ===== Migración para la tabla de las **categorías**: php artisan make:migration create_categories_table Fichero con la migración (''database/migrations/2025_03_28_200000_create_categories_table.php''): id(); $table->string('name')->unique(); $table->string('color')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('categories'); } } Modelo para las **categorías** (''app/Models/Category.php''): hasMany(Meal::class); } public function ingredients() { return $this->hasMany(Ingredient::class); } } ==== Controlador ==== Creamos un controlador asociado al modelo de las categorías: php artisan make:controller CategoryController -m Category Se creará el fichero ''app/Http/Controllers/CategoryController.php'' con la firma de los 7 métodos: * ''index()'' * ''create()'' * ''store()'' * ''show()'' * ''edit()'' * ''update()'' * ''destroy()'' ==== Vistas ==== Creamos las vistas para todos los métodos del controlador menos ''store()'', ''update()'' y ''destroy()'': php artisan make:view categories.index php artisan make:view categories.create php artisan make:view categories.show php artisan make:view categories.edit Se habrán creado los siguientes ficheros en el directorio ''resources/views/categories'': * ''index.blade.php'' * ''create.blade.php'' * ''show.blade.php'' * ''edit.blade.php'' ==== Rutas ==== En el fichero ''routes/web.php'' añadimos: Route::resource('categories', CategoryController::class); Podemos verificar con el siguiente comando las rutas registradas: php artisan route:list ===== Comidas ===== ==== Migración ==== **Migración** para la tabla de las **comidas**: php artisan make:migration create_meals_table Fichero con la migración (''database/migrations/2025_03_28_210000_create_meals_table.php''): id(); $table->foreignId('user_id')->nullable()->constrained()->cascadeOnDelete(); $table->string('name'); $table->text('description')->nullable(); $table->dateTime('date_time'); $table->integer('calories')->nullable(); $table->enum('meal_type', ['desayuno', 'comida', 'cena', 'tentempié']); $table->foreignId('category_id')->nullable()->constrained(); $table->enum('location_type', ['casa', 'fuera'])->default('casa'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('meals'); } }; ==== Modelo ==== Modelo para las categorías (''app/Models/Meal.php''): 'datetime', ]; // Relaciones public function user(): BelongsTo { return $this->belongsTo(User::class); } public function category(): BelongsTo { return $this->belongsTo(Category::class); } public function ingredients(): BelongsToMany { return $this->belongsToMany(Ingredient::class) ->withPivot('quantity') ->withTimestamps(); } public function tags(): BelongsToMany { return $this->belongsToMany(Tag::class) ->withTimestamps(); } // Accesor para el lugar public function getLocationAttribute(): string { return match($this->location_type) { 'casa' => 'En casa', 'casa_familiar' => 'Casa de familiar', 'restaurante' => $this->restaurant ?? 'Restaurante', default => 'Desconocido' }; } } ==== Controlador ==== Creamos un controlador asociado al modelo de las categorías: php artisan make:controller MealController -m Meal Se creará el fichero ''app/Http/Controllers/MealController.php'' con la firma de los 7 métodos: * index() * create() * store() * show() * edit() * update() * destroy() ==== Vistas ==== Creamos las vistas para todos los métodos del controlador menos ''store()'', ''update()'' y ''destroy()'': php artisan make:view meals.index php artisan make:view meals.create php artisan make:view meals.show php artisan make:view meals.edit Se habrán creado los siguientes ficheros en el directorio ''resources/views/meals'': * ''index.blade.php'' * ''create.blade.php'' * ''show.blade.php'' * ''edit.blade.php'' ==== Rutas ==== En el fichero ''routes/web.php'' añadimos: Route::resource('meals', MealController::class); Podemos verificar con el siguiente comando las rutas registradas: php artisan route:list