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

需要登入才可留言!

类似文章


dlaravel

如何在host直接运行容器内,不同Project的php artisan.

本篇为D-Laravel的运用教程,如何在主机端直接运行container内的php artisan. 自定义别名后,就能直接在host端的project数据夹内,直接运行contianer内的php artisan了。 alias a="../../artisan.sh"

dlaravel

使用D-Laravel build自己专用的php fpm image。

D-Laravel已提供了Build好的php image,如果需要自己调整及Build自己专用的Image相当简单。 一、首先在D-Laravel的录中,进入dockerfiles/fpm,选择您要Build的PHP版本,例如7.2。 命令如下...

docker,phpenv

在Linux上ping不到host.docker.internal

可用docker version检查,确认版本在Docker v20.10+即可添加extra_hosts如下: