by Devin Yang

建立於: 1年前 ( 更新: 1年前 )

PHP trait相信很多人都不陌生,因為Laravel到處可見,
但我還是寫出來分享給有緣人🙄。

PHP trait可以讓兩個不同的CLASS都可以使用相同的方法。
他不但能降低複雜度,更可讓程式碼重複被使用。

所以放個Browser系列功能在Laravel的ViewServiceProvider上使用,應該是滿方便的😝

關於ViewServiceProvider官方文件:

https://laravel.com/docs/9.x/views#view-composers

據說Trait隨便建隨便放,所以我就弄了個Browser traits在Laravel的/app/Ccc/Traits目錄中。
當然Namespace同目錄規則,大家應該看的出來吧(下面的程式碼範例)

正因為本網站大量webp圖檔,所以我Goolge取得了getBrowser這功能
(抱歉,隨便找的忘了出處啦),用他來檢測瀏覽器及版本,
他有個$ub變數未定義的Bug,後來我已修正。

有了這功能,我就能控制是否使用webp圖檔啦(is_support_webp)。
如果您還沒看過我webp轉碼bash文章(jpg轉webp,並且縮小jpg檔),可以點下方這篇看看:
https://www.ccc.tc/article/make-the-web-faster

另外就是弄了另一個方法,isMobile()。用來檢測是否為手機 。

trait Browser的內容如下: (簡化版本)

<?php

namespace App\Ccc\Traits;

use Illuminate\Support\Facades\Log;

trait Browser
{
    public function is_support_webp(){

        if (($this->getBrowser()->name == "Google Chrome" && $this->getBrowser()->version >= 107) ||
            ($this->getBrowser()->name == "Apple Safari" && $this->getBrowser()->version >= 16) ||
            ($this->getBrowser()->name == "Mozilla Firefox" && $this->getBrowser()->version >= 65)
        ) {
            return true;
        } else {
            return false;
        }
    }

    public function isMobile() {
        return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $_SERVER["HTTP_USER_AGENT"]);
    }

    public function getBrowser()
    {
        $u_agent = $_SERVER['HTTP_USER_AGENT'];
        $bname = 'Unknown';
        $platform = 'Unknown';
        $version = "";
   		$ub=""; //Default Value
   		
        //First get the platform?
        if (preg_match('/linux/i', $u_agent)) {
            $platform = 'linux';
        } elseif (preg_match('/macintosh|mac os x/i', $u_agent)) {
            $platform = 'mac';
        } elseif (preg_match('/windows|win32/i', $u_agent)) {
            $platform = 'windows';
        }

     
        // Next get the name of the useragent yes seperately and for good reason
        if (preg_match('/MSIE/i', $u_agent) && !preg_match('/Opera/i', $u_agent)) {
            $bname = 'Internet Explorer';
            $ub = "MSIE";
        } elseif (preg_match('/Firefox/i', $u_agent)) {
            $bname = 'Mozilla Firefox';
            $ub = "Firefox";
        } elseif (preg_match('/OPR/i', $u_agent)) {
            $bname = 'Opera';
            $ub = "Opera";
        } elseif (preg_match('/Chrome/i', $u_agent) && !preg_match('/Edge/i', $u_agent)) {
            $bname = 'Google Chrome';
            $ub = "Chrome";
        } elseif (preg_match('/Safari/i', $u_agent) && !preg_match('/Edge/i', $u_agent)) {
            $bname = 'Apple Safari';
            $ub = "Safari";
        } elseif (preg_match('/Netscape/i', $u_agent)) {
            $bname = 'Netscape';
            $ub = "Netscape";
        } elseif (preg_match('/Edge/i', $u_agent)) {
            $bname = 'Edge';
            $ub = "Edge";
        } elseif (preg_match('/Trident/i', $u_agent)) {
            $bname = 'Internet Explorer';
            $ub = "MSIE";
        }

        // finally get the correct version number
        $known = array('Version', $ub??"0", 'other');
        $pattern = '#(?<browser>' . join('|', $known) .
            ')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
        if (!preg_match_all($pattern, $u_agent, $matches)) {
            // we have no matching number just continue
        }
        // see how many we have
        $i = count($matches['browser']);
        if ($i != 1) {
            //we will have two since we are not using 'other' argument yet
            //see if version is before or after the name
            if (strripos($u_agent, "Version") < strripos($u_agent, $ub)) {
                $version = $matches['version'][0];
            } else {
                $version = $matches['version'][1];
            }
        } else {
            $version = $matches['version'][0];
        }

        // check if we have a number
        if ($version == null || $version == "") {
            $version = "?";
        }

        return (object)[
            'userAgent' => $u_agent,
            'name'      => $bname,
            'version'   => $version,
            'platform'  => $platform,
            'pattern'    => $pattern
        ];
    }

}


有上面的trait之後,我就可以知道用戶是用手機開View還是Desktop開囉。

以下也是我簡化後的版本
一、ViewServiceProvider使用App\Ccc\Traits\Browser。

use App\Ccc\Traits\Browser;


二、把檢測結果傳到$view上面

$view->with([
    "is_mobile"=>$this->isMobile()
]);


三、所以完整的ViewServiceProvider的全貌大概如下。

用指令建這個ViewServiceProvider檔案:

php artisan make:provider ViewServiceProvider

另外要在config/app.php中的providers陣列註冊這個Provider

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
        App\Providers\ViewServiceProvider::class,

 

<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
use App\Ccc\Traits\Browser;

class ViewServiceProvider extends ServiceProvider
{
    public $locale;
    use Browser;
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        View::composer('*', function ($view) {
        
           $view->with([
                "is_mobile"=>$this->isMobile()
            ]);
            
        });
    }
}

上面的'*' 應該用猜都猜的出來代表所有view不需解釋了。

所以任何view,當然包含了我的livewire元件,anywhere使用$is_mobile都不是問題,非常方便控制是Mobile用還Desktop用。

例如: 下方的Livewire元件中,手機的分頁我就讓他用小小的手機專用分頁。

<div class="root">
   <label class="d-none">{{ $this->getName() }}</label>
   {{-- 顯示手機版專用分頁 --}}
   @if($is_mobile)
   {{ $contents->links('livewire.mobile-pages') }}
   @endif
   <div class="row">
       @foreach ($contents as $content)
           @if ($loop->first&&!$is_mobile)
               <div class="col-md-12">

Tags: laravel trait php

Devin Yang

文章內容無法一一說明,如果您有什麼不了解處,歡迎提問哦:)

No Comment

Post your comment

需要登入才可留言!

類似的文章


php

Apache移除了Authorization Header問題

Apache移除了Authorization Header,在$_SERVER中看不到解法。

laravel,Laravel security

Laravel除錯模式鎖IP

Laravel的除錯模式相當豐富,Laravel官網有提醒,在本地端開發可設定APP_DEBUG為true,但是在產品環境,這個值必需永遠都是False。

docker,laravel

用Docker建立Lravel開發環境超簡單

Laravel 5.5系統環境您準備好了嗎? laravel/framework 5.5.x-dev requires php &gt;=7.0 -&gt; your PHP version (5.6.30) does not satisfy that requirement. 這篇文章描述如何使用Docker創建Laravel的開發環境。 有了簡單到爆炸的D-Laravel簡易bash, 不要在說我無法建立Laravel的開發環境了。