'Laravel with Arabic Slugs

i'm using Laravel 6 to build a blog application and the language of this app is Arabic but there is a problem with slug ,it looks like that Laravel doesn't support Arabic.

any idea to fix this?

Controller

public function post($slug)
{
    $post = Post::where('slug',$slug)->first();
    return view('content.post',compact('post'));
}

Store Method

public function store(Request $request)
{
    $this->validate($request, array(
        'title'         => 'required|max:255',
        'slug'          => 'required|min:3|max:255|unique:posts',
        'body'          => 'required',
    ));
    $post = new Post;
    $post->title = $request->input('title');
    $post->slug = Str::slug($request->slug, '-');
    $post->body = $request->input('body');
    $post->save();

    return redirect('admin/posts')->with('success', 'post is successfully saved');
}

Route

Route::get('post/{slug}', 'PagesController@post')->name('post.show');


Solution 1:[1]

You can use this function

public function slug($string, $separator = '-') {
    if (is_null($string)) {
        return "";
    }

    $string = trim($string);

    $string = mb_strtolower($string, "UTF-8");;

    $string = preg_replace("/[^a-z0-9_\s????????????????????????????????????]#u/", "", $string);

    $string = preg_replace("/[\s-]+/", " ", $string);

    $string = preg_replace("/[\s_]/", $separator, $string);

    return $string;
}
public function store(Request $request)
{
    $this->validate($request, array(
        'title'         => 'required|max:255',
        'slug'          => 'required|min:3|max:255|unique:posts',
        'body'          => 'required',
    ));
    $post = new Post;
    $post->title = $request->input('title');
    $post->slug = $this->slug($request->slug);
    $post->body = $request->input('body');
    $post->save();

    return redirect('admin/posts')->with('success', 'post is successfully saved');
}

It will make slug for each language arabic or english. and it will work fine.

Solution 2:[2]

Laravel's slugging support by transliterating languages such as Arabic is not very good. You could alternatively use PHP's Transliterator https://www.php.net/manual/en/transliterator.transliterate.php to get the transliterated string before sending through Laravel's Str::slug function.

For example, you could use something like this:

Str::slug(transliterator_transliterate("Any-Latin; Latin-ASCII; NFD; [:Nonspacing Mark:] Remove; NFC; [:Punctuation:] Remove; Lower();", "arabic sentence you need slugged"));

Do note that you'd need PECL intl installed for this to work.

Solution 3:[3]

I know there is a correct answer already by @Mohammed Aktaa but it has a missing part of removing backward and forward slashes which can lead to fatal mistake when request the get url that having the slug:

so correct the slug function by the following:

public static function slug_ar($string, $separator = '-') {
    if (is_null($string)) {
        return "";
    }
    $string = trim($string);
    $string = mb_strtolower($string, "UTF-8");
    // '/' and/or '\' if found and not remoeved it will change the get request route
    $string = str_replace('/', $separator, $string); 
    $string = str_replace('\\', $separator, $string);
    $string = preg_replace("/[^a-z0-9_\s????????????????????????????????????]#u/", "", 
    $string);
    $string = preg_replace("/[\s-]+/", " ", $string);
    $string = preg_replace("/[\s_]/", $separator, $string);
    return $string;
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 user3532758
Solution 3