Difference between revisions of "Basic Laravel Training (for CV)"
Jump to navigation
Jump to search
(32 intermediate revisions by the same user not shown) | |||
Line 4: | Line 4: | ||
== Installation == | == Installation == | ||
− | # Install LAMP Stack (ie. XAMPP) | + | === Requirements === |
+ | * PHP >= 7.1.3 | ||
+ | * OpenSSL PHP Extension | ||
+ | * PDO PHP Extension | ||
+ | * Mbstring PHP Extension | ||
+ | * Tokenizer PHP Extension | ||
+ | * XML PHP Extension | ||
+ | * Ctype PHP Extension | ||
+ | * JSON PHP Extension | ||
+ | * BCMath PHP Extension | ||
+ | === Steps === | ||
+ | # Install LAMP Stack (ie. XAMPP) อย่าลืมจำ mysql root password!! | ||
# Install Composer | # Install Composer | ||
#: https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos | #: https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos | ||
#: หมายเหตุ: เวลาเรียกใช้งาน composer อาจจะต้องใช้ <code>./composer.phar</code> แทนที่ <code>composer</code> ถ้าทำการ Install composer เป็น local | #: หมายเหตุ: เวลาเรียกใช้งาน composer อาจจะต้องใช้ <code>./composer.phar</code> แทนที่ <code>composer</code> ถ้าทำการ Install composer เป็น local | ||
− | # | + | # สร้าง Laravel Project โดยใช้ composer |
#: <pre>composer create-project --prefer-dist laravel/laravel PROJECT_NAME </pre> | #: <pre>composer create-project --prefer-dist laravel/laravel PROJECT_NAME </pre> | ||
# Run Local Development Server | # Run Local Development Server | ||
Line 14: | Line 25: | ||
#: or | #: or | ||
#: <pre>php artisan serve --port=8888 # for running on localhost:8888</pre> | #: <pre>php artisan serve --port=8888 # for running on localhost:8888</pre> | ||
+ | |||
+ | == Basic Tutorial == | ||
+ | === Important directory / file === | ||
+ | * <code>app</code> Where the models are | ||
+ | ** <code>Http</code> | ||
+ | *** <code>Controllers</code> | ||
+ | *** <code>Middleware</code> | ||
+ | * <code>config</code> | ||
+ | * <code>database</code> | ||
+ | * <code>public</code> Where the public files (ie. css, js) | ||
+ | * <code>resources</code> | ||
+ | ** <code>views</code> | ||
+ | * <code>routes</code> | ||
+ | ** <code>api.php</code> | ||
+ | ** <code>web.php</code> | ||
+ | * <code>vendor</code> Where the additional libraries store | ||
+ | * <code>.env</code> all environment variables (ie. DB username/password) | ||
+ | |||
+ | === Intro === | ||
+ | ==== Controller & Route ==== | ||
+ | # Let's make a controller: page_controller | ||
+ | #: <pre>php artisan make:controller CONTROLLER_NAME</pre> | ||
+ | #: จะมีไฟล์ <code>app/Http/Controllers/page_controller.php</code> ปรากฎ | ||
+ | # ในไฟล์จะมี code เหล่านี้ | ||
+ | #: <syntaxhighlight lang="php" line> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Http\Controllers; | ||
+ | |||
+ | use Illuminate\Http\Request; | ||
+ | |||
+ | class page_controller extends Controller | ||
+ | { | ||
+ | // | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | # ลองสร้าง method index | ||
+ | #: <syntaxhighlight lang="php" line> | ||
+ | public function index(){ | ||
+ | $menu = array("Home", "My course", "Setting"); | ||
+ | return $menu; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | # เพิ่ม Route ใน <code>routes/web.php</code> | ||
+ | #: <syntaxhighlight lang="php" line> | ||
+ | Route::get('home','page_controller@index'); | ||
+ | </syntaxhighlight> | ||
+ | # ลองทดสอบเรียก url | ||
+ | #: <pre>http://localhost:8000/home</pre> | ||
+ | # ปกติแล้วสิ่งที่ controller คืนมักจะไม่ใช่ array หรือ object ธรรมดา ยกเว้นกรณีที่กำลังเขียน api .. หากเป็นกรณี webpage มักจะคืนเป็น view | ||
+ | # ลองสร้าง view (การสร้าง view จะไม่สามารถเรียกผ่าน artisan ได้ จะต้องสร้างด้วยตัวเอง ใน <code>resources/views</code> โดยให้สร้าง view ชื่อว่า <code>home.blade.php</code> | ||
+ | # ใน controller method index จะเปลี่ยนแปลงการ return ให้ return view แทน | ||
+ | #: <syntaxhighlight lang="php" line> | ||
+ | public function index(){ | ||
+ | $menu = array("Home", "My course", "Setting"); | ||
+ | return view("home")->with('menu',$menu); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | # ใน <code>home.blade.php</code> ให้ลองเขียน html เพื่อแสดง menu เป็น unordered list | ||
+ | #: <syntaxhighlight lang="html" line> | ||
+ | <!DOCTYPE html> | ||
+ | <html lang="en"> | ||
+ | <head> | ||
+ | <meta charset="UTF-8"> | ||
+ | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
+ | <meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
+ | <title>Document</title> | ||
+ | </head> | ||
+ | <body> | ||
+ | <ul> | ||
+ | @foreach($menu as $eachmenu) | ||
+ | <li>{{$eachmenu}}</li> | ||
+ | @endforeach | ||
+ | </ul> | ||
+ | </body> | ||
+ | </html> | ||
+ | </syntaxhighlight> | ||
+ | ==== View (Blade Template) ==== | ||
+ | * <code><meta name="csrf-token" content="{{ csrf_token() }}"></code> | ||
+ | * <code>{{ config('app.name', 'Laravel') }}</code> | ||
+ | * @include('inc.messages') | ||
+ | * @yield('content') | ||
+ | * @extends('layouts.app') | ||
+ | * @section('content')<br>@endsection | ||
+ | * @if | ||
+ | * @for | ||
+ | * @foreach | ||
+ | * @csrf | ||
+ | * {{}} | ||
+ | * {!! !!} | ||
+ | |||
+ | === Database === | ||
+ | ==== Preparation ==== | ||
+ | * สร้าง database (สมมติว่าชื่อ laravel_training) | ||
+ | * แก้ไข <code>.env</code> | ||
+ | *: <syntaxhighlight> | ||
+ | DB_CONNECTION=mysql | ||
+ | DB_HOST=127.0.0.1 | ||
+ | DB_PORT=3306 | ||
+ | DB_DATABASE=laravel_training | ||
+ | DB_USERNAME=USERNAME | ||
+ | DB_PASSWORD=PASSWORD | ||
+ | </syntaxhighlight> | ||
+ | * แก้ไข file <code>app/Providers/AppServiceProvider.php</code> ข้างบนสุดเพิ่ม | ||
+ | *: <pre>use Illuminate\Support\Facades\Schema;</pre> | ||
+ | * แก้ไข file <code>app/Providers/AppServiceProvider.php</code> function boot เพิ่ม | ||
+ | *: <pre>Schema::defaultStringLength(191);</pre> | ||
+ | * ลอง migrate default script | ||
+ | *: <pre>php artisan migrate</pre> | ||
+ | |||
+ | ==== Model & DB ==== | ||
+ | * php artisan make:model MODEL_NAME --migration | ||
+ | * php artisan make:migration MIGRATION_NAME | ||
+ | * Sample | ||
+ | *: <!--syntaxhighlight lang="php"> | ||
+ | <?php | ||
+ | public function up() | ||
+ | { | ||
+ | Schema::enableForeignKeyConstraints(); | ||
+ | Schema::create('cvdrive_comments', function (Blueprint $table) { | ||
+ | $table->increments('id'); | ||
+ | $table->text('comment')->nullable($value = true); | ||
+ | $table->integer('cvdrive_item_id')->unsigned(); | ||
+ | $table->integer('user_id')->unsigned(); | ||
+ | $table->integer('cvdrive_comment_id')->unsigned()->nullable($value = true); | ||
+ | $table->timestamps(); | ||
+ | |||
+ | $table->foreign('cvdrive_item_id')->references('id')->on('cvdrive_items')->onDelete('cascade'); | ||
+ | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||
+ | $table->foreign('cvdrive_comment_id')->references('id')->on('cvdrive_comments')->onDelete('cascade'); | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | public function down() | ||
+ | { | ||
+ | Schema::dropIfExists('cvdrive_comments'); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight--> | ||
+ | |||
+ | ==== Eloquent ==== | ||
+ | * php artisan tinker | ||
+ | * new item | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | $course = new course(); | ||
+ | $course->number = "2110221"; | ||
+ | $course->title = "Computer Engineering Essentials"; | ||
+ | $course->year = 2018; | ||
+ | $course->semester = 2; | ||
+ | $course->save(); | ||
+ | </syntaxhighlight> | ||
+ | * duplicate item : $newcourse2 = $newcourse->replicate(); | ||
+ | * fetch item | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | $allcourses = course::all(); | ||
+ | $findcourse = course::find(1); | ||
+ | $findcourse = course::where(number,"2110221")->get(); | ||
+ | |||
+ | // ->where("title","like","%".$keyword."%") | ||
+ | // ->orderBy('created_at','desc') | ||
+ | // ->paginate(10); | ||
+ | // In view show page numbers: {{$items->links()}} | ||
+ | </syntaxhighlight> | ||
+ | * edit item | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | $course = course::find(1); | ||
+ | $course->title = "NEW NAME"; | ||
+ | $course->save(); | ||
+ | </syntaxhighlight> | ||
+ | * delete item | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | $course = course::find(1); | ||
+ | $course->delete(); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Handle CRUD ==== | ||
+ | * php artisan make:controller CONTROLLER_NAME --resource | ||
+ | * method: get, post, patch, delete | ||
+ | * Route::resource('ROUTE', 'CONTROLLER'); | ||
+ | * php artisan route:list | ||
+ | * Handle request | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | $name = $request->input('name', 'Default'); | ||
+ | $name = $request->name; | ||
+ | </syntaxhighlight> | ||
+ | * Validation --> [https://laravel.com/docs/5.8/validation See Doc] | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | $request->validate([ | ||
+ | 'title' => 'required|max:255', | ||
+ | 'body' => 'required', | ||
+ | ]); | ||
+ | |||
+ | // Frontend display error | ||
+ | @if ($errors->any()) | ||
+ | <div class="alert alert-danger"> | ||
+ | <ul> | ||
+ | @foreach ($errors->all() as $error) | ||
+ | <li>{{ $error }}</li> | ||
+ | @endforeach | ||
+ | </ul> | ||
+ | </div> | ||
+ | @endif | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Relationship ==== | ||
+ | ===== one to one ===== | ||
+ | * Defining relationship | ||
+ | *: return $this->hasOne('App\Phone', 'foreign_key', 'local_key'); | ||
+ | * Defining inverse relationship | ||
+ | *: return $this->belongsTo('App\User', 'foreign_key', 'other_key'); | ||
+ | |||
+ | ===== one to many ===== | ||
+ | * Defining relationship | ||
+ | *: return $this->hasMany('App\Comment', 'foreign_key', 'local_key'); | ||
+ | * Defining inverse relationship | ||
+ | *: return $this->belongsTo('App\Post', 'foreign_key', 'other_key'); | ||
+ | |||
+ | ===== many to many ===== | ||
+ | * Defining relationship | ||
+ | *: return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id'); | ||
+ | *: return $this->belongsToMany('Model','Intermediate table name','fk of current model','fk of another model') | ||
+ | * Defining inverse relationship | ||
+ | *: return $this->belongsToMany('App\User', 'role_user', 'role_id', 'user_id'); | ||
+ | *: return $this->belongsToMany('Model','Intermediate table name','fk of current model','fk of another model') | ||
+ | |||
+ | === Authentication === | ||
+ | ==== Preparation ==== | ||
+ | * php artisan make:auth | ||
+ | |||
+ | ==== User System ==== | ||
+ | * $user = Auth::user(); | ||
+ | * $id = Auth::id(); | ||
+ | * Protect route | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | // Protect in route | ||
+ | Route::get('index','homecontroller@index')->middleware('auth'); | ||
+ | |||
+ | // Protect in constructor | ||
+ | public __construct{ | ||
+ | $this->middleware('auth', ['except' => ['getActivate', 'anotherMethod']]); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | * Check if the user is loggedin | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | if (Auth::check()) { | ||
+ | // The user is logged in... | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Access Control ==== | ||
+ | * Using Policy | ||
+ | * php artisan make:policy POLICY_NAME | ||
+ | * php artisan make:policy POLICY_NAME --model=MODEL // Create with basic CRUD | ||
+ | * Register Policy in <code>App/Providers/Authserviceprovider.php</code> | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | protected $policies = [ | ||
+ | Post::class => PostPolicy::class, | ||
+ | ]; | ||
+ | </syntaxhighlight> | ||
+ | * Writing Policy | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | public function update(User $user, Post $post){ | ||
+ | return $user->id === $post->user_id; | ||
+ | } | ||
+ | |||
+ | // Check Policy | ||
+ | if ($user->can('update', $post)) { | ||
+ | // | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | * Writing Policy without model | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | public function create(User $user){ | ||
+ | // | ||
+ | } | ||
+ | |||
+ | // Check Policy | ||
+ | if ($user->can('create', Post::class)) { // ต้องบอก class เพื่อจะได้รู้ว่าจะไปเรียกจาก policy ของ class ไหน | ||
+ | // | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | * Writing Policy in View | ||
+ | *: <syntaxhighlight lang="php"> | ||
+ | @can('update', $post) | ||
+ | <!-- The Current User Can Update The Post --> | ||
+ | @elsecan('create', App\Post::class) | ||
+ | <!-- The Current User Can Create New Post --> | ||
+ | @endcan | ||
+ | |||
+ | |||
+ | @if (Auth::user()->can('update', $post)) | ||
+ | <!-- The Current User Can Update The Post --> | ||
+ | @endif | ||
+ | |||
+ | |||
+ | @unless (Auth::user()->can('update', $post)) | ||
+ | <!-- The Current User Can't Update The Post --> | ||
+ | @endunless | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Testing == | ||
+ | * Make test <syntaxhighlight> | ||
+ | // Create a test in the tests/Feature directory... | ||
+ | php artisan make:test UserTest | ||
+ | |||
+ | // Create a test in the tests/Unit directory... | ||
+ | php artisan make:test UserTest --unit | ||
+ | </syntaxhighlight> | ||
+ | * Run test : In your project root run <pre>vendor/bin/phpunit</pre> | ||
+ | * The CSRF middleware is automatically disabled when running tests | ||
+ | * Use model factory to generate fake object | ||
+ | ** Factory is at <code> database/factories/UserFactory.php</code> | ||
+ | ** In testing <syntaxhighlight lang="php"> | ||
+ | $user = factory(User::class)->create(); | ||
+ | $response = $this->actingAs($user)->withSession(['foo' => 'bar'])->get('/'); | ||
+ | </syntaxhighlight> | ||
+ | * Browser Test [[https://laravel.com/docs/5.8/dusk https://laravel.com/docs/5.8/dusk]] | ||
+ | * And more ... in Laravel Doc | ||
+ | |||
+ | == More and More == | ||
+ | === Middleware === | ||
+ | * อยู่ระหว่าง routing กับ controller | ||
+ | ** มีอยู่แล้วคือ Auth | ||
+ | ** อาจมีอื่นๆ เช่น CORS middleware, Log middleware | ||
+ | * การสร้าง Middleware | ||
+ | ** <code>php artisan make:middleware CheckAge</code> | ||
+ | ** File จะอยู่ที่ <code> app/Http/Middleware</code> | ||
+ | ** ตัวอย่างนี้ เป็น middleware ที่เช็ค age | ||
+ | *** ถ้า age <= 200 จะไม่อนุญาตให้ไปต่อ โดยจะ redirect ไปที่ home | ||
+ | *** ถ้า age > 200 จะไปต่อ โดยเรียก $next($request) $next คือ function ที่มันควรจะเข้าจริงๆ | ||
+ | ** <syntaxhighlight lang="php"> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Http\Middleware; | ||
+ | |||
+ | use Closure; | ||
+ | |||
+ | class CheckAge | ||
+ | { | ||
+ | /** | ||
+ | * Handle an incoming request. | ||
+ | * | ||
+ | * @param \Illuminate\Http\Request $request | ||
+ | * @param \Closure $next | ||
+ | * @return mixed | ||
+ | */ | ||
+ | public function handle($request, Closure $next) | ||
+ | { | ||
+ | if ($request->age <= 200) { | ||
+ | return redirect('home'); | ||
+ | } | ||
+ | |||
+ | return $next($request); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | ** Middleware อาจจะทำก่อน หริือ หลัง request ก็ได้ | ||
+ | *** ทำก่อน (ตัวอย่างกรณีข้างบน) | ||
+ | *** ทำหลัง <syntaxhighlight lang="php"> | ||
+ | public function handle($request, Closure $next) | ||
+ | { | ||
+ | $response = $next($request); | ||
+ | |||
+ | // Perform action | ||
+ | |||
+ | return $response; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | * หลังจากสร้างแล้ว จะต้องเอาไป register ไว้ที่ <code> app/Http/Kernel.php</code> | ||
+ | * การนำไปใช้ | ||
+ | ** จะเอาไปผูกกับ route <syntaxhighlight lang="php"> | ||
+ | Route::get('admin/profile', function () { | ||
+ | // | ||
+ | })->middleware('auth', 'second_middleware'); | ||
+ | </syntaxhighlight> | ||
+ | * Middleware group (Assign ทีเดียวหลายตัวเป็น group) | ||
+ | * Middleware parameters | ||
+ | ** ตัวอย่างการเช็ค role <syntaxhighlight lang="php"> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Http\Middleware; | ||
+ | |||
+ | use Closure; | ||
+ | |||
+ | class CheckRole | ||
+ | { | ||
+ | /** | ||
+ | * Handle the incoming request. | ||
+ | * | ||
+ | * @param \Illuminate\Http\Request $request | ||
+ | * @param \Closure $next | ||
+ | * @param string $role | ||
+ | * @return mixed | ||
+ | */ | ||
+ | public function handle($request, Closure $next, $role) | ||
+ | { | ||
+ | if (! $request->user()->hasRole($role)) { | ||
+ | // Redirect... | ||
+ | } | ||
+ | |||
+ | return $next($request); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | ** การนำไปใช้ กรณีนี้จะตรวจสอบว่า route นี้จะเข้าได้เฉพาะคนที่มี role เป็น editor เท่านั้น <syntaxhighlight lang="php"> | ||
+ | Route::put('post/{id}', function ($id) { | ||
+ | // | ||
+ | })->middleware('role:editor'); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === OAUTH === | ||
+ | * [[https://laravel.com/docs/5.8/passport Laravel Passport (Library for OAUTH Server)]] | ||
+ | |||
+ | == More References == | ||
+ | * [[https://github.com/alexeymezenin/laravel-best-practices#follow-laravel-naming-conventions Laravel Best Practices]] |
Latest revision as of 00:13, 26 April 2019
Contents
Reference
- Laravel Documentation
https://laravel.com/docs/5.8
Installation
Requirements
- PHP >= 7.1.3
- OpenSSL PHP Extension
- PDO PHP Extension
- Mbstring PHP Extension
- Tokenizer PHP Extension
- XML PHP Extension
- Ctype PHP Extension
- JSON PHP Extension
- BCMath PHP Extension
Steps
- Install LAMP Stack (ie. XAMPP) อย่าลืมจำ mysql root password!!
- Install Composer
- https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos
- หมายเหตุ: เวลาเรียกใช้งาน composer อาจจะต้องใช้
./composer.phar
แทนที่composer
ถ้าทำการ Install composer เป็น local
- สร้าง Laravel Project โดยใช้ composer
composer create-project --prefer-dist laravel/laravel PROJECT_NAME
- Run Local Development Server
php artisan serve # for running on localhost:8000
- or
php artisan serve --port=8888 # for running on localhost:8888
Basic Tutorial
Important directory / file
app
Where the models areHttp
Controllers
Middleware
config
database
public
Where the public files (ie. css, js)resources
views
routes
api.php
web.php
vendor
Where the additional libraries store.env
all environment variables (ie. DB username/password)
Intro
Controller & Route
- Let's make a controller: page_controller
php artisan make:controller CONTROLLER_NAME
- จะมีไฟล์
app/Http/Controllers/page_controller.php
ปรากฎ
- ในไฟล์จะมี code เหล่านี้
1 <?php 2 3 namespace App\Http\Controllers; 4 5 use Illuminate\Http\Request; 6 7 class page_controller extends Controller 8 { 9 // 10 }
- ลองสร้าง method index
1 public function index(){ 2 $menu = array("Home", "My course", "Setting"); 3 return $menu; 4 }
- เพิ่ม Route ใน
routes/web.php
1 Route::get('home','page_controller@index');
- ลองทดสอบเรียก url
http://localhost:8000/home
- ปกติแล้วสิ่งที่ controller คืนมักจะไม่ใช่ array หรือ object ธรรมดา ยกเว้นกรณีที่กำลังเขียน api .. หากเป็นกรณี webpage มักจะคืนเป็น view
- ลองสร้าง view (การสร้าง view จะไม่สามารถเรียกผ่าน artisan ได้ จะต้องสร้างด้วยตัวเอง ใน
resources/views
โดยให้สร้าง view ชื่อว่าhome.blade.php
- ใน controller method index จะเปลี่ยนแปลงการ return ให้ return view แทน
1 public function index(){ 2 $menu = array("Home", "My course", "Setting"); 3 return view("home")->with('menu',$menu); 4 }
- ใน
home.blade.php
ให้ลองเขียน html เพื่อแสดง menu เป็น unordered list1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>Document</title> 8 </head> 9 <body> 10 <ul> 11 @foreach($menu as $eachmenu) 12 <li>{{$eachmenu}}</li> 13 @endforeach 14 </ul> 15 </body> 16 </html>
View (Blade Template)
<meta name="csrf-token" content="Template:Csrf token()">
Template:Config('app.name', 'Laravel')
- @include('inc.messages')
- @yield('content')
- @extends('layouts.app')
- @section('content')
@endsection - @if
- @for
- @foreach
- @csrf
- {{}}
- {!! !!}
Database
Preparation
- สร้าง database (สมมติว่าชื่อ laravel_training)
- แก้ไข
.env
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel_training DB_USERNAME=USERNAME DB_PASSWORD=PASSWORD
- แก้ไข file
app/Providers/AppServiceProvider.php
ข้างบนสุดเพิ่มuse Illuminate\Support\Facades\Schema;
- แก้ไข file
app/Providers/AppServiceProvider.php
function boot เพิ่มSchema::defaultStringLength(191);
- ลอง migrate default script
php artisan migrate
Model & DB
- php artisan make:model MODEL_NAME --migration
- php artisan make:migration MIGRATION_NAME
- Sample
Eloquent
- php artisan tinker
- new item
$course = new course(); $course->number = "2110221"; $course->title = "Computer Engineering Essentials"; $course->year = 2018; $course->semester = 2; $course->save();
- duplicate item : $newcourse2 = $newcourse->replicate();
- fetch item
$allcourses = course::all(); $findcourse = course::find(1); $findcourse = course::where(number,"2110221")->get(); // ->where("title","like","%".$keyword."%") // ->orderBy('created_at','desc') // ->paginate(10); // In view show page numbers: {{$items->links()}}
- edit item
$course = course::find(1); $course->title = "NEW NAME"; $course->save();
- delete item
$course = course::find(1); $course->delete();
Handle CRUD
- php artisan make:controller CONTROLLER_NAME --resource
- method: get, post, patch, delete
- Route::resource('ROUTE', 'CONTROLLER');
- php artisan route:list
- Handle request
$name = $request->input('name', 'Default'); $name = $request->name;
- Validation --> See Doc
$request->validate([ 'title' => 'required|max:255', 'body' => 'required', ]); // Frontend display error @if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif
Relationship
one to one
- Defining relationship
- return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
- Defining inverse relationship
- return $this->belongsTo('App\User', 'foreign_key', 'other_key');
one to many
- Defining relationship
- return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
- Defining inverse relationship
- return $this->belongsTo('App\Post', 'foreign_key', 'other_key');
many to many
- Defining relationship
- return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
- return $this->belongsToMany('Model','Intermediate table name','fk of current model','fk of another model')
- Defining inverse relationship
- return $this->belongsToMany('App\User', 'role_user', 'role_id', 'user_id');
- return $this->belongsToMany('Model','Intermediate table name','fk of current model','fk of another model')
Authentication
Preparation
- php artisan make:auth
User System
- $user = Auth::user();
- $id = Auth::id();
- Protect route
// Protect in route Route::get('index','homecontroller@index')->middleware('auth'); // Protect in constructor public __construct{ $this->middleware('auth', ['except' => ['getActivate', 'anotherMethod']]); }
- Check if the user is loggedin
if (Auth::check()) { // The user is logged in... }
Access Control
- Using Policy
- php artisan make:policy POLICY_NAME
- php artisan make:policy POLICY_NAME --model=MODEL // Create with basic CRUD
- Register Policy in
App/Providers/Authserviceprovider.php
protected $policies = [ Post::class => PostPolicy::class, ];
- Writing Policy
public function update(User $user, Post $post){ return $user->id === $post->user_id; } // Check Policy if ($user->can('update', $post)) { // }
- Writing Policy without model
public function create(User $user){ // } // Check Policy if ($user->can('create', Post::class)) { // ต้องบอก class เพื่อจะได้รู้ว่าจะไปเรียกจาก policy ของ class ไหน // }
- Writing Policy in View
@can('update', $post) <!-- The Current User Can Update The Post --> @elsecan('create', App\Post::class) <!-- The Current User Can Create New Post --> @endcan @if (Auth::user()->can('update', $post)) <!-- The Current User Can Update The Post --> @endif @unless (Auth::user()->can('update', $post)) <!-- The Current User Can't Update The Post --> @endunless
Testing
- Make test
// Create a test in the tests/Feature directory... php artisan make:test UserTest // Create a test in the tests/Unit directory... php artisan make:test UserTest --unit
- Run test : In your project root run
vendor/bin/phpunit
- The CSRF middleware is automatically disabled when running tests
- Use model factory to generate fake object
- Factory is at
database/factories/UserFactory.php
- In testing
$user = factory(User::class)->create(); $response = $this->actingAs($user)->withSession(['foo' => 'bar'])->get('/');
- Factory is at
- Browser Test [https://laravel.com/docs/5.8/dusk]
- And more ... in Laravel Doc
More and More
Middleware
- อยู่ระหว่าง routing กับ controller
- มีอยู่แล้วคือ Auth
- อาจมีอื่นๆ เช่น CORS middleware, Log middleware
- การสร้าง Middleware
php artisan make:middleware CheckAge
- File จะอยู่ที่
app/Http/Middleware
- ตัวอย่างนี้ เป็น middleware ที่เช็ค age
- ถ้า age <= 200 จะไม่อนุญาตให้ไปต่อ โดยจะ redirect ไปที่ home
- ถ้า age > 200 จะไปต่อ โดยเรียก $next($request) $next คือ function ที่มันควรจะเข้าจริงๆ
<?php namespace App\Http\Middleware; use Closure; class CheckAge { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if ($request->age <= 200) { return redirect('home'); } return $next($request); } }
- Middleware อาจจะทำก่อน หริือ หลัง request ก็ได้
- ทำก่อน (ตัวอย่างกรณีข้างบน)
- ทำหลัง
public function handle($request, Closure $next) { $response = $next($request); // Perform action return $response; }
- หลังจากสร้างแล้ว จะต้องเอาไป register ไว้ที่
app/Http/Kernel.php
- การนำไปใช้
- จะเอาไปผูกกับ route
Route::get('admin/profile', function () { // })->middleware('auth', 'second_middleware');
- จะเอาไปผูกกับ route
- Middleware group (Assign ทีเดียวหลายตัวเป็น group)
- Middleware parameters
- ตัวอย่างการเช็ค role
<?php namespace App\Http\Middleware; use Closure; class CheckRole { /** * Handle the incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string $role * @return mixed */ public function handle($request, Closure $next, $role) { if (! $request->user()->hasRole($role)) { // Redirect... } return $next($request); } }
- การนำไปใช้ กรณีนี้จะตรวจสอบว่า route นี้จะเข้าได้เฉพาะคนที่มี role เป็น editor เท่านั้น
Route::put('post/{id}', function ($id) { // })->middleware('role:editor');
- ตัวอย่างการเช็ค role