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">
No Comment
Post your comment