195 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
| <?php namespace Gdoo\Index\Models;
 | ||
| 
 | ||
| use DB;
 | ||
| 
 | ||
| use Illuminate\Database\Eloquent\Model as Eloquent;
 | ||
| use App\Illuminate\Database\Query\Builder as QueryBuilder;
 | ||
| 
 | ||
| class BaseModel extends Eloquent
 | ||
| {
 | ||
|     public $timestamps = false;
 | ||
| 
 | ||
|     /**
 | ||
|      * 设置不允许批量赋值的字段
 | ||
|      */
 | ||
|     protected $guarded = ['id'];
 | ||
| 
 | ||
|     /**
 | ||
|      * 获取连接的新查询生成器实例
 | ||
|      *
 | ||
|      * @return \App\Database\Query\Builder
 | ||
|      */
 | ||
|     protected function newBaseQueryBuilder()
 | ||
|     {
 | ||
|         $connection = $this->getConnection();
 | ||
|         return new QueryBuilder(
 | ||
|             $connection,
 | ||
|             $connection->getQueryGrammar(),
 | ||
|             $connection->getPostProcessor()
 | ||
|         );
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 重写日期格式
 | ||
|      */
 | ||
|     public function getDateFormat()
 | ||
|     {
 | ||
|         return 'U';
 | ||
|     }
 | ||
| 
 | ||
|     public function getDates()
 | ||
|     {
 | ||
|         return [];
 | ||
|     }
 | ||
| 
 | ||
|     public function scopeWithAt($query, $relation, array $columns)
 | ||
|     {
 | ||
|         return $query->with([$relation => function ($query) use ($columns) {
 | ||
|             $query->select(array_merge(['id'], $columns));
 | ||
|         }]);
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 查询 Dialog 字段显示的值,其他模型可复写此方法
 | ||
|      */
 | ||
|     public function scopeDialog($query, $value)
 | ||
|     {
 | ||
|         return $query->whereIn('id', $value)->get();
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 取得所有层级
 | ||
|      *
 | ||
|      * @var string $columns 选择字段
 | ||
|      */
 | ||
|     public function scopeTree($query, $select = ['node.*'])
 | ||
|     {
 | ||
|         $rows = $this->from(DB::raw($this->from.' as node, '.$this->from.' as parent'))
 | ||
|         ->select($select)
 | ||
|         ->selectRaw('(COUNT(parent.id)-1) level')
 | ||
|         ->whereRaw('node.lft BETWEEN parent.lft AND parent.rgt')
 | ||
|         ->groupBy('node.id')
 | ||
|         ->orderBy('node.lft', 'asc');
 | ||
| 
 | ||
|         $result = array();
 | ||
| 
 | ||
|         if (is_array($rows)) {
 | ||
|             foreach ($rows as $row) {
 | ||
|                 $row['layer'] = str_repeat('|–', $row['level']);
 | ||
|                 $result[$row['id']] = $row;
 | ||
|             }
 | ||
|         }
 | ||
|         return $result;
 | ||
|     }
 | ||
|     
 | ||
|     /**
 | ||
|      * 取得指定层级集
 | ||
|      *
 | ||
|      * @var int $id 条件编号
 | ||
|      * $type int 0.包含自己的所有子类, 1.包含自己所有父类
 | ||
|      */
 | ||
|     public function scopeTreeById($query, $id, $type = 0)
 | ||
|     {
 | ||
|         $table = $this->table;
 | ||
|         $rows = $this->from(DB::raw($table.' as node, '.$table.' as parent'))
 | ||
|         ->whereRaw($type == 0 ? 'node.lft BETWEEN parent.lft AND parent.rgt' : 'parent.rgt BETWEEN node.lft AND node.rgt')
 | ||
|         ->where('parent.id', $id)
 | ||
|         ->groupBy('node.id')
 | ||
|         ->orderBy('node.lft', 'asc')
 | ||
|         ->select(['node.*'])
 | ||
|         ->get();
 | ||
| 
 | ||
|         return $rows;
 | ||
|     }
 | ||
| 
 | ||
|     public function scopeToTree($query, $text = 'name', $selected = 0, $state = 'closed')
 | ||
|     {
 | ||
|         if ($selected > 0) {
 | ||
|             $selected = $query->treeSinglePath($selected);
 | ||
|         }
 | ||
|         $nodes = $query->get()->toArray();
 | ||
| 
 | ||
|         // 格式化的树
 | ||
|         $tree = [];
 | ||
| 
 | ||
|         //临时扁平数据
 | ||
|         $map = [];
 | ||
| 
 | ||
|         foreach ($nodes as $node) {
 | ||
|             $node['text'] = $node[$text];
 | ||
|             $node['state'] = ($state == 'closed' && empty($selected[$node['id']])) ? 'closed' : 'open';
 | ||
|             $map[$node['id']] = $node;
 | ||
|         }
 | ||
|         unset($selected);
 | ||
| 
 | ||
|         foreach ($nodes as $node) {
 | ||
|             if (isset($map[$node['parent_id']])) {
 | ||
|                 $map[$node['parent_id']]['children'][] = &$map[$node['id']];
 | ||
|             } else {
 | ||
|                 $tree[] = &$map[$node['id']];
 | ||
|             }
 | ||
|         }
 | ||
|         unset($map, $nodes);
 | ||
|         return $tree;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 将所有子节点的ID压入根节点
 | ||
|      */
 | ||
|     public function scopeToChild($query, array $select = array('*'))
 | ||
|     {
 | ||
|         $items = $query->get($select)->keyBy('id')->toArray();
 | ||
|         $id = 0;
 | ||
|         foreach ($items as &$item) {
 | ||
|             $path = explode(',', $item['path']);
 | ||
|             $item['parent'] = $path;
 | ||
|         }
 | ||
|         return $items;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 返回当前节点的完整路径
 | ||
|      */
 | ||
|     public function scopeTreeSinglePath($query, $id)
 | ||
|     {
 | ||
|         $table = $this->table;
 | ||
|         $rows = $this->from(DB::raw($table.' as node, '.$table.' as parent'))
 | ||
|         ->whereRaw('node.lft BETWEEN parent.lft AND parent.rgt')
 | ||
|         ->where('node.id', $id)
 | ||
|         ->orderBy('node.lft', 'asc')
 | ||
|         ->select(['parent.*'])
 | ||
|         ->get()->keyBy('id');
 | ||
|         return $rows;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 重建树形结构的左右值
 | ||
|      *
 | ||
|      * @var $parent_id 构建的开始id
 | ||
|      */
 | ||
|     public function scopeTreeRebuild($query, $parent_id = 0, $left = 0, $layer = 0)
 | ||
|     {
 | ||
|         // 左值 +1 是右值
 | ||
|         $right = $left + 1;
 | ||
| 
 | ||
|         // 获得这个节点的所有子节点
 | ||
|         $rows = $this->where('parent_id', $parent_id)
 | ||
|         ->orderBy('sort', 'asc')
 | ||
|         ->get(['id', 'parent_id', 'lft', 'rgt']);
 | ||
| 
 | ||
|         if ($rows->count()) {
 | ||
|             foreach ($rows as $row) {
 | ||
|                 // 这个节点的子$right是当前的右值,这是由treeRebuild函数递增
 | ||
|                 $right = $this->TreeRebuild($row->id, $right, $layer + 1);
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         // 更新左右值
 | ||
|         $this->where('id', $parent_id)->orderBy('sort', 'asc')
 | ||
|         ->update(['lft'=>$left, 'rgt'=>$right, 'layer' => $layer]);
 | ||
| 
 | ||
|         // 返回此节点的右值+1
 | ||
|         return $right + 1;
 | ||
|     }
 | ||
| }
 |