---
description: https://learnhtml.gitbook.io/project/admin-laravel-admin-ok
---

# \[ADMIN] Laravel Admin, CoreUi Full (ok)

### Đọc thêm: Coreui giao diện admin sử dụng bootstrap 5 (ok)

[https://learnhtml.gitbook.io/project/coreui-giao-dien-admin-su-dung-bootstrap-5-ok](https://learnhtml.gitbook.io/project/coreui-giao-dien-admin-su-dung-bootstrap-5-ok)

### Phần 1: Sử dụng Laravel Admin

{% embed url="https://learnhtml.gitbook.io/project/admin-laravel-admin-ok" %}

Or

{% embed url="https://laravel-admin.org/docs/en/installation" %}

Use Admin Core Ui Bootstrap5  start 👇

#### [https://drive.google.com/file/d/1WXn1PUg9zdF2gjxJviRkPkAYaOSDaOr4/view?usp=share\_link](https://drive.google.com/file/d/1WXn1PUg9zdF2gjxJviRkPkAYaOSDaOr4/view?usp=share_link)

#### =========== /// ===============

Rất khó hiểu nhưng nhớ một điều quan trọng như sau

> Roles (vai trò) cũng có thể phân quyền&#x20;
>
> Permissions (phân quyền) là điều quyết định hơn cả.
>
> **Thông thường người ta sẽ quản lý Roles theo đúng tên và ý  nghĩa của nó như:**\
> **Ví dụ** subscriber **đặt tên** Subscriber **và** subscriber **được phân quyền xem do đó cấp quyền phương thức GET cho nó thôi 😒**

#### =========== /// ===============

#### [Laravel-admin: Xây dựng trang quản trị trong 1 nốt nhạc - Phần 1 CRUD](https://viblo.asia/p/laravel-admin-xay-dung-trang-quan-tri-trong-1-not-nhac-phan-1-crud-jvEla9Rmlkw)

```
1. composer require encore/laravel-admin
2. php artisan vendor:publish --provider="Encore\Admin\AdminServiceProvider"
3. php artisan admin:install
4. php artisan admin:controller App\\Models\\User
```

Chúng ta phải khai báo route mới trong **`app/Admin/routes.php`**

C:\xampp\htdocs\fronttest\app\Admin\routes.php

```php
<?php
use Illuminate\Routing\Router;
Admin::routes();
Route::group([
    'prefix'        => config('admin.route.prefix'),
    'namespace'     => config('admin.route.namespace'),
    'middleware'    => config('admin.route.middleware'),
    'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
    $router->get('/', 'HomeController@index')->name('home');
});
Route::group([
  'prefix'        => config('admin.route.prefix'),
  'namespace'     => config('admin.route.namespace'),
  'middleware'    => config('admin.route.middleware'),
  'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
  $router->resource('demo/users', UserController::class);
});
```

## Laravel-admin: Xây dựng trang quản trị trong 1 nốt nhạc - Phần 2 Model Grid



C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```
protected function grid()
{
    $grid = new Grid(new User());
    $grid->column('id', __('Id'));
    $grid->column('name', __('Name'));
    $grid->column('email', __('Email'));
    // $grid->column('email_verified_at', __('Email verified at'));
    $grid->column('password', __('Password'));
    // $grid->column('remember_token', __('Remember token'));
    $grid->column('created_at', __('Created at'));
    $grid->column('updated_at', __('Updated at'));
    // Thêm trực tiếp 1 cột thông qua tên trường
    $grid->name('Username Test');
    // Hiệu ứng tương tự như trên
    $grid->column('name', 'Username Test');
    // Hiển thị nhiều cột
    $grid->columns('email', 'name');
    // $grid->columns('email', 'name');
    return $grid;
}
```

Chúng ta có thể lấy dữ liệu theo điều kiện bằng cách sử dụng query:

```php
protected function grid()
{
    $grid = new Grid(new User());
    $grid->column('id', __('Id'));
    $grid->column('name', __('Name'));
    $grid->column('email', __('Email'));
    $grid->model()->where('id', '>', 1)
    ->whereIn('id', [1, 2])
    ->whereColumn('updated_at', '>=', 'created_at')
    ->orderBy('id', 'desc')
    ->take(100);
    return $grid;
}
```

Tùy chỉnh kết quả hiển thị của cột

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FtVrmL5Q0MfKlAb4Ji1qL%2Fimage.png?alt=media&#x26;token=80c96dc9-63a9-4876-a377-d9b9e9990f50" alt=""><figcaption></figcaption></figure>

```
protected function grid()
{
    $grid = new Grid(new User());
    $grid->column('id', __('Id'));
    $grid->column('email', __('Email'));
    $grid->name()->display(function ($name) {
      return "<span style='color:red;'>".$name."</span>";
    });
    return $grid;
}
```

Ta có thể tắt một số tính năng mặc định

```php
$grid->disableCreateButton();
$grid->disablePagination();
$grid->disableFilter();
$grid->disableExport();
$grid->disableRowSelector();
$grid->disableActions();
$grid->disableColumnSelector();
```

#### &#x20;Hiển thị dữ liệu có quan hệ - Relation <a href="#id-2-hien-thi-du-lieu-co-quan-he---relation-2" id="id-2-hien-thi-du-lieu-co-quan-he---relation-2"></a>

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FGqDQZc7MEnwY9yMKZhfH%2Fimage.png?alt=media&#x26;token=de94952d-3d06-489d-8344-6757501e3789" alt=""><figcaption></figcaption></figure>

**1. One to One**

C:\xampp\htdocs\fronttest\app\Admin\routes.php

```php
<?php
use Illuminate\Routing\Router;
Admin::routes();
Route::group([
    'prefix'        => config('admin.route.prefix'),
    'namespace'     => config('admin.route.namespace'),
    'middleware'    => config('admin.route.middleware'),
    'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
    $router->get('/', 'HomeController@index')->name('home');
});
Route::group([
  'prefix'        => config('admin.route.prefix'),
  'namespace'     => config('admin.route.namespace'),
  'middleware'    => config('admin.route.middleware'),
  'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
  $router->resource('demo/users', UserController::class);
});

```

C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class UserController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'User';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new User());
    $grid->column('id', 'ID')->sortable();
    $grid->column('name', 'Name');
    $grid->column('email', __('Email'));
    $grid->column('profile.age');
    $grid->column('profile.gender');
    $grid->profile()->age();
    $grid->profile()->gender();
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(User::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('name', __('Name'));
    $show->field('email', __('Email'));
    $show->field('email_verified_at', __('Email verified at'));
    $show->field('password', __('Password'));
    $show->field('remember_token', __('Remember token'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new User());
    $form->text('name', __('Name'));
    $form->email('email', __('Email'));
    $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
    $form->password('password', __('Password'));
    $form->text('remember_token', __('Remember token'));
    return $form;
  }
}

```

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

```php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
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',
        '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',
    ];
    public function profile() {
      return $this->hasOne(Profile::class,'user_id','id');
    }
}

```

C:\xampp\htdocs\fronttest\database\seeders\DatabaseSeeder.php

```php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Profile;
class DatabaseSeeder extends Seeder
{
  /**
   * Seed the application's database.
   *
   * @return void
   */
  public function run()
  {
    User::factory(10)->create();
    Profile::factory(10)->create();
  }
}

```

C:\xampp\htdocs\fronttest\app\Models\Profile.php

```
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
  use HasFactory;
  protected $table = 'profile';
  /**
   * The primary key associated with the table.
   *
   * @var string
   */
  protected $primaryKey = 'id';
  public $timestamps = false;
  protected $fillable = [
    'age',
    'gender',
  ];
}

```

C:\xampp\htdocs\fronttest\database\migrations\2022\_11\_29\_043641\_create\_profile\_table.php

```
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateProfileTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('profile', function (Blueprint $table) {
            $table->id();
            $table->integer("user_id");
            $table->integer("age");
            $table->integer("gender");
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('profile');
    }
}

```

C:\xampp\htdocs\fronttest\database\factories\ProfileFactory.php

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

```

**One to Many - Quan hệ 1-n**

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FX9hANAiqb4Z4GEIjTCQA%2Fimage.png?alt=media&#x26;token=fda7984b-3aef-44fe-b402-eab81aa95826" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\fronttest\app\Admin\routes.php

```php
<?php
use Illuminate\Routing\Router;
Admin::routes();
Route::group([
    'prefix'        => config('admin.route.prefix'),
    'namespace'     => config('admin.route.namespace'),
    'middleware'    => config('admin.route.middleware'),
    'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
    $router->get('/', 'HomeController@index')->name('home');
});
Route::group([
  'prefix'        => config('admin.route.prefix'),
  'namespace'     => config('admin.route.namespace'),
  'middleware'    => config('admin.route.middleware'),
  'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
  $router->resource('demo/users', UserController::class);
});
Route::group([
  'prefix'        => config('admin.route.prefix'),
  'namespace'     => config('admin.route.namespace'),
  'middleware'    => config('admin.route.middleware'),
  'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
  $router->resource('comments', CommentController::class);
});
Route::group([
  'prefix'        => config('admin.route.prefix'),
  'namespace'     => config('admin.route.namespace'),
  'middleware'    => config('admin.route.middleware'),
  'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
  $router->resource('posts', PostController::class);
});

```

C:\xampp\htdocs\fronttest\app\Admin\Controllers\CommentController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\Comment;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class CommentController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'Comment';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new Comment());
    $grid->column('id', __('Id'));
    // $grid->column('post_id', __('Post id'));
    $grid->column('title', __('Title'));
    $grid->column('content', __('Content'));
    $grid->column('post.title');
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(Comment::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('post_id', __('Post id'));
    $show->field('title', __('Title'));
    $show->field('content', __('Content'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new Comment());
    $form->number('post_id', __('Post id'));
    $form->text('title', __('Title'));
    $form->text('content', __('Content'));
    return $form;
  }
}

```

C:\xampp\htdocs\fronttest\app\Admin\Controllers\PostController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\Post;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class PostController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'Post';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new Post());
    $grid->column('id', __('Id'));
    $grid->column('title', __('Title'));
    $grid->column('content', __('Content'));
    $grid->column('comments', 'Comments count')->display(function ($comments) {
      $count = count($comments);
      return "<span class='label label-warning'>{$count}</span>";
    });
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(Post::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('title', __('Title'));
    $show->field('content', __('Content'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new Post());
    $form->text('title', __('Title'));
    $form->text('content', __('Content'));
    return $form;
  }
}

```

C:\xampp\htdocs\fronttest\database\seeders\DatabaseSeeder.php

```php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Profile;
use App\Models\Post;
use App\Models\Comment;
class DatabaseSeeder extends Seeder
{
  /**
   * Seed the application's database.
   *
   * @return void
   */
  public function run()
  {
    // User::factory(10)->create();
    // Profile::factory(10)->create();
    Post::factory(10)->create();
    Comment::factory(30)->create();
  }
}

```

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

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

```

C:\xampp\htdocs\fronttest\database\factories\CommentFactory.php

```php
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Comment;
class CommentFactory extends Factory
{
  protected $model = Comment::class;
  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition()
  {
    return [
      "title" => $this->faker->title(),
      "post_id" => $this->faker->numberBetween(1,20),
      "content" => $this->faker->text(200)
    ];
  }
}

```

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

```php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
  use HasFactory;
  public $timestamps = false;
  protected $table = 'posts';
  protected $fillable = [
    'title',
    'content'
  ];
  public function comments()
  {
    return $this->hasMany(Comment::class, 'post_id', 'id');
  }
}

```

C:\xampp\htdocs\fronttest\app\Models\Comment.php

```php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\Post;
class Comment extends Model
{
  use HasFactory;
  public $timestamps = false;
  protected $table = 'comments';
  protected $fillable = [
    'title',
    'post_id',
    'content'
  ];
  public function post()
  {
    return $this->belongsTo(Post::class, 'post_id', 'id');
  }
}
```

C:\xampp\htdocs\fronttest\database\migrations\2022\_11\_29\_053904\_create\_posts\_table.php

```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->id();
      $table->string('title');
      $table->string('content');
      $table->timestamps();
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('posts');
  }
}
```

C:\xampp\htdocs\fronttest\database\migrations\2022\_11\_29\_054010\_create\_comments\_table.php

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

```

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FM48h2TjA4YuqSq2C0tBi%2Fimage.png?alt=media&#x26;token=0c617c65-3de9-4dde-a23f-dfe5e38e365e" alt=""><figcaption></figcaption></figure>

**Many to Many - Quan hệ n-n**

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2Fk3mgFuXFjtgc4VSxdBPu%2Fimage.png?alt=media&#x26;token=ebb822cf-fa4b-4413-bbbd-577a04775bee" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\fronttest\app\Admin\routes.php

```php
<?php
use Illuminate\Routing\Router;
Admin::routes();
Route::group([
    'prefix'        => config('admin.route.prefix'),
    'namespace'     => config('admin.route.namespace'),
    'middleware'    => config('admin.route.middleware'),
    'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
    $router->get('/', 'HomeController@index')->name('home');
});
Route::group([
  'prefix'        => config('admin.route.prefix'),
  'namespace'     => config('admin.route.namespace'),
  'middleware'    => config('admin.route.middleware'),
  'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
  $router->resource('demo/users', UserController::class);
});
Route::group([
  'prefix'        => config('admin.route.prefix'),
  'namespace'     => config('admin.route.namespace'),
  'middleware'    => config('admin.route.middleware'),
  'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
  $router->resource('comments', CommentController::class);
});
Route::group([
  'prefix'        => config('admin.route.prefix'),
  'namespace'     => config('admin.route.namespace'),
  'middleware'    => config('admin.route.middleware'),
  'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {
  $router->resource('posts', PostController::class);
});

```

C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class UserController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'User';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new User());
    $grid->column('id', 'ID')->sortable();
    $grid->column('name', 'Name');
    $grid->name();
    $grid->roles()->display(function ($roles) {
      $roles = array_map(
        function ($role) {
          return "<span class='label label-success'>{$role['name']}</span>";
        },
        $roles
      );
      return join('&nbsp;', $roles);
    });
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(User::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('name', __('Name'));
    $show->field('email', __('Email'));
    $show->field('email_verified_at', __('Email verified at'));
    $show->field('password', __('Password'));
    $show->field('remember_token', __('Remember token'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new User());
    $form->text('name', __('Name'));
    $form->email('email', __('Email'));
    $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
    $form->password('password', __('Password'));
    $form->text('remember_token', __('Remember token'));
    return $form;
  }
}

```

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

```php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
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',
    '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',
  ];
  public function profile()
  {
    return $this->hasOne(Profile::class, 'user_id', 'id');
  }
  public function roles()
  {
    return $this->belongsToMany(Role::class);
  }
}
p
```

C:\xampp\htdocs\fronttest\database\seeders\DatabaseSeeder.php

```php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Profile;
use App\Models\Post;
use App\Models\Comment;
use App\Models\Role;
use App\Models\RoleUser;
class DatabaseSeeder extends Seeder
{
  /**
   * Seed the application's database.
   *
   * @return void
   */
  public function run()
  {
    // User::factory(10)->create();
    // Profile::factory(10)->create();
    // Post::factory(10)->create();
    // Comment::factory(30)->create();
    Role::factory(6)->create();
    RoleUser::factory(60)->create();
  }
}

```

C:\xampp\htdocs\fronttest\app\Models\Role.php

```php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
  use HasFactory;
  protected $table = 'roles';
  /**
   * The primary key associated with the table.
   *
   * @var string
   */
  protected $primaryKey = 'id';
  public $timestamps = false;
  protected $fillable = [
    'name',
  ];
}

```

C:\xampp\htdocs\fronttest\database\factories\RoleUserFactory.php

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

```

C:\xampp\htdocs\fronttest\app\Models\RoleUser.php

```php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class RoleUser extends Model
{
  use HasFactory;
  protected $table = 'role_user';
  /**
   * The primary key associated with the table.
   *
   * @var string
   */
  protected $primaryKey = 'id';
  public $timestamps = false;
  protected $fillable = [
    'role_id',
    'user_id'
  ];
}

```

C:\xampp\htdocs\fronttest\database\migrations\2022\_11\_29\_063932\_create\_role\_user\_table.php

```php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateRoleUserTable extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('role_user', function (Blueprint $table) {
      $table->id();
      $table->integer("role_id");
      $table->integer("user_id");
      $table->timestamps();
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::dropIfExists('role_user');
  }
}

```

C:\xampp\htdocs\fronttest\database\migrations\2022\_11\_29\_063121\_create\_roles\_table.php

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

```

#### Filters <a href="#id-3-filters-3" id="id-3-filters-3"></a>

Đây là Filter mặc định&#x20;

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2Fev85YE72VsPVmP00YwHc%2Fimage.png?alt=media&#x26;token=e78f97ae-a86d-4a37-894e-5a349cf766d6" alt=""><figcaption></figcaption></figure>

Filter sau  khi tùy chỉnh

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FUeTaJrJQqVtcHLMTvZit%2Fimage.png?alt=media&#x26;token=a8c7f636-0cfa-445b-afc6-469c63c00d0a" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class UserController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'User';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new User());
    $grid->column('id', 'ID')->sortable();
    $grid->column('name', 'Name');
    $grid->column('email', 'Email');
    $grid->filter(function ($filter) {
      // Xóa ID filter mặc định
      $filter->disableIdFilter();
      // Thêm 1 filter theo cột dữ liệu
      $filter->like('name', 'Name');
      $filter->like('email', 'Email');
    });
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(User::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('name', __('Name'));
    $show->field('email', __('Email'));
    $show->field('email_verified_at', __('Email verified at'));
    $show->field('password', __('Password'));
    $show->field('remember_token', __('Remember token'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new User());
    $form->text('name', __('Name'));
    $form->email('email', __('Email'));
    $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
    $form->password('password', __('Password'));
    $form->text('remember_token', __('Remember token'));
    return $form;
  }
}

```

**1. Filter type**

Laravel-admin xây dựng các loại filter tương tự như Query Builder:

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2Fj5EMVMolFaV8d8qnqaBm%2Fimage.png?alt=media&#x26;token=5036aba4-3512-4ee2-b334-4f1e73960b70" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class UserController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'User';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new User());
    $grid->column('id', 'ID')->sortable();
    $grid->column('name', 'Name');
    $grid->column('email', 'Email');
    $grid->filter(function ($filter) {
      $label = 'PlaceHolder Name';
      $filter->equal('name', $label);
      // $filter->notEqual('column', $label);
      // WHERE 'column' LIKE "%"$input"%"
      // $filter->like('column', $label);
      // $filter->contains('title');
      // // WHERE 'column' ILIKE "%"$input"%"
      // $filter->ilike('column', $label);
      // // WHERE 'column' LIKE $input"%"
      // $filter->startsWith('title');
      // // WHERE 'column' LIKE "%"$input
      // $filter->endsWith('title');
      // // WHERE 'column' > $input
      // $filter->gt('column', $label);
      // // WHERE 'column' < $input
      // $filter->lt('column', $label);
      // // WHERE 'column' BETWEEN "$start" AND "$end"：
      // $filter->between('column', $label); //![](https://images.viblo.asia/c2ce0145-c086-4094-91bf-2e6a951c4d29.png)
      // // set datetime field type
      // $filter->between('column', $label)->datetime();
      // // set time field type
      // $filter->between('column', $label)->time();
      // // WHERE 'column' IN (...$inputs)
      // $filter->in('column', $label)->multipleSelect(['key' => 'value']);
      // // WHERE 'column' NOT IN (...$inputs)
      // $filter->notIn('column', $label)->multipleSelect(['key' => 'value']);
      // // WHERE DATE(column) = $input
      // $filter->date('column', $label);
      // $filter->day('column', $label);
      // $filter->month('column', $label);
      // $filter->year('column', $label);
      // // Tạo truy vấn phức tạp
      // // WHERE title LIKE "%$input%" OR content LIKE "%$input%"
      // $filter->where(function ($query) {
      //   $query->where('title', 'like', "%{$this->input}%")
      //     ->orWhere('content', 'like', "%{$this->input}%");
      // }
      // , 'Text');
      // // Truy vấn với relationship
      // $filter->where(function ($query) {
      //   $query->whereHas('profile', function ($query) {
      //     $query->where('address', 'like', "%{$this->input}%")->orWhere('email', 'like', "%{$this->input}%");
      //   }
      //   );
      // }
      // , 'Address or mobile');
    });
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(User::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('name', __('Name'));
    $show->field('email', __('Email'));
    $show->field('email_verified_at', __('Email verified at'));
    $show->field('password', __('Password'));
    $show->field('remember_token', __('Remember token'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new User());
    $form->text('name', __('Name'));
    $form->email('email', __('Email'));
    $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
    $form->password('password', __('Password'));
    $form->text('remember_token', __('Remember token'));
    return $form;
  }
}

```

Tham khảo thêm

```php
// WHERE 'column' = $input
$filter->equal('column', $label);
$filter->notEqual('column', $label);

// WHERE 'column' LIKE "%"$input"%"
$filter->like('column', $label);
$filter->contains('title');

// WHERE 'column' ILIKE "%"$input"%"
$filter->ilike('column', $label);

// WHERE 'column' LIKE $input"%"
$filter->startsWith('title');

// WHERE 'column' LIKE "%"$input
$filter->endsWith('title');

// WHERE 'column' > $input
$filter->gt('column', $label);

// WHERE 'column' < $input
$filter->lt('column', $label);

// WHERE 'column' BETWEEN "$start" AND "$end"：
$filter->between('column', $label);![](https://images.viblo.asia/c2ce0145-c086-4094-91bf-2e6a951c4d29.png)

// set datetime field type
$filter->between('column', $label)->datetime();

// set time field type
$filter->between('column', $label)->time();

// WHERE 'column' IN (...$inputs)
$filter->in('column', $label)->multipleSelect(['key' => 'value']);

// WHERE 'column' NOT IN (...$inputs)
$filter->notIn('column', $label)->multipleSelect(['key' => 'value']);

// WHERE DATE(column) = $input
$filter->date('column', $label);
$filter->day('column', $label);
$filter->month('column', $label);
$filter->year('column', $label);

// Tạo truy vấn phức tạp
// WHERE title LIKE "%$input%" OR content LIKE "%$input%"
$filter->where(function ($query) {
    $query->where('title', 'like', "%{$this->input}%")
        ->orWhere('content', 'like', "%{$this->input}%");
}, 'Text');


// Truy vấn với relationship
$filter->where(function ($query) {
    $query->whereHas('profile', function ($query) {
        $query->where('address', 'like', "%{$this->input}%")->orWhere('email', 'like', "%{$this->input}%");
    });
}, 'Address or mobile');

```

**2. Truy vấn xác định (Define the scope of the query)**

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FFzcibu9wggGTevk8SoAO%2Fimage.png?alt=media&#x26;token=8255a294-d46a-4751-b515-d9df451665e4" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class UserController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'User';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new User());
    $grid->column('id', 'ID')->sortable();
    $grid->column('name', 'Name');
    $grid->column('email', 'Email');
    $grid->filter(function ($filter) {
      $filter->scope('male', 'Male')->where('gender', 'm');
      $filter->scope('new', 'Recently modified')
        ->whereDate('created_at', date('Y-m-d'))
        ->orWhere('updated_at', date('Y-m-d'));
      // Relationship query
      $filter->scope('address')->whereHas('profile', function ($query) {
        $query->whereNotNull('address');
      }
      );
      $filter->scope('trashed', 'Soft deleted data')->onlyTrashed();
    });
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(User::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('name', __('Name'));
    $show->field('email', __('Email'));
    $show->field('email_verified_at', __('Email verified at'));
    $show->field('password', __('Password'));
    $show->field('remember_token', __('Remember token'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new User());
    $form->text('name', __('Name'));
    $form->email('email', __('Email'));
    $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
    $form->password('password', __('Password'));
    $form->text('remember_token', __('Remember token'));
    return $form;
  }
}

```

**3. Field type**

Loại input mặc định là text và chúng ta có thể thay đổi type của input:

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2Fe75fqAD0UoeIIxLxdezL%2Fimage.png?alt=media&#x26;token=d9beed06-f498-400a-8680-867386eebd6b" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class UserController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'User';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new User());
    $grid->column('id', 'ID')->sortable();
    $grid->column('name', 'Name');
    $grid->column('email', 'Email');
    $grid->filter(function ($filter) {
      $filter->equal('name')->email();
    });
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(User::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('name', __('Name'));
    $show->field('email', __('Email'));
    $show->field('email_verified_at', __('Email verified at'));
    $show->field('password', __('Password'));
    $show->field('remember_token', __('Remember token'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new User());
    $form->text('name', __('Name'));
    $form->email('email', __('Email'));
    $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
    $form->password('password', __('Password'));
    $form->text('remember_token', __('Remember token'));
    return $form;
  }
}

```

Tham khảo thêm

```php
$filter->equal('column')->url();

$filter->equal('column')->email();

$filter->equal('column')->integer();

$filter->equal('column')->ip();

$filter->equal('column')->mac();

$filter->equal('column')->mobile();

// $options refer to https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md
$filter->equal('column')->decimal($options = []);

// $options refer to https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md
$filter->equal('column')->currency($options = []);

// $options refer to https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md
$filter->equal('column')->percentage($options = []);

// $options refer to https://github.com/RobinHerbots/Inputmask
$filter->equal('column')->inputmask($options = [], $icon = 'pencil');

// Select
$filter->equal('column')->select(['key' => 'value'...]);

// Hoặc select dữ liệu từ API
$filter->equal('column')->select('api/users');

// MultipleSelect - Tương đương với truy vấn IN, NOT IN
$filter->in('column')->multipleSelect(['key' => 'value'...]);
$filter->in('column')->multipleSelect('api/users');

// Radio
$filter->equal('released')->radio([
    ''   => 'All',
    0    => 'Unreleased',
    1    => 'Released',
]);

// Checkbox
$filter->in('gender')->checkbox([
    'm'    => 'Male',
    'f'    => 'Female',
]);

// Input kết hợp bootstrap-datetimepicker
$filter->equal('column')->datetime($options);

// `date()` equals to `datetime(['format' => 'YYYY-MM-DD'])`
$filter->equal('column')->date();

// `time()` equals to `datetime(['format' => 'HH:mm:ss'])`
$filter->equal('column')->time();

// `day()` equals to `datetime(['format' => 'DD'])`
$filter->equal('column')->day();

// `month()` equals to `datetime(['format' => 'MM'])`
$filter->equal('column')->month();

// `year()` equals to `datetime(['format' => 'YYYY'])`
$filter->equal('column')->year();


```

#### 4. Inline Editing <a href="#id-4-inline-editing-4" id="id-4-inline-editing-4"></a>

Chúng ta có thể sửa dữ liệu trực tiếp trong bằng bằng cách click vào dữ liệu, một pop-up dialog box sẽ hiện ra và chỉ việc save thôi.

**Lưu ý**: Đối với cột có thể sửa trực tiếp thì nó phải là cột tương ứng tồn tại trong model form.

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FVcaYSoLiMphjIzcwrA8P%2Fimage.png?alt=media&#x26;token=ba618754-1a7e-47b7-a3f8-91f7eeb4278f" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class UserController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'User';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new User());
    $grid->column('id', 'ID')->sortable();
    $grid->column('name', 'Name');
    $grid->column('email', 'Email');
    // Text input
    $grid->column('name')->editable();
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(User::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('name', __('Name'));
    $show->field('email', __('Email'));
    $show->field('email_verified_at', __('Email verified at'));
    $show->field('password', __('Password'));
    $show->field('remember_token', __('Remember token'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new User());
    $form->text('name', __('Name'));
    $form->email('email', __('Email'));
    $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
    $form->password('password', __('Password'));
    $form->text('remember_token', __('Remember token'));
    return $form;
  }

```

Tham khảo

```php
// Text input
$grid->column('title')->editable();

// Textarea input
$grid->column('title')->editable('textarea');

// Select
$grid->column('title')->editable('select', [1 => 'option1', 2 => 'option2', 3 => 'option3']);

// Date selection
$grid->column('birth')->editable('date');
$grid->column('published_at')->editable('datetime');
$grid->column('year')->editable('year');
$grid->column('month')->editable('month');
$grid->column('day')->editable('day');

// Switch
// set text, color, and stored values
$states = [
    'on' => ['value' => 1, 'text' => 'open', 'color' => 'primary'],
    'off' => ['value' => 2, 'text' => 'close', 'color' => 'default'],
];
$grid->column('status')->switch($states);

//Switch group
$states = [
    'on' => ['text' => 'YES'],
    'off' => ['text' => 'NO'],
];

$grid->column('switch_group')->switchGroup([
    'hot' => 'hot',
    'new' => 'latest'
    'recommend' => 'recommended',
], $states);

// Radio
$grid->column('options')->radio([
    1 => 'Sed ut perspiciatis unde omni',
    2 => 'voluptatem accusantium doloremque',
    3 => 'dicta sunt explicabo',
    4 => 'laudantium, totam rem aperiam',
]);

//Checkbox
$grid->column('options')->checkbox([
    1 => 'Sed ut perspiciatis unde omni',
    2 => 'voluptatem accusantium doloremque',
    3 => 'dicta sunt explicabo',
    4 => 'laudantium, totam rem aperiam',
]);

```

## [Laravel-admin: Xây dựng trang quản trị trong 1 nốt nhạc - Phần 3 Model Form](https://viblo.asia/p/laravel-admin-xay-dung-trang-quan-tri-trong-1-not-nhac-phan-3-model-form-vyDZO6RaKwj)

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FuNNsiesdwcVipIN7i06N%2Fimage.png?alt=media&#x26;token=7d29b41a-15a8-467e-9d1c-2f3544845e7f" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class UserController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'User';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new User());
    $grid->column('id', 'ID')->sortable();
    $grid->column('name', 'Name');
    $grid->column('email', 'Email');
    // Text input
    $grid->column('name')->editable();
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(User::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('name', __('Name'));
    $show->field('email', __('Email'));
    $show->field('email_verified_at', __('Email verified at'));
    $show->field('password', __('Password'));
    $show->field('remember_token', __('Remember token'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new User());
    $form->display('id', 'ID');
    $form->text('title', 'Movie title');
    // Input dạng select
    $directors = [
      'John'  => 1,
      'Smith' => 2,
      'Kate'  => 3,
    ];
    $form->select('director', 'Director')->options($directors);
    $form->text('name', __('Name'));
    $form->email('email', __('Email'));
    $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
    $form->password('password', __('Password'));
    $form->text('remember_token', __('Remember token'));
    return $form;
  }
}

```

Đọc thêm

```php
// Hiển thị ID của record
$form->display('id', 'ID');

// Thêm input dạng text
$form->text('title', 'Movie title');

// Input dạng select
$directors = [
    'John'  => 1,
    'Smith' => 2,
    'Kate'  => 3,
];

$form->select('director', 'Director')->options($directors);

// Input dạng textarea
$form->textarea('describe', 'Describe');

// Input dạng number
$form->number('rate', 'Rate');

// Input dạng select DateTime
$form->dateTime('release_at', 'release time');

```

Tùy chỉnh các nút chức năng mặc định ở Header

Mặc định&#x20;

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FPnvM43b6CVhm9XmqMFFA%2Fimage.png?alt=media&#x26;token=733f4d34-2d4b-491c-9410-edd8be2c71e2" alt=""><figcaption></figcaption></figure>

Sau khi đã được chỉnh sửa

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FpUazFMalnEzvNrnsLLft%2Fimage.png?alt=media&#x26;token=79a54139-6b78-4a72-a8c8-b3798d4633ef" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\fronttest\app\Admin\Controllers\UserController.php

```php
<?php
namespace App\Admin\Controllers;
use App\Models\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;
class UserController extends AdminController
{
  /**
   * Title for current resource.
   *
   * @var string
   */
  protected $title = 'User';
  /**
   * Make a grid builder.
   *
   * @return Grid
   */
  protected function grid()
  {
    $grid = new Grid(new User());
    $grid->column('id', 'ID')->sortable();
    $grid->column('name', 'Name');
    $grid->column('email', 'Email');
    // Text input
    $grid->column('name')->editable();
    return $grid;
  }
  /**
   * Make a show builder.
   *
   * @param mixed $id
   * @return Show
   */
  protected function detail($id)
  {
    $show = new Show(User::findOrFail($id));
    $show->field('id', __('Id'));
    $show->field('name', __('Name'));
    $show->field('email', __('Email'));
    $show->field('email_verified_at', __('Email verified at'));
    $show->field('password', __('Password'));
    $show->field('remember_token', __('Remember token'));
    $show->field('created_at', __('Created at'));
    $show->field('updated_at', __('Updated at'));
    return $show;
  }
  /**
   * Make a form builder.
   *
   * @return Form
   */
  protected function form()
  {
    $form = new Form(new User());
    $form->display('id', 'ID');
    $form->text('title', 'Movie title');
    // Input dạng select
    $directors = [
      'John'  => 1,
      'Smith' => 2,
      'Kate'  => 3,
    ];
    // ==
    $form->tools(function (Form\Tools $tools) {
      // Disable `List` btn.
      $tools->disableList();
      // Disable `Delete` btn.
      $tools->disableDelete();
      // Disable `view` btn.
      $tools->disableView();
      // Thêm 1 btn tùy chỉnh
      $tools->add('<a class="btn btn-sm btn-danger"><i class="fa fa-trash"></i>&nbsp;&nbsp;delete custom</a>');
    });
    // ==
    $form->select('director', 'Director')->options($directors);
    $form->text('name', __('Name'));
    $form->email('email', __('Email'));
    $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
    $form->password('password', __('Password'));
    $form->text('remember_token', __('Remember token'));
    return $form;
  }
}

```

Để xác định xem trang biểu mẫu hiện tại là Create hay Edit ta sử dụng method:

```
$form->isCreating();

$form->isEditing();

```

### Phần 2: Sử dụng CoreUI Free Laravel Bootstrap Admin [Template](https://github.com/coreui/coreui-free-laravel-admin-template)

Đã tùy chỉnh lại cho phù hợp với Laravel 9

C:\xampp8\htdocs\lva\webpack.mix.js

```javascript
const mix = require('laravel-mix');
/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */
//mix.js('resources/js/app.js', 'public/js')
//mix.sass('resources/sass/app.scss', 'public/css');
//**************** CSS ********************
//css
//mix.copy('resources/vendors/pace-progress/css/pace.min.css', 'public/css');
mix.copy('node_modules/@coreui/chartjs/dist/css/coreui-chartjs.css', 'public/css');
mix.copy('node_modules/cropperjs/dist/cropper.css', 'public/css');
//main css
mix.sass('resources/sass/style.scss', 'public/css');
//************** SCRIPTS ******************
// general scripts
mix.copy('node_modules/@coreui/utils/dist/coreui-utils.js', 'public/js');
mix.copy('node_modules/axios/dist/axios.min.js', 'public/js');
//mix.copy('node_modules/pace-progress/pace.min.js', 'public/js');
mix.copy('node_modules/@coreui/coreui/dist/js/coreui.bundle.min.js', 'public/js');
// views scripts
mix.copy('node_modules/chart.js/dist/chart.js', 'public/js');
mix.copy('node_modules/@coreui/chartjs/dist/js/coreui-chartjs.js', 'public/js');
mix.copy('node_modules/cropperjs/dist/cropper.js', 'public/js');
// details scripts
mix.copy('resources/js/coreui/main.js', 'public/js');
mix.copy('resources/js/coreui/colors.js', 'public/js');
mix.copy('resources/js/coreui/charts.js', 'public/js');
mix.copy('resources/js/coreui/widgets.js', 'public/js');
mix.copy('resources/js/coreui/popovers.js', 'public/js');
mix.copy('resources/js/coreui/tooltips.js', 'public/js');
// details scripts admin-panel
mix.js('resources/js/coreui/menu-create.js', 'public/js');
mix.js('resources/js/coreui/menu-edit.js', 'public/js');
mix.js('resources/js/coreui/media.js', 'public/js');
mix.js('resources/js/coreui/media-cropp.js', 'public/js');
//*************** OTHER ******************
//fonts
mix.copy('node_modules/@coreui/icons/fonts', 'public/fonts');
//icons
mix.copy('node_modules/@coreui/icons/css/free.min.css', 'public/css');
mix.copy('node_modules/@coreui/icons/css/brand.min.css', 'public/css');
mix.copy('node_modules/@coreui/icons/css/flag.min.css', 'public/css');
mix.copy('node_modules/@coreui/icons/svg/flag', 'public/svg/flag');
mix.copy('node_modules/@coreui/icons/sprites/', 'public/icons/sprites');
//images
mix.copy('resources/assets', 'public/assets');

```

C:\xampp8\htdocs\lva\package.json

```json
{
  "name": "@coreui/coreui-free-laravel-admin-template",
  "version": "2.0.1",
  "description": "CoreUI Free Laravel Bootstrap Admin Template",
  "keywords": [
    "admin",
    "admin panel",
    "admin template",
    "bootstrap",
    "css",
    "dashboard",
    "framework",
    "front-end",
    "responsive",
    "sass",
    "ui kit",
    "webapp",
    "laravel"
  ],
  "homepage": "https://coreui.io",
  "bugs": {
    "url": "https://github.com/coreui/coreui-free-laravel-admin-template/issues",
    "email": "support@coreui.io"
  },
  "license": "MIT",
  "author": {
    "name": "Łukasz Holeczek",
    "url": "http://holeczek.pl",
    "github": "https://github.com/mrholek",
    "twitter": "https://twitter.com/lukaszholeczek"
  },
  "contributors": [
    {
      "name": "Andrzej Kopański",
      "url": "https://github.com/xidedix"
    }
  ],
  "main": "public/index.php",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/coreui/coreui-free-laravel-admin-template.git"
  },
  "scripts": {
    "build": "npm-run-all build-clean build-copy build-vendors",
    "build-clean": "rimraf dist",
    "build-copy": "copyfiles -a -e \"public/scss/**/*\" -u 1 \"public/**/*\" dist/",
    "build-vendors": "node build/vendors.js",
    "css": "npm-run-all --parallel css-compile* --sequential css-prefix css-minify*",
    "css-compile": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 public/scss/style.scss public/css/style.css",
    "css-compile-vendors": "node build/vendors-sass.js",
    "css-lint": "stylelint --config build/.stylelintrc --syntax scss \"public/scss/**/*.scss\"",
    "css-minify": "cleancss --level 1 --source-map --source-map-inline-sources --output public/css/style.min.css public/css/style.css",
    "css-prefix": "postcss --config build/postcss.config.js --replace \"public/css/*.css\" \"!public/css/*.min.css\"",
    "js": "npm-run-all --parallel js-compile* js-lint*",
    "js-compile": "cross-env PLUGINS=true babel public/js/src/ --out-dir public/js/ --source-maps",
    "js-lint": "eslint public/js/src",
    "localhost": "browser-sync start --server \"./public\" --serveStatic \"./\" --files \"!./public/js/src/**/*, ./public/**/*, !./public/scss/**/*\"",
    "localhost-dist": "browser-sync start --server \"./dist\"",
    "pug": "node build/pug.js",
    "release-version": "node build/change-version.js",
    "serve": "npm-run-all --parallel localhost watch-css watch-js",
    "watch-css": "nodemon --ignore dist/ -e scss -x \"npm run css\"",
    "watch-js": "nodemon --watch public/js/src/ -x \"npm run js\"",
    "watch-pug": "nodemon -e pug -x \"npm run pug\"",
    "dev": "npm run development",
    "development": "mix",
    "watch": "npm run development -- --watch",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },
  "dependencies": {
    "@coreui/chartjs": "^3.0.0",
    "@coreui/coreui": "^4.2.6",
    "@coreui/icons": "^2.1.0",
    "@coreui/utils": "^1.3.1",
    "@popperjs/core": "^2.11.6",
    "axios": "^1.2.2",
    "chart.js": "^4.1.2",
    "cropperjs": "^1.5.13",
    "laravel-mix": "^6.0.49",
    "perfect-scrollbar": "^1.5.5"
  },
  "devDependencies": {
    "@babel/cli": "^7.20.7",
    "@babel/core": "^7.20.12",
    "@babel/plugin-proposal-object-rest-spread": "^7.20.7",
    "@babel/preset-env": "^7.20.2",
    "@coreui/svg-injector": "^1.0.0",
    "@coreui/vendors-injector": "^1.1.4",
    "autoprefixer": "^10.4.13",
    "babel-eslint": "^10.1.0",
    "babel-plugin-transform-es2015-modules-strip": "^0.1.2",
    "browser-sync": "^2.27.11",
    "chalk": "^5.2.0",
    "clean-css-cli": "^5.6.1",
    "copyfiles": "^2.4.1",
    "cross-env": "^7.0.3",
    "eslint": "^8.31.0",
    "eslint-config-x": "^1.0.1",
    "eslint-config-xo": "^0.43.1",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-unicorn": "^45.0.2",
    "foreach-cli": "^1.8.1",
    "js-beautify": "^1.14.7",
    "jsdom": "^21.0.0",
    "minimist": "^1.2.7",
    "node-sass": "^8.0.0",
    "nodemon": "^2.0.20",
    "npm-run-all": "^4.1.5",
    "postcss-cli": "^10.1.0",
    "postcss-combine-duplicated-selectors": "^10.0.3",
    "postcss-merge-rules": "^5.1.3",
    "pug": "^3.0.2",
    "resolve-url-loader": "^5.0.0",
    "rimraf": "^3.0.2",
    "sass": "^1.57.1",
    "sass-loader": "^13.2.0",
    "shelljs": "^0.8.5",
    "stylelint": "^14.16.1",
    "stylelint-config-recommended-scss": "^8.0.0",
    "stylelint-config-standard": "^29.0.0",
    "stylelint-order": "^6.0.1",
    "stylelint-scss": "^4.3.0",
    "sync-glob": "^1.4.0",
    "vue-template-compiler": "^2.7.14"
  },
  "engines": {
    "node": ">=8"
  },
  "browserslist": [
    "last 1 major version",
    ">= 1%",
    "Chrome >= 45",
    "Firefox >= 38",
    "Edge >= 12",
    "Explorer >= 10",
    "iOS >= 9",
    "Safari >= 9",
    "Android >= 4.4",
    "Opera >= 30"
  ]
}

```

C:\xampp8\htdocs\lva\composer.json

```json
{
  "name": "laravel/laravel",
  "type": "project",
  "description": "The Laravel Framework.",
  "keywords": [
      "framework",
      "laravel"
  ],
  "license": "MIT",
  "require": {
      "php": "^8.1.1",
      "fideloper/proxy": "^4.2",
      "laravel/framework": "^8.0",
      "fruitcake/laravel-cors": "^1.0",
      "guzzlehttp/guzzle": "^7.0.1",
      "laravel/tinker": "^2.3.0",
      "spatie/laravel-medialibrary": "^8.7.2",
      "spatie/laravel-permission": "^3.17",
      "laravel/ui": "^3.0"
  },
  "require-dev": {
      "facade/ignition": "^2.3.6",
      "fzaninotto/faker": "^1.9.1",
      "mockery/mockery": "^1.3.1",
      "nunomaduro/collision": "^5.0",
      "phpunit/phpunit": "^9.0"
  },
  "config": {
      "optimize-autoloader": true,
      "preferred-install": "dist",
      "sort-packages": true
  },
  "extra": {
      "laravel": {
          "dont-discover": []
      }
  },
  "autoload": {
      "psr-4": {
          "App\\": "app/",
          "Database\\Factories\\": "database/factories/",
          "Database\\Seeders\\": "database/seeders/"
      },
      "classmap": [
          "database",
          "database/seeders",
          "database/factories"
      ],
      "files": [
      ]
  },
  "autoload-dev": {
      "psr-4": {
          "Tests\\": "tests/"
      }
  },
  "minimum-stability": "dev",
  "prefer-stable": true,
  "scripts": {
      "post-autoload-dump": [
          "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
          "@php artisan package:discover --ansi"
      ],
      "post-root-package-install": [
          "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
      ],
      "post-create-project-cmd": [
          "@php artisan key:generate --ansi"
      ]
  }
}

```

{% file src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FA7y2n8oDC72OLfMWC1w2%2Ftestfront.rar?alt=media&token=69f392a8-6386-4560-b3cc-4a18b3a65ff3" %}

### Hướng dẫn sử dụng hệ thống compile:&#x20;

#### Compile file scss to css in public folder

```
$ yarn mix
```

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FA4q7eJlZDt9K7eb5a9Or%2Fimage.png?alt=media&#x26;token=4d20b1f0-31fc-409f-acfa-3b9dba73e8f4" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FxyvxxTpX720Hu8lRBpeR%2Fimage.png?alt=media&#x26;token=c1304d9f-f367-41c0-b008-0f14069c7840" alt=""><figcaption></figcaption></figure>

#### Copy file from public to build

```
yarn build
```

<figure><img src="https://1592565776-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVfVRgKBlsVnWvhnDaa%2Fuploads%2FksPXSsALcAQP9KPYe914%2Fimage.png?alt=media&#x26;token=dfc10d79-4df1-49b5-a9fc-910ac5fcc5f6" alt=""><figcaption></figcaption></figure>
