21 changed files with 940 additions and 3 deletions
-
15app/Constants/ErrorCode.php
-
68app/Controller/AttachmentController.php
-
35app/Exception/Handler/FilesystemExceptionHandler.php
-
35app/Exception/Handler/ValidationExceptionHandler.php
-
71app/Listener/ValidatorFactoryResolvedListener.php
-
47app/Request/AttachmentRequest.php
-
46app/Request/ImageBase64Request.php
-
46app/Request/ImageRequest.php
-
73app/Service/AttachmentService.php
-
23app/Service/AttachmentServiceInterface.php
-
5composer.json
-
1config/autoload/dependencies.php
-
2config/autoload/exceptions.php
-
94config/autoload/file.php
-
1config/autoload/listeners.php
-
3config/autoload/middlewares.php
-
4config/autoload/server.php
-
16config/autoload/translation.php
-
4config/routes.php
-
177storage/languages/en/validation.php
-
177storage/languages/zh_CN/validation.php
@ -0,0 +1,68 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Controller; |
||||
|
|
||||
|
use App\Request\AttachmentRequest; |
||||
|
use App\Request\ImageBase64Request; |
||||
|
use App\Service\AttachmentServiceInterface; |
||||
|
use Hyperf\Di\Annotation\Inject; |
||||
|
use App\Request\ImageRequest; |
||||
|
use League\Flysystem\Filesystem; |
||||
|
|
||||
|
class AttachmentController extends BaseController |
||||
|
{ |
||||
|
/** |
||||
|
* @Inject |
||||
|
* @var AttachmentServiceInterface |
||||
|
*/ |
||||
|
protected $attachmentService; |
||||
|
|
||||
|
/** |
||||
|
* 单文件表单上传 |
||||
|
* @param AttachmentRequest $request |
||||
|
* @param Filesystem $filesystem |
||||
|
* @return \Psr\Http\Message\ResponseInterface |
||||
|
*/ |
||||
|
public function upload(AttachmentRequest $request, Filesystem $filesystem) |
||||
|
{ |
||||
|
$file = $this->request->file('upload'); |
||||
|
$type = $this->request->input('type', ''); |
||||
|
|
||||
|
$fileName = $this->attachmentService->formUpload($file, $type, $filesystem, 'file'); |
||||
|
|
||||
|
return $this->success(['file_path' => $fileName]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 单图表单上传 |
||||
|
* @param ImageRequest $request |
||||
|
* @param Filesystem $filesystem |
||||
|
* @return \Psr\Http\Message\ResponseInterface |
||||
|
*/ |
||||
|
public function uploadImage(ImageRequest $request, Filesystem $filesystem) |
||||
|
{ |
||||
|
$file = $this->request->file('upload'); |
||||
|
$type = $this->request->input('type', ''); |
||||
|
|
||||
|
$fileName = $this->attachmentService->formUpload($file, $type, $filesystem); |
||||
|
|
||||
|
return $this->success(['file_path' => $fileName]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 单图base64上传 |
||||
|
* @param ImageBase64Request $request |
||||
|
* @param Filesystem $filesystem |
||||
|
* @return \Psr\Http\Message\ResponseInterface |
||||
|
*/ |
||||
|
public function uploadImageByBase64(ImageBase64Request $request, Filesystem $filesystem) |
||||
|
{ |
||||
|
$base64Code = $this->request->input('upload'); |
||||
|
$type = $this->request->input('type', ''); |
||||
|
|
||||
|
$fileName = $this->attachmentService->base64Upload($base64Code, $type, $filesystem); |
||||
|
|
||||
|
return $this->success(['file_path' => $fileName]); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Exception\Handler; |
||||
|
|
||||
|
use App\Constants\ErrorCode; |
||||
|
use Hyperf\ExceptionHandler\ExceptionHandler; |
||||
|
use Hyperf\HttpMessage\Stream\SwooleStream; |
||||
|
use League\Flysystem\FilesystemException; |
||||
|
use Psr\Http\Message\ResponseInterface; |
||||
|
use Throwable; |
||||
|
|
||||
|
class FilesystemExceptionHandler extends ExceptionHandler |
||||
|
{ |
||||
|
|
||||
|
public function handle(Throwable $throwable, ResponseInterface $response) |
||||
|
{ |
||||
|
$this->stopPropagation(); |
||||
|
|
||||
|
$content = json_encode([ |
||||
|
"status" => 'error', |
||||
|
"code" => ErrorCode::UPLOAD_INVALID, |
||||
|
"result" => [], |
||||
|
"message" => $throwable->getMessage() |
||||
|
]); |
||||
|
|
||||
|
return $response->withHeader('Content-Type', 'application/json') |
||||
|
->withStatus($throwable->status) |
||||
|
->withBody(new SwooleStream($content)); |
||||
|
} |
||||
|
|
||||
|
public function isValid(Throwable $throwable): bool |
||||
|
{ |
||||
|
return $throwable instanceof FilesystemException; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Exception\Handler; |
||||
|
|
||||
|
use App\Constants\ErrorCode; |
||||
|
use Hyperf\ExceptionHandler\ExceptionHandler; |
||||
|
use Hyperf\HttpMessage\Stream\SwooleStream; |
||||
|
use Hyperf\Validation\ValidationException; |
||||
|
use Psr\Http\Message\ResponseInterface; |
||||
|
use Throwable; |
||||
|
|
||||
|
class ValidationExceptionHandler extends ExceptionHandler |
||||
|
{ |
||||
|
|
||||
|
public function handle(Throwable $throwable, ResponseInterface $response) |
||||
|
{ |
||||
|
$this->stopPropagation(); |
||||
|
|
||||
|
$content = json_encode([ |
||||
|
"status" => 'error', |
||||
|
"code" => ErrorCode::PARAMS_INVALID, |
||||
|
"result" => [], |
||||
|
"message" => $throwable->validator->errors()->first() |
||||
|
]); |
||||
|
|
||||
|
return $response->withHeader('Content-Type', 'application/json') |
||||
|
->withStatus($throwable->status) |
||||
|
->withBody(new SwooleStream($content)); |
||||
|
} |
||||
|
|
||||
|
public function isValid(Throwable $throwable): bool |
||||
|
{ |
||||
|
return $throwable instanceof ValidationException; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Listener; |
||||
|
|
||||
|
use Hyperf\Event\Contract\ListenerInterface; |
||||
|
use Hyperf\Validation\Contract\ValidatorFactoryInterface; |
||||
|
use Hyperf\Validation\Event\ValidatorFactoryResolved; |
||||
|
|
||||
|
class ValidatorFactoryResolvedListener implements ListenerInterface |
||||
|
{ |
||||
|
|
||||
|
public function listen(): array |
||||
|
{ |
||||
|
return [ |
||||
|
ValidatorFactoryResolved::class, |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
public function process(object $event) |
||||
|
{ |
||||
|
/** |
||||
|
* @var ValidatorFactoryInterface $validatorFactory |
||||
|
*/ |
||||
|
$validatorFactory = $event->validatorFactory; |
||||
|
|
||||
|
// 注册了 nonempty 验证器规则
|
||||
|
$validatorFactory->extend('nonempty', function ($attribute, $value, $parameters, $validator) { |
||||
|
|
||||
|
return isset($value) |
||||
|
&& $value |
||||
|
&& !empty($value) |
||||
|
&& !is_null($value) |
||||
|
&& $value != 'undefined' |
||||
|
&& $value != 'unknown' |
||||
|
&& $value != 'null' |
||||
|
&& $value != 'false'; |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
// 注册了 base64 验证器规则
|
||||
|
$validatorFactory->extend('base64', function ($attribute, $value, $parameters, $validator) { |
||||
|
|
||||
|
preg_match('/^(data:\s*image\/(\w+);base64,)/', $value, $result); |
||||
|
|
||||
|
if (empty($result)) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if ( |
||||
|
in_array('image', $parameters) |
||||
|
&& !in_array($result[2], ['jpg','jpeg','png','gif','svg','bmp']) |
||||
|
) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
// 注册了 ext_not_in 验证器规则
|
||||
|
$validatorFactory->extend('ext_not_in', function ($attribute, $value, $parameters, $validator) { |
||||
|
|
||||
|
if (empty($parameters)) { |
||||
|
$parameters = ['', 'php', 'exe', 'sql', 'sh', 'bat', 'py', 'go', 'c', 'cpp']; |
||||
|
} |
||||
|
return !in_array($value->getExtension(), $parameters); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace App\Request; |
||||
|
|
||||
|
use Hyperf\Validation\Request\FormRequest; |
||||
|
|
||||
|
class AttachmentRequest extends FormRequest |
||||
|
{ |
||||
|
/** |
||||
|
* Determine if the user is authorized to make this request. |
||||
|
*/ |
||||
|
public function authorize(): bool |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the validation rules that apply to the request. |
||||
|
*/ |
||||
|
public function rules(): array |
||||
|
{ |
||||
|
return [ |
||||
|
'upload' => 'required|nonempty|file|ext_not_in', |
||||
|
'type' => 'nonempty|alpha' |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
public function messages(): array |
||||
|
{ |
||||
|
return [ |
||||
|
'upload.required' => '未选择上传的文件', |
||||
|
'upload.nonempty' => '文件异常', |
||||
|
'upload.file' => '文件上传不成功', |
||||
|
'upload.ext_not_in' => '文件不允许上传', |
||||
|
'type.nonempty' => '文件类型参数异常', |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
public function attributes(): array |
||||
|
{ |
||||
|
return [ |
||||
|
'upload' => '文件' |
||||
|
]; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace App\Request; |
||||
|
|
||||
|
use Hyperf\Validation\Request\FormRequest; |
||||
|
|
||||
|
class ImageBase64Request extends FormRequest |
||||
|
{ |
||||
|
/** |
||||
|
* Determine if the user is authorized to make this request. |
||||
|
*/ |
||||
|
public function authorize(): bool |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the validation rules that apply to the request. |
||||
|
*/ |
||||
|
public function rules(): array |
||||
|
{ |
||||
|
return [ |
||||
|
'upload' => 'required|nonempty|base64:image', |
||||
|
'type' => 'nonempty|alpha' |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
public function messages(): array |
||||
|
{ |
||||
|
return [ |
||||
|
'upload.required' => '未选择上传的文件', |
||||
|
'upload.base64' => '文件不是正常的图片', |
||||
|
'upload.nonempty' => '文件异常', |
||||
|
'type.nonempty' => '图片类型参数异常', |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
public function attributes(): array |
||||
|
{ |
||||
|
return [ |
||||
|
'upload' => '图片' |
||||
|
]; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
|
namespace App\Request; |
||||
|
|
||||
|
use Hyperf\Validation\Request\FormRequest; |
||||
|
|
||||
|
class ImageRequest extends FormRequest |
||||
|
{ |
||||
|
/** |
||||
|
* Determine if the user is authorized to make this request. |
||||
|
*/ |
||||
|
public function authorize(): bool |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the validation rules that apply to the request. |
||||
|
*/ |
||||
|
public function rules(): array |
||||
|
{ |
||||
|
return [ |
||||
|
'upload' => 'required|nonempty|file|image', |
||||
|
'type' => 'nonempty|alpha' |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
public function messages(): array |
||||
|
{ |
||||
|
return [ |
||||
|
'upload.required' => '未选择上传的文件', |
||||
|
'upload.image' => '文件不是正常的图片', |
||||
|
'upload.nonempty' => '文件异常', |
||||
|
'type.nonempty' => '图片类型参数异常', |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
public function attributes(): array |
||||
|
{ |
||||
|
return [ |
||||
|
'upload' => '图片' |
||||
|
]; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
<?php |
||||
|
|
||||
|
|
||||
|
namespace App\Service; |
||||
|
|
||||
|
use App\Constants\ErrorCode; |
||||
|
use League\Flysystem\FilesystemNotFoundException; |
||||
|
|
||||
|
class AttachmentService implements AttachmentServiceInterface |
||||
|
{ |
||||
|
|
||||
|
/** |
||||
|
* @inheritDoc |
||||
|
*/ |
||||
|
public function formUpload($file, $path, $filesystem, $attachmenttype = 'image') |
||||
|
{ |
||||
|
|
||||
|
$fileRealPath = $file->getRealPath(); |
||||
|
$fileHash = md5_file($fileRealPath); |
||||
|
|
||||
|
$path = $this->getBasePath($path, $attachmenttype); |
||||
|
$fileName = $path . '/' . $fileHash . '.' . $file->getExtension(); |
||||
|
|
||||
|
$stream = fopen($fileRealPath, 'r+'); |
||||
|
$filesystem->writeStream($fileName, $stream); |
||||
|
fclose($stream); |
||||
|
|
||||
|
return $fileName; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @inheritDoc |
||||
|
*/ |
||||
|
public function base64Upload($contents, $path, $filesystem) |
||||
|
{ |
||||
|
|
||||
|
preg_match('/^(data:\s*image\/(\w+);base64,)/', $contents, $result); |
||||
|
if (empty($result)) { |
||||
|
throw new FilesystemNotFoundException(ErrorCode::getMessage(ErrorCode::UPLOAD_INVALID),ErrorCode::UPLOAD_INVALID); |
||||
|
} |
||||
|
|
||||
|
$contents = base64_decode(str_replace($result[1], '', $contents)); |
||||
|
|
||||
|
$fileHash = md5($contents); |
||||
|
$path = $this->getBasePath($path); |
||||
|
$fileName = $path . '/' . $fileHash . '.' . $result[2]; |
||||
|
|
||||
|
$filesystem->write($fileName, $contents); |
||||
|
|
||||
|
return $fileName; |
||||
|
} |
||||
|
|
||||
|
protected function getBasePath($path, $attachmenttype = 'image') |
||||
|
{ |
||||
|
switch ($attachmenttype) { |
||||
|
case 'image': |
||||
|
$baseDir = env('IMAGE_BASE', '/attachment/images'); |
||||
|
break; |
||||
|
|
||||
|
case 'file': |
||||
|
$baseDir = env('FILES_BASE', '/attachment/files'); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
$baseDir = env('FILES_BASE', '/attachment'); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
$path = $path ? '/'.$path : ''; |
||||
|
$path .= '/'.date('Y').'/'.date('m').'/'.date('d'); |
||||
|
return $baseDir.$path; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Service; |
||||
|
|
||||
|
interface AttachmentServiceInterface |
||||
|
{ |
||||
|
/** |
||||
|
* 表单上传,单文件 |
||||
|
* @param $file |
||||
|
* @param $path |
||||
|
* @param $filesystem |
||||
|
* @param string $attachmenttype |
||||
|
*/ |
||||
|
public function formUpload($file, $path, $filesystem, $attachmenttype = 'image'); |
||||
|
|
||||
|
/** |
||||
|
* base64code上传,单文件 |
||||
|
* @param $contents |
||||
|
* @param $path |
||||
|
* @param $filesystem |
||||
|
*/ |
||||
|
public function base64Upload($contents, $path, $filesystem); |
||||
|
} |
||||
@ -0,0 +1,94 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
/** |
||||
|
* This file is part of Hyperf. |
||||
|
* |
||||
|
* @link https://www.hyperf.io |
||||
|
* @document https://hyperf.wiki |
||||
|
* @contact group@hyperf.io |
||||
|
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE |
||||
|
*/ |
||||
|
return [ |
||||
|
'default' => 'oss', |
||||
|
'storage' => [ |
||||
|
'local' => [ |
||||
|
'driver' => \Hyperf\Filesystem\Adapter\LocalAdapterFactory::class, |
||||
|
'root' => BASE_PATH . '/attachment', |
||||
|
], |
||||
|
'ftp' => [ |
||||
|
'driver' => \Hyperf\Filesystem\Adapter\FtpAdapterFactory::class, |
||||
|
'host' => 'ftp.example.com', |
||||
|
'username' => 'username', |
||||
|
'password' => 'password', |
||||
|
// 'port' => 21,
|
||||
|
// 'root' => '/path/to/root',
|
||||
|
// 'passive' => true,
|
||||
|
// 'ssl' => true,
|
||||
|
// 'timeout' => 30,
|
||||
|
// 'ignorePassiveAddress' => false,
|
||||
|
], |
||||
|
'memory' => [ |
||||
|
'driver' => \Hyperf\Filesystem\Adapter\MemoryAdapterFactory::class, |
||||
|
], |
||||
|
's3' => [ |
||||
|
'driver' => \Hyperf\Filesystem\Adapter\S3AdapterFactory::class, |
||||
|
'credentials' => [ |
||||
|
'key' => env('S3_KEY'), |
||||
|
'secret' => env('S3_SECRET'), |
||||
|
], |
||||
|
'region' => env('S3_REGION'), |
||||
|
'version' => 'latest', |
||||
|
'bucket_endpoint' => false, |
||||
|
'use_path_style_endpoint' => false, |
||||
|
'endpoint' => env('S3_ENDPOINT'), |
||||
|
'bucket_name' => env('S3_BUCKET'), |
||||
|
], |
||||
|
'minio' => [ |
||||
|
'driver' => \Hyperf\Filesystem\Adapter\S3AdapterFactory::class, |
||||
|
'credentials' => [ |
||||
|
'key' => env('S3_KEY'), |
||||
|
'secret' => env('S3_SECRET'), |
||||
|
], |
||||
|
'region' => env('S3_REGION'), |
||||
|
'version' => 'latest', |
||||
|
'bucket_endpoint' => false, |
||||
|
'use_path_style_endpoint' => true, |
||||
|
'endpoint' => env('S3_ENDPOINT'), |
||||
|
'bucket_name' => env('S3_BUCKET'), |
||||
|
], |
||||
|
'oss' => [ |
||||
|
'driver' => \Hyperf\Filesystem\Adapter\AliyunOssAdapterFactory::class, |
||||
|
'accessId' => env('OSS_ACCESS_ID'), |
||||
|
'accessSecret' => env('OSS_ACCESS_SECRET'), |
||||
|
'bucket' => env('OSS_BUCKET'), |
||||
|
'endpoint' => env('OSS_ENDPOINT'), |
||||
|
// 'timeout' => 3600,
|
||||
|
// 'connectTimeout' => 10,
|
||||
|
// 'isCName' => false,
|
||||
|
// 'token' => '',
|
||||
|
], |
||||
|
'qiniu' => [ |
||||
|
'driver' => \Hyperf\Filesystem\Adapter\QiniuAdapterFactory::class, |
||||
|
'accessKey' => env('QINIU_ACCESS_KEY'), |
||||
|
'secretKey' => env('QINIU_SECRET_KEY'), |
||||
|
'bucket' => env('QINIU_BUCKET'), |
||||
|
'domain' => env('QINBIU_DOMAIN'), |
||||
|
], |
||||
|
'cos' => [ |
||||
|
'driver' => \Hyperf\Filesystem\Adapter\CosAdapterFactory::class, |
||||
|
'region' => env('COS_REGION'), |
||||
|
'credentials' => [ |
||||
|
'appId' => env('COS_APPID'), |
||||
|
'secretId' => env('COS_SECRET_ID'), |
||||
|
'secretKey' => env('COS_SECRET_KEY'), |
||||
|
], |
||||
|
'bucket' => env('COS_BUCKET'), |
||||
|
'read_from_cdn' => false, |
||||
|
// 'timeout' => 60,
|
||||
|
// 'connect_timeout' => 60,
|
||||
|
// 'cdn' => '',
|
||||
|
// 'scheme' => 'https',
|
||||
|
], |
||||
|
], |
||||
|
]; |
||||
@ -0,0 +1,16 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
/** |
||||
|
* This file is part of Hyperf. |
||||
|
* |
||||
|
* @link https://www.hyperf.io |
||||
|
* @document https://hyperf.wiki |
||||
|
* @contact group@hyperf.io |
||||
|
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE |
||||
|
*/ |
||||
|
return [ |
||||
|
'locale' => 'zh_CN', |
||||
|
'fallback_locale' => 'en', |
||||
|
'path' => BASE_PATH . '/storage/languages', |
||||
|
]; |
||||
@ -0,0 +1,177 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
/** |
||||
|
* This file is part of Hyperf. |
||||
|
* |
||||
|
* @link https://www.hyperf.io |
||||
|
* @document https://hyperf.wiki |
||||
|
* @contact group@hyperf.io |
||||
|
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE |
||||
|
*/ |
||||
|
return [ |
||||
|
/* |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| Validation Language Lines |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| |
||||
|
| The following language lines contain the default error messages used by |
||||
|
| the validator class. Some of these rules have multiple versions such |
||||
|
| as the size rules. Feel free to tweak each of these messages here. |
||||
|
| |
||||
|
*/ |
||||
|
|
||||
|
'accepted' => 'The :attribute must be accepted.', |
||||
|
'active_url' => 'The :attribute is not a valid URL.', |
||||
|
'after' => 'The :attribute must be a date after :date.', |
||||
|
'after_or_equal' => 'The :attribute must be a date after or equal to :date.', |
||||
|
'alpha' => 'The :attribute may only contain letters.', |
||||
|
'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.', |
||||
|
'alpha_num' => 'The :attribute may only contain letters and numbers.', |
||||
|
'array' => 'The :attribute must be an array.', |
||||
|
'before' => 'The :attribute must be a date before :date.', |
||||
|
'before_or_equal' => 'The :attribute must be a date before or equal to :date.', |
||||
|
'between' => [ |
||||
|
'numeric' => 'The :attribute must be between :min and :max.', |
||||
|
'file' => 'The :attribute must be between :min and :max kilobytes.', |
||||
|
'string' => 'The :attribute must be between :min and :max characters.', |
||||
|
'array' => 'The :attribute must have between :min and :max items.', |
||||
|
], |
||||
|
'boolean' => 'The :attribute field must be true or false.', |
||||
|
'confirmed' => 'The :attribute confirmation does not match.', |
||||
|
'date' => 'The :attribute is not a valid date.', |
||||
|
'date_format' => 'The :attribute does not match the format :format.', |
||||
|
'different' => 'The :attribute and :other must be different.', |
||||
|
'digits' => 'The :attribute must be :digits digits.', |
||||
|
'digits_between' => 'The :attribute must be between :min and :max digits.', |
||||
|
'dimensions' => 'The :attribute has invalid image dimensions.', |
||||
|
'distinct' => 'The :attribute field has a duplicate value.', |
||||
|
'email' => 'The :attribute must be a valid email address.', |
||||
|
'exists' => 'The selected :attribute is invalid.', |
||||
|
'file' => 'The :attribute must be a file.', |
||||
|
'filled' => 'The :attribute field is required.', |
||||
|
'gt' => [ |
||||
|
'numeric' => 'The :attribute must be greater than :value', |
||||
|
'file' => 'The :attribute must be greater than :value kb', |
||||
|
'string' => 'The :attribute must be greater than :value characters', |
||||
|
'array' => 'The :attribute must be greater than :value items', |
||||
|
], |
||||
|
'gte' => [ |
||||
|
'numeric' => 'The :attribute must be great than or equal to :value', |
||||
|
'file' => 'The :attribute must be great than or equal to :value kb', |
||||
|
'string' => 'The :attribute must be great than or equal to :value characters', |
||||
|
'array' => 'The :attribute must be great than or equal to :value items', |
||||
|
], |
||||
|
'image' => 'The :attribute must be an image.', |
||||
|
'in' => 'The selected :attribute is invalid.', |
||||
|
'in_array' => 'The :attribute field does not exist in :other.', |
||||
|
'integer' => 'The :attribute must be an integer.', |
||||
|
'ip' => 'The :attribute must be a valid IP address.', |
||||
|
'ipv4' => 'The :attribute must be a valid IPv4 address.', |
||||
|
'ipv6' => 'The :attribute must be a valid IPv6 address.', |
||||
|
'json' => 'The :attribute must be a valid JSON string.', |
||||
|
'lt' => [ |
||||
|
'numeric' => 'The :attribute must be less than :value', |
||||
|
'file' => 'The :attribute must be less than :value kb', |
||||
|
'string' => 'The :attribute must be less than :value characters', |
||||
|
'array' => 'The :attribute must be less than :value items', |
||||
|
], |
||||
|
'lte' => [ |
||||
|
'numeric' => 'The :attribute must be less than or equal to :value', |
||||
|
'file' => 'The :attribute must be less than or equal to :value kb', |
||||
|
'string' => 'The :attribute must be less than or equal to :value characters', |
||||
|
'array' => 'The :attribute must be less than or equal to :value items', |
||||
|
], |
||||
|
'max' => [ |
||||
|
'numeric' => 'The :attribute may not be greater than :max.', |
||||
|
'file' => 'The :attribute may not be greater than :max kilobytes.', |
||||
|
'string' => 'The :attribute may not be greater than :max characters.', |
||||
|
'array' => 'The :attribute may not have more than :max items.', |
||||
|
], |
||||
|
'mimes' => 'The :attribute must be a file of type: :values.', |
||||
|
'mimetypes' => 'The :attribute must be a file of type: :values.', |
||||
|
'min' => [ |
||||
|
'numeric' => 'The :attribute must be at least :min.', |
||||
|
'file' => 'The :attribute must be at least :min kilobytes.', |
||||
|
'string' => 'The :attribute must be at least :min characters.', |
||||
|
'array' => 'The :attribute must have at least :min items.', |
||||
|
], |
||||
|
'not_in' => 'The selected :attribute is invalid.', |
||||
|
'not_regex' => 'The :attribute cannot match a given regular rule.', |
||||
|
'numeric' => 'The :attribute must be a number.', |
||||
|
'present' => 'The :attribute field must be present.', |
||||
|
'regex' => 'The :attribute format is invalid.', |
||||
|
'required' => 'The :attribute field is required.', |
||||
|
'required_if' => 'The :attribute field is required when :other is :value.', |
||||
|
'required_unless' => 'The :attribute field is required unless :other is in :values.', |
||||
|
'required_with' => 'The :attribute field is required when :values is present.', |
||||
|
'required_with_all' => 'The :attribute field is required when :values is present.', |
||||
|
'required_without' => 'The :attribute field is required when :values is not present.', |
||||
|
'required_without_all' => 'The :attribute field is required when none of :values are present.', |
||||
|
'same' => 'The :attribute and :other must match.', |
||||
|
'size' => [ |
||||
|
'numeric' => 'The :attribute must be :size.', |
||||
|
'file' => 'The :attribute must be :size kilobytes.', |
||||
|
'string' => 'The :attribute must be :size characters.', |
||||
|
'array' => 'The :attribute must contain :size items.', |
||||
|
], |
||||
|
'starts_with' => 'The :attribute must be start with :values ', |
||||
|
'string' => 'The :attribute must be a string.', |
||||
|
'timezone' => 'The :attribute must be a valid zone.', |
||||
|
'unique' => 'The :attribute has already been taken.', |
||||
|
'uploaded' => 'The :attribute failed to upload.', |
||||
|
'url' => 'The :attribute format is invalid.', |
||||
|
'uuid' => 'The :attribute is invalid UUID.', |
||||
|
'max_if' => [ |
||||
|
'numeric' => 'The :attribute may not be greater than :max when :other is :value.', |
||||
|
'file' => 'The :attribute may not be greater than :max kilobytes when :other is :value.', |
||||
|
'string' => 'The :attribute may not be greater than :max characters when :other is :value.', |
||||
|
'array' => 'The :attribute may not have more than :max items when :other is :value.', |
||||
|
], |
||||
|
'min_if' => [ |
||||
|
'numeric' => 'The :attribute must be at least :min when :other is :value.', |
||||
|
'file' => 'The :attribute must be at least :min kilobytes when :other is :value.', |
||||
|
'string' => 'The :attribute must be at least :min characters when :other is :value.', |
||||
|
'array' => 'The :attribute must have at least :min items when :other is :value.', |
||||
|
], |
||||
|
'between_if' => [ |
||||
|
'numeric' => 'The :attribute must be between :min and :max when :other is :value.', |
||||
|
'file' => 'The :attribute must be between :min and :max kilobytes when :other is :value.', |
||||
|
'string' => 'The :attribute must be between :min and :max characters when :other is :value.', |
||||
|
'array' => 'The :attribute must have between :min and :max items when :other is :value.', |
||||
|
], |
||||
|
/* |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| Custom Validation Language Lines |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| |
||||
|
| Here you may specify custom validation messages for attributes using the |
||||
|
| convention "attribute.rule" to name the lines. This makes it quick to |
||||
|
| specify a specific custom language line for a given attribute rule. |
||||
|
| |
||||
|
*/ |
||||
|
|
||||
|
'custom' => [ |
||||
|
'attribute-name' => [ |
||||
|
'rule-name' => 'custom-message', |
||||
|
], |
||||
|
], |
||||
|
|
||||
|
/* |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| Custom Validation Attributes |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| |
||||
|
| The following language lines are used to swap attribute place-holders |
||||
|
| with something more reader friendly such as E-Mail Address instead |
||||
|
| of "email". This simply helps us make messages a little cleaner. |
||||
|
| |
||||
|
*/ |
||||
|
|
||||
|
'attributes' => [], |
||||
|
'phone_number' => 'The :attribute must be a valid phone number', |
||||
|
'telephone_number' => 'The :attribute must be a valid telephone number', |
||||
|
|
||||
|
'chinese_word' => 'The :attribute must contain valid characters(chinese/english character, number, underscore)', |
||||
|
'sequential_array' => 'The :attribute must be sequential array', |
||||
|
]; |
||||
@ -0,0 +1,177 @@ |
|||||
|
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
/** |
||||
|
* This file is part of Hyperf. |
||||
|
* |
||||
|
* @link https://www.hyperf.io |
||||
|
* @document https://hyperf.wiki |
||||
|
* @contact group@hyperf.io |
||||
|
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE |
||||
|
*/ |
||||
|
return [ |
||||
|
/* |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| Validation Language Lines |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| |
||||
|
| The following language lines contain the default error messages used by |
||||
|
| the validator class. Some of these rules have multiple versions such |
||||
|
| as the size rules. Feel free to tweak each of these messages here. |
||||
|
| |
||||
|
*/ |
||||
|
|
||||
|
'accepted' => ':attribute 必须接受', |
||||
|
'active_url' => ':attribute 必须是一个合法的 URL', |
||||
|
'after' => ':attribute 必须是 :date 之后的一个日期', |
||||
|
'after_or_equal' => ':attribute 必须是 :date 之后或相同的一个日期', |
||||
|
'alpha' => ':attribute 只能包含字母', |
||||
|
'alpha_dash' => ':attribute 只能包含字母、数字、中划线或下划线', |
||||
|
'alpha_num' => ':attribute 只能包含字母和数字', |
||||
|
'array' => ':attribute 必须是一个数组', |
||||
|
'before' => ':attribute 必须是 :date 之前的一个日期', |
||||
|
'before_or_equal' => ':attribute 必须是 :date 之前或相同的一个日期', |
||||
|
'between' => [ |
||||
|
'numeric' => ':attribute 必须在 :min 到 :max 之间', |
||||
|
'file' => ':attribute 必须在 :min 到 :max kb 之间', |
||||
|
'string' => ':attribute 必须在 :min 到 :max 个字符之间', |
||||
|
'array' => ':attribute 必须在 :min 到 :max 项之间', |
||||
|
], |
||||
|
'boolean' => ':attribute 字符必须是 true 或 false, 1 或 0', |
||||
|
'confirmed' => ':attribute 二次确认不匹配', |
||||
|
'date' => ':attribute 必须是一个合法的日期', |
||||
|
'date_format' => ':attribute 与给定的格式 :format 不符合', |
||||
|
'different' => ':attribute 必须不同于 :other', |
||||
|
'digits' => ':attribute 必须是 :digits 位', |
||||
|
'digits_between' => ':attribute 必须在 :min 和 :max 位之间', |
||||
|
'dimensions' => ':attribute 具有无效的图片尺寸', |
||||
|
'distinct' => ':attribute 字段具有重复值', |
||||
|
'email' => ':attribute 必须是一个合法的电子邮件地址', |
||||
|
'exists' => '选定的 :attribute 是无效的', |
||||
|
'file' => ':attribute 必须是一个文件', |
||||
|
'filled' => ':attribute 的字段是必填的', |
||||
|
'gt' => [ |
||||
|
'numeric' => ':attribute 必须大于 :value', |
||||
|
'file' => ':attribute 必须大于 :value kb', |
||||
|
'string' => ':attribute 必须大于 :value 个字符', |
||||
|
'array' => ':attribute 必须大于 :value 项', |
||||
|
], |
||||
|
'gte' => [ |
||||
|
'numeric' => ':attribute 必须大于等于 :value', |
||||
|
'file' => ':attribute 必须大于等于 :value kb', |
||||
|
'string' => ':attribute 必须大于等于 :value 个字符', |
||||
|
'array' => ':attribute 必须大于等于 :value 项', |
||||
|
], |
||||
|
'image' => ':attribute 必须是 jpg, jpeg, png, bmp 或者 gif 格式的图片', |
||||
|
'in' => '选定的 :attribute 是无效的', |
||||
|
'in_array' => ':attribute 字段不存在于 :other', |
||||
|
'integer' => ':attribute 必须是个整数', |
||||
|
'ip' => ':attribute 必须是一个合法的 IP 地址', |
||||
|
'ipv4' => ':attribute 必须是一个合法的 IPv4 地址', |
||||
|
'ipv6' => ':attribute 必须是一个合法的 IPv6 地址', |
||||
|
'json' => ':attribute 必须是一个合法的 JSON 字符串', |
||||
|
'lt' => [ |
||||
|
'numeric' => ':attribute 必须小于 :value', |
||||
|
'file' => ':attribute 必须小于 :value kb', |
||||
|
'string' => ':attribute 必须小于 :value 个字符', |
||||
|
'array' => ':attribute 必须小于 :value 项', |
||||
|
], |
||||
|
'lte' => [ |
||||
|
'numeric' => ':attribute 必须小于等于 :value', |
||||
|
'file' => ':attribute 必须小于等于 :value kb', |
||||
|
'string' => ':attribute 必须小于等于 :value 个字符', |
||||
|
'array' => ':attribute 必须小于等于 :value 项', |
||||
|
], |
||||
|
'max' => [ |
||||
|
'numeric' => ':attribute 的最大值为 :max', |
||||
|
'file' => ':attribute 的最大为 :max kb', |
||||
|
'string' => ':attribute 的最大长度为 :max 字符', |
||||
|
'array' => ':attribute 至多有 :max 项', |
||||
|
], |
||||
|
'mimes' => ':attribute 的文件类型必须是 :values', |
||||
|
'mimetypes' => ':attribute 的文件MIME必须是 :values', |
||||
|
'min' => [ |
||||
|
'numeric' => ':attribute 的最小值为 :min', |
||||
|
'file' => ':attribute 大小至少为 :min kb', |
||||
|
'string' => ':attribute 的最小长度为 :min 字符', |
||||
|
'array' => ':attribute 至少有 :min 项', |
||||
|
], |
||||
|
'not_in' => '选定的 :attribute 是无效的', |
||||
|
'not_regex' => ':attribute 不能匹配给定的正则', |
||||
|
'numeric' => ':attribute 必须是数字', |
||||
|
'present' => ':attribute 字段必须存在', |
||||
|
'regex' => ':attribute 格式是无效的', |
||||
|
'required' => ':attribute 字段是必须的', |
||||
|
'required_if' => ':attribute 字段是必须的当 :other 是 :value', |
||||
|
'required_unless' => ':attribute 字段是必须的,除非 :other 是在 :values 中', |
||||
|
'required_with' => ':attribute 字段是必须的当 :values 是存在的', |
||||
|
'required_with_all' => ':attribute 字段是必须的当 :values 是存在的', |
||||
|
'required_without' => ':attribute 字段是必须的当 :values 是不存在的', |
||||
|
'required_without_all' => ':attribute 字段是必须的当 没有一个 :values 是存在的', |
||||
|
'same' => ':attribute 和 :other 必须匹配', |
||||
|
'size' => [ |
||||
|
'numeric' => ':attribute 必须是 :size', |
||||
|
'file' => ':attribute 必须是 :size kb', |
||||
|
'string' => ':attribute 必须是 :size 个字符', |
||||
|
'array' => ':attribute 必须包括 :size 项', |
||||
|
], |
||||
|
'starts_with' => ':attribute 必须以 :values 为开头', |
||||
|
'string' => ':attribute 必须是一个字符串', |
||||
|
'timezone' => ':attribute 必须是个有效的时区', |
||||
|
'unique' => ':attribute 已存在', |
||||
|
'uploaded' => ':attribute 上传失败', |
||||
|
'url' => ':attribute 无效的格式', |
||||
|
'uuid' => ':attribute 无效的UUID格式', |
||||
|
'max_if' => [ |
||||
|
'numeric' => '当 :other 为 :value 时 :attribute 不能大于 :max', |
||||
|
'file' => '当 :other 为 :value 时 :attribute 不能大于 :max kb', |
||||
|
'string' => '当 :other 为 :value 时 :attribute 不能大于 :max 个字符', |
||||
|
'array' => '当 :other 为 :value 时 :attribute 最多只有 :max 个单元', |
||||
|
], |
||||
|
'min_if' => [ |
||||
|
'numeric' => '当 :other 为 :value 时 :attribute 必须大于等于 :min', |
||||
|
'file' => '当 :other 为 :value 时 :attribute 大小不能小于 :min kb', |
||||
|
'string' => '当 :other 为 :value 时 :attribute 至少为 :min 个字符', |
||||
|
'array' => '当 :other 为 :value 时 :attribute 至少有 :min 个单元', |
||||
|
], |
||||
|
'between_if' => [ |
||||
|
'numeric' => '当 :other 为 :value 时 :attribute 必须介于 :min - :max 之间', |
||||
|
'file' => '当 :other 为 :value 时 :attribute 必须介于 :min - :max kb 之间', |
||||
|
'string' => '当 :other 为 :value 时 :attribute 必须介于 :min - :max 个字符之间', |
||||
|
'array' => '当 :other 为 :value 时 :attribute 必须只有 :min - :max 个单元', |
||||
|
], |
||||
|
/* |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| Custom Validation Language Lines |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| |
||||
|
| Here you may specify custom validation messages for attributes using the |
||||
|
| convention "attribute.rule" to name the lines. This makes it quick to |
||||
|
| specify a specific custom language line for a given attribute rule. |
||||
|
| |
||||
|
*/ |
||||
|
|
||||
|
'custom' => [ |
||||
|
'attribute-name' => [ |
||||
|
'rule-name' => 'custom-message', |
||||
|
], |
||||
|
], |
||||
|
|
||||
|
/* |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| Custom Validation Attributes |
||||
|
|-------------------------------------------------------------------------- |
||||
|
| |
||||
|
| The following language lines are used to swap attribute place-holders |
||||
|
| with something more reader friendly such as E-Mail Address instead |
||||
|
| of "email". This simply helps us make messages a little cleaner. |
||||
|
| |
||||
|
*/ |
||||
|
|
||||
|
'attributes' => [], |
||||
|
'phone_number' => ':attribute 必须为一个有效的电话号码', |
||||
|
'telephone_number' => ':attribute 必须为一个有效的手机号码', |
||||
|
|
||||
|
'chinese_word' => ':attribute 必须包含以下有效字符 (中文/英文,数字, 下划线)', |
||||
|
'sequential_array' => ':attribute 必须是一个有序数组', |
||||
|
]; |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue