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