Initial
commit
4bc96e314e
@ -0,0 +1,17 @@
|
||||
APP_NAME=skeleton
|
||||
APP_ENV=dev
|
||||
|
||||
DB_DRIVER=mysql
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=hyperf
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
DB_CHARSET=utf8mb4
|
||||
DB_COLLATION=utf8mb4_unicode_ci
|
||||
DB_PREFIX=
|
||||
|
||||
REDIS_HOST=localhost
|
||||
REDIS_AUTH=(null)
|
||||
REDIS_PORT=6379
|
||||
REDIS_DB=0
|
@ -0,0 +1,54 @@
|
||||
# Default Dockerfile
|
||||
#
|
||||
# @link https://www.hyperf.io
|
||||
# @document https://hyperf.wiki
|
||||
# @contact group@hyperf.io
|
||||
# @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
|
||||
FROM hyperf/hyperf:8.0-alpine-v3.12-swoole
|
||||
LABEL maintainer="Hyperf Developers <group@hyperf.io>" version="1.0" license="MIT" app.name="Hyperf"
|
||||
|
||||
##
|
||||
# ---------- env settings ----------
|
||||
##
|
||||
# --build-arg timezone=Asia/Shanghai
|
||||
ARG timezone
|
||||
|
||||
ENV TIMEZONE=${timezone:-"Asia/Shanghai"} \
|
||||
APP_ENV=prod \
|
||||
SCAN_CACHEABLE=(true)
|
||||
|
||||
# update
|
||||
RUN set -ex \
|
||||
# show php version and extensions
|
||||
&& php -v \
|
||||
&& php -m \
|
||||
&& php --ri swoole \
|
||||
# ---------- some config ----------
|
||||
&& cd /etc/php8 \
|
||||
# - config PHP
|
||||
&& { \
|
||||
echo "upload_max_filesize=128M"; \
|
||||
echo "post_max_size=128M"; \
|
||||
echo "memory_limit=1G"; \
|
||||
echo "date.timezone=${TIMEZONE}"; \
|
||||
} | tee conf.d/99_overrides.ini \
|
||||
# - config timezone
|
||||
&& ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
|
||||
&& echo "${TIMEZONE}" > /etc/timezone \
|
||||
# ---------- clear works ----------
|
||||
&& rm -rf /var/cache/apk/* /tmp/* /usr/share/man \
|
||||
&& echo -e "\033[42;37m Build Completed :).\033[0m\n"
|
||||
|
||||
WORKDIR /opt/www
|
||||
|
||||
# Composer Cache
|
||||
# COPY ./composer.* /opt/www/
|
||||
# RUN composer install --no-dev --no-scripts
|
||||
|
||||
COPY . /opt/www
|
||||
RUN print "\n" | composer install -o && php bin/hyperf.php
|
||||
|
||||
EXPOSE 9501
|
||||
|
||||
ENTRYPOINT ["php", "/opt/www/bin/hyperf.php", "start"]
|
@ -0,0 +1,12 @@
|
||||
name: Build Docker
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: cp -rf .github/workflows/Dockerfile . && docker build -t hyperf .
|
@ -0,0 +1,25 @@
|
||||
on:
|
||||
push:
|
||||
# Sequence of patterns matched against refs/tags
|
||||
tags:
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
name: Release
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
@ -0,0 +1,13 @@
|
||||
.buildpath
|
||||
.settings/
|
||||
.project
|
||||
*.patch
|
||||
.idea/
|
||||
.git/
|
||||
runtime/
|
||||
vendor/
|
||||
.phpintel/
|
||||
.env
|
||||
.DS_Store
|
||||
.phpunit*
|
||||
*.cache
|
@ -0,0 +1,57 @@
|
||||
# usermod -aG docker gitlab-runner
|
||||
|
||||
stages:
|
||||
- build
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
PROJECT_NAME: hyperf
|
||||
REGISTRY_URL: registry-docker.org
|
||||
|
||||
build_test_docker:
|
||||
stage: build
|
||||
before_script:
|
||||
# - git submodule sync --recursive
|
||||
# - git submodule update --init --recursive
|
||||
script:
|
||||
- docker build . -t $PROJECT_NAME
|
||||
- docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:test
|
||||
- docker push $REGISTRY_URL/$PROJECT_NAME:test
|
||||
only:
|
||||
- test
|
||||
tags:
|
||||
- builder
|
||||
|
||||
deploy_test_docker:
|
||||
stage: deploy
|
||||
script:
|
||||
- docker stack deploy -c deploy.test.yml --with-registry-auth $PROJECT_NAME
|
||||
only:
|
||||
- test
|
||||
tags:
|
||||
- test
|
||||
|
||||
build_docker:
|
||||
stage: build
|
||||
before_script:
|
||||
# - git submodule sync --recursive
|
||||
# - git submodule update --init --recursive
|
||||
script:
|
||||
- docker build . -t $PROJECT_NAME
|
||||
- docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:$CI_COMMIT_REF_NAME
|
||||
- docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:latest
|
||||
- docker push $REGISTRY_URL/$PROJECT_NAME:$CI_COMMIT_REF_NAME
|
||||
- docker push $REGISTRY_URL/$PROJECT_NAME:latest
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- builder
|
||||
|
||||
deploy_docker:
|
||||
stage: deploy
|
||||
script:
|
||||
- echo SUCCESS
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- builder
|
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
$header = <<<'EOF'
|
||||
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
|
||||
EOF;
|
||||
|
||||
return (new PhpCsFixer\Config())
|
||||
->setRiskyAllowed(true)
|
||||
->setRules([
|
||||
'@PSR2' => true,
|
||||
'@Symfony' => true,
|
||||
'@DoctrineAnnotation' => true,
|
||||
'@PhpCsFixer' => true,
|
||||
'header_comment' => [
|
||||
'comment_type' => 'PHPDoc',
|
||||
'header' => $header,
|
||||
'separate' => 'none',
|
||||
'location' => 'after_declare_strict',
|
||||
],
|
||||
'array_syntax' => [
|
||||
'syntax' => 'short'
|
||||
],
|
||||
'list_syntax' => [
|
||||
'syntax' => 'short'
|
||||
],
|
||||
'concat_space' => [
|
||||
'spacing' => 'one'
|
||||
],
|
||||
'blank_line_before_statement' => [
|
||||
'statements' => [
|
||||
'declare',
|
||||
],
|
||||
],
|
||||
'general_phpdoc_annotation_remove' => [
|
||||
'annotations' => [
|
||||
'author'
|
||||
],
|
||||
],
|
||||
'ordered_imports' => [
|
||||
'imports_order' => [
|
||||
'class', 'function', 'const',
|
||||
],
|
||||
'sort_algorithm' => 'alpha',
|
||||
],
|
||||
'single_line_comment_style' => [
|
||||
'comment_types' => [
|
||||
],
|
||||
],
|
||||
'yoda_style' => [
|
||||
'always_move_variable' => false,
|
||||
'equal' => false,
|
||||
'identical' => false,
|
||||
],
|
||||
'phpdoc_align' => [
|
||||
'align' => 'left',
|
||||
],
|
||||
'multiline_whitespace_before_semicolons' => [
|
||||
'strategy' => 'no_multi_line',
|
||||
],
|
||||
'constant_case' => [
|
||||
'case' => 'lower',
|
||||
],
|
||||
'class_attributes_separation' => true,
|
||||
'combine_consecutive_unsets' => true,
|
||||
'declare_strict_types' => true,
|
||||
'linebreak_after_opening_tag' => true,
|
||||
'lowercase_static_reference' => true,
|
||||
'no_useless_else' => true,
|
||||
'no_unused_imports' => true,
|
||||
'not_operator_with_successor_space' => true,
|
||||
'not_operator_with_space' => false,
|
||||
'ordered_class_elements' => true,
|
||||
'php_unit_strict' => false,
|
||||
'phpdoc_separation' => false,
|
||||
'single_quote' => true,
|
||||
'standardize_not_equals' => true,
|
||||
'multiline_comment_opening_closing' => true,
|
||||
])
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->exclude('public')
|
||||
->exclude('runtime')
|
||||
->exclude('vendor')
|
||||
->in(__DIR__)
|
||||
)
|
||||
->setUsingCache(false);
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace PHPSTORM_META {
|
||||
|
||||
// Reflect
|
||||
override(\Psr\Container\ContainerInterface::get(0), map('@'));
|
||||
override(\Hyperf\Utils\Context::get(0), map('@'));
|
||||
override(\make(0), map('@'));
|
||||
override(\di(0), map('@'));
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
# Default Dockerfile
|
||||
#
|
||||
# @link https://www.hyperf.io
|
||||
# @document https://hyperf.wiki
|
||||
# @contact group@hyperf.io
|
||||
# @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
|
||||
FROM hyperf/hyperf:8.0-alpine-v3.12-swoole
|
||||
LABEL maintainer="Hyperf Developers <group@hyperf.io>" version="1.0" license="MIT" app.name="Hyperf"
|
||||
|
||||
##
|
||||
# ---------- env settings ----------
|
||||
##
|
||||
# --build-arg timezone=Asia/Shanghai
|
||||
ARG timezone
|
||||
|
||||
ENV TIMEZONE=${timezone:-"Asia/Shanghai"} \
|
||||
APP_ENV=prod \
|
||||
SCAN_CACHEABLE=(true)
|
||||
|
||||
# update
|
||||
RUN set -ex \
|
||||
# show php version and extensions
|
||||
&& php -v \
|
||||
&& php -m \
|
||||
&& php --ri swoole \
|
||||
# ---------- some config ----------
|
||||
&& cd /etc/php8 \
|
||||
# - config PHP
|
||||
&& { \
|
||||
echo "upload_max_filesize=128M"; \
|
||||
echo "post_max_size=128M"; \
|
||||
echo "memory_limit=1G"; \
|
||||
echo "date.timezone=${TIMEZONE}"; \
|
||||
} | tee conf.d/99_overrides.ini \
|
||||
# - config timezone
|
||||
&& ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
|
||||
&& echo "${TIMEZONE}" > /etc/timezone \
|
||||
# ---------- clear works ----------
|
||||
&& rm -rf /var/cache/apk/* /tmp/* /usr/share/man \
|
||||
&& echo -e "\033[42;37m Build Completed :).\033[0m\n"
|
||||
|
||||
WORKDIR /opt/www
|
||||
|
||||
# Composer Cache
|
||||
# COPY ./composer.* /opt/www/
|
||||
# RUN composer install --no-dev --no-scripts
|
||||
|
||||
COPY . /opt/www
|
||||
RUN composer install --no-dev -o && php bin/hyperf.php
|
||||
|
||||
EXPOSE 9501
|
||||
|
||||
ENTRYPOINT ["php", "/opt/www/bin/hyperf.php", "start"]
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Helper\Client\Lanhuo;
|
||||
use Hyperf\Command\Command as HyperfCommand;
|
||||
use Hyperf\Command\Annotation\Command;
|
||||
use Hyperf\Contract\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @Command
|
||||
*/
|
||||
class JinlingCommand extends HyperfCommand
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
protected $admin;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
parent::__construct('jinling');
|
||||
}
|
||||
|
||||
public function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setDescription('廖金灵测试');
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
Lanhuo::addUser([
|
||||
'user_id' => 111,
|
||||
'account' => 'bbbbbbbabc111',
|
||||
'phone' => '18888888888',
|
||||
'device_type' => 2, // 设备类型(1-andriod 2-ios)
|
||||
'device_number' => 'ABCD',
|
||||
'name' =>'哈哈哈',
|
||||
'id_card' => '350824199911111111',
|
||||
'is_real' => 1, // 是否实名(1-实名 0-未实名)
|
||||
]);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Constants;
|
||||
|
||||
use Hyperf\Constants\AbstractConstants;
|
||||
use Hyperf\Constants\Annotation\Constants;
|
||||
|
||||
/**
|
||||
* @Constants
|
||||
*/
|
||||
class ResultCode extends AbstractConstants
|
||||
{
|
||||
/**
|
||||
* @Message("成功")
|
||||
*/
|
||||
const SUCCESS = 1000;
|
||||
|
||||
/**
|
||||
* @Message("错误")
|
||||
*/
|
||||
const DEFAULT_ERROR = 2000;
|
||||
|
||||
/**
|
||||
* @Message("Server Error")
|
||||
*/
|
||||
const SERVER_ERROR = 2001;
|
||||
|
||||
/**
|
||||
* @Message("参数错误")
|
||||
*/
|
||||
const SYSTEM_INVALID = 2002;
|
||||
|
||||
/**
|
||||
* @Message("Params %s is invalid.")
|
||||
*/
|
||||
const PARAMS_INVALID = 2003;
|
||||
|
||||
/**
|
||||
* @Message("记录不存在")
|
||||
*/
|
||||
const RECORD_NOT_FOUND = 2004;
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?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
|
||||
*/
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Constants\ResultCode;
|
||||
use App\Helper\Result;
|
||||
use Hyperf\Context\Context;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
use Hyperf\HttpServer\Contract\ResponseInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
abstract class AbstractController
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
* @var RequestInterface
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
* @var ResponseInterface
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
protected function success(string $message = '', int $code = ResultCode::SUCCESS): Result
|
||||
{
|
||||
return $this->respond($code, $message);
|
||||
}
|
||||
|
||||
protected function respond(int $code, string $message): Result
|
||||
{
|
||||
$data = Context::get('respondData', []);
|
||||
return new Result($code, $message, $data);
|
||||
}
|
||||
|
||||
protected function setData(array $data): AbstractController
|
||||
{
|
||||
Context::set('respondData', $data);
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use App\Job\AfterLoginJob;
|
||||
use App\Job\AfterRegisterJob;
|
||||
use App\Job\AfterSaveRoleJob;
|
||||
use App\Job\AfterSpendJob;
|
||||
use App\Helper\Queue;
|
||||
|
||||
class GameEventController extends AbstractController
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function recharge()
|
||||
{
|
||||
$payOrderNumber = $this->request->input('pay_order_number', '');
|
||||
if (!$payOrderNumber) {
|
||||
throw new BusinessException('缺少参数[pay_order_number]');
|
||||
}
|
||||
Queue::push(AfterSpendJob::class, ['pay_order_number' => $payOrderNumber]);
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
public function login()
|
||||
{
|
||||
$userId = (int)$this->request->input('user_id', 0);
|
||||
$gameId = (int)$this->request->input('game_id', 0);
|
||||
$loginTime = (int)$this->request->input('login_time', 0);
|
||||
if (!$userId) {
|
||||
throw new BusinessException('缺少参数[user_id]');
|
||||
}
|
||||
if (!$gameId) {
|
||||
throw new BusinessException('缺少参数[game_id]');
|
||||
}
|
||||
if (!$loginTime) {
|
||||
throw new BusinessException('缺少参数[login_time]');
|
||||
}
|
||||
Queue::push(AfterLoginJob::class, [
|
||||
'user_id' => $userId,
|
||||
'game_id' => $gameId,
|
||||
'login_time' => $loginTime
|
||||
]);
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
public function register()
|
||||
{
|
||||
$userId = $this->request->input('user_id', 0);
|
||||
$source = $this->request->input('source', 'SDK');
|
||||
if (!$userId) {
|
||||
throw new BusinessException('缺少参数[user_id]');
|
||||
}
|
||||
Queue::push(AfterRegisterJob::class, [
|
||||
'user_id' => $userId,
|
||||
]);
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
public function saveRole()
|
||||
{
|
||||
Queue::push(AfterSaveRoleJob::class, $this->request->all());
|
||||
return $this->success();
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?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
|
||||
*/
|
||||
namespace App\Controller;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$user = $this->request->input('user', 'Hyperf');
|
||||
$method = $this->request->getMethod();
|
||||
|
||||
return [
|
||||
'method' => $method,
|
||||
'message' => "Hello {$user}.",
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Service\PlayerService;
|
||||
|
||||
class StatisticsController extends AbstractController
|
||||
{
|
||||
|
||||
/**
|
||||
* @var PlayerService $playerService
|
||||
*/
|
||||
protected $playerService;
|
||||
|
||||
public function __construct(PlayerService $playerService)
|
||||
{
|
||||
$this->playerService = $playerService;
|
||||
}
|
||||
|
||||
public function playerRetention()
|
||||
{
|
||||
$records = $this->playerService->getPlayerRetention($this->request->all());
|
||||
return $this->setData(['records' => $records])->success();
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Exception;
|
||||
|
||||
use App\Constants\ResultCode;
|
||||
use Hyperf\Server\Exception\ServerException;
|
||||
use Throwable;
|
||||
|
||||
class BusinessException extends ServerException
|
||||
{
|
||||
public function __construct(string $message = null, int $code = ResultCode::DEFAULT_ERROR, Throwable $previous = null)
|
||||
{
|
||||
if (is_null($message)) {
|
||||
$message = ResultCode::getMessage($code);
|
||||
}
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Exception\Handler;
|
||||
|
||||
use App\Constants\ResultCode;
|
||||
use App\Exception\BusinessException;
|
||||
use App\Helper\Result;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\ExceptionHandler\ExceptionHandler;
|
||||
use Hyperf\HttpMessage\Stream\SwooleStream;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Throwable;
|
||||
use Hyperf\Database\Model\ModelNotFoundException;
|
||||
|
||||
class AppExceptionHandler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* @var StdoutLoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
public function __construct(StdoutLoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function handle(Throwable $throwable, ResponseInterface $response)
|
||||
{
|
||||
$data = [];
|
||||
$code = ResultCode::SERVER_ERROR;
|
||||
$message = '';
|
||||
$httpCode = 200;
|
||||
if ($throwable instanceof BusinessException) {
|
||||
$this->stopPropagation();
|
||||
$code = $throwable->getCode();
|
||||
$message = $throwable->getMessage();
|
||||
} elseif ($throwable instanceof ModelNotFoundException) {
|
||||
$this->stopPropagation();
|
||||
$code = ResultCode::RECORD_NOT_FOUND;
|
||||
$message = ResultCode::getMessage($code);
|
||||
} else {
|
||||
if (config('app_env') == 'dev') {
|
||||
$message = $throwable->getMessage();
|
||||
$data = [
|
||||
'line' => $throwable->getLine(),
|
||||
'file' => $throwable->getFile(),
|
||||
];
|
||||
} else {
|
||||
$message = ResultCode::getMessage($code);
|
||||
}
|
||||
$this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
|
||||
$this->logger->error($throwable->getTraceAsString());
|
||||
}
|
||||
$result = new Result($code, $message, $data);
|
||||
return $response
|
||||
->withAddedHeader('content-type', 'application/json; charset=utf-8')
|
||||
->withStatus($httpCode)
|
||||
->withBody(new SwooleStream(strval($result)));
|
||||
|
||||
}
|
||||
|
||||
public function isValid(Throwable $throwable): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use Hyperf\Di\Annotation\AnnotationCollector;
|
||||
|
||||
class Annotation
|
||||
{
|
||||
/**
|
||||
* 只支持系统默认收集器
|
||||
*/
|
||||
public static function getMethodsByAnnotationAndClass(string $annotation, string $class): array
|
||||
{
|
||||
$items = AnnotationCollector::getMethodsByAnnotation($annotation);
|
||||
$methods = [];
|
||||
foreach ($items as $item) {
|
||||
if ($item['class'] == $class) {
|
||||
$methods[] = $item;
|
||||
}
|
||||
}
|
||||
return $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* 只支持系统默认收集器
|
||||
*/
|
||||
public static function getPropertiesByAnnotationAndClass(string $annotation, string $class): array
|
||||
{
|
||||
$items = AnnotationCollector::getPropertiesByAnnotation($annotation);
|
||||
$properties = [];
|
||||
foreach ($items as $item) {
|
||||
if ($item['class'] == $class) {
|
||||
$properties[] = $item;
|
||||
}
|
||||
}
|
||||
return $properties;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
|
||||
/**
|
||||
* 缓存辅助类
|
||||
* @method static mixed get(string $key, mixed $default = null)
|
||||
* @method static bool set(string $key, mixed $value, null|int|\DateInterval $ttl = null)
|
||||
* @method static bool delete(string $key)
|
||||
* @method static bool clear()
|
||||
* @method static bool deleteMultiple(iterable $keys)
|
||||
* @method static iterable getMultiple(iterable $keys, mixed $default = null)
|
||||
* @method static bool setMultiple(iterable $values, null|int|\DateInterval $ttl = null)
|
||||
* @method static bool has(string $key)
|
||||
*/
|
||||
class Cache
|
||||
{
|
||||
private static $instance;
|
||||
|
||||
private static $cacheKeys = [
|
||||
];
|
||||
|
||||
public static function getKey($name, array $params = []): string
|
||||
{
|
||||
$cacheKey = self::$cacheKeys[$name] ?? null;
|
||||
if (is_null($cacheKey)) {
|
||||
throw new BusinessException('缓存不存在');
|
||||
}
|
||||
foreach ($params as $key => $value) {
|
||||
$cacheKey = str_replace('{' . $key . '}', $value, $cacheKey);
|
||||
}
|
||||
return $cacheKey;
|
||||
}
|
||||
|
||||
public static function getInstance()
|
||||
{
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = ApplicationContext::getContainer()->get(\Psr\SimpleCache\CacheInterface::class);
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function __callStatic($method, $args)
|
||||
{
|
||||
return call_user_func_array([self::getInstance(), $method], $args);
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper\Client;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use App\Helper\Log;
|
||||
use GuzzleHttp\Client;
|
||||
use Hyperf\Guzzle\CoroutineHandler;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
|
||||
class Lanhuo
|
||||
{
|
||||
const SUCCESS = 0;
|
||||
|
||||
private static $accessToken;
|
||||
private static $expiredAt;
|
||||
|
||||
private static $client;
|
||||
|
||||
public static function addUser($data)
|
||||
{
|
||||
$params = [
|
||||
'user_id' => $data['user_id'],
|
||||
'account' => $data['account'],
|
||||
'phone' => $data['phone'],
|
||||
'device_type' => $data['device_type'], // 设备类型(1-andriod 2-ios)
|
||||
'device_number' => $data['device_number'],
|
||||
'name' => $data['name'],
|
||||
'id_card' => $data['id_card'],
|
||||
'is_real' => $data['is_real'], // 是否实名(1-实名 0-未实名)
|
||||
];
|
||||
return self::api('/llwf/user/add', $params);
|
||||
}
|
||||
|
||||
public static function updateUser($data)
|
||||
{
|
||||
$params = [
|
||||
'user_id' => $data['user_id'],
|
||||
'phone' => $data['phone'],
|
||||
'device_type' => $data['device_type'], // 设备类型(1-andriod 2-ios)
|
||||
'device_number' => $data['device_number'],
|
||||
'name' => $data['name'],
|
||||
'id_card' => $data['id_card'],
|
||||
'is_real' => $data['is_real'], // 是否实名(1-实名 0-未实名)
|
||||
];
|
||||
return self::api('/llwf/user/update', $params);
|
||||
}
|
||||
|
||||
public static function addLoginLog($data)
|
||||
{
|
||||
$params = [
|
||||
'user_id' => $data['user_id'],
|
||||
'account' => $data['account'],
|
||||
'phone' => $data['phone'],
|
||||
'device_type' => $data['device_type'], // 设备类型(1-andriod 2-ios)
|
||||
'device_number' => $data['device_number'],
|
||||
];
|
||||
return self::api('/llwf/user/AddLoginLog', $params);
|
||||
}
|
||||
|
||||
public static function addOrder($data)
|
||||
{
|
||||
$params = [
|
||||
'order_code' => $data['pay_order_number'],
|
||||
'user_id' => $data['user_id'],
|
||||
'account' => $data['account'],
|
||||
'service_id' => $data['service_id'],
|
||||
'service_name' => $data['service_name'],
|
||||
'role_id' => $data['role_id'],
|
||||
'role_name' => $data['role_name'],
|
||||
'game_name' => $data['game_name'],
|
||||
'order_amount' => $data['order_amount'],
|
||||
'pay_time' => $data['pay_time'],
|
||||
'status' => $data['status'], //支付状态(待支付 0 已支付 1 支付失败 2)
|
||||
];
|
||||
return self::api('/llwf/order/add', $params);
|
||||
}
|
||||
|
||||
public static function addRole($data)
|
||||
{
|
||||
$params = [
|
||||
'user_id' => $data['user_id'],
|
||||
'service_id' => $data['service_id'],
|
||||
'service_name' => $data['service_name'],
|
||||
'role_id' => $data['role_id'],
|
||||
'role_name' => $data['role_name'],
|
||||
'role_level' => $data['role_level'],
|
||||
'profession_id' => '', // 职业ID
|
||||
'profession_name' => '', // 职业名称
|
||||
'power' => '', // 战力
|
||||
];
|
||||
return self::api('/llwf//role/add', $params);
|
||||
}
|
||||
|
||||
private static function auth()
|
||||
{
|
||||
$params = [
|
||||
'appId' => config('clients.lanhuo.app_id', ''),
|
||||
'appKey' => config('clients.lanhuo.app_key', ''),
|
||||
'appSecret' => config('clients.lanhuo.app_secret', ''),
|
||||
];
|
||||
return self::api('/auth', $params, false);
|
||||
}
|
||||
|
||||
private static function api($uri, array $params, $withAccessToken = true)
|
||||
{
|
||||
$headers = [];
|
||||
if ($withAccessToken) {
|
||||
if (!self::$accessToken || time() > self::$expiredAt) {
|
||||
self::refreshAccessToken();
|
||||
}
|
||||
$headers['accessToken'] = self::$accessToken;
|
||||
}
|
||||
|
||||
$result = self::post($uri, $params, $headers);
|
||||
if ($result['errorCode'] == self::SUCCESS) {
|
||||
return $result['data'];
|
||||
} else {
|
||||
Log::error('LANHUO_REQUEST_ERROR[' . $uri . ']: ' . $result['msg'], $params, 'lanhuo');
|
||||
throw new BusinessException('请求接口错误:' . $result['msg']);
|
||||
}
|
||||
}
|
||||
|
||||
private static function refreshAccessToken()
|
||||
{
|
||||
$data = self::auth();
|
||||
self::$accessToken = $data['accessToken'];
|
||||
self::$expiredAt = strtotime($data['createDt']) + $data['expireTime'] - 10; // 前置10秒
|
||||
}
|
||||
|
||||
private static function post($uri, array $params, array $headers = []): array
|
||||
{
|
||||
try {
|
||||
$response = self::getClient()->post('/openapi' . $uri, [
|
||||
'verify' => false,
|
||||
// 'form_params' => $params,
|
||||
'json' => $params,
|
||||
'headers' => $headers,
|
||||
]);
|
||||
$result = (string)$response->getBody();
|
||||
return json_decode($result, true);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('LANHUO_NET_ERROR[' . $uri . ']: ' . $e->getMessage(), $params, 'lanhuo');
|
||||
return [
|
||||
'errorCode' => 88888,
|
||||
'msg' => env('APP_ENV') == 'prod' ? '网络异常' : '网络异常:' . $e->getMessage(),
|
||||
'data' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private static function getClient()
|
||||
{
|
||||
if (is_null(self::$client)) {
|
||||
self::$client = new Client([
|
||||
'base_uri' => config('clients.lanhuo.base_url', ''),
|
||||
'handler' => HandlerStack::create(new CoroutineHandler()),
|
||||
'timeout' => 5,
|
||||
'swoole' => [
|
||||
'timeout' => 10,
|
||||
'socket_buffer_size' => 1024 * 1024 * 2,
|
||||
],
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/json',
|
||||
],
|
||||
]);
|
||||
}
|
||||
return self::$client;
|
||||
}
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use Hyperf\Database\Model\Collection;
|
||||
use Hyperf\Database\Query\Builder;
|
||||
use Hyperf\DbConnection\Db as DB;
|
||||
|
||||
class DataList implements Logic
|
||||
{
|
||||
public $name;
|
||||
|
||||
protected $params;
|
||||
protected $page;
|
||||
protected $limit;
|
||||
protected $offset;
|
||||
protected $pagination;
|
||||
protected $records = [];
|
||||
protected $isGroupQuery = false;
|
||||
protected $withoutPaginate = false;
|
||||
protected $isQuickPaginate = false;
|
||||
protected $isSpanRow = false;
|
||||
|
||||
/**
|
||||
* @param array $params 查询数据
|
||||
*/
|
||||
public function __construct(array $params = [])
|
||||
{
|
||||
$this->params = $params;
|
||||
$this->check();
|
||||
$this->init();
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function beforeGenerate($items)
|
||||
{
|
||||
return $items;
|
||||
}
|
||||
|
||||
protected function afterGenerate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function generateRecords($items)
|
||||
{
|
||||
$items = $this->beforeGenerate($items);
|
||||
$this->records = [];
|
||||
if ($this->isSpanRow) {
|
||||
foreach ($items as $item) {
|
||||
$this->records = array_merge($this->records, $this->toArray($item));
|
||||
}
|
||||
} else {
|
||||
foreach ($items as $item) {
|
||||
$this->records[] = $this->toArray($item);
|
||||
}
|
||||
}
|
||||
$this->afterGenerate();
|
||||
}
|
||||
|
||||
public function toArray($item)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function query()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function statOffset($page, $limit)
|
||||
{
|
||||
return ($page - 1) * $limit;
|
||||
}
|
||||
|
||||
public function paginate(): DataList
|
||||
{
|
||||
[$records, $pagination] = $this->doPaginate();
|
||||
$this->pagination = $pagination;
|
||||
$this->generateRecords($records);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function doPaginate(): array
|
||||
{
|
||||
$count = 0;
|
||||
$this->page = $page = intval($this->params['page'] ?? 1);
|
||||
$this->limit = $limit = intval($this->params['limit'] ?? 10);
|
||||
$this->offset = $offset = $this->statOffset($page, $limit);
|
||||
|
||||
$records = new Collection([]);
|
||||
$query = $this->query();
|
||||
if (is_null($query)) {
|
||||
$pagination = $this->generatePagination($page, $limit, $this->getCount());
|
||||
return [$records, $pagination];
|
||||
}
|
||||
|
||||
if ($this->withoutPaginate) {
|
||||
$searchQuery = clone $query;
|
||||
return [$searchQuery->get(), null];
|
||||
}
|
||||
|
||||
// 临时快速分页
|
||||
if ($this->isQuickPaginate) {
|
||||
return $this->quickPaginate(clone $query, $page, $limit);
|
||||
} else {
|
||||
$count = $this->getCount();
|
||||
if ($count) {
|
||||
$searchQuery = clone $query;
|
||||
$records = $searchQuery->offset($offset)->limit($limit)->get();
|
||||
}
|
||||
$pagination = $this->generatePagination($page, $limit, $count);
|
||||
}
|
||||
return [$records, $pagination];
|
||||
}
|
||||
|
||||
protected function quickPaginate($query, $page, $limit)
|
||||
{
|
||||
$count = 1;
|
||||
$offset = $this->statOffset($page, $limit);
|
||||
$records = $query->offset($offset)->limit($limit+1)->get();
|
||||
$recordCount = $records->count();
|
||||
if ($recordCount < $limit+1) {
|
||||
$hasMroe = false;
|
||||
} else {
|
||||
$records->pop();
|
||||
$hasMroe = true;
|
||||
}
|
||||
$pagination = $this->generatePagination($page, $limit, $count, $hasMroe);
|
||||
return [$records, $pagination];
|
||||
}
|
||||
|
||||
protected function generatePagination($page, $limit, $count, $hasMroe = false)
|
||||
{
|
||||
$pageCount = intval(ceil($count/$limit));
|
||||
if (! $hasMroe) {
|
||||
if ($page < $pageCount) {
|
||||
$hasMroe = true;
|
||||
}
|
||||
}
|
||||
return [
|
||||
'page' => $page,
|
||||
'count' => $count,
|
||||
'page_count' => $pageCount,
|
||||
'limit' => $limit,
|
||||
'has_more'=> $hasMroe,
|
||||
];
|
||||
}
|
||||
|
||||
public function getCount()
|
||||
{
|
||||
$query = $this->query();
|
||||
if (is_null($query)) {
|
||||
return 0;
|
||||
}
|
||||
$countQuery = clone $query;
|
||||
if ($this->isGroupQuery) {
|
||||
$countQuery->select([DB::raw('1')]);
|
||||
return DB::table(DB::raw("({$countQuery->toSql()}) as temp_count_table"))
|
||||
->mergeBindings($query instanceof Builder ? $countQuery : $countQuery->getQuery())
|
||||
->count();
|
||||
} else {
|
||||
return $countQuery->count();
|
||||
}
|
||||
}
|
||||
|
||||
public function getPagination(): ?array
|
||||
{
|
||||
return $this->pagination;
|
||||
}
|
||||
|
||||
public function setWithoutPaginate($withoutPaginate)
|
||||
{
|
||||
$this->withoutPaginate = $withoutPaginate;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRecords()
|
||||
{
|
||||
return $this->records;
|
||||
}
|
||||
|
||||
public function getSummary()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 记录(records)/分页(pagination)/汇总(summary)
|
||||
* @param array $appendOptions 追加信息一起返回
|
||||
* @return array
|
||||
*/
|
||||
public function all($appendOptions = [])
|
||||
{
|
||||
$data = [
|
||||
'records' => $this->getRecords(),
|
||||
'pagination' => $this->getPagination(),
|
||||
'summary' => $this->getSummary(),
|
||||
];
|
||||
return array_merge($data, $appendOptions);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
class DeviceType
|
||||
{
|
||||
const ANDROID = 1;
|
||||
const IOS = 2;
|
||||
|
||||
public static $deviceTypeList = [
|
||||
self::ANDROID => '安卓',
|
||||
self::IOS => '苹果',
|
||||
];
|
||||
|
||||
public static function getDeviceTypeText($deviceType)
|
||||
{
|
||||
return self::$deviceTypeList[$deviceType] ?? '未知';
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use App\Annotation\Dict as DictAnnotation;
|
||||
use Hyperf\Di\Annotation\AnnotationCollector;
|
||||
|
||||
class Dict
|
||||
{
|
||||
/**
|
||||
* @var int 是
|
||||
*/
|
||||
public const YES = 0;
|
||||
|
||||
/**
|
||||
* @var int 否
|
||||
*/
|
||||
public const NO = 1;
|
||||
|
||||
public static function get(array $names, int $language)
|
||||
{
|
||||
return array_merge(self::getFromProperties($names), self::getFromMethods($names, $language));
|
||||
}
|
||||
|
||||
private static function getFromProperties(array $names): array
|
||||
{
|
||||
$items = AnnotationCollector::getPropertiesByAnnotation(DictAnnotation::class);
|
||||
$properties = [];
|
||||
foreach ($items as $item) {
|
||||
$properties[$item['annotation']->name] = ['class' => $item['class'], 'property' => $item['property'], 'transform' => $item['annotation']->transform];
|
||||
}
|
||||
$records = [];
|
||||
foreach ($names as $name) {
|
||||
if (isset($properties[$name])) {
|
||||
$property = $properties[$name];
|
||||
$items = $property['class']::${$property['property']};
|
||||
if ($property['transform']) {
|
||||
foreach ($items as $key => $value) {
|
||||
$records[$name][] = ['key' => $key, 'value' => $value];
|
||||
}
|
||||
} else {
|
||||
$records[$name] = $items;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $records;
|
||||
}
|
||||
|
||||
private static function getFromMethods(array $names, int $language): array
|
||||
{
|
||||
$items = AnnotationCollector::getMethodsByAnnotation(DictAnnotation::class);
|
||||
$methods = [];
|
||||
foreach ($items as $item) {
|
||||
$methods[$item['annotation']->name] = ['class' => $item['class'], 'method' => $item['method']];
|
||||
}
|
||||
|
||||
$records = [];
|
||||
foreach ($names as $name) {
|
||||
if (isset($methods[$name])) {
|
||||
$method = $methods[$name];
|
||||
$object = make($method['class']);
|
||||
if ($language > 0) {
|
||||
$records[$name] = $object->{$method['method']}($language);
|
||||
} else {
|
||||
$records[$name] = $object->{$method['method']}();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $records;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
class Excel
|
||||
{
|
||||
public static function getColumnKey($index)
|
||||
{
|
||||
if ($index >= 256) {
|
||||
throw new \Exception('Too much Excel column!');
|
||||
}
|
||||
$keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
||||
if ($index < 26) {
|
||||
return $keys[$index];
|
||||
} else {
|
||||
$first = $index/26;
|
||||
$second = $index%26;
|
||||
return $keys[$first-1] . $keys[$second];
|
||||
}
|
||||
}
|
||||
|
||||
public static function generateUniqueCode(array $params, string $identity, $length = 8)
|
||||
{
|
||||
$md5Code = md5(microtime(true) . json_encode($params) . $identity . rand(0, 9999));
|
||||
return substr($md5Code, 0, $length);
|
||||
}
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use Closure;
|
||||
use Hyperf\Database\Model\Collection;
|
||||
|
||||
class Export
|
||||
{
|
||||
const MODE_QUERY = 1;
|
||||
const MODE_ARRAY = 2;
|
||||
const MODE_COLLECTION = 3;
|
||||
|
||||
public $name;
|
||||
|
||||
protected $params;
|
||||
protected $basePath = BASE_PATH . '/public';
|
||||
protected $writerType = '.xlsx';
|
||||
protected $fileName;
|
||||
protected $filePath;
|
||||
protected $fileUrl;
|
||||
protected $diskOptions;
|
||||
protected $list;
|
||||
public $chunkCompareEnable = true;
|
||||
|
||||
public $withSummary = false;
|
||||
|
||||
public $chunkCompareOptions = [
|
||||
'key' => 'id',
|
||||
'symbol' => '<'
|
||||
];
|
||||
|
||||
public function __construct(array $params = [])
|
||||
{
|
||||
$this->params = $params;
|
||||
$this->init();
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function query()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function array(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function collection(): Collection
|
||||
{
|
||||
return new Collection([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出时每行的数据
|
||||
*/
|
||||
public function map($item): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出时的表头
|
||||
*/
|
||||
public function headings(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function summary(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function rangeQueryItems($items)
|
||||
{
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出时文件后缀
|
||||
*/
|
||||
public function getExtension()
|
||||
{
|
||||
/* $extensions = [
|
||||
Excel::XLSX => '.xlsx',
|
||||
Excel::CSV => '.csv',
|
||||
// Excel::TSV => '.tsv',
|
||||
Excel::ODS => '.ods',
|
||||
Excel::XLS => '.xls',
|
||||
Excel::HTML => '.html',
|
||||
Excel::MPDF => '.pdf',
|
||||
Excel::DOMPDF => '.pdf',
|
||||
Excel::TCPDF => '.pdf',
|
||||
];
|
||||
|
||||
return $extensions[$this->writerType] ?? '.xlsx'; */
|
||||
return '.xlsx';
|
||||
}
|
||||
|
||||
public function generateFileName()
|
||||
{
|
||||
$uniqueCode = Excel::generateUniqueCode($this->params, '', 8);
|
||||
if (!$this->name) {
|
||||
$this->fileName = date('YmdHis') . $uniqueCode;
|
||||
} else {
|
||||
$this->fileName = date('YmdHis') . $uniqueCode . '_' . $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateFilePath()
|
||||
{
|
||||
if (!$this->fileName) {
|
||||
$this->generateFileName();
|
||||
}
|
||||
$excelPath = getRoutePrefix() . '/excels/';
|
||||
if (!is_dir($this->basePath . $excelPath)) {
|
||||
mkdir($this->basePath . $excelPath);
|
||||
}
|
||||
$this->fileUrl = $excelPath . $this->fileName. $this->getExtension();
|
||||
$this->filePath = $this->basePath . $this->fileUrl;
|
||||
}
|
||||
|
||||
public function getMode()
|
||||
{
|
||||
return self::MODE_QUERY;
|
||||
}
|
||||
|
||||
protected function prepare()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
$this->prepare();
|
||||
$this->generateFilePath();
|
||||
$exporter = new Exporter();
|
||||
$exporter->store($this, $this->filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回设置单元格样式的函数 function(Export, Worksheet)
|
||||
*/
|
||||
public function getStyleSetting(): ?Closure
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setFileName($fileName)
|
||||
{
|
||||
return $this->fileName = $fileName;
|
||||
}
|
||||
|
||||
public function getFileName()
|
||||
{
|
||||
return $this->fileName;
|
||||
}
|
||||
|
||||
public function getFileUrl()
|
||||
{
|
||||
return $this->fileUrl;
|
||||
}
|
||||
|
||||
protected function check()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static function identity()
|
||||
{
|
||||
return Str::encrypt(static::class);
|
||||
}
|
||||
|
||||
public static function getClassByIdentity($identity)
|
||||
{
|
||||
return Str::decrypt($identity);
|
||||
}
|
||||
}
|
@ -0,0 +1,190 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Style;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class Exporter
|
||||
{
|
||||
private $styleSettingClosure;
|
||||
|
||||
/**
|
||||
* @param object $export
|
||||
* @param string|null $fileName
|
||||
* @param string $writerType
|
||||
* @param array $headers
|
||||
*
|
||||
* @throws \PhpOffice\PhpSpreadsheet\Exception
|
||||
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
|
||||
* @return BinaryFileResponse
|
||||
*/
|
||||
public function download($export, string $fileName, string $writerType = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $export
|
||||
* @param string $filePath
|
||||
* @param string|null $disk
|
||||
* @param string $writerType
|
||||
* @param mixed $diskOptions
|
||||
*
|
||||
* @throws \PhpOffice\PhpSpreadsheet\Exception
|
||||
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
|
||||
* @return bool
|
||||
*/
|
||||
public function store(Export $export, string $filePath, string $writerType = null)
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$this->fillHeading($export, $sheet);
|
||||
$this->fillData($export, $sheet);
|
||||
$this->setAutoSize($export, $sheet);
|
||||
$closure = $export->getStyleSetting();
|
||||
if ($closure) {
|
||||
$closure($export, $sheet);
|
||||
}
|
||||
|
||||
$writer = new Xlsx($spreadsheet);
|
||||
$writer->save($filePath);
|
||||
}
|
||||
|
||||
private function fillHeading(Export $export, Worksheet $sheet)
|
||||
{
|
||||
$rowIndex = 0;
|
||||
$firstCellKey = null;
|
||||
$lastCellKey = null;
|
||||
foreach ($export->headings() as $columnIndex => $name) {
|
||||
$cellKey = $this->getCellKey($rowIndex, $columnIndex);
|
||||
$sheet->setCellValue($cellKey, $name);
|
||||
if ($columnIndex == 0) {
|
||||
$firstCellKey = $cellKey;
|
||||
}
|
||||
$lastCellKey = $cellKey;
|
||||
}
|
||||
|
||||
$this->setHeadingStyle($sheet, $firstCellKey . ':' . $lastCellKey);
|
||||
}
|
||||
|
||||
private function fillData(Export $export, Worksheet $sheet, $rowIndex = 1)
|
||||
{
|
||||
$mode = $export->getMode();
|
||||
if ($mode == Export::MODE_QUERY) {
|
||||
$rowIndex = $this->fillFromQuery($export, $sheet, $rowIndex);
|
||||
} elseif ($mode == Export::MODE_ARRAY) {
|
||||
$rowIndex = $this->fillFromArray($export, $sheet, $rowIndex);
|
||||
} elseif ($mode == Export::MODE_COLLECTION) {
|
||||
$rowIndex = $this->fillFromCollection($export, $sheet, $rowIndex);
|
||||
}
|
||||
|
||||
$summary = $export->withSummary ? $export->summary() : null;
|
||||
if (!empty($summary)) {
|
||||
$rowIndex = $this->fillItems($export, $sheet, [$summary], $rowIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private function setHeadingStyle(Worksheet $sheet, $cellRange)
|
||||
{
|
||||
$sharedStyle = new Style();
|
||||
$sharedStyle->applyFromArray(
|
||||
[
|
||||
'fill' => [
|
||||
'fillType' => Fill::FILL_SOLID,
|
||||
'color' => ['argb' => 'd9d9d9'],
|
||||
],
|
||||
'borders' => [
|
||||
'allBorders' => ['borderStyle' => Border::BORDER_THIN],
|
||||
],
|
||||
'font' => [
|
||||
'name' => '黑体',
|
||||
'bold' => true,
|
||||
'size' => 12
|
||||
]
|
||||
]
|
||||
);
|
||||
$sheet->duplicateStyle($sharedStyle, $cellRange);
|
||||
}
|
||||
|
||||
private function fillFromQuery(Export $export, Worksheet $sheet, $rowIndex)
|
||||
{
|
||||
$query = $export->query();
|
||||
if (is_null($query)) {
|
||||
throw new BusinessException('query 方法未实现');
|
||||
}
|
||||
$page = 1;
|
||||
$limit = 1000;
|
||||
$chunkCompareValue = null;
|
||||
$isFirstRound = true;
|
||||
do {
|
||||
$tmpQuery = clone $query;
|
||||
$offset = ($page-1) * $limit;
|
||||
$items = null;
|
||||
if ($export->chunkCompareEnable) {
|
||||
$options = $export->chunkCompareOptions;
|
||||
if (!$isFirstRound) {
|
||||
$tmpQuery->where($options['key'], $options['symbol'], $chunkCompareValue);
|
||||
}
|
||||
$items = $tmpQuery->limit($limit)->get();
|
||||
$lastItem = $items->last();
|
||||
$chunkCompareValue = $lastItem ? $lastItem->{$options['key']} : null;
|
||||
} else {
|
||||
$items = $tmpQuery->offset($offset)->limit($limit)->get();
|
||||
}
|
||||
$items = $export->rangeQueryItems($items);
|
||||
$rowIndex = $this->fillItems($export, $sheet, $items, $rowIndex);
|
||||
$isFirstRound = false;
|
||||
$count = count($items);
|
||||
$page ++;
|
||||
} while ($count == $limit);
|
||||
return $rowIndex;
|
||||
}
|
||||
|
||||
private function fillFromArray(Export $export, Worksheet $sheet, $rowIndex)
|
||||
{
|
||||
return $this->fillItems($export, $sheet, $export->array(), $rowIndex);
|
||||
}
|
||||
|
||||
private function fillFromCollection(Export $export, Worksheet $sheet, $rowIndex)
|
||||
{
|
||||
return $this->fillItems($export, $sheet, $export->collection(), $rowIndex);
|
||||
}
|
||||
|
||||
private function fillItems(Export $export, Worksheet $sheet, $items, $rowIndex)
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
foreach ($export->map($item) as $columnIndex => $value) {
|
||||
$cellKey = $this->getCellKey($rowIndex, $columnIndex);
|
||||
$sheet->setCellValue($cellKey, $value);
|
||||
}
|
||||
$rowIndex += 1;
|
||||
}
|
||||
return $rowIndex;
|
||||
}
|
||||
|
||||
private function concatCellKey($rowKey, $columnKey)
|
||||
{
|
||||
return $columnKey . $rowKey;
|
||||
}
|
||||
|
||||
private function getCellKey($rowIndex, $columnIndex)
|
||||
{
|
||||
return $this->concatCellKey($rowIndex + 1, Excel::getColumnKey($columnIndex));
|
||||
}
|
||||
|
||||
private function setAutoSize(Export $export, Worksheet $sheet)
|
||||
{
|
||||
foreach ($export->headings() as $columnIndex => $name) {
|
||||
$columnKey = Excel::getColumnKey($columnIndex);
|
||||
$sheet->getColumnDimension($columnKey)->setAutoSize(true);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use App\Annotation\Validation\After;
|
||||
use App\Exception\BusinessException;
|
||||
use App\Exception\ValidationException;
|
||||
use Hyperf\Contract\ValidatorInterface;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\Utils\Contracts\MessageBag;
|
||||
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
|
||||
|
||||
class Form implements Logic
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var ValidatorFactoryInterface
|
||||
*/
|
||||
protected $validationFactory;
|
||||
|
||||
protected $_data = [];
|
||||
|
||||
protected $scene;
|
||||
|
||||
protected $isCheckScene;
|
||||
|
||||
protected $scenes = [];
|
||||
|
||||
/**
|
||||
* @var ValidatorInterface $validator
|
||||
*/
|
||||
protected $validator;
|
||||
|
||||
/**
|
||||
* @param array $data 表单数据
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
foreach ($this->defaults() as $key => $value) {
|
||||
if (isset($data[$key])) {
|
||||
if (empty($value) && empty($data[$key])) {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
} else {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
}
|
||||
$this->_data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表单参数默认值,暂不支持多维数组
|
||||
* @return array
|
||||
*/
|
||||
public function defaults(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function attributes(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function before()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected final function handleBefore()
|
||||
{
|
||||
$this->before();
|
||||
$this->checkScene();
|
||||
}
|
||||
|
||||
protected function getRules()
|
||||
{
|
||||
$rules = $this->rules();
|
||||
$scene = $this->getScene();
|
||||
if ($scene && isset($this->scenes[$scene]) && is_array($this->scenes[$scene])) {
|
||||
$newRules = [];
|
||||
foreach ($this->scenes[$scene] as $field) {
|
||||
if (array_key_exists($field, $rules)) {
|
||||
$newRules[$field] = $rules[$field];
|
||||
}
|
||||
}
|
||||
return $newRules;
|
||||
}
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public final function validate($throwException = true)
|
||||
{
|
||||
$this->handleBefore();
|
||||
$this->validator = $this->validationFactory->make($this->_data, $this->getRules(), $this->messages(), $this->attributes());
|
||||
$this->handleAfter();
|
||||
|
||||
$fails = $this->validator->fails();
|
||||
if ($throwException && $fails) {
|
||||
throw new BusinessException($this->getErrorMessage());
|
||||
}
|
||||
|
||||
return !$fails;
|
||||
}
|
||||
|
||||
protected function after()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected final function handleAfter()
|
||||
{
|
||||
$this->validator->after(function ($validator) {
|
||||
$items = Annotation::getMethodsByAnnotationAndClass(After::class, static::class);
|
||||
foreach ($items as $item) {
|
||||
if (empty($item['annotation']->scenes) || in_array($this->scene, $item['annotation']->scenes)) {
|
||||
$this->{$item['method']}();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$this->after();
|
||||
}
|
||||
|
||||
public function addError($field, $message)
|
||||
{
|
||||
$this->validator->errors()->add($field, $message);
|
||||
}
|
||||
|
||||
public function errors(): MessageBag
|
||||
{
|
||||
return $this->validator->errors();
|
||||
}
|
||||
|
||||
public function getErrorMessage($isAll = false): string
|
||||
{
|
||||
if ($this->errors()->count() > 0) {
|
||||
$messages = $this->errors()->all();
|
||||
return $isAll ? implode('', $messages) : $messages[0];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public final function getData()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
public final function getSceneData()
|
||||
{
|
||||
$scene = $this->getScene();
|
||||
if ($scene && isset($this->scenes[$scene]) && is_array($this->scenes[$scene])) {
|
||||
$newData = [];
|
||||
foreach ($this->scenes[$scene] as $field) {
|
||||
if (array_key_exists($field, $this->_data)) {
|
||||
$newData[$field] = $this->_data[$field];
|
||||
}
|
||||
}
|
||||
return $newData;
|
||||
}
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $scene 场景名称
|
||||
* @param bool $isCheckScene 是否检查场景是否存在
|
||||
*/
|
||||
public final function setScene(string $scene, bool $isCheckScene = true): void
|
||||
{
|
||||
$this->scene = $scene;
|
||||
$this->isCheckScene = $isCheckScene;
|
||||
}
|
||||
|
||||
protected final function checkScene()
|
||||
{
|
||||
if ($this->getScene() && $this->isCheckScene && !isset($this->scenes[$this->scene])) {
|
||||
throw new BusinessException('Scene undefined!');
|
||||
}
|
||||
}
|
||||
|
||||
public final function getScene()
|
||||
{
|
||||
return $this->scene;
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
return isset($this->_data[$key]) ? $this->_data[$key] : null;
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this->_data[$key] = $value;
|
||||
}
|
||||
|
||||
public function __isset($key)
|
||||
{
|
||||
return $this->__get($key);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
use Hyperf\HttpServer\Router\Router;
|
||||
|
||||
if (!function_exists('loadRoutes')) {
|
||||
/**
|
||||
* 加载路由.
|
||||
*/
|
||||
function loadRoutes($path)
|
||||
{
|
||||
$files = scandir($path);
|
||||
foreach ($files as $file) {
|
||||
if ($file == '.' || $file == '..') {
|
||||
continue;
|
||||
}
|
||||
$filePath = $path . '/' . $file;
|
||||
if (is_dir($filePath)) {
|
||||
$prefix = '/' . $file;
|
||||
$options = [];
|
||||
if (file_exists($filePath . '/_init.php')) {
|
||||
$config = require($filePath . '/_init.php');
|
||||
$prefix = $config['prefix'] ?? $prefix;
|
||||
$options = $config['options'] ?? $options;
|
||||
}
|
||||
Router::addGroup($prefix, function () use ($filePath) {
|
||||
loadRoutes($filePath);
|
||||
}, $options);
|
||||
} elseif (is_file($filePath)) {
|
||||
if ($file == '_init.php') {
|
||||
continue;
|
||||
}
|
||||
require_once $filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('getClientIp')) {
|
||||
function getClientIp(RequestInterface $request)
|
||||
{
|
||||
$headers = $request->getHeaders();
|
||||
if(isset($headers['x-forwarded-for'][0]) && !empty($headers['x-forwarded-for'][0])) {
|
||||
$ips = explode(',', $headers['x-forwarded-for'][0]);
|
||||
return trim($ips[0]);
|
||||
} elseif (isset($headers['x-real-ip'][0]) && !empty($headers['x-real-ip'][0])) {
|
||||
return $headers['x-real-ip'][0];
|
||||
}
|
||||
|
||||
$serverParams = $request->getServerParams();
|
||||
return $serverParams['remote_addr'] ?? '';
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use Hyperf\Database\Model\Collection;
|
||||
|
||||
class ListExport extends Export implements Logic
|
||||
{
|
||||
protected $params;
|
||||
|
||||
/**
|
||||
* @var DataList
|
||||
*/
|
||||
protected $list;
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$this->generateList();
|
||||
if (empty($this->name)) {
|
||||
$this->name = $this->list->name;
|
||||
}
|
||||
$this->check();
|
||||
}
|
||||
|
||||
public function query()
|
||||
{
|
||||
return $this->list->query();
|
||||
}
|
||||
|
||||
public function array(): array
|
||||
{
|
||||
return $this->list->getRecords();
|
||||
}
|
||||
|
||||
public function summary(): array
|
||||
{
|
||||
return $this->list->getSummary();
|
||||
}
|
||||
|
||||
public function rangeQueryItems($items)
|
||||
{
|
||||
$this->list->generateRecords($items);
|
||||
return $this->list->getRecords();
|
||||
}
|
||||
|
||||
protected function prepare()
|
||||
{
|
||||
$query = $this->query();
|
||||
if ($this->getMode() == self::MODE_QUERY) {
|
||||
if (is_null($query)) {
|
||||
throw new BusinessException('query不能为空');
|
||||
}
|
||||
} else {
|
||||
$items = new Collection([]);
|
||||
if (!is_null($query)) {
|
||||
$items = $query->get();
|
||||
}
|
||||
$this->list->generateRecords($items);
|
||||
}
|
||||
}
|
||||
|
||||
protected function listClass()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function generateList()
|
||||
{
|
||||
$class = $this->listClass();
|
||||
if ($class) {
|
||||
$this->list = new $class($this->params);
|
||||
} else {
|
||||
throw new BusinessException('未配置对应DataList');
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use Hyperf\Logger\LoggerFactory;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
|
||||
class Log
|
||||
{
|
||||
public static function get(string $name = 'app')
|
||||
{
|
||||
return ApplicationContext::getContainer()->get(LoggerFactory::class)->get($name);
|
||||
}
|
||||
|
||||
public static function __callStatic($method, $args)
|
||||
{
|
||||
$name = 'app';
|
||||
if (isset($args[2])) {
|
||||
$name = $args[2];
|
||||
unset($args[2]);
|
||||
}
|
||||
return call_user_func_array([self::get($name), $method], $args);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
interface Logic
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper\Macro;
|
||||
|
||||
use App\Helper\Str;
|
||||
use Hyperf\Database\Model\Builder;
|
||||
use Hyperf\Database\Model\Relations;
|
||||
|
||||
class WhereHasIn
|
||||
{
|
||||
/**
|
||||
* @var Builder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $relation;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $nextRelation;
|
||||
|
||||
/**
|
||||
* @var \Closure
|
||||
*/
|
||||
protected $callback;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $method = 'whereIn';
|
||||
|
||||
public function __construct(Builder $builder, $relation, $callback)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->relation = $relation;
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if (! $this->relation) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
return $this->where(
|
||||
$this->formatRelation()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Relations\Relation $relation
|
||||
*
|
||||
* @return Builder
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function where($relation)
|
||||
{
|
||||
if ($relation instanceof Relations\MorphTo) {
|
||||
throw new \Exception('Please use whereHasMorphIn() for MorphTo relationships.');
|
||||
}
|
||||
|
||||
$relationQuery = $this->getRelationQuery($relation);
|
||||
$method = $this->method;
|
||||
|
||||
if (
|
||||
$relation instanceof Relations\MorphOne
|
||||
|| $relation instanceof Relations\MorphMany
|
||||
) {
|
||||
return $this->builder->{$method}(
|
||||
$relation->getQualifiedParentKeyName(),
|
||||
$this->withRelationQueryCallback(
|
||||
$relationQuery
|
||||
->select($relation->getQualifiedForeignKeyName())
|
||||
->whereColumn($relation->getQualifiedParentKeyName(), $relation->getQualifiedForeignKeyName())
|
||||
->where($relation->getQualifiedMorphType(), $relation->getMorphClass())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($relation instanceof Relations\MorphToMany) {
|
||||
return $this->builder->{$method}(
|
||||
$relation->getQualifiedParentKeyName(),
|
||||
$this->withRelationQueryCallback(
|
||||
$relationQuery
|
||||
->select($relation->getQualifiedForeignPivotKeyName())
|
||||
->whereColumn($relation->getQualifiedParentKeyName(), $relation->getQualifiedForeignPivotKeyName())
|
||||
->where($relation->getTable().'.'.$relation->getMorphType(), $relation->getMorphClass())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// BelongsTo
|
||||
if ($relation instanceof Relations\BelongsTo) {
|
||||
return $this->builder->{$method}(
|
||||
$this->getRelationQualifiedForeignKeyName($relation),
|
||||
$this->withRelationQueryCallback(
|
||||
$relationQuery
|
||||
->select($relation->getQualifiedOwnerKeyName())
|
||||
->whereColumn($this->getRelationQualifiedForeignKeyName($relation), $relation->getQualifiedOwnerKeyName())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
$relation instanceof Relations\HasOne
|
||||
|| $relation instanceof Relations\HasMany
|
||||
) {
|
||||
return $this->builder->{$method}(
|
||||
$relation->getQualifiedParentKeyName(),
|
||||
$this->withRelationQueryCallback(
|
||||
$relationQuery
|
||||
->select($relation->getQualifiedForeignKeyName())
|
||||
->whereColumn($relation->getQualifiedParentKeyName(), $relation->getQualifiedForeignKeyName())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// BelongsToMany
|
||||
if ($relation instanceof Relations\BelongsToMany) {
|
||||
return $this->builder->{$method}(
|
||||
$relation->getQualifiedParentKeyName(),
|
||||
$this->withRelationQueryCallback(
|
||||
$relationQuery
|
||||
->select($relation->getQualifiedForeignPivotKeyName())
|
||||
->whereColumn($relation->getQualifiedParentKeyName(), $relation->getQualifiedForeignPivotKeyName())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
$relation instanceof Relations\HasOneThrough
|
||||
|| $relation instanceof Relations\HasManyThrough
|
||||
) {
|
||||
return $this->builder->{$method}(
|
||||
$relation->getQualifiedLocalKeyName(),
|
||||
$this->withRelationQueryCallback(
|
||||
$relationQuery
|
||||
->select($relation->getQualifiedFirstKeyName())
|
||||
->whereColumn($relation->getQualifiedLocalKeyName(), $relation->getQualifiedFirstKeyName())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
throw new \Exception(sprintf('%s does not support "whereHasIn".', get_class($relation)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Relations\Relation $relation
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
protected function getRelationQuery($relation)
|
||||
{
|
||||
$q = $relation->getQuery();
|
||||
|
||||
if ($this->builder->getModel()->getConnectionName() !== $q->getModel()->getConnectionName()) {
|
||||
$databaseName = $this->getRelationDatabaseName($q);
|
||||
$table = $q->getModel()->getTable();
|
||||
|
||||
if (! Str::contains($table, ["`$databaseName`.", "{$databaseName}."])) {
|
||||
$q->from("{$databaseName}.{$table}");
|
||||
}
|
||||
}
|
||||
|
||||
return $q;
|
||||
}
|
||||
|
||||
protected function getRelationDatabaseName($q)
|
||||
{
|
||||
return config('database.connections.'.$q->getModel()->getConnectionName().'.database');
|
||||
}
|
||||
|
||||
protected function getRelationQualifiedForeignKeyName($relation)
|
||||
{
|
||||
if (method_exists($relation, 'getQualifiedForeignKeyName')) {
|
||||
return $relation->getQualifiedForeignKeyName();
|
||||
}
|
||||
|
||||
return $relation->getQualifiedForeignKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Relations\Relation
|
||||
*/
|
||||
protected function formatRelation()
|
||||
{
|
||||
if (is_object($this->relation)) {
|
||||
$relation = $this->relation;
|
||||
} else {
|
||||
$relationNames = explode('.', $this->relation);
|
||||
$this->nextRelation = implode('.', array_slice($relationNames, 1));
|
||||
|
||||
$method = $relationNames[0];
|
||||
|
||||
$relation = Relations\Relation::noConstraints(function () use ($method) {
|
||||
return $this->builder->getModel()->$method();
|
||||
});
|
||||
}
|
||||
|
||||
return $relation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Builder $relation
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
protected function withRelationQueryCallback($relationQuery)
|
||||
{
|
||||
return call_user_func($this->callback, $this->nextRelation, $relationQuery);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper\Macro;
|
||||
|
||||
use Hyperf\Database\Model\Relations\Relation;
|
||||
|
||||
class WhereHasMorphIn
|
||||
{
|
||||
public static function make()
|
||||
{
|
||||
return function ($relation, $types, $callback = null, $boolean = 'and') {
|
||||
$relation = $this->getRelationWithoutConstraints($relation);
|
||||
|
||||
$types = (array) $types;
|
||||
|
||||
if ($types === ['*']) {
|
||||
$types = $this->model->newModelQuery()->distinct()->pluck($relation->getMorphType())->all();
|
||||
|
||||
foreach ($types as &$type) {
|
||||
$type = Relation::getMorphedModel($type) ?? $type;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->where(function ($query) use ($relation, $callback, $types) {
|
||||
foreach ($types as $type) {
|
||||
$query->orWhere(function ($query) use ($relation, $callback, $type) {
|
||||
$belongsTo = $this->getBelongsToRelation($relation, $type);
|
||||
|
||||
if ($callback) {
|
||||
$callback = function ($query) use ($callback, $type) {
|
||||
return $callback($query, $type);
|
||||
};
|
||||
}
|
||||
|
||||
$query->where($relation->getRelated()->getTable().'.'.$relation->getMorphType(), '=', (new $type)->getMorphClass())
|
||||
->whereHasIn($belongsTo, $callback);
|
||||
});
|
||||
}
|
||||
}, null, null, $boolean);
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper\Macro;
|
||||
|
||||
class WhereHasNotIn extends WhereHasIn
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $method = 'whereNotIn';
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use Hyperf\Database\Model\Relations\Relation;
|
||||
|
||||
class Morph
|
||||
{
|
||||
/**
|
||||
* 只支持多态关联实体的关联键为id
|
||||
*
|
||||
* @param int $morphId
|
||||
* @param string $morphType
|
||||
* @return void
|
||||
*/
|
||||
public static function getMorph(int $morphId, string $morphType)
|
||||
{
|
||||
$class = self::getMorphClass($morphType);
|
||||
if (is_null($class)) {
|
||||
throw new BusinessException('Morph type error!');
|
||||
}
|
||||
return $class::where('id', $morphId)->first();
|
||||
}
|
||||
|
||||
public static function getMorphClass(string $morphType): ?string
|
||||
{
|
||||
return Relation::$morphMap[$morphType] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证评论类型是否存在
|
||||
*
|
||||
* @param string $morphType
|
||||
* @return void
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public static function checkMorphType(string $morphType)
|
||||
{
|
||||
if (is_null(self::getMorphClass($morphType))) {
|
||||
throw new BusinessException('Morph type error!');
|
||||
}
|
||||
}
|
||||
|
||||
public static function instanceOf(string $morphType, $instance): bool
|
||||
{
|
||||
return get_class($instance) === self::getMorphClass($morphType);
|
||||
}
|
||||
|
||||
public static function getMorphTypeOfInstance(object $instance): string
|
||||
{
|
||||
return self::getMorphType(get_class($instance));
|
||||
}
|
||||
|
||||
public static function getMorphType(string $class): string
|
||||
{
|
||||
$morphMap = Relation::$morphMap;
|
||||
$morphMap = array_flip($morphMap);
|
||||
return $morphMap[$class] ?? '';
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use Hyperf\AsyncQueue\Driver\DriverFactory;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
|
||||
class Queue
|
||||
{
|
||||
private static $factory;
|
||||
|
||||
private static function getFactory()
|
||||
{
|
||||
if (is_null(self::$factory)) {
|
||||
self::$factory = ApplicationContext::getContainer()->get(DriverFactory::class);
|
||||
}
|
||||
return self::$factory;
|
||||
}
|
||||
|
||||
public static function push($jobClass, $params, int $delay = 0): bool
|
||||
{
|
||||
$job = new $jobClass($params);
|
||||
return self::getFactory()->get($job->getQueueName())->push($job, $delay);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use Hyperf\Redis\RedisFactory;
|
||||
use Hyperf\Redis\RedisProxy;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
|
||||
/**
|
||||
* Redis辅助类
|
||||
*/
|
||||
class Redis
|
||||
{
|
||||
/**
|
||||
* @var RedisFactory
|
||||
*/
|
||||
private static $factory;
|
||||
|
||||
private static function getFactory(): RedisFactory
|
||||
{
|
||||
if (is_null(self::$factory)) {
|
||||
self::$factory = ApplicationContext::getContainer()->get(RedisFactory::class);
|
||||
}
|
||||
return self::$factory;
|
||||
}
|
||||
|
||||
public static function getInstance($poolName = 'default'): RedisProxy
|
||||
{
|
||||
return self::getFactory()->get($poolName);
|
||||
}
|
||||
|
||||
public static function __callStatic($method, $args)
|
||||
{
|
||||
return call_user_func_array([self::getInstance(), $method], $args);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use App\Constants\ResultCode;
|
||||
use Hyperf\Utils\Contracts\Arrayable;
|
||||
|
||||
class Result implements Arrayable
|
||||
{
|
||||
private $code;
|
||||
private $message;
|
||||
private $data = [];
|
||||
|
||||
public function __construct(int $code = ResultCode::SUCCESS, string $message = '', array $data = [])
|
||||
{
|
||||
$this->code = $code;
|
||||
$this->message = empty($message) ? ResultCode::getMessage($code) : $message;
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function getCode(): int
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setCode(int $code)
|
||||
{
|
||||
return $this->code = $code;
|
||||
}
|
||||
|
||||
public function getMessage(): string
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
public function setMessage(string $message)
|
||||
{
|
||||
return $this->message = empty($message) ? ResultCode::getMessage($this->code) : $message;
|
||||
}
|
||||
|
||||
public function getData(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function setData(array $data)
|
||||
{
|
||||
return $this->data = $data;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'code' => $this->code,
|
||||
'message' => $this->message,
|
||||
'data' => new \ArrayObject($this->data),
|
||||
];
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use Hyperf\Utils\Str as BaseStr;
|
||||
|
||||
class Str extends BaseStr
|
||||
{
|
||||
const PASSPHRASE = 'O0IP563o9WjoogRNFGN4';
|
||||
const CIPHER_ALGO = 'aes-256-cbc';
|
||||
|
||||
public static function getRandomString($length, $special = true)
|
||||
{
|
||||
$chars = array(
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
|
||||
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
|
||||
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2',
|
||||
'3', '4', '5', '6', '7', '8', '9'
|
||||
);
|
||||
|
||||
if($special){
|
||||
$chars = array_merge($chars, array(
|
||||
'!', '@', '#', '$', '?', '|', '{', '/', ':', ';',
|
||||
'%', '^', '&', '*', '(', ')', '-', '_', '[', ']',
|
||||
'}', '<', '>', '~', '+', '=', ',', '.'
|
||||
));
|
||||
}
|
||||
|
||||
$charsLen = count($chars) - 1;
|
||||
shuffle($chars);
|
||||
|
||||
$password = '';
|
||||
for($i=0; $i<$length; $i++){
|
||||
$password .= $chars[mt_rand(0, $charsLen)];
|
||||
}
|
||||
|
||||
return $password;
|
||||
}
|
||||
|
||||
public static function encrypt(string $data)
|
||||
{
|
||||
$iv = '62dTsnuD1Ow68pR8';
|
||||
return openssl_encrypt($data, self::CIPHER_ALGO, self::PASSPHRASE, 0, $iv);
|
||||
}
|
||||
|
||||
public static function decrypt(string $password)
|
||||
{
|
||||
$iv = '62dTsnuD1Ow68pR8';
|
||||
return openssl_decrypt($password, self::CIPHER_ALGO, self::PASSPHRASE, 0, $iv);
|
||||
}
|
||||
|
||||
public static function parseUrl(string $url)
|
||||
{
|
||||
if (empty($url)) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$item = explode(':', $url);
|
||||
if (!isset($item[0]) || in_array($item[0], ['http', 'https'])) {
|
||||
return $url;
|
||||
}
|
||||
return self::getFileUrlViaStorage($item[1], $item[0]);
|
||||
}
|
||||
|
||||
public static function getFileUrlViaStorage(string $url, string $storage): string
|
||||
{
|
||||
$domain = config('file.storage.' . $storage . '.domain');
|
||||
$prefixPath = config('file.storage.' . $storage . '.prefix_path', '');
|
||||
return $domain . $prefixPath . $url;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
class Time
|
||||
{
|
||||
public static function getDateList($start, $end)
|
||||
{
|
||||
$startTime = strtotime($start . ' 00:00:00');
|
||||
$endTime = strtotime($end . ' 00:00:00');
|
||||
$dateList = [];
|
||||
while ($startTime <= $endTime) {
|
||||
$dateList[] = date('Y-m-d', $startTime);
|
||||
$startTime += 24 * 60 * 60;
|
||||
}
|
||||
return $dateList;
|
||||
}
|
||||
|
||||
public static function dateTimeRange(array $dateRange, $withTime = true)
|
||||
{
|
||||
if (!isset($dateRange[0]) || !isset($dateRange[1]) || count($dateRange) != 2) {
|
||||
throw new \Exception('dateTimeRange param is error');
|
||||
}
|
||||
$dateRangeWithTime = false;
|
||||
if (
|
||||
self::checkFormatTime($dateRange[0], 'Y-m-d') &&
|
||||
self::checkFormatTime($dateRange[1], 'Y-m-d')
|
||||
) {
|
||||
$dateRangeWithTime = false;
|
||||
} elseif (
|
||||
self::checkFormatTime($dateRange[0], 'Y-m-d H:i:s') &&
|
||||
self::checkFormatTime($dateRange[1], 'Y-m-d H:i:s')
|
||||
) {
|
||||
$dateRangeWithTime = true;
|
||||
} else {
|
||||
throw new \Exception('dateTimeRange format is error');
|
||||
}
|
||||
|
||||
if ($withTime && !$dateRangeWithTime) {
|
||||
return [$dateRange[0] . ' 00:00:00', $dateRange[1] . ' 23:59:59'];
|
||||
} elseif (!$withTime && $dateRangeWithTime) {
|
||||
return [date('Y-m-d', strtotime($dateRange[0])), date('Y-m-d', strtotime($dateRange[1]))];
|
||||
}
|
||||
|
||||
return $dateRange;
|
||||
}
|
||||
|
||||
public static function checkFormatTime($timeString, $format = 'Y-m-d H:i:s') {
|
||||
$timestamp = strtotime($timeString);
|
||||
if (!$timestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(date($format, $timestamp) === $timeString) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getMonthLastDate($month)
|
||||
{
|
||||
$firstDate = $month . '-01';
|
||||
return date('Y-m-d', strtotime($firstDate . ' +1 month -1 day'));
|
||||
}
|
||||
|
||||
public static function getMonthDateRange($month)
|
||||
{
|
||||
$carbon = Carbon::parse($month);
|
||||
return [
|
||||
$carbon->firstOfMonth()->format('Y-m-d'),
|
||||
$carbon->lastOfMonth()->format('Y-m-d')
|
||||
];
|
||||
}
|
||||
|
||||
public static function getLastMonth()
|
||||
{
|
||||
return Carbon::now()->subMonth()->format('Y-m');
|
||||
}
|
||||
|
||||
public static function getNextMonth()
|
||||
{
|
||||
return Carbon::now()->addMonth()->format('Y-m');
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Job;
|
||||
|
||||
use App\Service\UserService;
|
||||
|
||||
class AfterLoginJob extends Job
|
||||
{
|
||||
public function handle()
|
||||
{
|
||||
$userId = (int)$this->params['user_id'] ?? 0;
|
||||
$gameId = (int)$this->params['game_id'] ?? 0;
|
||||
$loginTime = (int)$this->params['login_time'] ?? 0;
|
||||
|
||||
/**
|
||||
* @var UserService $userService
|
||||
*/
|
||||
$userService = make(UserService::class);
|
||||
$userService->afterLogin($userId, $gameId, $loginTime);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Job;
|
||||
|
||||
use App\Service\UserService;
|
||||
|
||||
class AfterRegisterJob extends Job
|
||||
{
|
||||
public function handle()
|
||||
{
|
||||
$userId = $this->params['user_id'] ?? '';
|
||||
|
||||
/**
|
||||
* @var UserService $userService
|
||||
*/
|
||||
$userService = make(UserService::class);
|
||||
$userService->afterRegister($userId);
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Job;
|
||||
|
||||
use App\Service\PlayerRoleService;
|
||||
|
||||
class AfterSaveRoleJob extends Job
|
||||
{
|
||||
public function handle()
|
||||
{
|
||||
/**
|
||||
* @var PlayerRoleService $playerRoleService
|
||||
*/
|
||||
$playerRoleService = make(PlayerRoleService::class);
|
||||
$playerRoleService->save($this->params);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Job;
|
||||
|
||||
use App\Service\SpendService;
|
||||
|
||||
class AfterSpendJob extends Job
|
||||
{
|
||||
public function handle()
|
||||
{
|
||||
$payOrderNumber = $this->params['pay_order_number'] ?? '';
|
||||
|
||||
/**
|
||||
* @var SpendService $spendService
|
||||
*/
|
||||
$spendService = make(SpendService::class);
|
||||
$spendService->afterSpend($payOrderNumber);
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Job;
|
||||
|
||||
use Hyperf\AsyncQueue\Job as BaseJob;
|
||||
|
||||
class Job extends BaseJob
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $params;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $context;
|
||||
|
||||
protected $queueName = 'default';
|
||||
|
||||
public function __construct(array $params, array $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
$this->params = $this->prepare($params);
|
||||
}
|
||||
|
||||
protected function prepare(array $params): array
|
||||
{
|
||||
return $params;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
}
|
||||
|
||||
protected function getJobName()
|
||||
{
|
||||
return get_called_class();
|
||||
}
|
||||
|
||||
public function getQueueName()
|
||||
{
|
||||
return $this->queueName;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<?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
|
||||
*/
|
||||
namespace App\Listener;
|
||||
|
||||
use Hyperf\Database\Events\QueryExecuted;
|
||||
use Hyperf\Event\Annotation\Listener;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
use Hyperf\Logger\LoggerFactory;
|
||||
use Hyperf\Utils\Arr;
|
||||
use Hyperf\Utils\Str;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* @Listener
|
||||
*/
|
||||
class DbQueryExecutedListener implements ListenerInterface
|
||||
{
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->logger = $container->get(LoggerFactory::class)->get('sql');
|
||||
}
|
||||
|
||||
public function listen(): array
|
||||
{
|
||||
return [
|
||||
QueryExecuted::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param QueryExecuted $event
|
||||
*/
|
||||
public function process(object $event)
|
||||
{
|
||||
if ($event instanceof QueryExecuted) {
|
||||
$sql = $event->sql;
|
||||
if (! Arr::isAssoc($event->bindings)) {
|
||||
foreach ($event->bindings as $key => $value) {
|
||||
$sql = Str::replaceFirst('?', "'{$value}'", $sql);
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->info(sprintf('[%s] %s', $event->time, $sql));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Listener;
|
||||
|
||||
use App\Helper\Macro\WhereHasIn;
|
||||
use App\Helper\Macro\WhereHasMorphIn;
|
||||
use App\Helper\Macro\WhereHasNotIn;
|
||||
use Hyperf\Database\Model\Builder;
|
||||
use Hyperf\Database\Model\Relations\Relation;
|
||||
use Hyperf\Event\Annotation\Listener;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
use Hyperf\Framework\Event\BootApplication;
|
||||
|
||||
/**
|
||||
* @Listener
|
||||
*/
|
||||
class ModelPrepareListener implements ListenerInterface
|
||||
{
|
||||
public function listen(): array
|
||||
{
|
||||
return [
|
||||
BootApplication::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function process(object $event)
|
||||
{
|
||||
$this->morphMapRelation();
|
||||
$this->macroWhereHasIn();
|
||||
}
|
||||
|
||||
private function morphMapRelation()
|
||||
{
|
||||
Relation::morphMap([
|
||||
]);
|
||||
}
|
||||
|
||||
private function macroWhereHasIn()
|
||||
{
|
||||
Builder::macro('whereHasIn', function ($relationName, $callable = null) {
|
||||
return (new WhereHasIn($this, $relationName, function ($nextRelation, $builder) use ($callable) {
|
||||
if ($nextRelation) {
|
||||
return $builder->whereHasIn($nextRelation, $callable);
|
||||
}
|
||||
|
||||
if ($callable) {
|
||||
return $builder->callScope($callable);
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}))->execute();
|
||||
});
|
||||
Builder::macro('orWhereHasIn', function ($relationName, $callable = null) {
|
||||
return $this->orWhere(function ($query) use ($relationName, $callable) {
|
||||
return $query->whereHasIn($relationName, $callable);
|
||||
});
|
||||
});
|
||||
|
||||
Builder::macro('whereHasNotIn', function ($relationName, $callable = null) {
|
||||
return (new WhereHasNotIn($this, $relationName, function ($nextRelation, $builder) use ($callable) {
|
||||
if ($nextRelation) {
|
||||
return $builder->whereHasNotIn($nextRelation, $callable);
|
||||
}
|
||||
|
||||
if ($callable) {
|
||||
return $builder->callScope($callable);
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}))->execute();
|
||||
});
|
||||
Builder::macro('orWhereHasNotIn', function ($relationName, $callable = null) {
|
||||
return $this->orWhere(function ($query) use ($relationName, $callable) {
|
||||
return $query->whereHasNotIn($relationName, $callable);
|
||||
});
|
||||
});
|
||||
|
||||
Builder::macro('whereHasMorphIn', WhereHasMorphIn::make());
|
||||
Builder::macro('orWhereHasMorphIn', function ($relation, $types, $callback = null) {
|
||||
return $this->whereHasMorphIn($relation, $types, $callback, 'or');
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
<?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
|
||||
*/
|
||||
namespace App\Listener;
|
||||
|
||||
use Hyperf\AsyncQueue\AnnotationJob;
|
||||
use Hyperf\AsyncQueue\Event\AfterHandle;
|
||||
use Hyperf\AsyncQueue\Event\BeforeHandle;
|
||||
use Hyperf\AsyncQueue\Event\Event;
|
||||
use Hyperf\AsyncQueue\Event\FailedHandle;
|
||||
use Hyperf\AsyncQueue\Event\RetryHandle;
|
||||
use Hyperf\Event\Annotation\Listener;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
use Hyperf\ExceptionHandler\Formatter\FormatterInterface;
|
||||
use Hyperf\Logger\LoggerFactory;
|
||||
|
||||
/**
|
||||
* @Listener
|
||||
*/
|
||||
class QueueHandleListener implements ListenerInterface
|
||||
{
|
||||
/**
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var FormatterInterface
|
||||
*/
|
||||
protected $formatter;
|
||||
|
||||
public function __construct(LoggerFactory $loggerFactory, FormatterInterface $formatter)
|
||||
{
|
||||
$this->logger = $loggerFactory->get('queue');
|
||||
$this->formatter = $formatter;
|
||||
}
|
||||
|
||||
public function listen(): array
|
||||
{
|
||||
return [
|
||||
AfterHandle::class,
|
||||
BeforeHandle::class,
|
||||
FailedHandle::class,
|
||||
RetryHandle::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function process(object $event)
|
||||
{
|
||||
if ($event instanceof Event && $event->message->job()) {
|
||||
$job = $event->message->job();
|
||||
$jobClass = get_class($job);
|
||||
if ($job instanceof AnnotationJob) {
|
||||
$jobClass = sprintf('Job[%s@%s]', $job->class, $job->method);
|
||||
}
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
switch (true) {
|
||||
case $event instanceof BeforeHandle:
|
||||
$this->logger->info(sprintf('[%s] Processing %s.', $date, $jobClass));
|
||||
break;
|
||||
case $event instanceof AfterHandle:
|
||||
$this->logger->info(sprintf('[%s] Processed %s.', $date, $jobClass));
|
||||
break;
|
||||
case $event instanceof FailedHandle:
|
||||
$this->logger->error(sprintf('[%s] Failed %s.', $date, $jobClass));
|
||||
$this->logger->error($this->formatter->format($event->getThrowable()));
|
||||
break;
|
||||
case $event instanceof RetryHandle:
|
||||
$this->logger->warning(sprintf('[%s] Retried %s.', $date, $jobClass));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class BaseGame extends Model
|
||||
{
|
||||
protected $table = 'tab_base_game';
|
||||
|
||||
public function scopeHasChild($query, $game)
|
||||
{
|
||||
return $query->where(function ($q) use($game) {
|
||||
$q->orWhere('android_game_id', $game->id)->orWhere('ios_game_id', $game->id);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class Game extends Model
|
||||
{
|
||||
protected $table = 'tab_game';
|
||||
|
||||
public function gameSource()
|
||||
{
|
||||
return $this->hasOne(GameSource::class, 'game_id', 'id');
|
||||
}
|
||||
|
||||
public function logo()
|
||||
{
|
||||
return $this->hasOne(Image::class, 'id', 'icon');
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class GameData extends Model
|
||||
{
|
||||
protected $table = 'tab_game_data';
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = ['game_id', 'pay_amount'];
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use App\Scopes\CommonTimeScopes;
|
||||
use Hyperf\DbConnection\Model\Model as BaseModel;
|
||||
|
||||
abstract class Model extends BaseModel
|
||||
{
|
||||
use CommonTimeScopes;
|
||||
|
||||
public static function alias($alias = null)
|
||||
{
|
||||
$name = with(new static)->getTable();
|
||||
if ($alias) {
|
||||
$name .= ' as ' . $alias;
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
public static function fromAlias($alias)
|
||||
{
|
||||
return static::from(static::alias($alias));
|
||||
}
|
||||
|
||||
public function getRawAttribute($key)
|
||||
{
|
||||
if (!$key) {
|
||||
return null;
|
||||
}
|
||||
return $this->attributes[$key] ?? null;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use App\Scopes\CommonPromoteScopes;
|
||||
use App\Scopes\PlayerScopes;
|
||||
|
||||
class Player extends Model
|
||||
{
|
||||
use CommonPromoteScopes;
|
||||
|
||||
protected $table = 'tab_user_play';
|
||||
|
||||
public function promote()
|
||||
{
|
||||
return $this->belongsTo(Promote::class, 'promote_id', 'id');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class PlayerRetention extends Model
|
||||
{
|
||||
|
||||
protected $table = 'tab_player_retention';
|
||||
|
||||
public static $dayList = [1, 2, 3, 4, 5, 6, 7, 15, 30];
|
||||
|
||||
public function player()
|
||||
{
|
||||
return $this->belongsTo(Player::class, 'player_id', 'id');
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use App\Scopes\CommonPromoteScopes;
|
||||
use App\Scopes\PlayerRoleScopes;
|
||||
use App\Helper\DeviceType;
|
||||
|
||||
class PlayerRole extends Model
|
||||
{
|
||||
use CommonPromoteScopes;
|
||||
use PlayerRoleScopes;
|
||||
|
||||
protected $table = 'tab_user_play_info';
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
public function promote()
|
||||
{
|
||||
return $this->belongsTo(Promote::class, 'promote_id', 'id');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||
}
|
||||
|
||||
public function testingBinding()
|
||||
{
|
||||
return $this->hasOne(TestingBinding::class, 'role_key', 'role_key');
|
||||
}
|
||||
|
||||
public function bindTestingBinding()
|
||||
{
|
||||
return $this->hasOne(TestingBinding::class, 'bind_role_key', 'role_key');
|
||||
}
|
||||
|
||||
public function getDeviceTypeNameAttribute()
|
||||
{
|
||||
return DeviceType::getDeviceTypeText($this->sdk_version);
|
||||
}
|
||||
|
||||
public function getBaseGameNameAttribute()
|
||||
{
|
||||
return strtr($this->game_name, ['(安卓版)' => '', '(苹果版)' => '']);
|
||||
}
|
||||
|
||||
public static function generateUniqueCode($gameId, $userId, $roleId)
|
||||
{
|
||||
if (is_null($roleId)) {
|
||||
$roleId = 'UNKNOW';
|
||||
}
|
||||
return substr(md5($gameId . '#' . $userId . '#' . $roleId), 8, 16);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use App\Scopes\PromoteScopes;
|
||||
|
||||
class Promote extends Model
|
||||
{
|
||||
use PromoteScopes;
|
||||
|
||||
protected $table = 'tab_promote';
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class PromoteCompany extends Model
|
||||
{
|
||||
protected $table = 'tab_promote_company';
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class RebateGift extends Model
|
||||
{
|
||||
protected $table = 'tab_rebate_gifts';
|
||||
|
||||
protected $casts = [
|
||||
'config' => 'array',
|
||||
];
|
||||
|
||||
public $typeDisplayNames = [
|
||||
'A' => '单笔充值福利',
|
||||
'B' => '月卡福利发放',
|
||||
'C' => '累充福利发放',
|
||||
'D' => '首充福利发放',
|
||||
'E' => '单日累充福利发放',
|
||||
'F' => '周卡福利发放',
|
||||
'G' => '首次进游福利',
|
||||
'H' => '签到福利发放',
|
||||
'I' => '充值返利发放',
|
||||
];
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class RebateOrder extends Model
|
||||
{
|
||||
protected $table = 'tab_rebate_orders';
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class RebateTimesSetting extends Model
|
||||
{
|
||||
protected $table = 'tab_rebate_times_setting';
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class Server extends Model
|
||||
{
|
||||
protected $table = 'tab_server';
|
||||
|
||||
public $timestamps = false;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class ServerUnion extends Model
|
||||
{
|
||||
protected $table = 'tab_server_union';
|
||||
|
||||
public $timestamps = false;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class SimulateSpend extends Model
|
||||
{
|
||||
protected $table = 'tab_simulate_spend';
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use App\Helper\DeviceType;
|
||||
|
||||
class Spend extends Model
|
||||
{
|
||||
const STATUS_FAILED = 0;
|
||||
const STATUS_SUCCESS = 1;
|
||||
|
||||
protected $table = 'tab_spend';
|
||||
|
||||
public static $payWays = [
|
||||
-1 => '绑币',
|
||||
0 => '平台币',
|
||||
1 => '支付宝',
|
||||
2 => '微信',
|
||||
3 => '微信APP',
|
||||
9 => '双乾支付',
|
||||
15 => '双乾支付-快捷',
|
||||
17 => '易宝支付'
|
||||
];
|
||||
|
||||
public static $payStatusList = [
|
||||
self::STATUS_FAILED => '失败',
|
||||
self::STATUS_SUCCESS => '成功',
|
||||
];
|
||||
|
||||
public function getPayWayTextAttribute()
|
||||
{
|
||||
return self::$payWays[$this->pay_way] ?? '未知';
|
||||
}
|
||||
|
||||
public function getDeviceTypeNameAttribute()
|
||||
{
|
||||
return DeviceType::getDeviceTypeText($this->sdk_version);
|
||||
}
|
||||
|
||||
public function getPayStatusTextAttribute()
|
||||
{
|
||||
return self::$payStatusList[$this->pay_status] ?? '未知';
|
||||
}
|
||||
|
||||
public function promote()
|
||||
{
|
||||
return $this->belongsTo(Promote::class, 'promote_id', 'id');
|
||||
}
|
||||
|
||||
public function isSuccess()
|
||||
{
|
||||
return $this->pay_status === self::STATUS_SUCCESS;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class Tool extends Model
|
||||
{
|
||||
const STATUS_OPEN = 1;
|
||||
|
||||
protected $table = 'tab_tool';
|
||||
|
||||
private $configItems;
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
public static $groups = [
|
||||
'sms' => ['sms_set', 'zhongwang', 'juhedata'],
|
||||
];
|
||||
|
||||
public function get(string $name)
|
||||
{
|
||||
if ($this->configItems == null) {
|
||||
$this->configItems = (json_decode($this->config, true) ?? []);
|
||||
}
|
||||
return $this->configItems[$name] ?? null;
|
||||
}
|
||||
|
||||
public static function getActiveByGroup($group)
|
||||
{
|
||||
if (!isset(self::$groups[$group])) {
|
||||
return null;
|
||||
}
|
||||
return static::where('status', self::STATUS_OPEN)->whereIn('name', self::$groups[$group])->first();
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use App\Scopes\CommonPromoteScopes;
|
||||
use App\Scopes\UserScopes;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
use CommonPromoteScopes;
|
||||
use UserScopes;
|
||||
|
||||
protected $table = 'tab_user';
|
||||
|
||||
public function promote()
|
||||
{
|
||||
return $this->belongsTo(Promote::class, 'promote_id', 'id');
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class UserData extends Model
|
||||
{
|
||||
protected $table = 'tab_user_data';
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = ['user_id', 'pay_amount'];
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class UserPlayDataCount extends Model
|
||||
{
|
||||
protected $table = 'tab_user_play_data_count';
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?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
|
||||
*/
|
||||
namespace App\Process;
|
||||
|
||||
use Hyperf\AsyncQueue\Process\ConsumerProcess;
|
||||
use Hyperf\Process\Annotation\Process;
|
||||
|
||||
/**
|
||||
* @Process
|
||||
*/
|
||||
class AsyncQueueConsumer extends ConsumerProcess
|
||||
{
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
trait CommonPromoteScopes
|
||||
{
|
||||
/**
|
||||
* 查询属于某个推广员的玩家
|
||||
* @param $query
|
||||
* @param $promote 推广员
|
||||
* @param $containSubPromotes 是否包含所有下级
|
||||
*/
|
||||
public function scopeOfPromote($query, $promote, $containSubPromotes = true)
|
||||
{
|
||||
if ($containSubPromotes) {
|
||||
$query->whereHas('promote', function ($query) use ($promote) {
|
||||
$query->ofParent($promote)->orWhere('promote_id', $promote->id);
|
||||
});
|
||||
} else {
|
||||
$query->where('promote_id', $promote->id);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
use App\Helper\Time;
|
||||
|
||||
trait CommonTimeScopes
|
||||
{
|
||||
public function scopeRangeTime($query, $column, $timeRange, $withTime = true)
|
||||
{
|
||||
if (!$timeRange) {
|
||||
return $query;
|
||||
}
|
||||
$timeRange = Time::dateTimeRange($timeRange, $withTime);
|
||||
return $query->whereBetween($column, [strtotime($timeRange[0]), strtotime($timeRange[1])]);
|
||||
}
|
||||
|
||||
public function scopeOfMonth($query, $column, $month, $withTime = true)
|
||||
{
|
||||
if (!$month) {
|
||||
return $query;
|
||||
}
|
||||
$firstDate = $month . '-01';
|
||||
$lastDate = Time::getMonthLastDate($month);
|
||||
$timeRange = Time::dateTimeRange([$firstDate, $lastDate], $withTime);
|
||||
return $query->whereBetween($column, [strtotime($timeRange[0]), strtotime($timeRange[1])]);
|
||||
}
|
||||
|
||||
public function scopeTimeOverlay($query, $rangeColumns, $timeRange)
|
||||
{
|
||||
return $query->whereNot(function ($q) use ($rangeColumns, $timeRange) {
|
||||
$q->where($rangeColumns[1], '<', $timeRange[0])->orWhere($rangeColumns[0], '<', $timeRange[1]);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
trait GameScopes
|
||||
{
|
||||
public function scopeOfConditions($query, $params)
|
||||
{
|
||||
if (!empty($params['relation_game_id'])) {
|
||||
$query->where('relation_game_id', $params['relation_game_id']);
|
||||
}
|
||||
if (!empty($params['base_game_id'])) {
|
||||
$query->where('base_game_id', $params['base_game_id']);
|
||||
}
|
||||
if (!empty($params['sdk_version'])) {
|
||||
$query->where('sdk_version', $params['sdk_version']);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
trait PlayerRoleScopes
|
||||
{
|
||||
public function scopeOfConditions($query, $params)
|
||||
{
|
||||
if (!empty($params['server_id'])) {
|
||||
$query->where('server_id', $params['server_id']);
|
||||
}
|
||||
if (!empty($params['sdk_version'])) {
|
||||
$query->where('sdk_version', $params['sdk_version']);
|
||||
}
|
||||
if (!empty($params['game_id'])) {
|
||||
$query->where('game_id', $params['game_id']);
|
||||
}
|
||||
if (!empty($params['role_name'])) {
|
||||
$query->where('role_name', $params['role_name']);
|
||||
}
|
||||
if (!empty($params['server_name'])) {
|
||||
$query->where('server_name', $params['server_name']);
|
||||
}
|
||||
if (!empty($params['user_account'])) {
|
||||
$query->where('user_account', $params['user_account']);
|
||||
}
|
||||
if (!empty($params['role_id'])) {
|
||||
$query->where('role_id', $params['role_id']);
|
||||
}
|
||||
}
|
||||
|
||||
public function scopeRangeRoleLevel($query, ?array $roleLevelRange)
|
||||
{
|
||||
if (is_null($roleLevelRange)) {
|
||||
return $query;
|
||||
}
|
||||
$min = $roleLevelRange[0] ?? null;
|
||||
$min == '' ? null : $min;
|
||||
|
||||
$max = $roleLevelRange[1] ?? null;
|
||||
$max == '' ? null : $max;
|
||||
|
||||
if (!is_null($min)) {
|
||||
$query->where('role_level', '>=', $min);
|
||||
}
|
||||
|
||||
if (!is_null($max)) {
|
||||
$query->where('role_level', '<=', $max);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
trait PlayerScopes
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
trait PromoteScopes
|
||||
{
|
||||
public function scopeOfConditions($query, $params)
|
||||
{
|
||||
if (!empty($params['level'])) {
|
||||
$query->where('level', $params['level']);
|
||||
}
|
||||
if (!empty($params['parent_id'])) {
|
||||
$query->where('parent_id', $params['parent_id']);
|
||||
}
|
||||
if (!empty($params['account'])) {
|
||||
$query->where('account', 'like', '%' . $params['account'] . '%');
|
||||
}
|
||||
if (!empty($params['mobile'])) {
|
||||
$query->where('mobile_phone', 'like', '%' . $params['mobile'] . '%');
|
||||
}
|
||||
if (!empty($params['idcard'])) {
|
||||
$query->where('idcard', 'like', '%' . $params['idcard'] . '%');
|
||||
}
|
||||
if (!empty($params['realname'])) {
|
||||
$query->where('real_name', 'like', '%' . $params['realname'] . '%');
|
||||
}
|
||||
if (isset($params['status']) && $params['status'] != -1) {
|
||||
$query->where('status', $params['status']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找子推广账号
|
||||
*/
|
||||
public function scopeOfParent($query, $promote)
|
||||
{
|
||||
return $query->where('chain', 'like', $promote->chain . $promote->id . '/%');
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
use App\Model\Promote;
|
||||
|
||||
trait SpendScopes
|
||||
{
|
||||
public function scopeOfConditions($query, $params)
|
||||
{
|
||||
if (!empty($params['server_id'])) {
|
||||
$query->where('server_id', $params['server_id']);
|
||||
}
|
||||
if (!empty($params['server_name'])) {
|
||||
$query->where('server_name', $params['server_name']);
|
||||
}
|
||||
if (!empty($params['game_id'])) {
|
||||
$query->where('game_id', $params['game_id']);
|
||||
}
|
||||
if (!empty($params['game_name'])) {
|
||||
$query->where('game_name', $params['game_name']);
|
||||
}
|
||||
if (isset($params['pay_status']) && $params['pay_status'] != -1) {
|
||||
$query->where('pay_status', $params['pay_status']);
|
||||
}
|
||||
if (isset($params['pay_way']) && $params['pay_way'] != -99) {
|
||||
$query->where('pay_way', $params['pay_way']);
|
||||
}
|
||||
if (!empty($params['pay_order_number'])) {
|
||||
$query->where('pay_order_number', $params['pay_order_number']);
|
||||
}
|
||||
if (!empty($params['user_account'])) {
|
||||
$query->where('user_account', $params['user_account']);
|
||||
}
|
||||
if (!empty($params['role_name'])) {
|
||||
$query->where('game_player_name', $params['game_player_name']);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function scopeSettleOrder($query, string $tableAlias = null)
|
||||
{
|
||||
$column = 'is_check';
|
||||
if ($tableAlias) {
|
||||
$column = $tableAlias . '.' . $column;
|
||||
}
|
||||
return $query->where($column, 1);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
trait UserScopes
|
||||
{
|
||||
public function scopeOfConditions($query, $params)
|
||||
{
|
||||
if (!empty($params['account'])) {
|
||||
$query->where('account', $params['account']);
|
||||
}
|
||||
if (!empty($params['id'])) {
|
||||
$query->where('id', $params['id']);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use App\Model\Game;
|
||||
use App\Model\PlayerRole;
|
||||
use App\Model\Server;
|
||||
use App\Model\ServerUnion;
|
||||
use App\Model\User;
|
||||
|
||||
class PlayerRoleService extends Service
|
||||
{
|
||||
public function save($params)
|
||||
{
|
||||
$userId = $params['user_id'] ?? 0;
|
||||
$gameId = $params['game_id'] ?? 0;
|
||||
$serverId = $params['server_id'] ?? 0;
|
||||
$serverName = $params['server_name'] ?? 0;
|
||||
$roleName = $params['game_player_name'] ?? 0;
|
||||
$roleId = $params['game_player_id'] ?? 0;
|
||||
$roleLevel = $params['role_level'] ?? 0;
|
||||
$time = $params['time'] ?? 0;
|
||||
$clientIp = $params['client_ip'] ?? '';
|
||||
$sdkVersion = $params['sdk_version'] ?? 0;
|
||||
|
||||
$user = User::where('id', $userId)->first(['id', 'account', 'nickname', 'puid', 'promote_id', 'promote_account']);
|
||||
if ($user == null) {
|
||||
throw new BusinessException('用户不存在');
|
||||
}
|
||||
|
||||
$game = Game::where('id', $gameId)->first(['id', 'game_name', 'sdk_version']);
|
||||
if ($game == null) {
|
||||
throw new BusinessException('游戏不存在');
|
||||
}
|
||||
|
||||
$serverInfo = ['server_id' => $serverId, 'server_name' => $serverName];
|
||||
$roleInfo = ['role_id' => $roleId, 'role_name' => $roleName, 'role_level' => $roleLevel];
|
||||
|
||||
$this->saveRole($game, $user, $serverInfo, $roleInfo, $time, $clientIp);
|
||||
$this->saveServer($serverInfo, $game, $time);
|
||||
$this->saveServerUnion($serverInfo, $game, $time);
|
||||
}
|
||||
|
||||
private function saveRole(
|
||||
Game $game,
|
||||
User $user,
|
||||
array $serverInfo,
|
||||
array $roleInfo,
|
||||
int $time = 0,
|
||||
string $clientIp = ''
|
||||
) {
|
||||
$role = PlayerRole::where('user_id', $user->id)
|
||||
->where('game_id', $game->id)
|
||||
->where('server_id', $serverInfo['server_id'])
|
||||
->where('role_id', $roleInfo['role_id'])
|
||||
->first();
|
||||
|
||||
if ($role == null) {
|
||||
$role = new PlayerRole();
|
||||
$role->create_time = $time;
|
||||
$role->create_ip = $clientIp;
|
||||
$role->promote_id = $user->promote_id;
|
||||
$role->promote_account = $user->promote_account;
|
||||
}
|
||||
|
||||
$role->game_id = $game->id;
|
||||
$role->game_name = $game->game_name;
|
||||
$role->server_id = $serverInfo['server_id'];
|
||||
$role->server_name = $serverInfo['server_name'];
|
||||
$role->role_id = $roleInfo['role_id'];
|
||||
$role->role_name = $roleInfo['role_name'];
|
||||
$role->role_level = $roleInfo['role_level'];
|
||||
$role->game_role_id = $game->id . '#' . $roleInfo['role_id'];;
|
||||
$role->user_id = $user->id;
|
||||
$role->user_account = $user->account;
|
||||
$role->user_nickname = $user->nickname;
|
||||
$role->play_time = $time;
|
||||
$role->sdk_version = $game->sdk_version;
|
||||
$role->play_ip = $clientIp;
|
||||
$role->pipuid = $user->puid;
|
||||
$role->save();
|
||||
}
|
||||
|
||||
private function saveServer(array $serverInfo, Game $game, int $time = 0)
|
||||
{
|
||||
$serverName = $serverInfo['server_name'] ?? '';
|
||||
$serverId = $serverInfo['server_id'] ?? 0;
|
||||
|
||||
$server = Server::where('game_id', $game->id)->where('server_id', $serverId)->first();
|
||||
if ($server == null) {
|
||||
$server = new Server();
|
||||
$server->game_id = $game->id;
|
||||
$server->game_name = $game->game_name;
|
||||
$server->server_name = $serverName;
|
||||
$server->server_num = $serverId;
|
||||
$server->server_id = $serverId;
|
||||
$server->server_version = $game->sdk_version;
|
||||
$server->create_time = $time;
|
||||
$server->start_time = $time;
|
||||
$server->save();
|
||||
} else {
|
||||
if ($server->server_name != $serverName) {
|
||||
$server->server_name = $serverName;
|
||||
$server->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function saveServerUnion(array $serverInfo, Game $game, int $time = 0)
|
||||
{
|
||||
$serverName = $serverInfo['server_name'] ?? '';
|
||||
$serverId = $serverInfo['server_id'] ?? 0;
|
||||
|
||||
$server = Server::where('server_name', $serverName)->where('game_id', $game->id)->first(['id']);
|
||||
if ($server) {
|
||||
return;
|
||||
}
|
||||
|
||||
$serverUnion = ServerUnion::where('server_name', $serverName)->where('game_id', $game->id)->first(['id']);
|
||||
if ($serverUnion == null) {
|
||||
$serverUnion = new ServerUnion();
|
||||
$serverUnion->game_id = $game->id;
|
||||
$serverUnion->game_name = $game->game_name;
|
||||
$serverUnion->server_name = $serverName;
|
||||
$serverUnion->server_num = $serverId;
|
||||
$serverUnion->server_id = $serverId;
|
||||
$serverUnion->server_version = $game->sdk_version;
|
||||
$serverUnion->create_time = $time;
|
||||
$serverUnion->start_time = $time;
|
||||
$serverUnion->save();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Helper\Time;
|
||||
use App\Model\Player;
|
||||
use App\Model\PlayerRetention;
|
||||
use App\Model\Promote;
|
||||
use App\Model\PromoteCompany;
|
||||
use Hyperf\DbConnection\Db;
|
||||
|
||||
class PlayerService extends Service
|
||||
{
|
||||
public function getPlayerRetention(array $params): array
|
||||
{
|
||||
$startTime = $params['start_time'] ?? date('Y-m-d');
|
||||
$endTime = $params['end_time'] ?? date('Y-m-d');
|
||||
$gameIds = $params['game_ids'] ?? [];
|
||||
$promoteId = $params['promote_id'] ?? 0;
|
||||
$companyId = $params['company_id'] ?? 0;
|
||||
$gameId = $params['game_id'] ?? 0;
|
||||
|
||||
if (empty($gameIds) && $gameId) {
|
||||
$gameIds = [$gameId];
|
||||
}
|
||||
|
||||
$promote = null;
|
||||
$promoteCompany = null;
|
||||
if ($promoteId) {
|
||||
$promote = Promote::where('id', $promoteId)->first(['id', 'chain', 'parent_id']);
|
||||
} elseif ($companyId) {
|
||||
$promoteCompany = PromoteCompany::where('id', $promoteId)->first(['id']);
|
||||
}
|
||||
|
||||
$dateList = Time::getDateList($startTime, $endTime);
|
||||
|
||||
$startTime = strtotime($startTime . ' 00:00:00');
|
||||
$endTime = strtotime($endTime . ' 23:59:59');
|
||||
$dailyData = $this->getDailyRetention($startTime, $endTime, $gameIds, $promote, $promoteCompany);
|
||||
|
||||
$dailyRecords = [];
|
||||
foreach ($dailyData as $item) {
|
||||
$dailyRecords[$item->date] = $item;
|
||||
}
|
||||
|
||||
$query = Player::select(DB::raw('FROM_UNIXTIME(create_time, "%Y-%m-%d") date'), DB::raw('count(*) count'))
|
||||
->whereBetween('create_time', [$startTime, $endTime])
|
||||
->whereIn('game_id', $gameIds);
|
||||
if ($promote) {
|
||||
$query->ofPromote($promote, true);
|
||||
} elseif ($promoteCompany) {
|
||||
$query->ofPromoteCompany($promoteCompany);
|
||||
}
|
||||
|
||||
$countList = $query->groupBy('date')->get()->pluck('count', 'date');
|
||||
|
||||
$records = [];
|
||||
foreach ($dateList as $date) {
|
||||
$record = [
|
||||
'date' => $date,
|
||||
'register_count' => isset($countList[$date]) ? $countList[$date] : 0,
|
||||
];
|
||||
foreach (PlayerRetention::$dayList as $day) {
|
||||
$item = $dailyRecords[$date] ?? null;
|
||||
$record['retention_day' . $day] = $item ? $item->{'day' . $day} : 0;
|
||||
}
|
||||
$records[] = $record;
|
||||
}
|
||||
|
||||
return $records;
|
||||
}
|
||||
|
||||
public function getDailyRetention($start, $end, $gameIds, $promote = null, $promoteCompany = null)
|
||||
{
|
||||
$columns = [
|
||||
'FROM_UNIXTIME(b.create_time, "%Y-%m-%d") date',
|
||||
'sum(day1) day1',
|
||||
'sum(day2) day2',
|
||||
'sum(day3) day3',
|
||||
'sum(day4) day4',
|
||||
'sum(day5) day5',
|
||||
'sum(day6) day6',
|
||||
'sum(day7) day7',
|
||||
'sum(day15) day15',
|
||||
'sum(day30) day30'
|
||||
];
|
||||
|
||||
$query = PlayerRetention::fromAlias('a')
|
||||
->select(Db::raw(implode(',', $columns)))
|
||||
->leftJoin(Player::alias('b'), function ($join) {
|
||||
$join->on('a.player_id', '=', 'b.id');
|
||||
})
|
||||
->whereBetween('b.create_time', [$start, $end])
|
||||
->whereIn('a.game_id', $gameIds)
|
||||
->groupBy('date');
|
||||
|
||||
$promoteTable = Promote::alias('c');
|
||||
if ($promote) {
|
||||
$query->leftJoin($promoteTable, function ($join) {
|
||||
$join->on('b.promote_id', '=', 'c.id');
|
||||
})->whereRaw('(c.chain like "'. $promote->chain . $promote->id . '/%" or c.id=' . $promote->id . ')');
|
||||
} elseif ($promoteCompany) {
|
||||
$query->leftJoin($promoteTable, function ($join) {
|
||||
$join->on('b.promote_id', '=', 'c.id');
|
||||
})->whereRaw('c.company_id = ' . $promoteCompany->id);
|
||||
}
|
||||
return $query->get();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
class Service
|
||||
{
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use App\Model\GameData;
|
||||
use App\Model\Spend;
|
||||
use App\Model\UserData;
|
||||
use App\Model\UserPlayDataCount;
|
||||
use App\Helper\Log;
|
||||
use Hyperf\DbConnection\Db;
|
||||
|
||||
class SpendService extends Service
|
||||
{
|
||||
public function afterSpend($payOrderNumber)
|
||||
{
|
||||
Log::info('[GAME-RECHARGE]产生充值订单:' . $payOrderNumber);
|
||||
|
||||
$spend = Spend::where('pay_order_number', $payOrderNumber)->first();
|
||||
if (!$spend) {
|
||||
throw new BusinessException('订单不存在');
|
||||
}
|
||||
if ($spend->pay_status != 1) {
|
||||
throw new BusinessException('订单支付未成功');
|
||||
}
|
||||
if ($spend->event_status == 1) {
|
||||
throw new BusinessException('该订单已处理');
|
||||
}
|
||||
|
||||
$this->saveUserPlayDataCountBySpend($spend);
|
||||
$this->addUserDataPayAmount($spend);
|
||||
$this->addGameDataPayAmount($spend);
|
||||
|
||||
$spend->event_status = 1;
|
||||
$spend->save();
|
||||
}
|
||||
|
||||
private function saveUserPlayDataCountBySpend(Spend $spend)
|
||||
{
|
||||
$date = strtotime(date('Y-m-d 00:00:00', $spend->pay_time));
|
||||
$record = UserPlayDataCount::where('user_id', $spend->user_id)
|
||||
->where('game_id', $spend->game_id)
|
||||
->where('server_id', $spend->server_id)
|
||||
->where('role_id', $spend->game_player_id)
|
||||
->where('create_time', $date)
|
||||
->first();
|
||||
if (!$record) {
|
||||
$record = new UserPlayDataCount();
|
||||
$record->user_id = $spend->user_id;
|
||||
$record->promote_id = $spend->promote_id;
|
||||
$record->game_id = $spend->game_id;
|
||||
$record->server_id = $spend->server_id;
|
||||
$record->role_id = $spend->game_player_id;
|
||||
$record->create_time = $date;
|
||||
$record->recharge_cost = $spend->pay_amount;
|
||||
$record->recharge_count = 1;
|
||||
} else {
|
||||
$record->recharge_cost = Db::raw('recharge_cost+' . $spend->pay_amount);
|
||||
$record->recharge_count = Db::raw('recharge_count+1');
|
||||
}
|
||||
$record->save();
|
||||
}
|
||||
|
||||
private function addUserDataPayAmount($spend)
|
||||
{
|
||||
UserData::updateOrCreate(
|
||||
['user_id' => $spend->user_id],
|
||||
['pay_amount' => Db::raw('pay_amount+' . $spend->pay_amount)]
|
||||
);
|
||||
}
|
||||
|
||||
private function addGameDataPayAmount($spend)
|
||||
{
|
||||
GameData::updateOrCreate(
|
||||
['game_id' => $spend->game_id],
|
||||
['pay_amount' => Db::raw('pay_amount+' . $spend->pay_amount)]
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use App\Model\Player;
|
||||
use App\Model\PlayerRetention;
|
||||
use App\Model\User;
|
||||
use App\Helper\Log;
|
||||
|
||||
class UserService extends Service
|
||||
{
|
||||
public function afterLogin($gameId, $userId, $loginTime = 0)
|
||||
{
|
||||
if (empty($time)) {
|
||||
$loginTime = time();
|
||||
}
|
||||
|
||||
Log::info('[USER-LOGIN]用户['. $userId . ']登录游戏[' . $gameId . ']');
|
||||
|
||||
$player = Player::where('user_id', $userId)->where('game_id', $gameId)->first(['id', 'create_time']);
|
||||
if (!$player) {
|
||||
throw new BusinessException('玩家信息不存在');
|
||||
}
|
||||
|
||||
$playerRetention = PlayerRetention::where('player_id', $player->id)->first();
|
||||
|
||||
$retentionDay = $this->getRetentionDay($player->create_time, $loginTime);
|
||||
if ($retentionDay > 0) {
|
||||
if (!$playerRetention) {
|
||||
$playerRetention = new PlayerRetention();
|
||||
$playerRetention->player_id = $player->id;
|
||||
$playerRetention->game_id = $gameId;
|
||||
$playerRetention->user_id = $userId;
|
||||
}
|
||||
$playerRetention->{'day' . $retentionDay} = 1;
|
||||
$playerRetention->save();
|
||||
}
|
||||
}
|
||||
|
||||
private function getRetentionDay($createTime, $loginTime)
|
||||
{
|
||||
$dayTime = 24 * 60 * 60;
|
||||
$retentionDay = 0;
|
||||
foreach (PlayerRetention::$dayList as $day) {
|
||||
$date = date('Ymd', $createTime + $day * $dayTime);
|
||||
if ($date == date('Ymd', $loginTime)) {
|
||||
$retentionDay = $day;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return $retentionDay;
|
||||
}
|
||||
|
||||
public function afterRegister($userId)
|
||||
{
|
||||
Log::info('[USER-REGISTER]用户['. $userId . ']注册');
|
||||
|
||||
$user = User::where('id', $userId)->first(['device_number', 'register_ip', 'id']);
|
||||
if (!$user) {
|
||||
throw new BusinessException('用户不存在');
|
||||
}
|
||||
|
||||
$repeatUser = User::where('device_number', $user->device_number)
|
||||
->where('register_ip', $user->register_ip)
|
||||
->where('id', '<', $user->id)
|
||||
->first();
|
||||
if ($repeatUser) {
|
||||
$user->is_repeat = 1;
|
||||
$user->save();
|
||||
Log::info('[USER-REGISTER]用户['. $userId . ']为重复账号');
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
ini_set('display_startup_errors', 'on');
|
||||
ini_set('memory_limit', '1G');
|
||||
|
||||
error_reporting(E_ALL);
|
||||
date_default_timezone_set('Asia/Shanghai');
|
||||
|
||||
! defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
|
||||
! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
|
||||
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
|
||||
// Self-called anonymous function that creates its own scope and keep the global namespace clean.
|
||||
(function () {
|
||||
Hyperf\Di\ClassLoader::init();
|
||||
/** @var Psr\Container\ContainerInterface $container */
|
||||
$container = require BASE_PATH . '/config/container.php';
|
||||
|
||||
$application = $container->get(Hyperf\Contract\ApplicationInterface::class);
|
||||
$application->run();
|
||||
})();
|
@ -0,0 +1,89 @@
|
||||
{
|
||||
"name": "hyperf/hyperf-skeleton",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"php",
|
||||
"swoole",
|
||||
"framework",
|
||||
"hyperf",
|
||||
"microservice",
|
||||
"middleware"
|
||||
],
|
||||
"description": "A coroutine framework that focuses on hyperspeed and flexible, specifically use for build microservices and middlewares.",
|
||||
"license": "Apache-2.0",
|
||||
"require": {
|
||||
"php": ">=7.3",
|
||||
"hyperf/async-queue": "~2.2.0",
|
||||
"hyperf/cache": "~2.2.0",
|
||||
"hyperf/command": "~2.2.0",
|
||||
"hyperf/config": "~2.2.0",
|
||||
"hyperf/constants": "~2.2.0",
|
||||
"hyperf/database": "~2.2.0",
|
||||
"hyperf/db-connection": "~2.2.0",
|
||||
"hyperf/framework": "~2.2.0",
|
||||
"hyperf/guzzle": "~2.2.0",
|
||||
"hyperf/http-server": "~2.2.0",
|
||||
"hyperf/json-rpc": "~2.2.0",
|
||||
"hyperf/logger": "~2.2.0",
|
||||
"hyperf/memory": "~2.2.0",
|
||||
"hyperf/model-cache": "~2.2.0",
|
||||
"hyperf/process": "~2.2.0",
|
||||
"hyperf/redis": "~2.2.0",
|
||||
"hyperf/rpc": "~2.2.0",
|
||||
"hyperf/rpc-client": "~2.2.0",
|
||||
"hyperf/rpc-server": "~2.2.0",
|
||||
"hyperf/validation": "^2.2",
|
||||
"phpoffice/phpspreadsheet": "^1.24"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.0",
|
||||
"hyperf/devtool": "~2.2.0",
|
||||
"hyperf/ide-helper": "~2.2.0",
|
||||
"hyperf/testing": "~2.2.0",
|
||||
"mockery/mockery": "^1.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"swoole/ide-helper": "^4.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-openssl": "Required to use HTTPS.",
|
||||
"ext-json": "Required to use JSON.",
|
||||
"ext-pdo": "Required to use MySQL Client.",
|
||||
"ext-pdo_mysql": "Required to use MySQL Client.",
|
||||
"ext-redis": "Required to use Redis Client."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/"
|
||||
},
|
||||
"files": [
|
||||
"app/Helper/Functions.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"HyperfTest\\": "./test/"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": [],
|
||||
"scripts": {
|
||||
"post-root-package-install": [
|
||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||
],
|
||||
"post-autoload-dump": [
|
||||
"rm -rf runtime/container"
|
||||
],
|
||||
"test": "co-phpunit --prepend test/bootstrap.php -c phpunit.xml --colors=always",
|
||||
"cs-fix": "php-cs-fixer fix $1",
|
||||
"analyse": "phpstan analyse --memory-limit 300M -l 0 -c phpstan.neon ./app ./config",
|
||||
"start": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"php ./bin/hyperf.php start"
|
||||
]
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,21 @@
|
||||
<?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 [
|
||||
'scan' => [
|
||||
'paths' => [
|
||||
BASE_PATH . '/app',
|
||||
],
|
||||
'ignore_annotations' => [
|
||||
'mixin',
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
<?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 [
|
||||
];
|
@ -0,0 +1,27 @@
|
||||
<?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' => [
|
||||
'driver' => Hyperf\AsyncQueue\Driver\RedisDriver::class,
|
||||
'redis' => [
|
||||
'pool' => 'default',
|
||||
],
|
||||
'channel' => '{queue}',
|
||||
'timeout' => 2,
|
||||
'retry_seconds' => 5,
|
||||
'handle_timeout' => 10,
|
||||
'processes' => 1,
|
||||
'concurrent' => [
|
||||
'limit' => 10,
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,18 @@
|
||||
<?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' => [
|
||||
'driver' => Hyperf\Cache\Driver\RedisDriver::class,
|
||||
'packer' => Hyperf\Utils\Packer\PhpSerializerPacker::class,
|
||||
'prefix' => 'c:',
|
||||
],
|
||||
];
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'lanhuo' => [
|
||||
'base_url' => env('LANHUO_URL', 'https://c.lshygame.com'),
|
||||
'app_id' => 'LLWF71700000001644',
|
||||
'app_key' => '31h8a',
|
||||
'app_secret' => '9b0c2130ea023243ff76bf7bc724cfc2',
|
||||
],
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
<?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 [
|
||||
];
|
@ -0,0 +1,49 @@
|
||||
<?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' => [
|
||||
'driver' => env('DB_DRIVER', 'mysql'),
|
||||
'host' => env('DB_HOST', 'localhost'),
|
||||
'port' => env('DB_PORT', 3306),
|
||||
'database' => env('DB_DATABASE', 'hyperf'),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8mb4'),
|
||||
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
|
||||
'prefix' => env('DB_PREFIX', ''),
|
||||
'pool' => [
|
||||
'min_connections' => 1,
|
||||
'max_connections' => 10,
|
||||
'connect_timeout' => 10.0,
|
||||
'wait_timeout' => 3.0,
|
||||
'heartbeat' => -1,
|
||||
'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
|
||||
],
|
||||
'cache' => [
|
||||
'handler' => Hyperf\ModelCache\Handler\RedisHandler::class,
|
||||
'cache_key' => '{mc:%s:m:%s}:%s:%s',
|
||||
'prefix' => 'default',
|
||||
'ttl' => 3600 * 24,
|
||||
'empty_model_ttl' => 600,
|
||||
'load_script' => true,
|
||||
],
|
||||
'commands' => [
|
||||
'gen:model' => [
|
||||
'path' => 'app/Model',
|
||||
'force_casts' => true,
|
||||
'inheritance' => 'Model',
|
||||
'uses' => '',
|
||||
'table_mapping' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
<?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 [
|
||||
];
|
@ -0,0 +1,44 @@
|
||||
<?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 [
|
||||
'generator' => [
|
||||
'amqp' => [
|
||||
'consumer' => [
|
||||
'namespace' => 'App\\Amqp\\Consumer',
|
||||
],
|
||||
'producer' => [
|
||||
'namespace' => 'App\\Amqp\\Producer',
|
||||
],
|
||||
],
|
||||
'aspect' => [
|
||||
'namespace' => 'App\\Aspect',
|
||||
],
|
||||
'command' => [
|
||||
'namespace' => 'App\\Command',
|
||||
],
|
||||
'controller' => [
|
||||
'namespace' => 'App\\Controller',
|
||||
],
|
||||
'job' => [
|
||||
'namespace' => 'App\\Job',
|
||||
],
|
||||
'listener' => [
|
||||
'namespace' => 'App\\Listener',
|
||||
],
|
||||
'middleware' => [
|
||||
'namespace' => 'App\\Middleware',
|
||||
],
|
||||
'Process' => [
|
||||
'namespace' => 'App\\Processes',
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,19 @@
|
||||
<?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 [
|
||||
'handler' => [
|
||||
'http' => [
|
||||
Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
|
||||
App\Exception\Handler\AppExceptionHandler::class,
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
<?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 [
|
||||
];
|
@ -0,0 +1,56 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
$logPath = rtrim(env('LOG_PATH', '@runtime'), '/');
|
||||
$logPath = $logPath === '@runtime' ? BASE_PATH . '/runtime/logs/' : $logPath;
|
||||
$logFileName = $logPath . '/' . env('LOG_FILE_NAME', env('APP_NAME', 'hyperf') . '.log');
|
||||
|
||||
/* return [
|
||||
'default' => [
|
||||
'handler' => [
|
||||
'class' => \Monolog\Handler\StreamHandler::class,
|
||||
'constructor' => [
|
||||
'stream' => $logFileName,
|
||||
'level' => \Monolog\Logger::DEBUG,
|
||||
],
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => \Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [
|
||||
'format' => null,
|
||||
'dateFormat' => null,
|
||||
'allowInlineLineBreaks' => true,
|
||||
]
|
||||
],
|
||||
],
|
||||
]; */
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'handler' => [
|
||||
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||
'constructor' => [
|
||||
'filename' => $logFileName,
|
||||
'maxFiles' => env('LOG_MAX_FILES', 7),
|
||||
'level' => Monolog\Logger::DEBUG,
|
||||
],
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [
|
||||
'format' => null,
|
||||
'dateFormat' => 'Y-m-d H:i:s',
|
||||
'allowInlineLineBreaks' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue