Yêu cầu thg 9 25, 2019 1:59 SA 731 0 1
  • 731 0 1
+1

Phân trang trong laravel ( có sử dụng đệ quy)

Chia sẻ
  • 731 0 1

Chào ace Viblo , Mình đang gặp một vấn đề phân trang với đệ quy. mình có 1 bảng Daily ( id, title, affID,nguoigt ) Bây giờ nhiệm vụ mình cần liệt kê ra tất cả các đại lý con của 1 đại lý bất kỳ ( trường hợp nhiều hơn 10 con thì phân trang ) . Nếu list tất cả các con thì mình dùng đệ quy đã lấy ra được nhưng ngặt nỗi là không thể phân trang TH nếu dữ liệu có đến hàng nghìn, triệu con thì có vẻ không ổn. đây là code mình đang dùng.

  • Trong model DaiLy
public function categories()
      {
          return $this->hasMany('App\DaiLy', 'nguoigt', 'affID');
      }
    public function childrenCategories()
      {
        return $this->hasMany('App\DaiLy', 'nguoigt', 'affID')->with('childrenCategories');
      }
  • Controller
public function getDaiLyChild()
	{
		$daily = DaiLy::where('affID',2)->with('childrenCategories')->paginate(2);
		return view('view.daily', compact('daily'));
	}
  • View.daily
<ul>
      @foreach ($daily as $category)
          <li>{{ $category->name }}</li>
          <ul>
          @foreach ($category->childrenCategories as $childCategory)
              @include('view.child', ['child_category' => $childCategory])
          @endforeach
          </ul>
      @endforeach
</ul>
  • view.child
<li>{{ $child_category->name }}- {{ $child_category->affID }}</li>
	@if ($child_category->categories)
	    <ul>
	        @foreach ($child_category->categories as $childCategory)
	            @include('view.child', ['child_category' => $childCategory])
	        @endforeach
	    </ul>
	@endif
Cảm ơn mọi người!
thg 9 25, 2019 2:16 SA

Bạn viết code vào trong cặp dấu như này để nó có màu mè cho dễ nhìn nhé:

```php

public function hello($name) { echo 'Hello '$name; }

```

Khi hiển thị trông nó sẽ như này:

public function hello($name)
{
    echo 'Hello '$name;
}
Avatar TinhTN @tinhtn89
thg 9 25, 2019 2:22 SA
thg 9 25, 2019 2:54 SA

@tinhtn89 Trông đẹp hơn hẳn 😆

1 CÂU TRẢ LỜI


Đã trả lời thg 9 25, 2019 4:42 SA
0

hàng triệu daily thì mình nghĩ hệ thống ko đạt đến ngướng đó đâu. còn cả khi khi nhiều như vậy hàm paginate của laravel đã tự lấy request->page để làm pagination ví dụ somehost?page=2 và số item perpage là 10 thì query tương đương với select * from daily... limit 10 offset 10 nếu bạn đánh index nguoigt và affID thì mình nghĩ tốc độ ko đến nỗi nào đâu

Chia sẻ
Avatar TinhTN @tinhtn89
thg 9 25, 2019 4:49 SA

Cảm ơn bạn, có vẻ bạn chưa hiểu ý của mình lắm. Cái mình cần là phân trang mà chưa phân trang được. Nó có 1 điểm khù khoằm ở đây là khi dùng paginate(10) thì nó lấy đủ 10 cái và phân trang nhưng ở đây lại sử dụng đệ quy gọi ngược trở lại và như thế thì những thằng gọi đến child đó nó lại không nằm trong truy vấn nên paginate not work.

thg 9 25, 2019 6:09 SA

@tinhtn89 Bạn thử sửa

 public function childrenCategories()
      {
        return $this->hasMany('App\DaiLy', 'nguoigt', 'affID')->with('childrenCategories');
      }

--->

 public function childrenCategories()
      {
        return $this->categories->with('childrenCategories');
      }

số query sẽ không tăng theo số record mà sẽ tăng theo deep của tree, thử check xem kết quả DaiLy::where('affID',2)->with('childrenCategories')->get() có là 1 collection không ? ok rồi thì làm bước tiếp theo

bạn muốn paginate list bao gồm con nó, con của con nó .... đúng không ?

vậy thì phải map lại kết quả, ở đây bạn xử lý ở server, nên bạn có thể viết 1 hàm để map lại nó, trong model hay helper hay gì tùy bạn

pseudocode

function mapDailyChildrenRecursiveToFlatList(Collection $collection, Array $arr = []): Collection {
    if (!empty($collection->categories)) {
        foreach($collection->categories as $cate) {
            // u can exclude some keys u dont want
            $arr[] = $cate;
            $this->mapDailyChildrenRecursiveToFlatList($cate, $arr);
    	}
    } else {
        return collect($arr);
    }
}

// in controller
$daily = DaiLy::where('affID',2)->with('childrenCategories')->paginate(2);
$childrenFlatList = mapDailyChildrenRecursiveToFlatList($daily);

return view('view.daily', ['daily' => $childrenFlatList ]);
Avatar TinhTN @tinhtn89
thg 9 25, 2019 6:47 SA

@Plumpboy cảm ơn bạn nghe có vẻ rất hợp lý để mình thử xem. 👍

Avatar TinhTN @tinhtn89
thg 9 25, 2019 5:23 CH

@Plumpboy Mình đã test thì nó không chạy và báo lỗi ở Model 111.JPG

Model:

 public function categories()
      {
          return $this->hasMany('App\DaiLy', 'nguoigt', 'affID');
      }

      public function childrenCategories()
      {
        return $this->categories->with('childrenCategories');
      }
Avatar TinhTN @tinhtn89
thg 9 25, 2019 5:26 CH

Mình có thử một cách khác lấy ra được các mảng con của nó, nhưng dưới dạng mảng trong mảng, không biết từ đó có lấy ra được danh sách ID không. Capture.JPG

Controller:

$daily = DaiLy::where('affID',5)->select('id','affID','nguoigt')->with('childrenCategories')->get()->toArray();
		$collection = collect($daily);
    	$collapsed = $collection->collapse();
		$d = $collapsed->all();
		dd($d);```
Avatar TinhTN @tinhtn89
thg 9 26, 2019 1:57 SA

Mình đã giải quyết được bài toàn, nhưng không biết đã tối ưu hoặc có cách nào hay hơn không?

Model:

class DaiLy extends Model
{
protected $table ='daily';
public function categories()
      {
          return $this->hasMany('App\DaiLy', 'nguoigt', 'affID');
      }
     public function childrenCategories()
       {
        return $this->hasMany('App\DaiLy', 'nguoigt', 'affID')->with('childrenCategories')->select('id','affID','nguoigt');
      }
}

Controller:

public function getTree()
	{
		$daily = DaiLy::where('affID',8)->with('childrenCategories')->select('id','affID','nguoigt')->get()->toArray();
		$collection = collect($daily);
    	$collapsed = $collection->flatten();
		$arr = array();
		foreach($collapsed as $key=>$v) { if($key%3 ==0) { $arr[]=$v; } }
		$dailyChild = DaiLy::whereIn('id',$arr)->select('id','affID','nguoigt','name','diachi')->Orderby('id','ASC')->paginate(5);
		return view('tinh', compact('dailyChild'));
	}

View

<ul> {{ $stt =0 }}
      @foreach ($daily as $category)
          <li>{{ $category->name }}</li>
          <ul>
          @foreach ($category->categories as $childCategory)
              @include('child_category', ['child_category' => $childCategory,'stt'=>$stt])
          @endforeach
          </ul>
      @endforeach
</ul>
<div class="paginate">{!--{$daily->links()}--}</div>

Cảm ơn @Plumpboy .

thg 2 3, 2023 4:06 SA

@tinhtn89 cho mình xem chỗ view child_category bạn viết như thế nào được không ạ

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí