Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Вывожу историю платажей для пользователя. У пользователя несколько платежей. Отношение один ко многим. У платежа один платежный метод отношение один к одному
Модели
class User extends Authenticatable
{
public function payments()
{
return $this->hasMany(Payment::class, $this->getForeignKey())->orderBy('created_at', 'desc');
}
}
class Payment extends Model
{
public function payment_method()
{
return $this->belongsTo(PaymentMethod::class, 'payment_method_id', 'id');
}
И в шаблоне
<table border="1">
<tr>
<th>
</th>
<th>
summ
</th>
<th>
date
</th>
<th>
payment method
</th>
<th>
subscription
</th>
<th></th>
</tr>
@foreach($user -> payments()->get() as $payment)
<tr>
<td>
{{$payment->type}}
</td>
<td>
{{$payment->amount}}$
</td>
<td>
{{$payment->created_at}}
</td>
<td>
@if($payment -> payment_method()->first()->type == PaymentMethod::PAYPAL_ACCOUNT)
<div><strong>Paypal: </strong> {{ $payment -> payment_method() -> first() -> paypal_email }}</div>
@else
<div><strong>Card: </strong>{{ $payment -> payment_method() -> first() -> card_brand }} **** **** **** {{ $payment -> payment_method() -> first() -> card_last_four }}</div>
@endif
</td>
<td>
<div><strong>plan:</strong> {{ $payment->subscription->plan->name }}</div>
<div><strong>period:</strong> {{ $payment->period_start->format('d.m.Y')}} - {{ $payment->period_end->format('d.m.Y') }}</div>
</td>
<td>
@if (!empty($payment -> void_at))
<div>void {{ $payment -> void_at }}</div>
@elseif (!empty($payment->refund_at))
<div>refunded {{ $payment->refund_at }} </div>
@elseif(!empty($payment->refunded_transaction_id ))
<div>refund</div>
@endif
</td>
</tr>
@endforeach
</table>
Все это порождает множество запросов типа
select * from `payment_method` where `payment_method`.`id` = '3' and `payment_method`.`deleted_at` is null limit 1
select * from `payment_method` where `payment_method`.`id` = '3' and `payment_method`.`deleted_at` is null limit 1
Как это зарефакторить и переместить в модель, что бы не было множество запросов?
Не в сети
Загружай все данные и передавай коллекции в представление. Ну и используй нетерпеливую загрузку.
Не в сети
Я понимаю что можно подгрузить в контролере. Но а если а хочу что бы в модель передавать только $user и далее обращаться через его отношения, но без кучи этих подзапросов? В какую сторону смотреть что то типа With ? А хорошая ли это практика в данном случае?
Изменено htclog81 (17.11.2017 11:29:24)
Не в сети
Ну и используй нетерпеливую загрузку.
Да, вижу как раз про with речь и идет...
Видимо имеет смысл добавить в модель метод который вернет то что нужно используя with ну и в шаблоне дергать его. А в контроллере передавать только $user
В целом я верно понимаю?
Изменено htclog81 (17.11.2017 11:32:15)
Не в сети
Готово так
<table border="1">
@foreach($user -> paymentWithMethod() as $payment)
<tr>
<td>
<div><strong>id:</strong> {{$payment->id }}</div>
<div><strong>gateway id:</strong> {{ $payment->gateway_id }}</div>
</td>
<td>
{{$payment->type}}
</td>
<td>
{{$payment->amount}}$
</td>
<td>
{{$payment->created_at}}
</td>
<td>
@if($payment -> payment_method -> type == PaymentMethod::PAYPAL_ACCOUNT)
<div><strong>Paypal: </strong> {{ $payment -> payment_method -> paypal_email }}</div>
@else
<div><strong>Card: </strong>{{ $payment -> payment_method -> card_brand }} **** **** **** {{ $payment -> payment_method -> card_last_four }}</div>
@endif
<div><strong>id:</strong> {{ $payment -> payment_method -> id }}</div>
<div><strong>gateway id:</strong>{{ $payment -> payment_method -> braintree_id }}</div>
</td>
<td>
<div><strong>id:</strong> {{$payment->subscription->id }}</div>
<div><strong>gateway id:</strong> {{ $payment->subscription->braintree_id }}</div>
<div><strong>plan:</strong> {{ $payment->subscription->plan->name }}</div>
<div><strong>period:</strong> {{ $payment->period_start->format('d.m.Y')}} - {{ $payment->period_end->format('d.m.Y') }}</div>
</td>
<td>
@if (!empty($payment -> void_at))
<div>void {{$payment -> void_at}}</div>
@else
@if (!empty($payment->refund_at))
<div>refunded {{$payment->refund_at}} </div>
@endif
@if (!$payment->refunded_transaction_id && !$payment->refund_at)
<div><a href="{{ route('admin.payment_cancel', [$user->id, $payment->id]) }}" onclick="return confirm('Are you sure?')">Refund payment</a></div>
@endif
@if ($payment->refunded_transaction_id)
<div>refund {{$payment->refunded_transaction_id}}</div>
@endif
<div><a href="{{ route('admin.payment_settle', [$user->id, $payment->id]) }}" onclick="return confirm('Are you sure?')">Settle payment</a> <small>(Only in testing enviroment)</small></div>
@endif
</td>
</tr>
@endforeach
</table>
class User extends Authenticatable
{
public function payments()
{
return $this->hasMany(Payment::class, $this->getForeignKey())->orderBy('created_at', 'desc');
}
public function paymentWithMethod()
{
return $this->payments()->with('payment_method', 'subscription.plan')->get();
}
Даже два отношения понадобилось. В целом все понятно и применена нетерпеливая загрузка
Изменено htclog81 (17.11.2017 15:29:00)
Не в сети