У меня есть таблицы:
REGIONS id | name ----+------------------ 1 | South Luzon ----+------------------ 2 | North West Luzon ----+------------------ 3 | North East Luzon ===================================== BRANCHES machinenum | name | region_id -----------+-----------+----------- 108 | Alaminos | 1 -----------+-----------+----------- 104 | Alexander | 3 -----------+-----------+----------- 131 | Santiago | 3 -----------+-----------+----------- 114 | Apalit | 1 -----------+-----------+----------- 137 | Baliuag | 1 -----------+-----------+----------- 115 | Baguio | 2 -----------+-----------+----------- 116 | Bantay | 2 -----------+-----------+----------- 130 | San Jose | 3 ======================================= USERS id | name | machinenum ---+-------+------------- 1 | user1 | 108 ---+-------+------------- 2 | user2 | 104 ---+-------+------------- 3 | user3 | 131 ======================================== PENDINGS user_id | docdate --------+------------ 2 | 2016-07-14 --------+------------ 1 | 2016-07-13 --------+------------ 1 | 2016-07-14 --------+------------ 3 | 2016-07-13
Я хочу показать все ожидающие отправленные пользователями, сгруппированными по отраслям и регионам. Таким образом, мой запрос похож на выбор всех регионов, и внутри циклов выберите ветви, которые соответствуют region_id
, inner join
users
tbl, чтобы получить user_id
и внутри этого, выберите все ожидающие соответствия, которые совпадали с user_id
и отобразите docdate
если запрос вернется NOT NULL
else отображает 0
.
Вот мой запрос внутри моего контроллера:
$regions = DB::select('SELECT * FROM regions'); foreach ($regions as $region) { echo $region->name . "<br>"; $branches = DB::select('SELECT b.machinenum, b.name AS bname, u.id as uid FROM branches AS b INNER JOIN users AS u ON b.machinenum=u.machinenum WHERE region_id=:id ORDER BY b.name ASC', ['id' => $region->id]); foreach ($branches as $branch) { echo $branch->bname . "<br>"; $pendings = DB::select('SELECT * FROM pendings WHERE user_id=:id', ['id' => $branch->uid]); if ($pendings) { foreach ($pendings as $pending) { echo $pending->docdate . "<br>"; } echo "<br>"; } else { echo "0 <br>"; } } echo "<br>"; }
Результат будет:
South Luzon Alaminos 2016-07-14 -- docdate Apalit 0 -- return 0 if no pending Baliuag 0 -- return 0 if no pending North West Luzon Baguio 0 -- return 0 if no pending Bantay 0 -- return 0 if no pending North East Luzon Alexander 2016-07-13 -- docdate 2016-07-14 -- docdate San Jose 0 -- return 0 if no pending Santiago 2016-07-13 -- docdate
Ну, это именно то, чего я хочу. Но эта логика находится внутри моего контроллера. Я хочу, чтобы это было на мой взгляд. Как я могу вернуть эту логику на мой взгляд? Есть ли способ сделать это? Все, что я могу сделать, на мой взгляд, это @foreach and @if
.
Вот мой текущий код на мой взгляд (не против отношения между пользователями и филиалами, у меня уже есть это в моей модели):
// Note! In controller I have: $regions = Region::all(); $branches = Branch::all(); $pendings = Pending::all(); return view('pending.index', compact('regions', 'branches', 'pendings')); <table class="table table-noborder table-extra-condensed"> <thead> <tr> <th class="custom-td text-center">Date</th> </tr> </thead> <tbody> @foreach ($regions as $region) <tr> <th colspan="19">{{ $region->name }}</th> </tr> @foreach ($branches as $branch) @if ($region->id === $branch->region_id) <tr> <td>{{ $branch->name }}</td> </tr> @foreach ($pendings as $pending) @if ($branch->machinenum === $pending->user->machinenum) <tr> <td class="custom-td text-center">{{ $pending->docdate->format('d') }}</td> </tr> @endif @endforeach @endif @endforeach @endforeach </tbody> </table>
Давайте сломаем его.
Вы можете сопоставить эти отношения с моделью Region и просто называть его «pendings», поэтому вы каскадируете реальность, чтобы сделать ее более читаемой, и просто назовите Region :: with ('branch') -> get (); и вернуть его так, как вы хотите. Проверьте это.
Вот как мы это сделаем.
//Region.php function branches(){ return $this->hasMany('App\Branch')->with('usermachines'); }
Вот сложная часть, давайте притворимся, что таблица пользователей – это много-много таблиц отношений между ветвями и зависаниями и использование ветвей hasManyThrough, чтобы сделать для нас трудную часть:
//Branch.php function usermachines(){ return $this->hasManyThrough('App\Pending','App\User','machinenum','user_id')->with('pendings'); }
Готово! При всей этой настройке все, что вам нужно сделать, это:
в вашем контроллере:
$regions = Region::with('branches')->get(); return view('pending.index', compact('regions'));
и, на ваш взгляд, я удаляю ваш второй foreach и использую forelse, это похоже на foreach, но с другим, когда откидывания равны нулю, checkit out:
<table class="table table-noborder table-extra-condensed"> <thead> <tr> <th class="custom-td text-center">Date</th> </tr> </thead> <tbody> @foreach ($regions as $region) <tr> <th colspan="19">{{ $region->name }}</th> </tr> @foreach ($region->branches as $branch) <tr> <td>{{ $branch->name }}</td> </tr> @forelse($branch->pendings as $pending) <tr> <td class="custom-td text-center">{{ $pending->docdate->format('d') }}</td> </tr> @empty <tr> <td>0</td> </tr> @endforelse @endforeach @endforeach </tbody>