
Créer un blog – les données
On a vu dans le précédent article la présentation générale du projet de blog et on a aussi créé un Laravel 8 de base avec l’authentification avec Laravel Breeze. On va maintenant se lancer et on va commencer par s’intéresser aux données. Que va contenir notre base ? Quelles tables nous sont nécessaires avec quelles colonnes ? Que va-t-on avoir comme relations ? Quelle sont les données de populations qu’on va générer pour que notre blog fonctionne dès le départ ? Ce sont les bonnes questions à se poser quand on démarre un projet, même si ça évolue forcément en cours de route
Vous pouvez télécharger le code final de cet article ici.
Les données de base de Laravel
Pour le moment avec notre Laravel de base on a ces migrations :
Donc :
- une migration pour la table users
- une migration pour la table password_resets pour le renouvellement des mots de passe
- une migration pour la table failed_jobs pour les tâches qui ont échoué
Comme on va utiliser le système de notifications de Laravel pour notre blog (on va même un peu le détourner) on va ajouter la migration correspondante :
php artisan notifications:table
Les utilisateurs
Par défaut la table users comporte ces colonnes :
Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); });
On va avoir besoin d’autres informations :
- role : pour savoir quelles sont les permissions de l’utilisateur : administrateur, rédacteur ou simple utilisateur. Ce n’est pas la peine d’utiliser un package pour ce genre de chose.
- valid : pour valider un utilisateur au niveau des commentaires, le premier commentaire d’un utilisateur n’apparaît pas tout de suite, il faut que ce soit validé par l’administrateur ou l’auteur de l’article, les commentaires suivants par contre apparaitront tout de suite, c’est une façon d’éviter les trolls.
On ajoute donc ces deux colonnes :
Schema::create('users', function (Blueprint $table) { ... $table->enum('role', array('user', 'redac', 'admin'))->default('user'); $table->boolean('valid')->default(false); ... });
On a déjà un modèle User. Toutefois on va ajouter les deux colonnes qu’on a créées dans la propriété $fillable :
protected $fillable = [ 'name', 'email', 'password', 'role', 'valid', ];
C’est facile à oublier et ensuite on cherche le bug un bon moment 🙂
On dispose déjà d’un factory pour cette table (database/factories/UserFactory.php). On va juste le compléter pour mettre la colonne valid à true :
return [ 'name' => $this->faker->name, 'email' => $this->faker->unique()->safeEmail, 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'remember_token' => Str::random(10), 'valid' => true, ];
Les catégories
Les articles vont être organisées en catégories, on va donc créer une table pour mémoriser ces informations. On va créer simultanément le modèle et la migration :
php artisan make:model Category -m
Pour les catégories on va avoir besoin de deux informations :
- title : le titre
- slug : c’est le texte qui va apparaître dans l’url et qui ne doit comporter que des caractères autorisés
D’autre part on ne va pas utiliser les timestamps, quel intérêt de savoir quand une catégorie a été créée ou modifiée ? On a donc :
Schema::create('categories', function (Blueprint $table) { $table->id(); $table->string('title')->unique(); $table->string('slug')->unique(); });
Pour le modèle on va supprimer le trait HasFactory qui ne nous servira pas et on crée la propriété $fillable :
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Category extends Model { protected $fillable = [ 'title', 'slug', ]; public $timestamps = false; }
Les étiquettes (tags)
Les articles vont être aussi identifiables avec des étiquettes, ce qui permet une sélection transversale alors que les catégories créent une organisation verticale. On crée le modèle et la migration :
php artisan make:model Tag -m
Pour les étiquettes on va avoir besoin de deux informations comme pour les cétégories :
- tag : le titre
- slug : c’est le texte qui va apparaître dans l’url et qui ne doit comporter que des caractères autorisés
D’autre part on ne va pas non plus utiliser les timestamps, quel intérêt de savoir quand une étiquette a été créée ou modifiée ? On a donc :
Schema::create('tags', function(Blueprint $table) { $table->id(); $table->string('tag', 50)->unique(); $table->string('slug')->unique(); });
Pour le modèle on va aussi supprimer le trait HasFactory qui ne nous servira pas et on crée la propriété $fillable :
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Tag extends Model { /** * The attributes that are mass assignable. * * @var array */ protected $fillable = ['tag']; public $timestamps = false; }
Les articles (posts)
Là c’est le gros morceau évidemment ! On crée le modèle, la migration et le factory :
php artisan make:model Post -mfc
On va avoir besoin de pas mal d’informations :
- title : le titre
- slug
- seo_title : le titre pour le SEO
-
meta_keywords : les mots clés pour le SEO
- meta_description : la description pour le SEO
-
excerpt : le texte d’introduction (celui qui apparaît en résumé sur la page d’accueil)
- body : le corps de l’article
- active : pour savoir si l’article est publié
- image : pour le nom de l’image réduite pour la page d’accueil
Schema::create('posts', function(Blueprint $table) { $table->id(); $table->timestamps(); $table->string('title'); $table->string('slug')->unique(); $table->string('seo_title')->nullable(); $table->text('excerpt'); $table->text('body'); $table->text('meta_description'); $table->text('meta_keywords'); $table->boolean('active')->default(false); $table->string('image')->nullable(); });
Pour le factory on va prévoir le remplissage automatique de quelques colonnes :
public function definition() { return [ 'meta_description' => $this->faker->sentence($nbWords = 6, $variableNbWords = true), 'meta_keywords' => implode(',', $this->faker->words($nb = 3, $asText = false)), 'excerpt' => $this->faker->paragraph($nbSentences = 4, $variableNbSentences = true), 'body' => $this->faker->paragraphs($nb = 8, $asText = true), 'active' => true, ]; }
On gèrera titre, slug et image directement dans la population.
Pour le modèle on va créer la propriété $fillable et aussi prévoir le trait Notifiable :
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use App\Events\ModelCreated; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Notifications\Notifiable; class Post extends Model { use HasFactory, Notifiable; protected $fillable = [ 'title', 'slug', 'seo_title', 'excerpt', 'body', 'meta_description', 'meta_keywords', 'active', 'image', 'user_id', ]; }
Les relations
Arrivé à ce stade il est temps de s’intéresser aux relations. On va avoir :
- un utilisateur peut avoir plusieurs articles (et réciproquement un article appartient à un seul utilisateur)
- une catégorie peut avoir plusieurs articles et réciproquement un article peut appartenir à plusieurs catégories
- un article peut avoir plusieurs étiquettes et une étiquette peut appartenir à plusieurs articles
Un utilisateur a plusieurs articles
Il faut mettre une clé étrangère dans la table posts, donc dans la migration :
public function up() { Schema::create('posts', function(Blueprint $table) { ... $table->foreignId('user_id') ->constrained() ->onDelete('cascade') ->onUpdate('cascade'); }); }
J’ai opté pour une cascade en cas de suppression ou de modification.
Au niveau des modèles on ajoute la relation dans User :
public function posts() { return $this->hasMany(Post::class); }
Et dans Post :
public function user() { return $this->belongsTo(User::class); }
Relation entre catégories et articles
Là c’est une relation many to many, il faut donc une table pivot :
php artisan make:migration category_post_table
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CategoryPostTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('category_post', function(Blueprint $table) { $table->id(); $table->foreignId('category_id') ->constrained() ->onDelete('cascade') ->onUpdate('cascade'); $table->foreignId('post_id') ->constrained() ->onDelete('cascade') ->onUpdate('cascade'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('category_post'); } }
On a évidemment dans cette table deux clés étrangères :
- category_id : pour référencer la catégorie
- post_id : pour référencer l’article
On ajoute la relation dans Category :
public function posts() { return $this->belongsToMany(Post::class); }
Et dans Post :
public function categories() { return $this->belongsToMany(Category::class); }
Relation entre étiquettes et articles
Là c’est encore une relation many to many, il faut donc une table pivot :
php artisan make:migration post_tag_table
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class PostTagTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('post_tag', function(Blueprint $table) { $table->id(); $table->foreignId('post_id') ->constrained() ->onDelete('cascade') ->onUpdate('cascade'); $table->foreignId('tag_id') ->constrained() ->onDelete('cascade') ->onUpdate('cascade'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('post_tag'); } }
On a évidemment aussi dans cette table deux clés étrangères :
- tag_id : pour référencer l’étiquette
- post_id : pour référencer l’article
On ajoute la relation dans Tag :
public function posts() { return $this->belongsToMany(Post::class); }
Et dans Post :
public function tags() { return $this->belongsToMany(Tag::class); }
Les commentaires
Pour les commentaires on a quelque chose d’un peu spécial parce on a un système hiérarchique, on a des commentaires de commentaire, et des des commentaires de commentaire de commentaire, et ainsi de suite. Pour gérer ça on va utiliser le package NestedSet. Il faut d’abord l’installer :
composer require kalnoy/nestedset
On crée le modèle avec factory et migration :
php artisan make:model Comment -mfc
Pour la migration on a pas besoin de grand chose, juste une colonne body pour le texte du commentaire. Par contre on va ajouter les colonnes nécessaires pour la gestion des relations entre les commentaires, mais le package va bien nous aider. En plus il faut relier cette table aux utilisateurs et articles :
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateCommentsTable extends Migration { public function up() { Schema::create('comments', function(Blueprint $table) { $table->id(); $table->timestamps(); $table->text('body'); $table->nestedSet(); $table->foreignId('user_id') ->constrained() ->onDelete('cascade') ->onUpdate('cascade'); $table->foreignId('post_id') ->constrained() ->onDelete('cascade') ->onUpdate('cascade'); }); } public function down() { Schema::dropIfExists('comments'); } }
Pour le factory on renseigne juste body :
public function definition() { return [ 'body' => $this->faker->paragraph($nbSentences = 4, $variableNbSentences = true), ]; }
Pour le modèle Comment on va ajouter le trait NodeTrait pour le package, et aussi Notifiable. D’autre part on crée la propriété $fillable.
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Kalnoy\Nestedset\NodeTrait; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Notifications\Notifiable; class Comment extends Model { use NodeTrait, HasFactory, Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'body', 'post_id', 'user_id', ]; }
Pour les relations on a :
- un utilisateur a plusieurs commentaires et un commentaire appartient à un utilisateur
- un article a plusieurs commentaires et un commentaire appartient à un article
Donc dans User :
public function comments() { return $this->hasMany(Comment::class); }
Dans Post :
public function comments() { return $this->hasMany(Comment::class); }
Dans Post on va ajouter une relation spécifique pour récupérer les commentaires valides (en fait les commentaires qui ont été rédigés par un utilisateur validé) :
public function validComments() { return $this->comments()->whereHas('user', function ($query) { $query->whereValid(true); }); }
Et dans Comment on précise l’appartenance à l’utilisateur et à l’article :
public function user() { return $this->belongsTo(User::class); } public function post() { return $this->belongsTo(Post::class); }
Une petite visualisation de la situation :
La population
Maintenant qu’on a créé les migrations essentielles vous pouvez lancer la migration pour voir si tout se passe bien :
php artisan migrate
Vous devez obtenir ces 11 tables :
Vous pouvez aussi vérifier que vous avez les bonnes colonnes dans chacune de ces tables.
On ajoutera utltérieurement d’autres tables pour les contacts, les pages… Mais pour le moment on va s’en passer et on va faire tourner le blog.
Pour nos essais on va avoir besoin de données dans les tables, on va utiliser pour ça la population (seeder) avec ce fichier :
Pour le moment la fonction run est vide (on a juste un peu de code commenté) :
public function run() { // \App\Models\User::factory(10)->create(); }
Les utilisateurs
On va créer un administrateur, 2 rédacteurs et 3 utilisateurs de base :
use App\Models\{ User, Contact, Post, Comment, Page }; use Illuminate\Support\Facades\DB; ... User::withoutEvents(function () { // Create 1 admin User::factory()->create([ 'role' => 'admin', ]); // Create 2 redactors User::factory()->count(2)->create([ 'role' => 'redac', ]); // Create 3 users User::factory()->count(3)->create(); }); $nbrUsers = 6;
J’utilise withoutEvents pour inhiber les événements, pour l’instant on n’en a pas mais on en mettra en place plus tard, du coup ça n’aura pas d’impact sur la population.
Les catégories
On crée 3 catégories :
DB::table('categories')->insert([ [ 'title' => 'Category 1', 'slug' => 'category-1' ], [ 'title' => 'Category 2', 'slug' => 'category-2' ], [ 'title' => 'Category 3', 'slug' => 'category-3' ], ]); $nbrCategories = 3;
Les étiquettes
On prévoit 6 étiquettes :
DB::table('tags')->insert([ ['tag' => 'Tag1', 'slug' => 'tag1'], ['tag' => 'Tag2', 'slug' => 'tag2'], ['tag' => 'Tag3', 'slug' => 'tag3'], ['tag' => 'Tag4', 'slug' => 'tag4'], ['tag' => 'Tag5', 'slug' => 'tag5'], ['tag' => 'Tag6', 'slug' => 'tag6'] ]); $nbrTags = 6;
Les articles
On crée 9 articles qu’on attribue aux 2 rédacteurs :
Post::withoutEvents(function () { foreach (range(1, 2) as $i) { Post::factory()->create([ 'title' => 'Post ' . $i, 'slug' => 'post-' . $i, 'seo_title' => 'Post ' . $i, 'user_id' => 2, 'image' => 'img0' . $i . '.jpg', ]); } foreach (range(3, 9) as $i) { Post::factory()->create([ 'title' => 'Post ' . $i, 'slug' => 'post-' . $i, 'seo_title' => 'Post ' . $i, 'user_id' => 3, 'image' => 'img0' . $i . '.jpg', ]); } }); $nbrPosts = 9;
Pour les images je pars du principe qu’on a des images qui s’appellent img00, img01, img02…
On va attacher des étiquettes et des catégories aux articles :
// Tags attachment $posts = Post::all(); foreach ($posts as $post) { if ($post->id === 9) { $numbers=[1,2,5,6]; $n = 4; } else { $numbers = range (1, $nbrTags); shuffle ($numbers); $n = rand (2, 4); } for($i = 0; $i < $n; ++$i) { $post->tags()->attach($numbers[$i]); } } // Set categories foreach ($posts as $post) { if ($post->id === 9) { DB::table ('category_post')->insert ([ 'category_id' => 1, 'post_id' => 9, ]); } else { $numbers = range (1, $nbrCategories); shuffle ($numbers); $n = rand (1, 2); for ($i = 0; $i < $n; ++$i) { DB::table ('category_post')->insert ([ 'category_id' => $numbers[$i], 'post_id' => $post->id, ]); } } }
Les commentaires
On commence par créer des commentaires de premier niveau :
foreach (range(1, $nbrPosts - 1) as $i) { Comment::factory()->create([ 'post_id' => $i, 'user_id' => rand(1, $nbrUsers), ]); }
Pour les commentaires des autres niveaux le package permet d’utiliser des tableaux, ce qui est bien pratique :
$faker = \Faker\Factory::create(); Comment::create([ 'post_id' => 2, 'user_id' => 3, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), 'children' => [ [ 'post_id' => 2, 'user_id' => 4, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), 'children' => [ [ 'post_id' => 2, 'user_id' => 2, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), ], ], ], ], ]); Comment::create([ 'post_id' => 2, 'user_id' => 6, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), 'children' => [ [ 'post_id' => 2, 'user_id' => 3, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), ], [ 'post_id' => 2, 'user_id' => 6, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), 'children' => [ [ 'post_id' => 2, 'user_id' => 3, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), 'children' => [ [ 'post_id' => 2, 'user_id' => 6, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), ], ], ], ], ], ], ]); Comment::create([ 'post_id' => 4, 'user_id' => 4, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), 'children' => [ [ 'post_id' => 4, 'user_id' => 5, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), 'children' => [ [ 'post_id' => 4, 'user_id' => 2, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), ], [ 'post_id' => 4, 'user_id' => 1, 'body' => $faker->paragraph($nbSentences = 4, $variableNbSentences = true), ], ], ], ], ]);
Il ne reste plus qu’à lancer la population :
php artisan db:seed
Vérifiez dans vos tables que vous obtenez bien les données attendues.
Conclusion
On dispose maintenant des tables et des données pour commencer à coder notre frontend, ce que nous feraons dans le prochain article. Il faudra aussi s’occuper des medias avec un nouveau package.


49 commentaires
WinnerK
Bonjour coach j’ai suivi tous les cours à la lettre mais au niveau du migrate, je tombe sur cette erreur:
Illuminate\Database\QueryException
SQLSTATE[HY000] [2002] Aucune connexion n’a pu être établie car l’ordinateur cible l’a expressément refusée (SQL: select * from information_schema.tables where table_schema = laravel and table_name = migrations and table_type = ‘BASE TABLE’)
at C:\wamp64\www\monblog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:712
708▕ // If an exception occurs when attempting to run a query, we’ll format the error
709▕ // message to include the bindings with SQL, which will make this exception a
710▕ // lot more helpful to the developer instead of just the database’s errors.
711▕ catch (Exception $e) {
➜ 712▕ throw new QueryException(
713▕ $query, $this->prepareBindings($bindings), $e
714▕ );
715▕ }
716▕ }
1 C:\wamp64\www\monblog\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70
PDOException::(« SQLSTATE[HY000] [2002] Aucune connexion n’a pu être établie car l’ordinateur cible l’a expressément refusée »)
2 C:\wamp64\www\monblog\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70
PDO::__construct(« mysql:host=127.0.0.1;port=3306;dbname=laravel », « root », « », [])
bestmomo
Bonjour,
La base de données semble inaccessible, il faudrait vérifier login et mot de passe pour y accéder.
devotion1
bonjour coach, je reviens pour solliciter votre aide une fois de plus,
j’ai suivis avec detaille les etapes et j’ai cette erreur après avoir taper :
php artisan db:seed
Illuminate\Database\QueryException
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ‘Category 1’ for key ‘categories_title_unique’ (SQL: insert into `categories` (`slug`, `title`) values (category-1, Category 1), (category-2, Category 2), (category-3, Category 3))
at C:\laragon\www\objets\vendor\laravel\framework\src\Illuminate\Database\Connection.php:703
699▕ // If an exception occurs when attempting to run a query, we’ll format the error
700▕ // message to include the bindings with SQL, which will make this exception a
701▕ // lot more helpful to the developer instead of just the database’s errors.
702▕ catch (Exception $e) {
➜ 703▕ throw new QueryException(
704▕ $query, $this->prepareBindings($bindings), $e
705▕ );
706▕ }
707▕ }
1 C:\laragon\www\objets\vendor\laravel\framework\src\Illuminate\Database\Connection.php:492
PDOException::(« SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ‘Category 1’ for key ‘categories_title_unique' »)
2 C:\laragon\www\objets\vendor\laravel\framework\src\Illuminate\Database\Connection.php:492
PDOStatement::execute()
bestmomo
Salut,
Normal si la base a déjà été remplie. Il faut utiliser cette commande pour tout régénérer :
php artisan migrate:fresh --seed
devotion1
bonjour chef, voici la reponse lorque le tape
λ php artisan migrate:fresh –seed
Dropped all tables successfully.
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (547.73ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (517.68ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (479.09ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated: 2019_12_14_000001_create_personal_access_tokens_table (744.92ms)
Migrating: 2021_10_27_102135_create_notifications_table
Migrated: 2021_10_27_102135_create_notifications_table (978.47ms)
Migrating: 2021_10_27_105211_create_categories_table
Migrated: 2021_10_27_105211_create_categories_table (747.38ms)
Migrating: 2021_10_27_144539_create_tags_table
Migrated: 2021_10_27_144539_create_tags_table (624.37ms)
Migrating: 2021_10_27_145251_create_posts_table
Migrated: 2021_10_27_145251_create_posts_table (1,166.64ms)
Migrating: 2021_10_27_161252_category_post_table
Migrated: 2021_10_27_161252_category_post_table (4,385.08ms)
Migrating: 2021_10_27_164406_post_tag_table
Migrated: 2021_10_27_164406_post_tag_table (2,018.66ms)
Migrating: 2021_10_27_165859_create_commets_table
Migrated: 2021_10_27_165859_create_commets_table (1,963.57ms)
Illuminate\Database\QueryException
SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘updated_at’ in ‘field list’ (SQL: insert into `posts` (`meta_descr
iption`, `meta_keywords`, `excerpt`, `body`, `active`, `title`, `slug`, `seo_title`, `user_id`, `image`, `updated_at`, `crea
ted_at`) values (Sunt autem illum dignissimos dolores voluptas repellat molestias. Iusto quis voluptas dicta nulla beatae ex
quasi. Mollitia error voluptates consequatur sunt. Necessitatibus in magnam animi ut. Facilis sit beatae excepturi velit. E
os incidunt velit iste facere., nisi,consequatur,sit, Iste maxime nam optio ut accusantium magni. Eveniet architecto possimu
s quo. Non quia ut omnis magnam. Id est iure eos autem ut est vero. Non blanditiis vero nemo qui., Aut expedita nulla suscip
it. Aut et voluptatem omnis consequuntur. Nihil est voluptatem aut porro. Voluptatem sunt distinctio quia. Earum officia quo
s corrupti dignissimos labore dolorum ratione., 1, Post 1, post-1, Post 1, 2, img01.jpg, 2021-12-22 09:20:08, 2021-12-22 09:
20:08))
at C:\laragon\www\objets\vendor\laravel\framework\src\Illuminate\Database\Connection.php:703
699▕ // If an exception occurs when attempting to run a query, we’ll format the error
700▕ // message to include the bindings with SQL, which will make this exception a
701▕ // lot more helpful to the developer instead of just the database’s errors.
702▕ catch (Exception $e) {
➜ 703▕ throw new QueryException(
704▕ $query, $this->prepareBindings($bindings), $e
705▕ );
706▕ }
707▕ }
• A column was not found: You might have forgotten to run your migrations. You can run your migrations using `php artisan
migrate`.
https://laravel.com/docs/master/migrations#running-migrations
1 C:\laragon\www\objets\vendor\laravel\framework\src\Illuminate\Database\Connection.php:486
PDOException::(« SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘updated_at’ in ‘field list' »)
2 C:\laragon\www\objets\vendor\laravel\framework\src\Illuminate\Database\Connection.php:486
PDO::prepare(« insert into `posts` (`meta_description`, `meta_keywords`, `excerpt`, `body`, `active`, `title`, `slug`,
`seo_title`, `user_id`, `image`, `updated_at`, `created_at`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) »)
bestmomo
Salut,
Dans la migration de la table posts (2021_10_27_145251_create_posts_table) tu as bien cette ligne ?
$table->timestamps();
devotion1
Salut Coach,
Dans ma migration de la table posts (2021_10_27_145251_create_posts_table) j’ai pas la ligne ?
$table->timestamps();
bestmomo
Salut,
Alors ajoute cette ligne.
devotion1
Salut, je suis un apprenti au développement web.
j’ai suivi à la lettre les étapes mais j’ai eu une erreur.
je besoin de votre expertise
Illuminate\Database\QueryException
SQLSTATE[HY000] [2002] Aucune connexion n’a pu être établie car l’ordinateur ci
le l’a expressément refusée (SQL: SHOW FULL TABLES WHERE table_type = ‘BASE TABL
‘)
at C:\xampp\htdocs\freecod\projets\tuto\blog\vendor\laravel\framework\src\Illum
nate\Database\Connection.php:692
688▕ // If an exception occurs when attempting to run a query, we’ll
ormat the error
689▕ // message to include the bindings with SQL, which will make thi
exception a
690▕ // lot more helpful to the developer instead of just the databas
‘s errors.
691▕ catch (Exception $e) {
➜ 692▕ throw new QueryException(
693▕ $query, $this->prepareBindings($bindings), $e
694▕ );
695▕ }
696▕ }
1 C:\xampp\htdocs\freecod\projets\tuto\blog\vendor\laravel\framework\src\Illu
inate\Database\Connectors\Connector.php:70
PDOException::(« SQLSTATE[HY000] [2002] Aucune connexion n’a pu être établie
car l’ordinateur cible l’a expressément refusée »)
2 C:\xampp\htdocs\freecod\projets\tuto\blog\vendor\laravel\framework\src\Illu
inate\Database\Connectors\Connector.php:70
PDO::__construct(« mysql:host=127.0.0.1;port=3306;dbname=laravel », « root », »
, [])
bestmomo
Salut,
Est-ce que MySql est bien accessible avec le bon identifiant et mot de passe ?
devotion1
oui MYSQL est accessible
identifiant ‘root’ et pas de mot de pass
bestmomo
Tu peux montrer la partie du fichier .env qui concerne la connexion à la base ?
devotion1
voici le fichier .env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:MOgspTew72U835sbv/scUxfmbi8sYjGcbSiif95U4uE=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME= »${APP_NAME} »
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
bestmomo
Tout ça me paraît correct et je ne vois pas ce qui peut coincer. L’environnement de xampp est intéressant, mais tu devrais essayer plutôt Laragon qui est en général moins source de problèmes.
devotion1
j’ai resoulu le probleme, il ne reconnaissais pas la base
Fiston
Bonjour,
Merci beaucoup pour ce site qui m’aide beaucoup dans mon apprentissage !!
Je rencontre un problème que je ne parviens pas à résoudre, peut être pourras-tu m’aider..
Lorsque je lance la migration j’ai un message d’erreur, j’ai pourtant tout double checké et en desespoir de cause j’ai même copier coller tes fichiers pensant que j’avais fait une boulette mais rien n’y fait.
Voici l’erreur retournée:
PHP Fatal error: Cannot declare class CreateNotificationsTable, because the name is already in use in C:\laragon\www\monblog\database\migrations\2021_08_10_030312_create_notifications_table.php on line 7
Symfony\Component\ErrorHandler\Error\FatalError
Cannot declare class CreateNotificationsTable, because the name is already in use
Merci d’avance pour ton aide 🙂
bestmomo
Salut,
Essaie de relancer l’autoload avec composer dumpautoload.
Fiston
ça ne fonctionne toujours pas, je vais creuser..Merci 😉
elProfessor
Bonjour. Je rencontre un souci avec use NodeTrait; Bien que j’aie utilisé la façade use Kalnoy\Nestedset\NodeTrait; dans l’espace des noms, le soulignement est toujours en rouge. J’ai verifié sur https://packagist.org/packages/kalnoy/nestedset? pour me rassurer de la bonne écriture c’est la même. Je me demande comment résoudre cela. Pouvez-vous m’aider ?
bestmomo
Bonjour,
Le soulignement rouge indique juste que l’éditeur utilisé n’est pas capable de résoudre la dépendance mais est-ce que ça fonctionne ?
elProfessor
Oui ça fonctionne.
bestmomo
Tu peux installer l’helper pour aider ton éditeur à résoudre les dépendances.
khadidja
Bonjour,
j’ai suivit les étapes jusqu’à la migration, j’ai rencontré cette erreur : La table ‘posts’ existe déjà, veuillez m’aider ou se trouve l’erreur . plus de détaill :
SQLSTATE[42S01]: Base table or view already exists: 1050 La table ‘posts’ existe déjà (SQL: create table `posts` (`id` bigint unsigned not null auto_increment primary key, `created_at` timestamp null, `updated_at` timestamp
null, `title` varchar(255) not null, `slug` varchar(255) not null, `ceo-title` varchar(255) null, `excerpt` varchar(255) not null, `body` varchar(255) not null, `meta-discription` text not null, `meta-keywords` text not null,
`active` tinyint(1) not null default ‘0’, `image` varchar(255) null, `user_id` bigint unsigned not null) default
character set utf8mb4 collate ‘utf8mb4_unicode_ci’)
at C:\wamp\www\Courses\monblog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:692
688▕ // If an exception occurs when attempting to run a query, we’ll format the error
689▕ // message to include the bindings with SQL, which will make this exception a
690▕ // lot more helpful to the developer instead of just the database’s errors.
691▕ catch (Exception $e) {
➜ 692▕ throw new QueryException(
693▕ $query, $this->prepareBindings($bindings), $e
694▕ );
695▕ }
696▕
1 C:\wamp\www\Courses\monblog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:485
PDOException::(« SQLSTATE[42S01]: Base table or view already exists: 1050 La table ‘posts’ existe déjà »)
2 C:\wamp\www\Courses\monblog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:485
PDOStatement::execute()
khadidja
merci, j’ai trouvé la solution : php artisan migrate:reset
bestmomo
tu peux aussi utiliser php artisan migrate:fresh pour régénérer la base
fifi
Bonjour Bestmomo et merci pour ce tutoriel,
J’ai un problème avec la migration ( J’ai ajouté le mot de passe: DB_PASSWORD=motdepasse)
PS C:\laragon\www\monblog> php artisan migrate
Illuminate\Database\QueryException
SQLSTATE[HY000] [1045] Access denied for user ‘root’@’localhost’ (using password: YES) (SQL: select * from information_schema.tables where table_schema = monblog and table_name = migrations and table_type = ‘BASE TABLE’)
at C:\laragon\www\monblog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:678
674▕ // If an exception occurs when attempting to run a query, we’ll format the error
675▕ // message to include the bindings with SQL, which will make this exception a
676▕ // lot more helpful to the developer instead of just the database’s errors.
677▕ catch (Exception $e) {
➜ 678▕ throw new QueryException(
679▕ $query, $this->prepareBindings($bindings), $e
680▕ );
681▕ }
682▕
1 C:\laragon\www\monblog\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70
PDOException::(« SQLSTATE[HY000] [1045] Access denied for user ‘root’@’localhost’ (using password: YES) »)
2 C:\laragon\www\monblog\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70
PDO::__construct(« mysql:host=127.0.0.1;port=3306;dbname=monblog », « root », « motdepasse », [])
bestmomo
Salut,
Par défaut MySQL n’a pas de mot de passe avec root.
fifi
Merci.
webwatson
Hello à tous!
Besoin d’eclaicissement sur cette erreur https://ibb.co/qgjxkDH
J’aui suivi toutes les étapes à la lettre.
Comment puis-je y remédié.
bestmomo
Salut,
Apparemment il manque la colonne meta_description dans la table posts.
webwatson
Merci pour la reponse.
Regarder dans la table ici https://ibb.co/GpwsW25
On a les champs qui sont remplis y compris la colonne meta_description mais les autres ne fonctionne plus vu qu’il stop dès qu’il y’a une erreur.
Je trouve ça bizarre qu’on me retourne une erreur pourtant ce ne l’est pas en réalité !
bestmomo
Salut,
Je remarque que la table concernée là est « users » (insert into users) et que les colonnes correspondent à celles de la table « posts ». Est-ce que c’est le bon modèle déclaré dans PostFactory ?
DaniBlou
Bonjour
Merci deja pour cette formation quentu nous offre et pour ta disponibilite
en fait j’ai un soucis quand je veux installer laravel Breeze
j’ai cette erreur
PHP Warning: require(/home/daniel/BlogPro/vendor/autoload.php): Failed to open stream: No such file or directory in /home/daniel/BlogPro/artisan on line 18
PHP Fatal error: Uncaught Error: Failed opening required ‘/home/daniel/BlogPro/vendor/autoload.php’ (include_path=’.:/usr/share/php’) in /home/daniel/BlogPro/artisan:18
Stack trace:
j’ai essaiye tout ce dont j’ai vu mais pas de solution. je compte sur toi pour m’aider
merci d’avance
bestmomo
Salut,
Tu as vraiment fait composer install ?
Junior Ndono Jb
bonjour Best MOmo et merci pour ce tutoriel. Pour ma part j’ai un petit problème avec la commande **composer require kalnoy/nestedset** elle m’affiche une erreur du style
** [InvalidArgumentException]
Could not find package kalnoy/nestedset.
Did you mean one of these?
kalnoy/nestedset
nerio/mongo-nestedset**
S’il vous plait j’ai besoin d’aide.
Junior Ndono Jb
merci, le pb est résolu. Je poense que c’était dû à la version 2.x de mon composer. Donc j’ai dû rentrer de version avant d’exécuter la commande et elle a fonctionné.
bestmomo
Parfait si le problème est résolu mais normalement la version 2 de Composer doit tout digérer, du moins je n’ai aucun problème avec elle.
Michel
Bonjour,
Pour mon travail, j’ai besoin de construire un blog, cependant je suis un amateur aussi je vous remercie pour votre titoriel que je trouve passionnant et j’espère y arriver.
Arrivé à ce point, je rencontre un message d’erreur:
C:\laragon\www\monblog
λ php artisan db:seed
Illuminate\Database\QueryException
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ‘Category 1’ for key ‘categories_title_unique’ (SQL: insert into `categories` (`slug`, `title`) values (category-1, Category 1), (category-2, Category 2), (category-3, Category 3))
at C:\laragon\www\monblog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:678
674▕ // If an exception occurs when attempting to run a query, we’ll format the error
675▕ // message to include the bindings with SQL, which will make this exception a
676▕ // lot more helpful to the developer instead of just the database’s errors.
677▕ catch (Exception $e) {
➜ 678▕ throw new QueryException(
679▕ $query, $this->prepareBindings($bindings), $e
680▕ );
681▕ }
682▕
1 C:\laragon\www\monblog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:471
PDOException::(« SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ‘Category 1’ for key ‘categories_title_unique' »)
2 C:\laragon\www\monblog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:471
PDOStatement::execute()
Dans mes tables j’ai les utilisateurs et les 3 catégories; les tables tag, post, comment sont vides…
Quand je me connecte, http://monblog.test/login. J’arrive à l’identification, j’ai choisi l’utilisateur id 2 et là j’arrive au dashbord de Laravel.
Que dois je faire, svp ?
Encore merci pour votre aide.
bestmomo
Bonjour,
Comme la population (seeder) impose des enregistrements, une fois que la base a été remplie de données si on veut refaire une population il faut rafraichir la base :
php artisan migrate:fresh --seed
En ce qui concerne la page qui s’affiche à l’issue du login pour le moment c’est la dashboard de Laravel, ça sera changé quand l’authentification adaptée au blog sera mise en place.
qanielutis
Bonjour et merci pour tes formations ca m’aide enormement.
J’ai un probleme au niveau UTILISATEURS (On va créer un administrateur, 2 rédacteurs et 3 utilisateurs de base 🙂
J’aimerai savoir dans quel dossier(fichier) on insere les code? Je suis un peu embrouille a ce niveau.
bestmomo
Salut,
C’est vrai que je n’ai pas précisé à ce niveau, le code va dans le fichier database/seeders/DatabaseSeeder, dans la fonction run.
webwatson
Merci pour la suite du projet.
J’ai un soucis dans la création du seed.
L’érreur qui s’affiche est que le trait notifiable n’est pas trouvé.
App\Models\Notifiable not found
bestmomo
Salut,
Il faut ajouter le trait Notifiable aux modèles Post et Comment (pour User il est déjà présent par défaut).
webwatson
Je l’avais mis vu que j’ai suivi toute les étapes.
*Post.php*
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Events\ModelCreated;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
class Post extends Model
{
use HasFactory, Notifiable;
…
…
*Comment.php*
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Kalnoy\Nestedset\NodeTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
class Comment extends Model
{
use NodeTrait, HasFactory, Notifiable;
bestmomo
Ah oui tu déclares bien tout…
Essaie un petit composer dumpautoload pour régénérer le chargement des classes.
gil
Hello,
J’avais vu, mais je m’étais dit que c’était fait exprès pour que les lecteurs réfléchissent 🙂
Non je blague, mais il est vrai que c’est un peu le problème des tutoriaux, on a tendance à ne faire que du copier-coller.
Une idée d’ailleurs pourrait être de présenter des tutos en ayant en certains endroits des choses expendables-collapsable, cachées par défaut. Pas partout, mais parfois de dire « faites ceci », ou « créer ceci en en ajoutant 2 champs, un label ‘title’ et un booléen ‘valid’ « .
(maintenant, c’est juste une idée)
Et du coup (même si ça revient plutôt bien), je vais faire tes anciens tuto laravel 7 et , qui m’obligeront à réfléchir !
bestmomo
Ah oui ça serait marrant des trucs cachés, je vais voir s’il y a un plugin qui fait ça dans WordPress. J’aurais dû partir avec un blog perso 🙂
eric.lecathelinais@gmail.com
Salut,
Déjà merci pour ton blog sur laravel dans lequel j’apprends plein de chose
Sinon juste une petite correction sur cette page
php artisan migrate au lieu de php artisan:migrate
Continue comme ça, c’est top 😉
bestmomo
Salut !
C’est corrigé, merci 😉