Way High

การทำ Url บน Laravel ให้อ่านง่าย สวยงาม หรือ Friendly Url รองรับภาษาไทย บน Laravel

​ผมได้ทำการต่อยอดจาก package ของฝรั่งชื่อ https://github.com/cviebrock/eloquent-sluggable ที่มีปัญหาว่าถ้ามีภาษาไทยโผลเข้าไปก็บึ้มพังเลยใช้ไม่ได้ ก็เลยลองๆเอามาแก้ดูให้รองรับภาษาไทยก็ใช้งานได้ดีครับ หรือจะเอามาใช้ส่วนของการทำ slug เฉยๆก็ได้ครับ


Slug คืออะไร

slug คือการใช้ข้อความแทน id ของเรคคอร์ดในฐานข้อมูล โดยหลักการก็คือเพิ่มอีก field ให้กับตารางเรา อาจจะชื่อ slug เฉยๆก็ได้ แล้วเวลาจะหา record เราก็ where เอาจากเจ้า slug field ตัวนี้แทน

ใช้ package สิง่ายดีออก

ขั้นแรกก็เพิ่ม package นี้เข้าไปในส่วนของ require ของไฟล์ composer.json 

{    
    "require": {
"expstudio/friendlyurl": "dev-master"
},
}

 เพิ่ม provider ในไฟล์ app/config/app.php

    'providers' => array( 
        //...
'Expstudio\FriendlyUrl\SluggableServiceProvider',
);

เสร็จแล้วก็รัน  command line  php artisan config:publish expstudio/friendlyurl เพื่อ publish  ไฟล์คอนฟิกเริ่มต้น

อัพเดท Model ให้รองรับ


โมเดลที่อยากทำ friendly url ต้องทีการ implement อินเตอรเฟส Sluggable และ ใช้ trait ของมันด้วยนะครับ เรากำหนดค่าได้ในตัวแฟร $sluggable ว่าจะเอาอะไรมาเป็นส่วนประกอบของ slug ลองดูเพิ่มเติมใน github อีกทีละกันครับ

use Expstudio\FriendlyUrl\SluggableInterface;
use Expstudio\FriendlyUrl\SluggableTrait;
class Post extends Eloquent implements SluggableInterface{
use SluggableTrait;
protected $sluggable = array(
'build_from' => 'title',
'save_to' => 'slug',
);
}

แน่นอนว่าฐานข้อมูลของเรามันต้องการฟีลไว้เก้บเจ้า  slug นี้
เราสามารถเพิ่มตรงนี้ได้ง่ายๆด้วย built-in artisan command ตามตัวอย่าง

php artisan sluggable:table posts

ถ้าทำตามคำสั่งมันจะไปสร้างไฟล์ migration ที่เพิ่มคอลัมน์ "slug"เข้าไปในตาราง posts ถ้าต้องการให้คอลัมน์เป็นชื่ออื่นก็ลองคำสั่งข้างล่างนี้ดู

php artisan sluggable:table posts slug_column

อย่างลิมไปเปลี่ยนค่าsave_to ในค่าคอนฟิกของโมเดล ให้ตรงกับคอลัมน์ใหม่นี้ด้วยนะจ๊ะ

แค่นี้ก็ใช้งานได้แล้ว


แถมอีกวิธี

ถ้าไม่อยากไปแก้ไขโมเดล เราสามารถทำเองง่ายๆก็ได้ครับไปแก้ไฟล์ /start/global.php โดยการเพิ่มตัวดัก saving เข้าไปตามนี้

Post::saving(function($post){
if(!$post->slug)
$post->slug = Slugger::slug($post->title);
});

แล้วก็ไปแก้ controller ให้มันหาจากคอลัมน์ slug ตามนี้จ้า

public function show($id)
{
$categories = $this->getCategories();
$post = $this->post->where('slug', '=', $id)->first();
$post = $post ? $post : $this->post->findOrFail($id);
return View::make('posts.show', compact('post', 'categories'));
}

วิธีนี้ก็มีข้อดีตรงรองรับการทำงานกับ Host เก่าๆ PHP 5.3 ครับ

ขอบคุณทุกท่านที่สละเวลาเข้าชมนะครับ มีอะไรสอบถามได้เลยจ้า