同步更新

This commit is contained in:
2026-01-13 17:27:32 +08:00
parent 45785dd33f
commit 5d6e2fc5e0
38 changed files with 1211 additions and 305 deletions

View File

@@ -0,0 +1,243 @@
<?php
declare (strict_types=1);
namespace think\traits;
/**
* 域名处理 trait
*/
trait DomainHandler
{
/**
* 域名(含协议及端口)
* @var string
*/
protected $domain;
/**
* 域名根
* @var string
*/
protected $rootDomain = '';
/**
* 子域名
* @var string
*/
protected $subDomain = '';
/**
* 泛域名
* @var string
*/
protected $panDomain = '';
/**
* 特殊域名根标识 用于识别com.cn org.cn 这种
* @var array
*/
protected $domainSpecialSuffix = ['com', 'net', 'org', 'edu', 'gov', 'mil', 'co', 'info'];
/**
* 设置当前域名
* @access public
* @param string $domain 域名
* @return $this
*/
public function setDomain(string $domain)
{
$this->domain = $domain;
return $this;
}
/**
* 获取当前域名
* @access public
* @param bool $port 是否需要包含端口
* @return string
*/
public function domain(bool $port = false): string
{
if (!$this->domain) {
$this->domain = $this->scheme() . '://' . $this->host();
}
return $port ? $this->domain : rtrim($this->domain, ':');
}
/**
* 设置域名根
* @access public
* @param string $domain 域名根
* @return $this
*/
public function setRootDomain(string $domain)
{
$this->rootDomain = $domain;
return $this;
}
/**
* 获取域名根
* @access public
* @return string
*/
public function rootDomain(): string
{
if (!$this->rootDomain) {
$item = explode('.', $this->host());
$count = count($item);
$suffix = $this->config('app.domain_suffix');
if ($suffix && in_array($item[$count - 2], $this->domainSpecialSuffix)) {
$this->rootDomain = $item[$count - 3] . '.' . $item[$count - 2] . '.' . $item[$count - 1];
} elseif ($suffix) {
$this->rootDomain = $item[$count - 2] . '.' . $item[$count - 1];
} else {
$this->rootDomain = $item[$count - 2] . '.' . $item[$count - 1];
}
}
return $this->rootDomain;
}
/**
* 设置子域名
* @access public
* @param string $domain 子域名
* @return $this
*/
public function setSubDomain(string $domain)
{
$this->subDomain = $domain;
return $this;
}
/**
* 获取子域名
* @access public
* @return string
*/
public function subDomain(): string
{
if (!$this->subDomain) {
if ($this->isCli()) {
return '';
}
$rootDomain = $this->rootDomain();
if ($rootDomain) {
$this->subDomain = rtrim(strstr($this->host(), $rootDomain, true), '.');
} else {
$this->subDomain = '';
}
}
return $this->subDomain;
}
/**
* 设置泛域名
* @access public
* @param string $domain 泛域名
* @return $this
*/
public function setPanDomain(string $domain)
{
$this->panDomain = $domain;
return $this;
}
/**
* 获取泛域名
* @access public
* @return string
*/
public function panDomain(): string
{
if (!$this->panDomain) {
if ($this->isCli()) {
return '';
}
$rootDomain = $this->rootDomain();
if ($rootDomain) {
$this->panDomain = '*' . $rootDomain;
} else {
$this->panDomain = '';
}
}
return $this->panDomain;
}
/**
* 获取当前HOST
* @access public
* @param bool $strict 是否严格模式
* @return string
*/
public function host(bool $strict = true): string
{
if ($this->server('HTTP_X_FORWARDED_HOST')) {
$host = $this->server('HTTP_X_FORWARDED_HOST');
} elseif ($this->server('HTTP_HOST')) {
$host = $this->server('HTTP_HOST');
} else {
$host = $this->server('SERVER_NAME') . ($this->server('SERVER_PORT') == '80' ? '' : ':' . $this->server('SERVER_PORT'));
}
return true === $strict && strpos($host, ':') ? strstr($host, ':', true) : $host;
}
/**
* 获取当前请求的协议
* @access public
* @return string
*/
public function scheme(): string
{
return $this->isSsl() ? 'https' : 'http';
}
/**
* 当前是否SSL
* @access public
* @return bool
*/
public function isSsl(): bool
{
if ($this->server('HTTPS') && ('1' == $this->server('HTTPS') || 'on' == strtolower($this->server('HTTPS')))) {
return true;
} elseif ('https' == $this->server('REQUEST_SCHEME')) {
return true;
} elseif ('443' == $this->server('SERVER_PORT')) {
return true;
} elseif ('https' == $this->server('HTTP_X_FORWARDED_PROTO')) {
return true;
}
return false;
}
/**
* 获取当前请求的端口
* @access public
* @return int
*/
public function port(): int
{
return $this->server('SERVER_PORT') ?? 80;
}
/**
* 获取当前请求的远程端口
* @access public
* @return int
*/
public function remotePort(): int
{
return $this->server('REMOTE_PORT') ?? 0;
}
}

View File

@@ -0,0 +1,213 @@
<?php
declare (strict_types=1);
namespace think\traits;
/**
* HTTP方法处理 trait
*/
trait HttpMethodHandler
{
/**
* 请求类型
* @var string
*/
protected $varMethod = '_method';
/**
* 表单ajax伪装变量
* @var string
*/
protected $varAjax = '_ajax';
/**
* 表单pjax伪装变量
* @var string
*/
protected $varPjax = '_pjax';
/**
* 请求类型
* @var string
*/
protected $method;
/**
* 获取请求类型
* @access public
* @param bool $origin 是否获取原始请求类型
* @return string
*/
public function method(bool $origin = false): string
{
if ($origin) {
return $this->server('REQUEST_METHOD') ?: 'GET';
} elseif (!$this->method) {
if (isset($_POST[$this->varMethod])) {
$this->method = strtoupper($_POST[$this->varMethod]);
$this->{$this->method}($_POST);
} elseif ($this->server('HTTP_X_HTTP_METHOD_OVERRIDE')) {
$this->method = $this->server('HTTP_X_HTTP_METHOD_OVERRIDE');
} else {
$this->method = $this->server('REQUEST_METHOD') ?: 'GET';
}
}
return $this->method;
}
/**
* 是否为GET请求
* @access public
* @return bool
*/
public function isGet(): bool
{
return $this->method() == 'GET';
}
/**
* 是否为POST请求
* @access public
* @return bool
*/
public function isPost(): bool
{
return $this->method() == 'POST';
}
/**
* 是否为PUT请求
* @access public
* @return bool
*/
public function isPut(): bool
{
return $this->method() == 'PUT';
}
/**
* 是否为DELTE请求
* @access public
* @return bool
*/
public function isDelete(): bool
{
return $this->method() == 'DELETE';
}
/**
* 是否为HEAD请求
* @access public
* @return bool
*/
public function isHead(): bool
{
return $this->method() == 'HEAD';
}
/**
* 是否为PATCH请求
* @access public
* @return bool
*/
public function isPatch(): bool
{
return $this->method() == 'PATCH';
}
/**
* 是否为OPTIONS请求
* @access public
* @return bool
*/
public function isOptions(): bool
{
return $this->method() == 'OPTIONS';
}
/**
* 是否为CLI
* @access public
* @return bool
*/
public function isCli(): bool
{
return PHP_SAPI == 'cli';
}
/**
* 是否为CGI
* @access public
* @return bool
*/
public function isCgi(): bool
{
return str_starts_with(PHP_SAPI, 'cgi');
}
/**
* 是否为ajax请求
* @access public
* @param bool $ajax true 获取原始ajax请求
* @return bool
*/
public function isAjax(bool $ajax = false): bool
{
$result = $this->server('HTTP_X_REQUESTED_WITH', '', 'strtolower') === 'xmlhttprequest';
if (true === $ajax) {
return $result;
}
return $this->param($this->varAjax) ? true : $result;
}
/**
* 是否为pjax请求
* @access public
* @param bool $pjax true 获取原始pjax请求
* @return bool
*/
public function isPjax(bool $pjax = false): bool
{
$result = !empty($this->server('HTTP_X_PJAX'));
if (true === $pjax) {
return $result;
}
return $this->param($this->varPjax) ? true : $result;
}
/**
* 是否为JSON请求
* @access public
* @return bool
*/
public function isJson(): bool
{
return false !== strpos($this->type(), 'json');
}
/**
* 是否为手机访问
* @access public
* @return bool
*/
public function isMobile(): bool
{
if ($this->server('HTTP_VIA') && stristr($this->server('HTTP_VIA'), 'wap')) {
return true;
} elseif ($this->server('HTTP_ACCEPT') && strpos(strtoupper($this->server('HTTP_ACCEPT')), 'VND.WAP.WML')) {
return true;
} elseif ($this->server('HTTP_X_WAP_PROFILE') || $this->server('HTTP_PROFILE')) {
return true;
} elseif ($this->server('HTTP_USER_AGENT') && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc-|htc_|htc-|iemobile|kindle|midp|mmp|mobile|novarra|o2 |opera mini|opera mobi|palm|palmos|pocket|portalmmm|proxynet|sharp-|sharp t-mobile|sonyericsson |sonyericsson|symbian|symbianos|up.browser|up.link|vodafone|wap |webos|windows ce|windows phone|xda |xda_)/i', $this->server('HTTP_USER_AGENT'))) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,233 @@
<?php
declare (strict_types=1);
namespace think\traits;
/**
* URL处理 trait
*/
trait UrlHandler
{
/**
* 当前URL地址
* @var string
*/
protected $url;
/**
* 当前URL地址 不含QUERY_STRING
* @var string
*/
protected $baseUrl;
/**
* 当前执行的文件 SCRIPT_NAME
* @var string
*/
protected $baseFile;
/**
* URL访问根地址
* @var string
*/
protected $root;
/**
* 设置当前请求的URL
* @access public
* @param string $url URL地址
* @return $this
*/
public function setUrl(string $url)
{
$this->url = $url;
return $this;
}
/**
* 获取当前请求URL
* @access public
* @param bool $complete 是否包含完整域名
* @return string
*/
public function url(bool $complete = false): string
{
if ($this->url) {
$url = $this->url;
} elseif ($this->server('HTTP_X_REWRITE_URL')) {
$url = $this->server('HTTP_X_REWRITE_URL');
} elseif ($this->server('REQUEST_URI')) {
$url = $this->server('REQUEST_URI');
} elseif ($this->server('ORIG_PATH_INFO')) {
$url = $this->server('ORIG_PATH_INFO') . (!empty($this->server('QUERY_STRING')) ? '?' . $this->server('QUERY_STRING') : '');
} elseif (isset($_SERVER['argv'][1])) {
$url = $_SERVER['argv'][1];
} else {
$url = '';
}
return $complete ? $this->domain() . $url : $url;
}
/**
* 设置当前URL 不含QUERY_STRING
* @access public
* @param string $url URL地址
* @return $this
*/
public function setBaseUrl(string $url)
{
$this->baseUrl = $url;
return $this;
}
/**
* 获取当前URL 不含QUERY_STRING
* @access public
* @param bool $complete 是否包含完整域名
* @return string
*/
public function baseUrl(bool $complete = false): string
{
if (!$this->baseUrl) {
$str = $this->url();
$this->baseUrl = str_contains($str, '?') ? strstr($str, '?', true) : $str;
}
return $complete ? $this->domain() . $this->baseUrl : $this->baseUrl;
}
/**
* 获取当前执行的文件 SCRIPT_NAME
* @access public
* @param bool $complete 是否包含完整域名
* @return string
*/
public function baseFile(bool $complete = false): string
{
if (!$this->baseFile) {
$url = '';
if (!$this->isCli()) {
$script_name = basename($this->server('SCRIPT_FILENAME'));
if (basename($this->server('SCRIPT_NAME')) === $script_name) {
$url = $this->server('SCRIPT_NAME');
} elseif (basename($this->server('PHP_SELF')) === $script_name) {
$url = $this->server('PHP_SELF');
} elseif (basename($this->server('ORIG_SCRIPT_NAME')) === $script_name) {
$url = $this->server('ORIG_SCRIPT_NAME');
} elseif (($pos = strpos($this->server('PHP_SELF'), '/' . $script_name)) !== false) {
$url = substr($this->server('SCRIPT_NAME'), 0, $pos) . '/' . $script_name;
} elseif ($this->server('DOCUMENT_ROOT') && str_starts_with($this->server('SCRIPT_FILENAME'), $this->server('DOCUMENT_ROOT'))) {
$url = str_replace('\\', '/', str_replace($this->server('DOCUMENT_ROOT'), '', $this->server('SCRIPT_FILENAME')));
}
}
$this->baseFile = $url;
}
return $complete ? $this->domain() . $this->baseFile : $this->baseFile;
}
/**
* 设置URL访问根地址
* @access public
* @param string $url URL地址
* @return $this
*/
public function setRoot(string $url)
{
$this->root = $url;
return $this;
}
/**
* 获取URL访问根地址
* @access public
* @param bool $complete 是否包含完整域名
* @return string
*/
public function root(bool $complete = false): string
{
if (!$this->root) {
$file = $this->baseFile();
if ($file && !str_starts_with($this->url(), $file)) {
$file = str_replace('\\', '/', dirname($file));
}
$this->root = rtrim($file, '/');
}
return $complete ? $this->domain() . $this->root : $this->root;
}
/**
* 获取URL访问根地址
* @access public
* @return string
*/
public function rootUrl(): string
{
$base = $this->root();
$root = '' === $base ? dirname($this->baseUrl()) : $base;
return $root;
}
/**
* 获取当前请求URL的pathinfo信息含URL后缀
* @access public
* @return string
*/
public function pathinfo(): string
{
if (isset($_SERVER['PATH_INFO'])) {
return ltrim($_SERVER['PATH_INFO'], '/');
}
$url = $this->url();
$base = $this->rootUrl();
if ($base && str_starts_with($url, $base)) {
$url = substr($url, strlen($base));
}
return ltrim($url, '/');
}
/**
* 获取当前请求URL的pathinfo信息(不含URL后缀)
* @access public
* @return string
*/
public function path(): string
{
$pathinfo = $this->pathinfo();
$suffix = $this->config('url_html_suffix');
if (false === $suffix) {
return $pathinfo;
}
return preg_replace('/\.(' . $suffix . ')$/i', '', $pathinfo);
}
/**
* 获取URL后缀
* @access public
* @return string
*/
public function ext(): string
{
return pathinfo($this->pathinfo(), PATHINFO_EXTENSION);
}
/**
* 获取当前请求的时间
* @access public
* @param bool $float 是否使用浮点数
* @return float|int
*/
public function time(bool $float = false)
{
return $float ? $_SERVER['REQUEST_TIME_FLOAT'] : $_SERVER['REQUEST_TIME'];
}
}