Sau khi gặp các lỗi phát sinh migration giờ chúng ta có bản full (ok)

Laravel Factory: Manual Increment of Column, Number

class AliasCommandFactory extends Factory {

    private static $order = 1;

    protected $model = AliasCommand::class;

    public function definition() {
         $faker = $this->faker;
         return [
            'user_id' => User::inRandomOrder()->first()->id,
            'command' => $faker->word,
            'content' => $faker->sentence,
            'order'   => self::$order++
        ];
    }
}

Một cách sử dụng trực tiếp MenusTableSeeder::class để làm db:seed

Kết quả thật tuyệt tạo menu có cả phân quyền :) tham khảo ở Laravel Admi CoreUi 👌 Nhớ cài cả spatie permission

composer require spatie/laravel-permission

C:\xampp8\htdocs\managementsystem\database\factories\MenuroleFactory.php

<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
namespace Database\Factories;
use App\Models\Menurole;
use Faker\Generator as Faker;
use Illuminate\Support\Str;
$factory->define(Menurole::class, function (Faker $faker) {
  return [
    'role_name' => 'guest',
    'menus_id'  => factory(App\Models\Menus::class)->create()->id,
  ];
});

C:\xampp8\htdocs\managementsystem\database\factories\MenusFactory.php

<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
namespace Database\Factories;
use App\Models\Menus;
use Faker\Generator as Faker;
use Illuminate\Support\Str;
$factory->define(Menus::class, function (Faker $faker) {
  return [
    'name'          => $faker->sentence(4, true),
    'href'          => '/href',
    'icon'          => NULL,
    'slug'          => 'link',
    'parent_id'     => NULL,
    'menu_id'       => 1,
    'sequence'      => 1
  ];
});

C:\xampp8\htdocs\managementsystem\database\migrations\2019_11_08_102827_create_menus_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMenusTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('menus', function (Blueprint $table) {
      $table->bigIncrements('id');
      $table->string('name');
      $table->string('href')->nullable();
      $table->string('icon')->nullable();
      $table->string('slug');
      $table->integer('parent_id')->unsigned()->nullable();
      $table->integer('menu_id')->unsigned();
      $table->integer('sequence');
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('menus');
  }
}

C:\xampp8\htdocs\managementsystem\database\migrations\2019_11_13_092213_create_menurole_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMenuroleTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('menu_role', function (Blueprint $table) {
      $table->bigIncrements('id');
      $table->string('role_name');
      $table->integer('menus_id')->unsigned();
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('menu_role');
  }
}

C:\xampp8\htdocs\managementsystem\database\migrations\2019_12_11_091036_create_menulist_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateMenulistTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('menulist', function (Blueprint $table) {
      $table->bigIncrements('id');
      $table->string('name');
    });
  }

  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('menulist');
  }
}

C:\xampp8\htdocs\managementsystem\database\seeders\MenusTableSeeder.php

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Illuminate\Support\Facades\DB;
class MenusTableSeeder extends Seeder
{
  private $menuId = null;
  private $dropdownId = array();
  private $dropdown = false;
  private $sequence = 1;
  private $joinData = array();
  private $adminRole = null;
  private $userRole = null;
  private $subFolder = '';
  public function join($roles, $menusId)
  {
    $roles = explode(',', $roles);
    foreach ($roles as $role) {
      array_push($this->joinData, array('role_name' => $role, 'menus_id' => $menusId));
    }
  }
  /*
        Function assigns menu elements to roles
        Must by use on end of this seeder
    */
  public function joinAllByTransaction()
  {
    DB::beginTransaction();
    foreach ($this->joinData as $data) {
      DB::table('menu_role')->insert([
        'role_name' => $data['role_name'],
        'menus_id' => $data['menus_id'],
      ]);
    }
    DB::commit();
  }
  public function insertLink($roles, $name, $href, $icon = null)
  {
    $href = $this->subFolder . $href;
    if ($this->dropdown === false) {
      DB::table('menus')->insert([
        'slug' => 'link',
        'name' => $name,
        'icon' => $icon,
        'href' => $href,
        'menu_id' => $this->menuId,
        'sequence' => $this->sequence
      ]);
    } else {
      DB::table('menus')->insert([
        'slug' => 'link',
        'name' => $name,
        'icon' => $icon,
        'href' => $href,
        'menu_id' => $this->menuId,
        'parent_id' => $this->dropdownId[count($this->dropdownId) - 1],
        'sequence' => $this->sequence
      ]);
    }
    $this->sequence++;
    $lastId = DB::getPdo()->lastInsertId();
    $this->join($roles, $lastId);
    $permission = Permission::where('name', '=', $name)->get();
    if (empty($permission)) {
      $permission = Permission::create(['name' => 'visit ' . $name]);
    }
    $roles = explode(',', $roles);
    if (in_array('user', $roles)) {
      $this->userRole->givePermissionTo($permission);
    }
    if (in_array('admin', $roles)) {
      $this->adminRole->givePermissionTo($permission);
    }
    return $lastId;
  }
  public function insertTitle($roles, $name)
  {
    DB::table('menus')->insert([
      'slug' => 'title',
      'name' => $name,
      'menu_id' => $this->menuId,
      'sequence' => $this->sequence
    ]);
    $this->sequence++;
    $lastId = DB::getPdo()->lastInsertId();
    $this->join($roles, $lastId);
    return $lastId;
  }
  public function beginDropdown($roles, $name, $icon = '')
  {
    if (count($this->dropdownId)) {
      $parentId = $this->dropdownId[count($this->dropdownId) - 1];
    } else {
      $parentId = null;
    }
    DB::table('menus')->insert([
      'slug' => 'dropdown',
      'name' => $name,
      'icon' => $icon,
      'menu_id' => $this->menuId,
      'sequence' => $this->sequence,
      'parent_id' => $parentId
    ]);
    $lastId = DB::getPdo()->lastInsertId();
    array_push($this->dropdownId, $lastId);
    $this->dropdown = true;
    $this->sequence++;
    $this->join($roles, $lastId);
    return $lastId;
  }
  public function endDropdown()
  {
    $this->dropdown = false;
    array_pop($this->dropdownId);
  }
  /**
   * Run the database seeds.
   *
   * @return void
   */
  public function run()
  {
    /* Get roles */
    $this->adminRole = Role::where('name', '=', 'admin')->first();
    $this->userRole = Role::where('name', '=', 'user')->first();
    /* Create Sidebar menu */
    DB::table('menulist')->insert([
      'name' => 'sidebar menu'
    ]);
    $this->menuId = DB::getPdo()->lastInsertId();  //set menuId
    $this->insertLink('guest,user,admin', 'Dashboard', '/', 'cil-speedometer');
    $this->beginDropdown('admin', 'Settings', 'cil-calculator');
    $this->insertLink('admin', 'Notes',                   '/notes');
    $this->insertLink('admin', 'Users',                   '/users');
    $this->insertLink('admin', 'Edit menu',               '/menu/menu');
    $this->insertLink('admin', 'Edit menu elements',      '/menu/element');
    $this->insertLink('admin', 'Edit roles',              '/roles');
    $this->insertLink('admin', 'Media',                   '/media');
    $this->insertLink('admin', 'BREAD',                   '/bread');
    $this->insertLink('admin', 'Email',                   '/mail');
    $this->endDropdown();
    $this->insertLink('guest', 'Login', '/login', 'cil-account-logout');
    $this->insertLink('guest', 'Register', '/register', 'cil-account-logout');
    $this->insertTitle('user,admin', 'Theme');
    $this->insertLink('user,admin', 'Colors', '/colors', 'cil-drop1');
    $this->insertLink('user,admin', 'Typography', '/typography', 'cil-pencil');
    $this->beginDropdown('user,admin', 'Base', 'cil-puzzle');
    $this->insertLink('user,admin', 'Breadcrumb',    '/base/breadcrumb');
    $this->insertLink('user,admin', 'Cards',         '/base/cards');
    $this->insertLink('user,admin', 'Carousel',      '/base/carousel');
    $this->insertLink('user,admin', 'Collapse',      '/base/collapse');
    $this->insertLink('user,admin', 'Forms',         '/base/forms');
    $this->insertLink('user,admin', 'Jumbotron',     '/base/jumbotron');
    $this->insertLink('user,admin', 'List group',    '/base/list-group');
    $this->insertLink('user,admin', 'Navs',          '/base/navs');
    $this->insertLink('user,admin', 'Pagination',    '/base/pagination');
    $this->insertLink('user,admin', 'Popovers',      '/base/popovers');
    $this->insertLink('user,admin', 'Progress',      '/base/progress');
    $this->insertLink('user,admin', 'Scrollspy',     '/base/scrollspy');
    $this->insertLink('user,admin', 'Switches',      '/base/switches');
    $this->insertLink('user,admin', 'Tables',        '/base/tables');
    $this->insertLink('user,admin', 'Tabs',          '/base/tabs');
    $this->insertLink('user,admin', 'Tooltips',      '/base/tooltips');
    $this->endDropdown();
    $this->beginDropdown('user,admin', 'Buttons', 'cil-cursor');
    $this->insertLink('user,admin', 'Buttons',           '/buttons/buttons');
    $this->insertLink('user,admin', 'Buttons Group',     '/buttons/button-group');
    $this->insertLink('user,admin', 'Dropdowns',         '/buttons/dropdowns');
    $this->insertLink('user,admin', 'Brand Buttons',     '/buttons/brand-buttons');
    $this->endDropdown();
    $this->insertLink('user,admin', 'Charts', '/charts', 'cil-chart-pie');
    $this->beginDropdown('user,admin', 'Icons', 'cil-star');
    $this->insertLink('user,admin', 'CoreUI Icons',      '/icon/coreui-icons');
    $this->insertLink('user,admin', 'Flags',             '/icon/flags');
    $this->insertLink('user,admin', 'Brands',            '/icon/brands');
    $this->endDropdown();
    $this->beginDropdown('user,admin', 'Notifications', 'cil-bell');
    $this->insertLink('user,admin', 'Alerts',     '/notifications/alerts');
    $this->insertLink('user,admin', 'Badge',      '/notifications/badge');
    $this->insertLink('user,admin', 'Modals',     '/notifications/modals');
    $this->endDropdown();
    $this->insertLink('user,admin', 'Widgets', '/widgets', 'cil-calculator');
    $this->insertTitle('user,admin', 'Extras');
    $this->beginDropdown('user,admin', 'Pages', 'cil-star');
    $this->insertLink('user,admin', 'Login',         '/login');
    $this->insertLink('user,admin', 'Register',      '/register');
    $this->insertLink('user,admin', 'Error 404',     '/404');
    $this->insertLink('user,admin', 'Error 500',     '/500');
    $this->endDropdown();
    $this->insertLink('guest,user,admin', 'Download CoreUI', 'https://coreui.io', 'cil-cloud-download');
    $this->insertLink('guest,user,admin', 'Try CoreUI PRO', 'https://coreui.io/pro/', 'cil-layers');
    /* Create top menu */
    DB::table('menulist')->insert([
      'name' => 'top menu'
    ]);
    $this->menuId = DB::getPdo()->lastInsertId();  //set menuId
    $this->beginDropdown('guest,user,admin', 'Pages');
    $id = $this->insertLink('guest,user,admin', 'Dashboard',    '/');
    $id = $this->insertLink('user,admin', 'Notes',              '/notes');
    $id = $this->insertLink('admin', 'Users',                   '/users');
    $this->endDropdown();
    $id = $this->beginDropdown('admin', 'Settings');
    $id = $this->insertLink('admin', 'Edit menu',               '/menu/menu');
    $id = $this->insertLink('admin', 'Edit menu elements',      '/menu/element');
    $id = $this->insertLink('admin', 'Edit roles',              '/roles');
    $id = $this->insertLink('admin', 'Media',                   '/media');
    $id = $this->insertLink('admin', 'BREAD',                   '/bread');
    $this->endDropdown();
    $this->joinAllByTransaction(); ///   <===== Must by use on end of this seeder
  }
}

C:\xampp8\htdocs\managementsystem\database\seeders\DatabaseSeeder.php

<?php
namespace Database\Seeders;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use App\Models\User;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
  /**
   * Seed the application's database.
   *
   * @return void
   */
  public function run()
  {
    User::factory(12)->create();
    $this->call([
      MenusTableSeeder::class
    ]);
  }
}

C:\xampp8\htdocs\managementsystem\app\Models\Menulist.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Menulist extends Model
{
  protected $table = 'menulist';
  public $timestamps = false;
}

C:\xampp8\htdocs\managementsystem\app\Models\Menurole.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Menurole extends Model
{
  protected $table = 'menu_role';
  public $timestamps = false;
}

C:\xampp8\htdocs\managementsystem\app\Models\Menus.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Menus extends Model
{
  protected $table = 'menus';
  public $timestamps = false;
}

Trước khi bắt tay vào công việc tạo các file chúng ta cần lưu ý

😒 Thứ tự thời gian tạo các file rất quan trọng (vì có các mối quan hệ ràng buộc trong bảng do đó những bảng phụ phải được tạo trước)

😒 Cách lệnh được sử dụng (Thứ tự phải như sau) $php artisan migrate $php artisan db:seed --class=CountrySeeder $php artisan db:seed --class=UserSeeder $php artisan db:seed --class=PostSeeder

Factories

C:\xampp\htdocs\test\database\factories\CountryFactory.php

<?php
namespace Database\Factories;
use App\Models\Country;
use Illuminate\Database\Eloquent\Factories\Factory;
class CountryFactory extends Factory {
  protected $model = Country::class;
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition() {
    return [
      'name'    => $this->faker->text(10),
    ];
  }
}

C:\xampp\htdocs\test\database\factories\PostFactory.php

<?php
namespace Database\Factories;
use App\Models\Post;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory {
  protected $model = Post::class;
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition() {
    return [
      'name'    => $this->faker->text(10),
      'user_id' => $this->faker->numberBetween(1, 10)
    ];
  }
}

C:\xampp\htdocs\test\database\factories\UserFactory.php

<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory {
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition() {
    return [
      'name'              => $this->faker->name(),
      'email'             => $this->faker->unique()->safeEmail(),
      'country_id'        => $this->faker->numberBetween(1, 10),
      'email_verified_at' => now(),
      'password'          => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
      'remember_token'    => Str::random(10),
    ];
  }
  /**
   * Indicate that the model's email address should be unverified.
   *
   * @return \Illuminate\Database\Eloquent\Factories\Factory
   */
  public function unverified() {
    return $this->state(function (array $attributes) {
      return [
        'email_verified_at' => null,
      ];
    });
  }
}

Migrations

C:\xampp\htdocs\test\database\migrations\2012_05_10_163257_create_countries_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCountriesTable extends Migration {
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up() {
    Schema::create('countries', function (Blueprint $table) {
      $table->bigIncrements('id');
      $table->string('name');
      $table->timestamps();
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down() {
    Schema::dropIfExists('countries');
  }
}

C:\xampp\htdocs\test\database\migrations\2014_10_12_000000_create_users_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration {
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up() {
    Schema::create('users', function (Blueprint $table) {
      $table->bigIncrements('id'); 
      $table->string('name');
      $table->string('email')->unique();
      $table->bigInteger('country_id')->unsigned();
      $table->timestamp('email_verified_at')->nullable();
      $table->string('password');
      $table->rememberToken();
      $table->timestamps();
      $table->foreign('country_id')->references('id')->on('countries');
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down() {
    Schema::dropIfExists('users');
  }
}

C:\xampp\htdocs\test\database\migrations\2022_05_10_163113_create_posts_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration {
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up() {
    Schema::create('posts', function (Blueprint $table) {
      $table->bigIncrements('id');
      $table->string("name");
      $table->bigInteger('user_id')->unsigned();
      $table->timestamps();
      $table->foreign('user_id')->references('id')->on('users');
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down() {
    Schema::dropIfExists('posts');
  }
}

Seeders

C:\xampp\htdocs\test\database\seeders\CountrySeeder.php

<?php
namespace Database\Seeders;
use App\Models\Country;
use Illuminate\Database\Seeder;
class CountrySeeder extends Seeder {
  /**
   * Run the database seeds.
   *
   * @return void
   */
  public function run() {
    Country::factory()->count(10)->create();
  }
}

C:\xampp\htdocs\test\database\seeders\PostSeeder.php

<?php
namespace Database\Seeders;
use App\Models\Post;
use Illuminate\Database\Seeder;
class PostSeeder extends Seeder {
  /**
   * Run the database seeds.
   *
   * @return void
   */
  public function run() {
    Post::factory()->count(10)->create();
  }
}

C:\xampp\htdocs\test\database\seeders\UserSeeder.php

<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
class UserSeeder extends Seeder {
  /**
   * Run the database seeds.
   *
   * @return void
   */
  public function run() {
    User::factory(10)->create();
  }
}

Models

C:\xampp\htdocs\test\app\Models\Country.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Country extends Model {
  use HasFactory;
  protected $table = 'countries';
  /**
   * The primary key associated with the table.
   *
   * @var string
   */
  protected $primaryKey = 'id';
}

C:\xampp\htdocs\test\app\Models\Post.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model {
  use HasFactory;
  protected $fillable = [
    'name', 'user_id'
  ];
}

C:\xampp\htdocs\test\app\Models\User.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable {
  use HasApiTokens, HasFactory, Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array<int, string>
   */
  protected $fillable = [
    'name',
    'email',
    'country_id',
    'password',
  ];
  /**
   * The attributes that should be hidden for serialization.
   *
   * @var array<int, string>
   */
  protected $hidden = [
    'password',
    'remember_token',
  ];
  /**
   * The attributes that should be cast.
   *
   * @var array<string, string>
   */
  protected $casts = [
    'email_verified_at' => 'datetime',
  ];
}

Controllers

C:\xampp\htdocs\test\app\Http\Controllers\TestController.php

<?php
namespace App\Http\Controllers;
use App\Models\Country;
class TestController extends Controller {
  public function show() {
    $country = Country::find(1);
    $posts = $country->posts;
    return view('test')->with(compact('posts'));
  }
}

C:\xampp\htdocs\test\routes\web.php

<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
 */
Route::get('/test', [App\Http\Controllers\TestController::class, 'show'])->name('home');
Auth::routes();
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');

View

C:\xampp\htdocs\test\resources\views\test.blade.php

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Laravel</title>
    <link rel="stylesheet" type="text/css" href="{{asset('public/css/app.css')}}">
  </head>
  <body class="antialiased">
    <div class="container">
      <div class="row">
        <h1>Lorem ipsum dolor sit amet 1.</h1>
        <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
          @foreach ($posts as $post)
            <p class="text-info">{{  $post->name }} </p>
          @endforeach
        </div>
      </div>
    </div>
  </body>
</html>

Ket qua

Last updated