mirror of https://github.com/1099438829/apeblog
提交更新,待完善邮件发送
This commit is contained in:
parent
0c450018f0
commit
1c766e107a
|
|
@ -6,31 +6,6 @@ use think\db\exception\DataNotFoundException;
|
|||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
|
||||
// 应用公共文件
|
||||
if (!function_exists('system_config_more')) {
|
||||
/**
|
||||
* 获取系统配置值
|
||||
* @param array $formNames
|
||||
* @return array
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
function system_config_more(array $formNames): array
|
||||
{
|
||||
$systemConfig = cache(Data::DATA_SYSTEM_CONFIG);
|
||||
if (empty($systemConfig)) {
|
||||
$systemConfig = SystemConfig::getSystemConfigValues();
|
||||
cache(Data::DATA_SYSTEM_CONFIG, $systemConfig);
|
||||
}
|
||||
$data = [];
|
||||
foreach ($formNames as $v) {
|
||||
$data[$v] = $systemConfig[$v] ?? '';
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('param_to_array')) {
|
||||
/**
|
||||
* 参数分割成数组
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
namespace app\common\extend;
|
||||
/**
|
||||
* @author 李玉坤
|
||||
* @date 2022-01-22 1:29
|
||||
*/
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
class Mail
|
||||
{
|
||||
public function sendMail($to)
|
||||
{
|
||||
|
||||
|
||||
$toemail = 'xxx';//定义收件人的邮箱
|
||||
|
||||
$mail = new PHPMailer();
|
||||
|
||||
$mail->isSMTP();// 使用SMTP服务
|
||||
$mail->CharSet = "utf8";// 编码格式为utf8,不设置编码的话,中文会出现乱码
|
||||
$mail->Host = "smtp.qq.com";// 发送方的SMTP服务器地址
|
||||
$mail->SMTPAuth = true;// 是否使用身份验证
|
||||
$mail->Username = "xxx";// 发送方的163邮箱用户名,就是你申请163的SMTP服务使用的163邮箱</span><span style="color:#333333;">
|
||||
$mail->Password = "这里填写授权码不要填qq密码";// 发送方的邮箱密码,注意用163邮箱这里填写的是“客户端授权密码”而不是邮箱的登录密码!</span><span style="color:#333333;">
|
||||
$mail->SMTPSecure = "ssl";// 使用ssl协议方式</span><span style="color:#333333;">
|
||||
$mail->Port = 465;// 163邮箱的ssl协议方式端口号是465/994
|
||||
|
||||
$mail->setFrom("xxx","Mailer");// 设置发件人信息,如邮件格式说明中的发件人,这里会显示为Mailer(xxxx@163.com),Mailer是当做名字显示
|
||||
$mail->addAddress($toemail,'Wang');// 设置收件人信息,如邮件格式说明中的收件人,这里会显示为Liang(yyyy@163.com)
|
||||
$mail->addReplyTo("xxx","Reply");// 设置回复人信息,指的是收件人收到邮件后,如果要回复,回复邮件将发送到的邮箱地址
|
||||
//$mail->addCC("xxx@163.com");// 设置邮件抄送人,可以只写地址,上述的设置也可以只写地址(这个人也能收到邮件)
|
||||
//$mail->addBCC("xxx@163.com");// 设置秘密抄送人(这个人也能收到邮件)
|
||||
//$mail->addAttachment("bug0.jpg");// 添加附件
|
||||
|
||||
|
||||
$mail->Subject = "这是一个测试邮件";// 邮件标题
|
||||
$mail->Body = "邮件内容是 <b>您的验证码是:123456</b>,哈哈哈!";// 邮件正文
|
||||
//$mail->AltBody = "This is the plain text纯文本";// 这个是设置纯文本方式显示的正文内容,如果不支持Html方式,就会用到这个,基本无用
|
||||
|
||||
if(!$mail->send()){// 发送邮件
|
||||
echo "Message could not be sent.";
|
||||
echo "Mailer Error: ".$mail->ErrorInfo;// 输出错误信息
|
||||
}else{
|
||||
echo '发送成功';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -68,8 +68,8 @@ class User extends BaseModel
|
|||
if (!$res) {
|
||||
return self::setErrorInfo("账号注册失败,请稍后再试");
|
||||
} else {
|
||||
$info = self::where('id', "=", $res)->find();
|
||||
return self::setLoginInfo($info);
|
||||
//开始发送激活邮件,激活邮件处理
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class Login extends Base
|
|||
if (!captcha_check($captcha)) return app("json")->fail("验证码不正确!");
|
||||
// 验证登录
|
||||
if (!userModel::register($username,$email, $password)) return app("json")->fail(userModel::getErrorInfo());
|
||||
return app("json")->success("登录成功!");
|
||||
return app("json")->success("注册成功!我们给您邮箱发送了一封激活邮件,请按照邮件提示激活用户");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
"topthink/think-multi-app": "^1.0",
|
||||
"xaboy/form-builder": "^2.0",
|
||||
"topthink/think-captcha": "^3.0",
|
||||
"phpmailer/phpmailer": "^6.1",
|
||||
"phpmailer/phpmailer": "^6.5",
|
||||
"spatie/macroable": "^1.0",
|
||||
"topthink/think-view": "^1.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -124,16 +124,13 @@
|
|||
<ul class="user-menu">
|
||||
<li>
|
||||
<a class="user-menu-main">
|
||||
<img class="user-avatar" width="30" height="30" src="{$user_info.avatar}" data-pagespeed-url-hash="801193799">
|
||||
<img class="user-avatar" width="30" height="30" src="{$user_info.avatar}" onerror="javascript:this.src='__IMG__/avatar.png';">
|
||||
<span class="user-menu-name">{$user_info.username}</span>
|
||||
</a>
|
||||
<ul class="user-sub-menu sub-menu">
|
||||
<li>
|
||||
<a href="{:url('index/login/profile')}"><i class="fas fa-user-cog"></i> 账号设置</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{:url('index/login/pwd')}"><i class="fas fa-user-cog"></i> 修改密码</a>
|
||||
</li>
|
||||
<!-- <li>-->
|
||||
<!-- <a href="{:url('index/login/loginout')}"><i class="far fa-edit"></i>新建文章</a>-->
|
||||
<!-- </li>-->
|
||||
|
|
|
|||
|
|
@ -83,17 +83,17 @@
|
|||
},
|
||||
{
|
||||
"name": "doctrine/lexer",
|
||||
"version": "1.2.1",
|
||||
"version_normalized": "1.2.1.0",
|
||||
"version": "1.2.2",
|
||||
"version_normalized": "1.2.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/lexer.git",
|
||||
"reference": "e864bbf5904cb8f5bb334f99209b48018522f042"
|
||||
"reference": "9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042",
|
||||
"reference": "e864bbf5904cb8f5bb334f99209b48018522f042",
|
||||
"url": "https://api.github.com/repos/doctrine/lexer/zipball/9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c",
|
||||
"reference": "9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
|
|
@ -103,20 +103,16 @@
|
|||
]
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^6.0",
|
||||
"phpstan/phpstan": "^0.11.8",
|
||||
"phpunit/phpunit": "^8.2"
|
||||
"doctrine/coding-standard": "^9.0",
|
||||
"phpstan/phpstan": "1.3",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"vimeo/psalm": "^4.11"
|
||||
},
|
||||
"time": "2020-05-25T17:44:05+00:00",
|
||||
"time": "2022-01-12T08:27:12+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.2.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
@ -152,7 +148,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/lexer/issues",
|
||||
"source": "https://github.com/doctrine/lexer/tree/1.2.1"
|
||||
"source": "https://github.com/doctrine/lexer/tree/1.2.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -1000,17 +996,17 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.23.1",
|
||||
"version_normalized": "1.23.1.0",
|
||||
"version": "v1.24.0",
|
||||
"version_normalized": "1.24.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
|
||||
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
|
|
@ -1022,10 +1018,13 @@
|
|||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"provide": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"time": "2021-05-27T12:26:48+00:00",
|
||||
"time": "2021-11-30T18:21:41+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
|
@ -1069,7 +1068,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.24.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -1089,8 +1088,8 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.23.0",
|
||||
"version_normalized": "1.23.0.0",
|
||||
"version": "v1.24.0",
|
||||
"version_normalized": "1.24.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
|
|
@ -1154,7 +1153,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0"
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.24.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -1174,17 +1173,17 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.23.1",
|
||||
"version_normalized": "1.23.1.0",
|
||||
"version": "v1.24.0",
|
||||
"version_normalized": "1.24.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
|
||||
"reference": "57b712b08eddb97c762a8caa32c84e037892d2e9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
|
||||
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9",
|
||||
"reference": "57b712b08eddb97c762a8caa32c84e037892d2e9",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
|
|
@ -1196,7 +1195,7 @@
|
|||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"time": "2021-07-28T13:41:28+00:00",
|
||||
"time": "2021-09-13T13:58:33+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
|
@ -1246,7 +1245,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -1364,17 +1363,17 @@
|
|||
},
|
||||
{
|
||||
"name": "topthink/framework",
|
||||
"version": "v6.0.10",
|
||||
"version_normalized": "6.0.10.0",
|
||||
"version": "v6.0.12",
|
||||
"version_normalized": "6.0.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/framework.git",
|
||||
"reference": "d9cadb6971ae92ff85ba5f2be77a40b0ad5718fb"
|
||||
"reference": "e478316ac843c1a884a3b3a7a94db17c4001ff5c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/framework/zipball/d9cadb6971ae92ff85ba5f2be77a40b0ad5718fb",
|
||||
"reference": "d9cadb6971ae92ff85ba5f2be77a40b0ad5718fb",
|
||||
"url": "https://api.github.com/repos/top-think/framework/zipball/e478316ac843c1a884a3b3a7a94db17c4001ff5c",
|
||||
"reference": "e478316ac843c1a884a3b3a7a94db17c4001ff5c",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
|
|
@ -1402,7 +1401,7 @@
|
|||
"mockery/mockery": "^1.2",
|
||||
"phpunit/phpunit": "^7.0"
|
||||
},
|
||||
"time": "2021-12-31T09:14:28+00:00",
|
||||
"time": "2022-01-21T06:31:07+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
|
|
@ -1434,7 +1433,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/framework/issues",
|
||||
"source": "https://github.com/top-think/framework/tree/v6.0.10"
|
||||
"source": "https://github.com/top-think/framework/tree/v6.0.12"
|
||||
},
|
||||
"install-path": "../topthink/framework"
|
||||
},
|
||||
|
|
@ -1614,17 +1613,17 @@
|
|||
},
|
||||
{
|
||||
"name": "topthink/think-orm",
|
||||
"version": "v2.0.47",
|
||||
"version_normalized": "2.0.47.0",
|
||||
"version": "v2.0.51",
|
||||
"version_normalized": "2.0.51.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-orm.git",
|
||||
"reference": "e69151fba9dd21f86e392a0ae208825904d6d49a"
|
||||
"reference": "149d266acdc4b2f07c6a94f1733b6b97d340e0e2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-orm/zipball/e69151fba9dd21f86e392a0ae208825904d6d49a",
|
||||
"reference": "e69151fba9dd21f86e392a0ae208825904d6d49a",
|
||||
"url": "https://api.github.com/repos/top-think/think-orm/zipball/149d266acdc4b2f07c6a94f1733b6b97d340e0e2",
|
||||
"reference": "149d266acdc4b2f07c6a94f1733b6b97d340e0e2",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
|
|
@ -1644,7 +1643,7 @@
|
|||
"require-dev": {
|
||||
"phpunit/phpunit": "^7|^8|^9.5"
|
||||
},
|
||||
"time": "2021-12-31T06:12:13+00:00",
|
||||
"time": "2022-01-21T06:25:25+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
|
|
@ -1672,7 +1671,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/think-orm/issues",
|
||||
"source": "https://github.com/top-think/think-orm/tree/v2.0.47"
|
||||
"source": "https://github.com/top-think/think-orm/tree/v2.0.51"
|
||||
},
|
||||
"install-path": "../topthink/think-orm"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => 'ae98df79618898655c1e41dedd3b193518617109',
|
||||
'reference' => '0c450018f0159a262d26966718fc8891dd645cf3',
|
||||
'name' => 'topthink/think',
|
||||
'dev' => true,
|
||||
),
|
||||
|
|
@ -20,12 +20,12 @@
|
|||
'dev_requirement' => false,
|
||||
),
|
||||
'doctrine/lexer' => array(
|
||||
'pretty_version' => '1.2.1',
|
||||
'version' => '1.2.1.0',
|
||||
'pretty_version' => '1.2.2',
|
||||
'version' => '1.2.2.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../doctrine/lexer',
|
||||
'aliases' => array(),
|
||||
'reference' => 'e864bbf5904cb8f5bb334f99209b48018522f042',
|
||||
'reference' => '9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'league/flysystem' => array(
|
||||
|
|
@ -137,17 +137,17 @@
|
|||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => 'v1.23.1',
|
||||
'version' => '1.23.1.0',
|
||||
'pretty_version' => 'v1.24.0',
|
||||
'version' => '1.24.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'reference' => '9174a3d80210dca8daa7f31fec659150bbeabfc6',
|
||||
'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php72' => array(
|
||||
'pretty_version' => 'v1.23.0',
|
||||
'version' => '1.23.0.0',
|
||||
'pretty_version' => 'v1.24.0',
|
||||
'version' => '1.24.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php72',
|
||||
'aliases' => array(),
|
||||
|
|
@ -155,12 +155,12 @@
|
|||
'dev_requirement' => true,
|
||||
),
|
||||
'symfony/polyfill-php80' => array(
|
||||
'pretty_version' => 'v1.23.1',
|
||||
'version' => '1.23.1.0',
|
||||
'pretty_version' => 'v1.24.0',
|
||||
'version' => '1.24.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||
'aliases' => array(),
|
||||
'reference' => '1100343ed1a92e3a38f9ae122fc0eb21602547be',
|
||||
'reference' => '57b712b08eddb97c762a8caa32c84e037892d2e9',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/var-dumper' => array(
|
||||
|
|
@ -173,12 +173,12 @@
|
|||
'dev_requirement' => true,
|
||||
),
|
||||
'topthink/framework' => array(
|
||||
'pretty_version' => 'v6.0.10',
|
||||
'version' => '6.0.10.0',
|
||||
'pretty_version' => 'v6.0.12',
|
||||
'version' => '6.0.12.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/framework',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd9cadb6971ae92ff85ba5f2be77a40b0ad5718fb',
|
||||
'reference' => 'e478316ac843c1a884a3b3a7a94db17c4001ff5c',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think' => array(
|
||||
|
|
@ -187,7 +187,7 @@
|
|||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => 'ae98df79618898655c1e41dedd3b193518617109',
|
||||
'reference' => '0c450018f0159a262d26966718fc8891dd645cf3',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-captcha' => array(
|
||||
|
|
@ -218,12 +218,12 @@
|
|||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-orm' => array(
|
||||
'pretty_version' => 'v2.0.47',
|
||||
'version' => '2.0.47.0',
|
||||
'pretty_version' => 'v2.0.51',
|
||||
'version' => '2.0.51.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/think-orm',
|
||||
'aliases' => array(),
|
||||
'reference' => 'e69151fba9dd21f86e392a0ae208825904d6d49a',
|
||||
'reference' => '149d266acdc4b2f07c6a94f1733b6b97d340e0e2',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-template' => array(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Doctrine Lexer
|
||||
|
||||
Build Status: [](https://travis-ci.org/doctrine/lexer)
|
||||
[](https://github.com/doctrine/lexer/actions)
|
||||
|
||||
Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.
|
||||
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@
|
|||
{"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^6.0",
|
||||
"phpstan/phpstan": "^0.11.8",
|
||||
"phpunit/phpunit": "^8.2"
|
||||
"doctrine/coding-standard": "^9.0",
|
||||
"phpstan/phpstan": "1.3",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"vimeo/psalm": "^4.11"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" }
|
||||
|
|
@ -30,12 +31,11 @@
|
|||
"autoload-dev": {
|
||||
"psr-4": { "Doctrine\\Tests\\": "tests/Doctrine" }
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.2.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
},
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,17 @@ declare(strict_types=1);
|
|||
namespace Doctrine\Common\Lexer;
|
||||
|
||||
use ReflectionClass;
|
||||
use const PREG_SPLIT_DELIM_CAPTURE;
|
||||
use const PREG_SPLIT_NO_EMPTY;
|
||||
use const PREG_SPLIT_OFFSET_CAPTURE;
|
||||
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function preg_split;
|
||||
use function sprintf;
|
||||
use function substr;
|
||||
|
||||
use const PREG_SPLIT_DELIM_CAPTURE;
|
||||
use const PREG_SPLIT_NO_EMPTY;
|
||||
use const PREG_SPLIT_OFFSET_CAPTURE;
|
||||
|
||||
/**
|
||||
* Base class for writing simple lexers, i.e. for creating small DSLs.
|
||||
*/
|
||||
|
|
@ -35,7 +37,8 @@ abstract class AbstractLexer
|
|||
* parameter, none)
|
||||
* - 'position' : the position of the token in the input string
|
||||
*
|
||||
* @var array
|
||||
* @var mixed[][]
|
||||
* @psalm-var list<array{value: string, type: string|int|null, position: int}>
|
||||
*/
|
||||
private $tokens = [];
|
||||
|
||||
|
|
@ -56,21 +59,23 @@ abstract class AbstractLexer
|
|||
/**
|
||||
* The next token in the input.
|
||||
*
|
||||
* @var array|null
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{value: string, type: string|int|null, position: int}|null
|
||||
*/
|
||||
public $lookahead;
|
||||
|
||||
/**
|
||||
* The last matched/seen token.
|
||||
*
|
||||
* @var array|null
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{value: string, type: string|int|null, position: int}|null
|
||||
*/
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* Composed regex for input parsing.
|
||||
*
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
private $regex;
|
||||
|
||||
|
|
@ -155,7 +160,7 @@ abstract class AbstractLexer
|
|||
/**
|
||||
* Checks whether any of the given tokens matches the current lookahead.
|
||||
*
|
||||
* @param array $tokens
|
||||
* @param string[] $tokens
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
|
@ -209,7 +214,8 @@ abstract class AbstractLexer
|
|||
/**
|
||||
* Moves the lookahead token forward.
|
||||
*
|
||||
* @return array|null The next token or NULL if there are no more tokens ahead.
|
||||
* @return mixed[]|null The next token or NULL if there are no more tokens ahead.
|
||||
* @psalm-return array{value: string, type: string|int|null, position: int}|null
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
|
|
@ -223,7 +229,8 @@ abstract class AbstractLexer
|
|||
/**
|
||||
* Peeks at the next token, returns it and immediately resets the peek.
|
||||
*
|
||||
* @return array|null The next token or NULL if there are no more tokens ahead.
|
||||
* @return mixed[]|null The next token or NULL if there are no more tokens ahead.
|
||||
* @psalm-return array{value: string, type: string|int|null, position: int}|null
|
||||
*/
|
||||
public function glimpse()
|
||||
{
|
||||
|
|
@ -306,14 +313,14 @@ abstract class AbstractLexer
|
|||
/**
|
||||
* Lexical catchable patterns.
|
||||
*
|
||||
* @return array
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function getCatchablePatterns();
|
||||
|
||||
/**
|
||||
* Lexical non-catchable patterns.
|
||||
*
|
||||
* @return array
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function getNonCatchablePatterns();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
errorLevel="5"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="lib/Doctrine/Common/Lexer" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
</psalm>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
// This file is automatically generated at:2022-01-03 02:16:55
|
||||
// This file is automatically generated at:2022-01-22 01:25:41
|
||||
declare (strict_types = 1);
|
||||
return array (
|
||||
0 => 'think\\captcha\\CaptchaService',
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ final class Mbstring
|
|||
|
||||
public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
|
||||
{
|
||||
if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
|
||||
if (\is_array($fromEncoding) || ($fromEncoding !== null && false !== strpos($fromEncoding, ','))) {
|
||||
$fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
|
||||
} else {
|
||||
$fromEncoding = self::getEncoding($fromEncoding);
|
||||
|
|
@ -602,6 +602,9 @@ final class Mbstring
|
|||
if (80000 > \PHP_VERSION_ID) {
|
||||
return false;
|
||||
}
|
||||
if (\is_int($c) || 'long' === $c || 'entity' === $c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"provide": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
|
||||
"files": [ "bootstrap.php" ]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
class UnhandledMatchError extends Error
|
||||
{
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
class UnhandledMatchError extends Error
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
class ValueError extends Error
|
||||
{
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
class ValueError extends Error
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ use think\initializer\RegisterService;
|
|||
*/
|
||||
class App extends Container
|
||||
{
|
||||
const VERSION = '6.0.10LTS';
|
||||
const VERSION = '6.0.12LTS';
|
||||
|
||||
/**
|
||||
* 应用调试模式
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ class Env implements ArrayAccess
|
|||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($name)
|
||||
public function offsetUnset($name): void
|
||||
{
|
||||
throw new Exception('not support: unset');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ abstract class Driver implements CacheInterface, CacheHandlerInterface
|
|||
* @param string $data 缓存数据
|
||||
* @return mixed
|
||||
*/
|
||||
protected function unserialize(string $data)
|
||||
protected function unserialize($data)
|
||||
{
|
||||
if (is_numeric($data)) {
|
||||
return $data;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace think\console\input;
|
|||
class Option
|
||||
{
|
||||
// 无需传值
|
||||
const VALUE_NONE = 1;
|
||||
const VALUE_NONE = 1;
|
||||
// 必须传值
|
||||
const VALUE_REQUIRED = 2;
|
||||
// 可选传值
|
||||
|
|
@ -30,13 +30,13 @@ class Option
|
|||
* 选项名
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
private $name = '';
|
||||
|
||||
/**
|
||||
* 选项短名称
|
||||
* @var string
|
||||
*/
|
||||
private $shortcut;
|
||||
private $shortcut = '';
|
||||
|
||||
/**
|
||||
* 选项类型
|
||||
|
|
@ -54,7 +54,7 @@ class Option
|
|||
* 选项描述
|
||||
* @var string
|
||||
*/
|
||||
private $description;
|
||||
private $description = '';
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
|
|
@ -76,10 +76,10 @@ class Option
|
|||
}
|
||||
|
||||
if (empty($shortcut)) {
|
||||
$shortcut = null;
|
||||
$shortcut = '';
|
||||
}
|
||||
|
||||
if (null !== $shortcut) {
|
||||
if ('' !== $shortcut) {
|
||||
if (is_array($shortcut)) {
|
||||
$shortcut = implode('|', $shortcut);
|
||||
}
|
||||
|
|
@ -114,7 +114,7 @@ class Option
|
|||
* 获取短名称
|
||||
* @return string
|
||||
*/
|
||||
public function getShortcut()
|
||||
public function getShortcut(): string
|
||||
{
|
||||
return $this->shortcut;
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ class Option
|
|||
* 获取选项名
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
|
@ -132,7 +132,7 @@ class Option
|
|||
* 是否可以设置值
|
||||
* @return bool 类型不是 self::VALUE_NONE 的时候返回true,其他均返回false
|
||||
*/
|
||||
public function acceptValue()
|
||||
public function acceptValue(): bool
|
||||
{
|
||||
return $this->isValueRequired() || $this->isValueOptional();
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ class Option
|
|||
* 是否必须
|
||||
* @return bool 类型是 self::VALUE_REQUIRED 的时候返回true,其他均返回false
|
||||
*/
|
||||
public function isValueRequired()
|
||||
public function isValueRequired(): bool
|
||||
{
|
||||
return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
|
||||
}
|
||||
|
|
@ -150,7 +150,7 @@ class Option
|
|||
* 是否可选
|
||||
* @return bool 类型是 self::VALUE_OPTIONAL 的时候返回true,其他均返回false
|
||||
*/
|
||||
public function isValueOptional()
|
||||
public function isValueOptional(): bool
|
||||
{
|
||||
return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ class Option
|
|||
* 选项值是否接受数组
|
||||
* @return bool 类型是 self::VALUE_IS_ARRAY 的时候返回true,其他均返回false
|
||||
*/
|
||||
public function isArray()
|
||||
public function isArray(): bool
|
||||
{
|
||||
return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
|
||||
}
|
||||
|
|
@ -199,7 +199,7 @@ class Option
|
|||
* 获取描述文字
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
|
@ -209,7 +209,7 @@ class Option
|
|||
* @param Option $option
|
||||
* @return bool
|
||||
*/
|
||||
public function equals(Option $option)
|
||||
public function equals(Option $option): bool
|
||||
{
|
||||
return $option->getName() === $this->getName()
|
||||
&& $option->getShortcut() === $this->getShortcut()
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ class Resource extends RuleGroup
|
|||
}
|
||||
|
||||
/**
|
||||
* 绑定资源模型
|
||||
* 绑定资源中间件
|
||||
* @access public
|
||||
* @param array|string $name 资源类型或者中间件定义
|
||||
* @param array|string $middleware 中间件定义
|
||||
|
|
|
|||
|
|
@ -532,6 +532,17 @@ abstract class Rule
|
|||
return $this->setOption('view', $view);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过闭包检查路由是否匹配
|
||||
* @access public
|
||||
* @param callable $match 闭包
|
||||
* @return $this
|
||||
*/
|
||||
public function match(callable $match)
|
||||
{
|
||||
return $this->setOption('match', $match);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置路由完整匹配
|
||||
* @access public
|
||||
|
|
@ -694,6 +705,13 @@ abstract class Rule
|
|||
*/
|
||||
protected function checkOption(array $option, Request $request): bool
|
||||
{
|
||||
// 检查当前路由是否匹配
|
||||
if (isset($option['match']) && is_callable($option['match'])) {
|
||||
if (false === $option['match']($this, $request)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 请求类型检测
|
||||
if (!empty($option['method'])) {
|
||||
if (is_string($option['method']) && false === stripos($option['method'], $request->method())) {
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ class RuleItem extends Rule
|
|||
$url = $this->urlSuffixCheck($request, $url, $option);
|
||||
|
||||
if (is_null($match)) {
|
||||
$match = $this->match($url, $option, $pattern, $completeMatch);
|
||||
$match = $this->checkMatch($url, $option, $pattern, $completeMatch);
|
||||
}
|
||||
|
||||
if (false !== $match) {
|
||||
|
|
@ -252,7 +252,7 @@ class RuleItem extends Rule
|
|||
* @param bool $completeMatch 是否完全匹配
|
||||
* @return array|false
|
||||
*/
|
||||
private function match(string $url, array $option, array $pattern, bool $completeMatch)
|
||||
private function checkMatch(string $url, array $option, array $pattern, bool $completeMatch)
|
||||
{
|
||||
if (isset($option['complete_match'])) {
|
||||
$completeMatch = $option['complete_match'];
|
||||
|
|
|
|||
|
|
@ -243,29 +243,6 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
|
|||
}
|
||||
}
|
||||
|
||||
$this->filter(function ($result, $options) {
|
||||
// 关联查询
|
||||
if (!empty($options['relation'])) {
|
||||
$result->relationQuery($options['relation'], $options['with_relation_attr']);
|
||||
}
|
||||
|
||||
// 预载入查询
|
||||
if (empty($options['is_resultSet']) && !empty($options['with'])) {
|
||||
$result->eagerlyResult($result, $options['with'], $options['with_relation_attr'], false, $options['with_cache'] ?? false);
|
||||
}
|
||||
|
||||
// JOIN预载入查询
|
||||
if (empty($options['is_resultSet']) && !empty($options['with_join'])) {
|
||||
$result->eagerlyResult($result, $options['with_join'], $options['with_relation_attr'], true, $options['with_cache'] ?? false);
|
||||
}
|
||||
|
||||
// 关联统计
|
||||
if (!empty($options['with_count'])) {
|
||||
foreach ($options['with_count'] as $val) {
|
||||
$result->relationCount($this, (array) $val[0], $val[1], $val[2], false);
|
||||
}
|
||||
}
|
||||
});
|
||||
// 执行初始化操作
|
||||
$this->initialize();
|
||||
}
|
||||
|
|
@ -308,11 +285,6 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
|
|||
|
||||
$model->setUpdateWhere($where);
|
||||
|
||||
// 查询数据处理
|
||||
foreach ($this->filter as $filter) {
|
||||
call_user_func_array($filter, [$model, $options]);
|
||||
}
|
||||
|
||||
$model->trigger('AfterRead');
|
||||
|
||||
return $model;
|
||||
|
|
|
|||
|
|
@ -106,12 +106,6 @@ abstract class BaseQuery
|
|||
$name = Str::snake(substr($method, 5));
|
||||
array_unshift($args, $name);
|
||||
return call_user_func_array([$this, 'where'], $args);
|
||||
} elseif ($this->model && in_array($method, ['hidden', 'visible', 'append'])) {
|
||||
// 调用模型类方法
|
||||
$this->model->filter(function ($model, $options) use ($method, $args) {
|
||||
call_user_func_array([$model, $method], $args);
|
||||
});
|
||||
return $this;
|
||||
} elseif ($this->model && method_exists($this->model, 'scope' . $method)) {
|
||||
// 动态调用命名范围
|
||||
$method = 'scope' . $method;
|
||||
|
|
@ -284,9 +278,11 @@ abstract class BaseQuery
|
|||
public function column($field, string $key = ''): array
|
||||
{
|
||||
$result = $this->connection->column($this, $field, $key);
|
||||
|
||||
if (count($result) != count($result, 1)) {
|
||||
$this->resultSet($result, false);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
@ -1158,7 +1154,7 @@ abstract class BaseQuery
|
|||
|
||||
if (!empty($this->model)) {
|
||||
// 返回模型对象
|
||||
$this->resultToModel($result, $this->options);
|
||||
$this->resultToModel($result);
|
||||
} else {
|
||||
$this->result($result);
|
||||
}
|
||||
|
|
@ -1187,7 +1183,7 @@ abstract class BaseQuery
|
|||
$this->parseView($options);
|
||||
}
|
||||
|
||||
foreach (['data', 'order', 'join', 'union', 'filter', 'json'] as $name) {
|
||||
foreach (['data', 'order', 'join', 'union', 'filter', 'json', 'with_attr', 'with_relation_attr'] as $name) {
|
||||
if (!isset($options[$name])) {
|
||||
$options[$name] = [];
|
||||
}
|
||||
|
|
@ -1197,7 +1193,7 @@ abstract class BaseQuery
|
|||
$options['strict'] = $this->connection->getConfig('fields_strict');
|
||||
}
|
||||
|
||||
foreach (['master', 'lock', 'fetch_sql', 'array', 'distinct', 'procedure'] as $name) {
|
||||
foreach (['master', 'lock', 'fetch_sql', 'array', 'distinct', 'procedure', 'with_cache'] as $name) {
|
||||
if (!isset($options[$name])) {
|
||||
$options[$name] = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -421,10 +421,8 @@ class Fetch
|
|||
|
||||
if (!empty($options['group'])) {
|
||||
// 支持GROUP
|
||||
$bind = $this->query->getBind();
|
||||
$subSql = $this->query->options($options)->field('count(' . $field . ') AS think_count')->bind($bind)->buildSql();
|
||||
|
||||
$query = $this->query->newQuery()->table([$subSql => '_group_count_']);
|
||||
$subSql = $this->query->field('count(' . $field . ') AS think_count')->buildSql();
|
||||
$query = $this->query->newQuery()->table([$subSql => '_group_count_']);
|
||||
|
||||
return $query->fetchsql()->aggregate('COUNT', '*');
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -630,7 +630,7 @@ class Mongo extends BaseQuery
|
|||
$options['table'] = $this->getTable();
|
||||
}
|
||||
|
||||
foreach (['where', 'data'] as $name) {
|
||||
foreach (['where', 'data', 'projection', 'filter', 'json', 'with_attr', 'with_relation_attr'] as $name) {
|
||||
if (!isset($options[$name])) {
|
||||
$options[$name] = [];
|
||||
}
|
||||
|
|
@ -649,10 +649,6 @@ class Mongo extends BaseQuery
|
|||
$options['modifiers'] = $modifiers;
|
||||
}
|
||||
|
||||
if (!isset($options['projection'])) {
|
||||
$options['projection'] = [];
|
||||
}
|
||||
|
||||
if (!isset($options['typeMap'])) {
|
||||
$options['typeMap'] = $this->getConfig('type_map');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ class Sqlite extends Builder
|
|||
/**
|
||||
* limit
|
||||
* @access public
|
||||
* @param Query $query 查询对象
|
||||
* @param mixed $limit
|
||||
* @param Query $query 查询对象
|
||||
* @param mixed $limit
|
||||
* @return string
|
||||
*/
|
||||
public function parseLimit(Query $query, string $limit): string
|
||||
|
|
@ -47,7 +47,7 @@ class Sqlite extends Builder
|
|||
/**
|
||||
* 随机排序
|
||||
* @access protected
|
||||
* @param Query $query 查询对象
|
||||
* @param Query $query 查询对象
|
||||
* @return string
|
||||
*/
|
||||
protected function parseRand(Query $query): string
|
||||
|
|
@ -58,9 +58,9 @@ class Sqlite extends Builder
|
|||
/**
|
||||
* 字段和表名处理
|
||||
* @access public
|
||||
* @param Query $query 查询对象
|
||||
* @param mixed $key 字段名
|
||||
* @param bool $strict 严格检测
|
||||
* @param Query $query 查询对象
|
||||
* @param mixed $key 字段名
|
||||
* @param bool $strict 严格检测
|
||||
* @return string
|
||||
*/
|
||||
public function parseKey(Query $query, $key, bool $strict = false): string
|
||||
|
|
@ -73,7 +73,7 @@ class Sqlite extends Builder
|
|||
|
||||
$key = trim($key);
|
||||
|
||||
if (strpos($key, '.')) {
|
||||
if (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
|
||||
[$table, $key] = explode('.', $key, 2);
|
||||
|
||||
$alias = $query->getOptions('alias');
|
||||
|
|
@ -88,8 +88,12 @@ class Sqlite extends Builder
|
|||
}
|
||||
}
|
||||
|
||||
if ('*' != $key && !preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {
|
||||
$key = '`' . $key . '`';
|
||||
}
|
||||
|
||||
if (isset($table)) {
|
||||
$key = $table . '.' . $key;
|
||||
$key = '`' . $table . '`.' . $key;
|
||||
}
|
||||
|
||||
return $key;
|
||||
|
|
@ -98,8 +102,8 @@ class Sqlite extends Builder
|
|||
/**
|
||||
* 设置锁机制
|
||||
* @access protected
|
||||
* @param Query $query 查询对象
|
||||
* @param bool|string $lock
|
||||
* @param Query $query 查询对象
|
||||
* @param bool|string $lock
|
||||
* @return string
|
||||
*/
|
||||
protected function parseLock(Query $query, $lock = false): string
|
||||
|
|
|
|||
|
|
@ -51,6 +51,45 @@ trait ModelRelationQuery
|
|||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置需要隐藏的输出属性
|
||||
* @access public
|
||||
* @param array $hidden 属性列表
|
||||
* @return $this
|
||||
*/
|
||||
public function hidden(array $hidden = [])
|
||||
{
|
||||
$this->options['hidden'] = $hidden;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置需要输出的属性
|
||||
* @access public
|
||||
* @param array $visible
|
||||
* @return $this
|
||||
*/
|
||||
public function visible(array $visible = [])
|
||||
{
|
||||
$this->options['visible'] = $visible;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置需要附加的输出属性
|
||||
* @access public
|
||||
* @param array $append 属性列表
|
||||
* @return $this
|
||||
*/
|
||||
public function append(array $append = [])
|
||||
{
|
||||
$this->options['append'] = $append;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加查询范围
|
||||
* @access public
|
||||
|
|
@ -94,10 +133,11 @@ trait ModelRelationQuery
|
|||
*/
|
||||
public function relation(array $relation)
|
||||
{
|
||||
if (!empty($relation)) {
|
||||
$this->options['relation'] = $relation;
|
||||
if (empty($this->model) || empty($relation)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->options['relation'] = $relation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -139,21 +179,33 @@ trait ModelRelationQuery
|
|||
/**
|
||||
* 设置数据字段获取器
|
||||
* @access public
|
||||
* @param string|array $name 字段名
|
||||
* @param callable $callback 闭包获取器
|
||||
* @param string|array $name 字段名
|
||||
* @param callable $callback 闭包获取器
|
||||
* @return $this
|
||||
*/
|
||||
public function withAttr($name, callable $callback = null)
|
||||
{
|
||||
if (is_array($name)) {
|
||||
$this->options['with_attr'] = $name;
|
||||
} else {
|
||||
$this->options['with_attr'][$name] = $callback;
|
||||
foreach ($name as $key => $val) {
|
||||
$this->withAttr($key, $val);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this->filter(function ($result) {
|
||||
return $this->getResultAttr($result, $this->options['with_attr']);
|
||||
}, 'with_attr');
|
||||
$this->options['with_attr'][$name] = $callback;
|
||||
|
||||
if (strpos($name, '.')) {
|
||||
[$relation, $field] = explode('.', $name);
|
||||
|
||||
if (!empty($this->options['json']) && in_array($relation, $this->options['json'])) {
|
||||
|
||||
} else {
|
||||
$this->options['with_relation_attr'][$relation][$field] = $callback;
|
||||
unset($this->options['with_attr'][$name]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -164,10 +216,11 @@ trait ModelRelationQuery
|
|||
*/
|
||||
public function with($with)
|
||||
{
|
||||
if (!empty($with)) {
|
||||
$this->options['with'] = (array) $with;
|
||||
if (empty($this->model) || empty($with)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->options['with'] = (array) $with;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +233,7 @@ trait ModelRelationQuery
|
|||
*/
|
||||
public function withJoin($with, string $joinType = '')
|
||||
{
|
||||
if (empty($with)) {
|
||||
if (empty($this->model) || empty($with)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +265,6 @@ trait ModelRelationQuery
|
|||
}
|
||||
|
||||
$this->via();
|
||||
|
||||
$this->options['with_join'] = $with;
|
||||
|
||||
return $this;
|
||||
|
|
@ -229,16 +281,20 @@ trait ModelRelationQuery
|
|||
*/
|
||||
protected function withAggregate($relations, string $aggregate = 'count', $field = '*', bool $subQuery = true)
|
||||
{
|
||||
if (!$subQuery) {
|
||||
$this->options['with_count'][] = [$relations, $aggregate, $field];
|
||||
} else {
|
||||
if (!isset($this->options['field'])) {
|
||||
$this->field('*');
|
||||
}
|
||||
|
||||
$this->model->relationCount($this, (array) $relations, $aggregate, $field, true);
|
||||
if (empty($this->model)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (!$subQuery) {
|
||||
$this->options['with_aggregate'][] = [(array) $relations, $aggregate, $field];
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (!isset($this->options['field'])) {
|
||||
$this->field('*');
|
||||
}
|
||||
|
||||
$this->model->relationCount($this, (array) $relations, $aggregate, $field, true);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -253,6 +309,10 @@ trait ModelRelationQuery
|
|||
*/
|
||||
public function withCache($relation = true, $key = true, $expire = null, string $tag = null)
|
||||
{
|
||||
if (empty($this->model)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (false === $relation || false === $key || !$this->getConnection()->getCache()) {
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -372,6 +432,32 @@ trait ModelRelationQuery
|
|||
return $this->model->hasWhere($relation, $where, $fields, $joinType, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字段数据转换
|
||||
* @access protected
|
||||
* @param array $result 查询数据
|
||||
* @return void
|
||||
*/
|
||||
protected function jsonModelResult(array &$result): void
|
||||
{
|
||||
$withAttr = $this->options['with_attr'];
|
||||
foreach ($this->options['json'] as $name) {
|
||||
if (!isset($result[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$jsonData = json_decode($result[$name], true);
|
||||
|
||||
if (isset($withAttr[$name])) {
|
||||
foreach ($withAttr[$name] as $key => $closure) {
|
||||
$jsonData[$key] = $closure($jsonData[$key] ?? null, $jsonData);
|
||||
}
|
||||
}
|
||||
|
||||
$result[$name] = !$this->options['json_assoc'] ? (object) $jsonData : $jsonData;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据转换为模型数据集对象
|
||||
* @access protected
|
||||
|
|
@ -384,20 +470,24 @@ trait ModelRelationQuery
|
|||
return $this->model->toCollection();
|
||||
}
|
||||
|
||||
$withRelationAttr = $this->getWithRelationAttr();
|
||||
$this->options['is_resultSet'] = true;
|
||||
|
||||
foreach ($resultSet as $key => &$result) {
|
||||
// 数据转换为模型对象
|
||||
$this->resultToModel($result, $this->options, true);
|
||||
$this->resultToModel($result);
|
||||
}
|
||||
|
||||
if (!empty($this->options['with'])) {
|
||||
// 预载入
|
||||
$result->eagerlyResultSet($resultSet, $this->options['with'], $withRelationAttr, false, $this->options['with_cache'] ?? false);
|
||||
}
|
||||
|
||||
if (!empty($this->options['with_join'])) {
|
||||
// 预载入
|
||||
$result->eagerlyResultSet($resultSet, $this->options['with_join'], $withRelationAttr, true, $this->options['with_cache'] ?? false);
|
||||
foreach (['with', 'with_join'] as $with) {
|
||||
// 关联预载入
|
||||
if (!empty($this->options[$with])) {
|
||||
$result->eagerlyResultSet(
|
||||
$resultSet,
|
||||
$this->options[$with],
|
||||
$this->options['with_relation_attr'],
|
||||
'with_join' == $with ? true : false,
|
||||
$this->options['with_cache'] ?? false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 模型数据集转换
|
||||
|
|
@ -405,55 +495,68 @@ trait ModelRelationQuery
|
|||
}
|
||||
|
||||
/**
|
||||
* 检查动态获取器
|
||||
* 查询数据转换为模型对象
|
||||
* @access protected
|
||||
* @return array
|
||||
* @param array $result 查询数据
|
||||
* @return void
|
||||
*/
|
||||
protected function getWithRelationAttr(): array
|
||||
protected function resultToModel(array &$result): void
|
||||
{
|
||||
if (isset($this->options['with_relation_attr'])) {
|
||||
return $this->options['with_relation_attr'];
|
||||
// JSON数据处理
|
||||
if (!empty($this->options['json'])) {
|
||||
$this->jsonModelResult($result);
|
||||
}
|
||||
|
||||
$withRelationAttr = [];
|
||||
if (!empty($this->options['with_attr'])) {
|
||||
foreach ($this->options['with_attr'] as $name => $val) {
|
||||
if (strpos($name, '.')) {
|
||||
[$relation, $field] = explode('.', $name);
|
||||
$result = $this->model->newInstance(
|
||||
$result,
|
||||
!empty($this->options['is_resultSet']) ? null : $this->getModelUpdateCondition($this->options),
|
||||
$this->options
|
||||
);
|
||||
|
||||
$withRelationAttr[$relation][$field] = $val;
|
||||
unset($this->options['with_attr'][$name]);
|
||||
// 模型数据处理
|
||||
foreach ($this->options['filter'] as $filter) {
|
||||
call_user_func_array($filter, [$result, $this->options]);
|
||||
}
|
||||
|
||||
// 关联查询
|
||||
if (!empty($this->options['relation'])) {
|
||||
$result->relationQuery($this->options['relation'], $this->options['with_relation_attr']);
|
||||
}
|
||||
|
||||
// 关联预载入查询
|
||||
if (empty($this->options['is_resultSet'])) {
|
||||
foreach (['with', 'with_join'] as $with) {
|
||||
if (!empty($this->options[$with])) {
|
||||
$result->eagerlyResult(
|
||||
$this->options[$with],
|
||||
$this->options['with_relation_attr'],
|
||||
'with_join' == $with ? true : false,
|
||||
$this->options['with_cache'] ?? false
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->options['with_relation_attr'] = $withRelationAttr;
|
||||
return $withRelationAttr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据转换为模型对象
|
||||
* @access protected
|
||||
* @param array $result 查询数据
|
||||
* @param array $options 查询参数
|
||||
* @param bool $resultSet 是否为数据集查询
|
||||
* @return void
|
||||
*/
|
||||
protected function resultToModel(array &$result, array $options = [], bool $resultSet = false): void
|
||||
{
|
||||
$options['with_relation_attr'] = $this->getWithRelationAttr();
|
||||
$options['is_resultSet'] = $resultSet;
|
||||
|
||||
// JSON 数据处理
|
||||
if (!empty($options['json'])) {
|
||||
$this->jsonResult($result, $options['json'], $options['json_assoc'], $options['with_relation_attr']);
|
||||
// 关联统计查询
|
||||
if (!empty($this->options['with_aggregate'])) {
|
||||
foreach ($this->options['with_aggregate'] as $val) {
|
||||
$result->relationCount($this, $val[0], $val[1], $val[2], false);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->options['filter'] as $filter) {
|
||||
$result = call_user_func($filter, $result);
|
||||
// 动态获取器
|
||||
if (!empty($this->options['with_attr'])) {
|
||||
$result->withAttr($this->options['with_attr']);
|
||||
}
|
||||
|
||||
$result = $this->model->newInstance($result, $resultSet ? null : $this->getModelUpdateCondition($options), $options);
|
||||
foreach (['hidden', 'visible', 'append'] as $name) {
|
||||
if (!empty($this->options[$name])) {
|
||||
$result->$name($this->options[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新原始数据
|
||||
$result->refreshOrigin();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use think\Model;
|
|||
trait ResultOperation
|
||||
{
|
||||
/**
|
||||
* 设置数据处理
|
||||
* 设置数据处理(支持模型)
|
||||
* @access public
|
||||
* @param callable $filter 数据处理Callable
|
||||
* @param string $index 索引(唯一)
|
||||
|
|
@ -75,12 +75,19 @@ trait ResultOperation
|
|||
*/
|
||||
protected function result(array &$result): void
|
||||
{
|
||||
// JSON数据处理
|
||||
if (!empty($this->options['json'])) {
|
||||
$this->jsonResult($result, $this->options['json'], true);
|
||||
$this->jsonResult($result);
|
||||
}
|
||||
|
||||
// 查询数据处理
|
||||
foreach ($this->options['filter'] as $filter) {
|
||||
$result = call_user_func($filter, $result);
|
||||
$result = call_user_func_array($filter, [$result, $this->options]);
|
||||
}
|
||||
|
||||
// 获取器
|
||||
if (!empty($this->options['with_attr'])) {
|
||||
$this->getResultAttr($result, $this->options['with_attr']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,9 +115,9 @@ trait ResultOperation
|
|||
* @access protected
|
||||
* @param array $result 查询数据
|
||||
* @param array $withAttr 字段获取器
|
||||
* @return array
|
||||
* @return void
|
||||
*/
|
||||
protected function getResultAttr(array $result, array $withAttr = []): array
|
||||
protected function getResultAttr(array &$result, array $withAttr = []): void
|
||||
{
|
||||
foreach ($withAttr as $name => $closure) {
|
||||
$name = Str::snake($name);
|
||||
|
|
@ -126,8 +133,6 @@ trait ResultOperation
|
|||
$result[$name] = $closure($result[$name] ?? null, $result);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,30 +166,17 @@ trait ResultOperation
|
|||
/**
|
||||
* JSON字段数据转换
|
||||
* @access protected
|
||||
* @param array $result 查询数据
|
||||
* @param array $json JSON字段
|
||||
* @param bool $assoc 是否转换为数组
|
||||
* @param array $withRelationAttr 关联获取器
|
||||
* @param array $result 查询数据
|
||||
* @return void
|
||||
*/
|
||||
protected function jsonResult(array &$result, array $json = [], bool $assoc = false, array $withRelationAttr = []): void
|
||||
protected function jsonResult(array &$result): void
|
||||
{
|
||||
foreach ($json as $name) {
|
||||
foreach ($this->options['json'] as $name) {
|
||||
if (!isset($result[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result[$name] = json_decode($result[$name], true);
|
||||
|
||||
if (isset($withRelationAttr[$name])) {
|
||||
foreach ($withRelationAttr[$name] as $key => $closure) {
|
||||
$result[$name][$key] = $closure($result[$name][$key] ?? null, $result[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$assoc) {
|
||||
$result[$name] = (object) $result[$name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class Sqlite extends PDOConnection
|
|||
public function getFields(string $tableName): array
|
||||
{
|
||||
[$tableName] = explode(' ', $tableName);
|
||||
$sql = 'PRAGMA table_info( ' . $tableName . ' )';
|
||||
$sql = 'PRAGMA table_info( \'' . $tableName . '\' )';
|
||||
|
||||
$pdo = $this->getPDOStatement($sql);
|
||||
$result = $pdo->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
|
|
|||
|
|
@ -106,12 +106,6 @@ trait Attribute
|
|||
*/
|
||||
private $withAttr = [];
|
||||
|
||||
/**
|
||||
* 数据处理
|
||||
* @var array
|
||||
*/
|
||||
private $filter = [];
|
||||
|
||||
/**
|
||||
* 获取模型对象的主键
|
||||
* @access public
|
||||
|
|
@ -183,24 +177,6 @@ trait Attribute
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置模型数据处理
|
||||
* @access public
|
||||
* @param callable $filter 数据处理Callable
|
||||
* @param string $index 索引(唯一)
|
||||
* @return $this
|
||||
*/
|
||||
public function filter(callable $filter, string $index = null)
|
||||
{
|
||||
if ($index) {
|
||||
$this->filter[$index] = $filter;
|
||||
} else {
|
||||
$this->filter[] = $filter;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实际的字段名
|
||||
* @access protected
|
||||
|
|
@ -274,6 +250,17 @@ trait Attribute
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新对象原始数据(为当前数据)
|
||||
* @access public
|
||||
* @return $this
|
||||
*/
|
||||
public function refreshOrigin()
|
||||
{
|
||||
$this->origin = $this->data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象原始数据 如果不存在指定字段返回null
|
||||
* @access public
|
||||
|
|
@ -395,6 +382,9 @@ trait Attribute
|
|||
} elseif (isset($this->type[$name])) {
|
||||
// 类型转换
|
||||
$value = $this->writeTransform($value, $this->type[$name]);
|
||||
} elseif (is_object($value) && method_exists($value, '__toString')) {
|
||||
// 对象类型
|
||||
$value = $value->__toString();
|
||||
}
|
||||
|
||||
// 设置数据对象属性
|
||||
|
|
@ -555,6 +545,10 @@ trait Attribute
|
|||
*/
|
||||
protected function getJsonValue($name, $value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
foreach ($this->withAttr[$name] as $key => $closure) {
|
||||
if ($this->jsonAssoc) {
|
||||
$value[$key] = $closure($value[$key], $value);
|
||||
|
|
|
|||
|
|
@ -291,14 +291,13 @@ trait RelationShip
|
|||
/**
|
||||
* 预载入关联查询 返回模型对象
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param array $relations 关联
|
||||
* @param array $withRelationAttr 关联获取器
|
||||
* @param bool $join 是否为JOIN方式
|
||||
* @param mixed $cache 关联缓存
|
||||
* @return void
|
||||
*/
|
||||
public function eagerlyResult(Model $result, array $relations, array $withRelationAttr = [], bool $join = false, $cache = false): void
|
||||
public function eagerlyResult(array $relations, array $withRelationAttr = [], bool $join = false, $cache = false): void
|
||||
{
|
||||
foreach ($relations as $key => $relation) {
|
||||
$subRelation = [];
|
||||
|
|
@ -333,7 +332,7 @@ trait RelationShip
|
|||
$relationCache = $cache[$relationName] ?? [];
|
||||
}
|
||||
|
||||
$relationResult->eagerlyResult($result, $relationName, $subRelation, $closure, $relationCache, $join);
|
||||
$relationResult->eagerlyResult($this, $relationName, $subRelation, $closure, $relationCache, $join);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -236,12 +236,11 @@ class BelongsTo extends OneToOne
|
|||
$relationModel->exists(true);
|
||||
}
|
||||
|
||||
// 设置关联属性
|
||||
$result->setRelation($relation, $relationModel);
|
||||
if (!empty($this->bindAttr)) {
|
||||
// 绑定关联属性
|
||||
$this->bindAttr($result, $relationModel);
|
||||
} else {
|
||||
// 设置关联属性
|
||||
$result->setRelation($relation, $relationModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -277,12 +276,12 @@ class BelongsTo extends OneToOne
|
|||
$relationModel->exists(true);
|
||||
}
|
||||
|
||||
// 设置关联属性
|
||||
$result->setRelation($relation, $relationModel);
|
||||
|
||||
if (!empty($this->bindAttr)) {
|
||||
// 绑定关联属性
|
||||
$this->bindAttr($result, $relationModel);
|
||||
} else {
|
||||
// 设置关联属性
|
||||
$result->setRelation($relation, $relationModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,30 @@ class BelongsToMany extends Relation
|
|||
->setParent(clone $this->parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装Pivot模型
|
||||
* @access public
|
||||
* @param Model $result 模型对象
|
||||
* @return array
|
||||
*/
|
||||
protected function matchPivot(Model $result): array
|
||||
{
|
||||
$pivot = [];
|
||||
foreach ($result->getData() as $key => $val) {
|
||||
if (strpos($key, '__')) {
|
||||
[$name, $attr] = explode('__', $key, 2);
|
||||
|
||||
if ('pivot' == $name) {
|
||||
$pivot[$attr] = $val;
|
||||
unset($result->$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result->setRelation($this->pivotDataName, $this->newPivot($pivot));
|
||||
return $pivot;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据关联条件查询当前模型
|
||||
* @access public
|
||||
|
|
@ -326,24 +350,13 @@ class BelongsToMany extends Relation
|
|||
// 组装模型数据
|
||||
$data = [];
|
||||
foreach ($list as $set) {
|
||||
$pivot = [];
|
||||
foreach ($set->getData() as $key => $val) {
|
||||
if (strpos($key, '__')) {
|
||||
[$name, $attr] = explode('__', $key, 2);
|
||||
if ('pivot' == $name) {
|
||||
$pivot[$attr] = $val;
|
||||
unset($set->$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
$key = $pivot[$this->localKey];
|
||||
$pivot = $this->matchPivot($set);
|
||||
$key = $pivot[$this->localKey];
|
||||
|
||||
if ($this->withLimit && isset($data[$key]) && count($data[$key]) >= $this->withLimit) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$set->setRelation($this->pivotDataName, $this->newPivot($pivot));
|
||||
|
||||
$data[$key][] = $set;
|
||||
}
|
||||
|
||||
|
|
@ -594,21 +607,8 @@ class BelongsToMany extends Relation
|
|||
$foreignKey = $this->foreignKey;
|
||||
$localKey = $this->localKey;
|
||||
|
||||
$this->query->getModel()->filter(function ($result, $options) {
|
||||
$pivot = [];
|
||||
|
||||
foreach ($result->getData() as $key => $val) {
|
||||
if (strpos($key, '__')) {
|
||||
[$name, $attr] = explode('__', $key, 2);
|
||||
|
||||
if ('pivot' == $name) {
|
||||
$pivot[$attr] = $val;
|
||||
unset($result->$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result->setRelation($this->pivotDataName, $this->newPivot($pivot));
|
||||
$this->query->filter(function ($result, $options) {
|
||||
$this->matchPivot($result);
|
||||
});
|
||||
|
||||
// 关联查询
|
||||
|
|
|
|||
|
|
@ -258,8 +258,14 @@ class HasManyThrough extends Relation
|
|||
$closure($this->getClosureType($closure));
|
||||
}
|
||||
|
||||
$throughKey = $this->throughKey;
|
||||
|
||||
if ($this->baseQuery) {
|
||||
$throughKey = Str::snake(class_basename($this->model)) . "." . $this->throughKey;
|
||||
}
|
||||
|
||||
$list = $this->query
|
||||
->where($this->throughKey, 'in', $keys)
|
||||
->where($throughKey, 'in', $keys)
|
||||
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
|
||||
->select();
|
||||
|
||||
|
|
|
|||
|
|
@ -234,13 +234,12 @@ class HasOne extends OneToOne
|
|||
$relationModel->setParent(clone $result);
|
||||
$relationModel->exists(true);
|
||||
}
|
||||
// 设置关联属性
|
||||
$result->setRelation($relation, $relationModel);
|
||||
|
||||
if (!empty($this->bindAttr)) {
|
||||
// 绑定关联属性
|
||||
$this->bindAttr($result, $relationModel);
|
||||
} else {
|
||||
// 设置关联属性
|
||||
$result->setRelation($relation, $relationModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -276,11 +275,12 @@ class HasOne extends OneToOne
|
|||
$relationModel->exists(true);
|
||||
}
|
||||
|
||||
// 设置关联属性
|
||||
$result->setRelation($relation, $relationModel);
|
||||
|
||||
if (!empty($this->bindAttr)) {
|
||||
// 绑定关联属性
|
||||
$this->bindAttr($result, $relationModel);
|
||||
} else {
|
||||
$result->setRelation($relation, $relationModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue