473 lines
14 KiB
PHP
473 lines
14 KiB
PHP
|
|
<?php
|
||
|
|
declare (strict_types=1);
|
||
|
|
|
||
|
|
namespace app\model;
|
||
|
|
|
||
|
|
use app\exception\ModelEmptyException;
|
||
|
|
use app\exception\ModelException;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @mixin \think\Model
|
||
|
|
*/
|
||
|
|
class Route extends Model
|
||
|
|
{
|
||
|
|
|
||
|
|
public function category(): \think\model\relation\BelongsTo
|
||
|
|
{
|
||
|
|
return $this->belongsTo(Category::class);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array $where
|
||
|
|
* @param int $limit
|
||
|
|
* @return array
|
||
|
|
* @throws ModelException
|
||
|
|
*/
|
||
|
|
public function getRouteList(array $where = [], int $limit = 10): array
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
$res = $this->where($where)->paginate($limit);
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
throw new ModelException($e->getMessage());
|
||
|
|
}
|
||
|
|
return dataReturn($this->sucCode, $this->getMsg, $res);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array $where
|
||
|
|
* @param string[] $order
|
||
|
|
* @return array
|
||
|
|
* @throws ModelException
|
||
|
|
*/
|
||
|
|
public function getAllRoute(array $where, array $order=['id','asc']): array
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
$res = $this->where($where)->order($order[0],$order[1])->select();
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
throw new ModelException($e->getMessage());
|
||
|
|
}
|
||
|
|
return dataReturn($this->sucCode, $this->getMsg, $res);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array $where
|
||
|
|
* @return array
|
||
|
|
* @throws ModelEmptyException
|
||
|
|
* @throws ModelException
|
||
|
|
*/
|
||
|
|
public function getRoute(array $where = [],$with=[]): array
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
$res = $this->with($with)->where($where)->find();
|
||
|
|
if (empty($res)) {
|
||
|
|
throw new ModelEmptyException();
|
||
|
|
}
|
||
|
|
} catch (ModelEmptyException $me) {
|
||
|
|
throw new ModelEmptyException();
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
throw new ModelException($e->getMessage());
|
||
|
|
}
|
||
|
|
return dataReturn($this->sucCode, $this->getMsg, $res);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array $where
|
||
|
|
* @return array
|
||
|
|
* @throws ModelException
|
||
|
|
*/
|
||
|
|
public function exitRoute(array $where = []): array
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
$res = $this->where($where)->find();
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
throw new ModelException($e->getMessage());
|
||
|
|
}
|
||
|
|
return dataReturn($this->sucCode, $this->getMsg, $res);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param $param
|
||
|
|
* @return array
|
||
|
|
* @throws ModelException
|
||
|
|
*/
|
||
|
|
public function addRoute($param): array
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
$res = self::create($param);
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
throw new ModelException($e->getMessage());
|
||
|
|
}
|
||
|
|
return dataReturn($this->sucCode, $this->addMsg, $res);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array $where
|
||
|
|
* @param array $param
|
||
|
|
* @return array
|
||
|
|
* @throws ModelException
|
||
|
|
*/
|
||
|
|
public function updateRoute(array $where = [], array $param = []): array
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
$res = self::where($where)->update($param);
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
throw new ModelException($e->getMessage());
|
||
|
|
}
|
||
|
|
return dataReturn($this->sucCode, $this->updateMsg, $res);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param $where
|
||
|
|
* @return array
|
||
|
|
* @throws ModelException
|
||
|
|
*/
|
||
|
|
public function softDelRoute($where): array
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
$res = $this->where($where)->update($this->delData);
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
throw new ModelException($e->getMessage());
|
||
|
|
}
|
||
|
|
return dataReturn($this->sucCode, $this->delMsg, $res);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param $where
|
||
|
|
* @return array
|
||
|
|
* @throws ModelException
|
||
|
|
*/
|
||
|
|
public function delRoute($where): array
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
$res = $this->where($where)->delete();
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
throw new ModelException($e->getMessage());
|
||
|
|
}
|
||
|
|
return dataReturn($this->sucCode, $this->delMsg, $res);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @throws ModelException
|
||
|
|
* @throws ModelEmptyException
|
||
|
|
*/
|
||
|
|
public function getRoutes($siteId, $sellerId, $lang): array
|
||
|
|
{
|
||
|
|
$routes = $this->alias('r')
|
||
|
|
->field('r.*,c.path')
|
||
|
|
->leftJoin('category c','r.category_id = c.id')
|
||
|
|
->where('r.seller_id',$sellerId)
|
||
|
|
->where('r.website_id',$siteId)
|
||
|
|
->where('r.lang',$lang)
|
||
|
|
->where('r.status',1)
|
||
|
|
->where('c.type','in',[1,4])
|
||
|
|
->select()->toArray();
|
||
|
|
// dd($routes);
|
||
|
|
$Website = new Website();
|
||
|
|
$websiteDomain = $Website->getWebsite(['id'=>$siteId,'seller_id'=>$sellerId])['data']['domain'];
|
||
|
|
|
||
|
|
// 如果有子站点,更新子站点
|
||
|
|
$subSiteList = $Website->where([
|
||
|
|
['seller_id', '=', $sellerId],
|
||
|
|
['parent_id', '=', $siteId],
|
||
|
|
])->select()->toArray();
|
||
|
|
|
||
|
|
foreach ($subSiteList as $value) {
|
||
|
|
$this->getRoutes($value['id'], $sellerId, $lang);
|
||
|
|
}
|
||
|
|
|
||
|
|
$allRoutes = [];
|
||
|
|
$cacheRoutes = [];
|
||
|
|
foreach ($routes as $er) {
|
||
|
|
|
||
|
|
$fullUrl = htmlspecialchars_decode($er['full_url']);
|
||
|
|
// 解析URL
|
||
|
|
$info = parse_url($fullUrl);
|
||
|
|
|
||
|
|
$vars = [];
|
||
|
|
// 解析参数
|
||
|
|
if (isset($info['query'])) { // 解析地址里面参数 合并到vars
|
||
|
|
parse_str($info['query'], $vars);
|
||
|
|
ksort($vars);
|
||
|
|
}
|
||
|
|
|
||
|
|
$path = explode("/", $info['path']);
|
||
|
|
|
||
|
|
if (count($path) != 2) {//必须是完整 url
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$path = $info['path'];
|
||
|
|
|
||
|
|
$fullUrl = $path . (empty($vars) ? "" : "?") . http_build_query($vars);
|
||
|
|
|
||
|
|
$url = htmlspecialchars_decode($er['url']);
|
||
|
|
if (!isset($cacheRoutes[$path])) {
|
||
|
|
$cacheRoutes[$path] = [];
|
||
|
|
}
|
||
|
|
array_push($cacheRoutes[$path], ['vars' => $vars]);
|
||
|
|
|
||
|
|
if (empty($er['pattern'])) {
|
||
|
|
$allRoutes[$url] = $fullUrl;
|
||
|
|
} else {
|
||
|
|
$allRoutes[$url] = [$fullUrl, [], json_decode($er['pattern'],true)];//[routeUrl,options,patterns]
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
$fileStr = [
|
||
|
|
'<?php',
|
||
|
|
'use think\facade\Route;',
|
||
|
|
'',
|
||
|
|
"Route::domain('$websiteDomain',function(){",
|
||
|
|
];
|
||
|
|
$customerStr = [];
|
||
|
|
if($lang != config('lang.default_lang')){
|
||
|
|
array_push($customerStr,"Route::group('$lang',function(){");
|
||
|
|
}else{
|
||
|
|
array_push($customerStr,'Route::group(function(){');
|
||
|
|
}
|
||
|
|
foreach ($allRoutes as $rule => $route) {
|
||
|
|
$pattern = '';
|
||
|
|
if (is_array($route)) {
|
||
|
|
$routeUrl = $route[0];
|
||
|
|
if (!empty($route[2])) {
|
||
|
|
$pattern = stripslashes(var_export($route[2], true));
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
$routeUrl = $route;
|
||
|
|
}
|
||
|
|
$ruleName = $routeUrl;
|
||
|
|
$query = [];
|
||
|
|
if (strpos($routeUrl, '?') > 0) {
|
||
|
|
$routeUrlArr = parse_url($routeUrl);
|
||
|
|
$routeUrl = $routeUrlArr['path'];
|
||
|
|
parse_str($routeUrlArr['query'], $query);
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->setRouteFile($rule, $routeUrl, $ruleName, $query, $pattern, $customerStr);
|
||
|
|
|
||
|
|
if ($rule == '/') {
|
||
|
|
$rule = '/index';
|
||
|
|
$this->setRouteFile($rule, $routeUrl, $ruleName, $query, $pattern, $customerStr);
|
||
|
|
} elseif ($rule == '/index') {
|
||
|
|
$rule = '/';
|
||
|
|
$this->setRouteFile($rule, $routeUrl, $ruleName, $query, $pattern, $customerStr);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// dd($customerStr);
|
||
|
|
// 获取前台公共路由
|
||
|
|
$indexRoute = app()->getRootPath() . 'route' . DIRECTORY_SEPARATOR . 'index.php';
|
||
|
|
$index_route = file($indexRoute);
|
||
|
|
foreach ($index_route as $key => $val){
|
||
|
|
if(trim($val) == "<?php" || trim($val) == "use think\\facade\\Route;" || $val ==PHP_EOL){
|
||
|
|
unset($index_route[$key]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
$customerStr = array_merge($customerStr,$index_route);
|
||
|
|
|
||
|
|
$customerStr[] = "})->prefix('frontend.');";
|
||
|
|
$fileStr = array_merge($fileStr,$customerStr);
|
||
|
|
if( $lang == config('lang.default_lang')){
|
||
|
|
$adminRoute = app()->getRootPath() . 'route' . DIRECTORY_SEPARATOR . 'admin.php';
|
||
|
|
$admin_route = file($adminRoute);
|
||
|
|
foreach ($admin_route as $key => $val){
|
||
|
|
if(trim($val) == "<?php" || trim($val) == "use think\\facade\\Route;"){
|
||
|
|
unset($admin_route[$key]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
$fileStr = array_merge($fileStr,$admin_route);
|
||
|
|
}
|
||
|
|
array_push($fileStr,"});");
|
||
|
|
|
||
|
|
$content = join("\n", $fileStr);
|
||
|
|
$path = $this->createRoutePath($siteId,$lang);
|
||
|
|
// 前台页面路由
|
||
|
|
$th = fopen($path['frontend'],'w');
|
||
|
|
file_put_contents($path['frontend'], $content . "\n\n");
|
||
|
|
fclose($th);
|
||
|
|
return $cacheRoutes;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function setRouteFile($rule, $routeUrl, $ruleName, $query, $pattern, &$customerStr)
|
||
|
|
{
|
||
|
|
$routeCode = "Route::get('$rule', '$routeUrl')";
|
||
|
|
$routeCode .= "->name('$ruleName')";
|
||
|
|
|
||
|
|
if (!empty($query)) {
|
||
|
|
$query = var_export($query, true);
|
||
|
|
$query = str_replace(["\n", 'array ( '], ['', 'array('], $query);
|
||
|
|
$routeCode .= "->append($query)";
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!empty($pattern)) {
|
||
|
|
$pattern = str_replace(["\n", 'array ( '], ['', 'array('], $pattern);
|
||
|
|
$routeCode .= "\n->pattern($pattern)";
|
||
|
|
}
|
||
|
|
|
||
|
|
$routeCode .= ";\n";
|
||
|
|
$customerStr [] = $routeCode;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function createRoutePath($siteId,$lang): array
|
||
|
|
{
|
||
|
|
$routeDir = app()->getRootPath() . "route";
|
||
|
|
if (!file_exists($routeDir)) {
|
||
|
|
mkdir($routeDir);
|
||
|
|
}
|
||
|
|
|
||
|
|
$apiRouteFile = $routeDir.DIRECTORY_SEPARATOR .$siteId .'_' .$lang . "_api.php";
|
||
|
|
$frontendRouteFile = $routeDir .DIRECTORY_SEPARATOR .$siteId.'_' .$lang . "_frontend.php";
|
||
|
|
return [
|
||
|
|
'frontend' => $frontendRouteFile,
|
||
|
|
'api' => $apiRouteFile,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getUrl($action, $vars)
|
||
|
|
{
|
||
|
|
$fullUrl = $this->buildFullUrl($action, $vars);
|
||
|
|
|
||
|
|
$url = $this->where('full_url', $fullUrl)->value('url');
|
||
|
|
|
||
|
|
return empty($url) ? '' : $url;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getFullUrlByUrl($url)
|
||
|
|
{
|
||
|
|
$full_url = $this->where('url', $url)->value('full_url');
|
||
|
|
|
||
|
|
return empty($full_url) ? '' : $full_url;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getFullUrl($where): array
|
||
|
|
{
|
||
|
|
$full_url = $this->where($where)->column('full_url');
|
||
|
|
|
||
|
|
return empty($full_url)? [] : $full_url;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function buildFullUrl($action, $vars): string
|
||
|
|
{
|
||
|
|
// 解析参数
|
||
|
|
if (is_string($vars)) {
|
||
|
|
// aaa=1&bbb=2 转换成数组
|
||
|
|
parse_str($vars, $vars);
|
||
|
|
}
|
||
|
|
if (!empty($vars)) {
|
||
|
|
ksort($vars);
|
||
|
|
$fullUrl = $action . '?' . http_build_query($vars);
|
||
|
|
} else {
|
||
|
|
$fullUrl = $action;
|
||
|
|
}
|
||
|
|
return $fullUrl;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function existsRoute($url, $fullUrl): bool
|
||
|
|
{
|
||
|
|
$findRouteCount = $this->where('url', $url)->whereNotLike('full_url', $fullUrl)->count();
|
||
|
|
|
||
|
|
return $findRouteCount > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @throws ModelException
|
||
|
|
*/
|
||
|
|
public function setRoute($url, $action, $vars,$lang, $type, $sort, $seller_id, $category_id,$siteId,$category_title = '',$pattern=''): array
|
||
|
|
{
|
||
|
|
if (preg_match("/[()'\";]/", $url)) {
|
||
|
|
return dataReturn(-1, lang('url格式错误'));
|
||
|
|
}
|
||
|
|
|
||
|
|
$Website = new Website();
|
||
|
|
// 如果有子站点,更新子站点
|
||
|
|
$subSiteList = $Website->where([
|
||
|
|
['seller_id', '=', $seller_id],
|
||
|
|
['parent_id', '=', $siteId],
|
||
|
|
])->select()->toArray();
|
||
|
|
|
||
|
|
foreach ($subSiteList as $value) {
|
||
|
|
// 查询子站点的栏目,对应起来
|
||
|
|
$categoryModel = new Category();
|
||
|
|
$subCateArr = $categoryModel->where([
|
||
|
|
['website_id', '=', $value['id']],
|
||
|
|
['parent_map', '=', $category_id],
|
||
|
|
])->field('id, title, parent_map')->find();
|
||
|
|
|
||
|
|
$subCategoryId = $category_id;
|
||
|
|
$subCategoryTitle = $category_title;
|
||
|
|
$subVar = $vars;
|
||
|
|
if (!empty($subCateArr['id'])) {
|
||
|
|
$subCategoryId = $subCateArr['id'];
|
||
|
|
$subCategoryTitle = $subCateArr['title'];
|
||
|
|
if (isset($subVar['cid'])) {
|
||
|
|
$subVar['cid'] = $subCategoryId;
|
||
|
|
$subCategoryTitle .= lang('详情页');
|
||
|
|
} else {
|
||
|
|
$subVar['id'] = $subCategoryId;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->setRoute($url, $action, $subVar,$lang, $type, $sort, $seller_id, $subCategoryId,$value['id'],$subCategoryTitle,$pattern);
|
||
|
|
}
|
||
|
|
|
||
|
|
$fullUrl = $this->buildFullUrl($action, $vars);
|
||
|
|
|
||
|
|
$findRoute = $this->exitRoute(['seller_id'=>$seller_id,'website_id'=>$siteId,'lang'=>$lang,'full_url'=>$fullUrl,'url'=>$url])['data'];
|
||
|
|
|
||
|
|
if (!empty($findRoute)) {
|
||
|
|
if (empty($url)) {
|
||
|
|
$data = $this->delRoute(['id' => $findRoute['id'], 'seller_id' => $seller_id]);
|
||
|
|
} else {
|
||
|
|
$updateData = [
|
||
|
|
'url' => $url,
|
||
|
|
'sort' => $sort,
|
||
|
|
'type' => $type,
|
||
|
|
'category_id' => $category_id,
|
||
|
|
'pattern' => $pattern
|
||
|
|
];
|
||
|
|
$data = $this->updateRoute(['id' => $findRoute['id'], 'seller_id' => $seller_id], $updateData);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (!empty($url)) {
|
||
|
|
$addData = [
|
||
|
|
'seller_id' => $seller_id,
|
||
|
|
'full_url' => $fullUrl,
|
||
|
|
'website_id' => $siteId,
|
||
|
|
'url' => $url,
|
||
|
|
'sort' => $sort,
|
||
|
|
'type' => $type,
|
||
|
|
'lang' => $lang,
|
||
|
|
'category_title' => $category_title,
|
||
|
|
'category_id' => $category_id,
|
||
|
|
'pattern' => $pattern
|
||
|
|
];
|
||
|
|
$data = $this->addRoute($addData);
|
||
|
|
|
||
|
|
} else {
|
||
|
|
$data = [$this->sucCode, $this->getMsg];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $data;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param $action
|
||
|
|
* @param $vars
|
||
|
|
* @return bool
|
||
|
|
* @throws \Exception
|
||
|
|
*/
|
||
|
|
public function deleteRoute($action, $vars): bool
|
||
|
|
{
|
||
|
|
$fullUrl = $this->buildFullUrl($action, $vars);
|
||
|
|
$this->where('full_url', $fullUrl)->delete();
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|