Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 17.11.2017 10:34:47

htclog81
Откуда: Москва
Сообщений: 192
Сайт

Как убрать eloquent запросы из blade в модель, что бы было меньше sql

Вывожу историю платажей для пользователя. У пользователя несколько платежей. Отношение один ко многим. У платежа один платежный метод отношение один к одному

Модели

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

Как это зарефакторить и переместить в модель, что бы не было множество запросов?

Не в сети

#2 17.11.2017 10:53:55

Re: Как убрать eloquent запросы из blade в модель, что бы было меньше sql

Загружай все данные и передавай коллекции в представление. Ну и используй нетерпеливую загрузку.

Не в сети

#3 17.11.2017 11:29:06

htclog81
Откуда: Москва
Сообщений: 192
Сайт

Re: Как убрать eloquent запросы из blade в модель, что бы было меньше sql

Я понимаю что можно подгрузить в контролере. Но а если а хочу что бы в модель передавать только $user и далее обращаться через его отношения, но без кучи этих подзапросов? В какую сторону смотреть что то типа With ? А хорошая ли это практика в данном случае?

Изменено htclog81 (17.11.2017 11:29:24)

Не в сети

#4 17.11.2017 11:31:58

htclog81
Откуда: Москва
Сообщений: 192
Сайт

Re: Как убрать eloquent запросы из blade в модель, что бы было меньше sql

Ну и используй нетерпеливую загрузку.


Да, вижу как раз про with речь и идет...

Видимо имеет смысл добавить в модель метод который вернет то что нужно используя with ну и в шаблоне дергать его. А в контроллере передавать только $user

В целом я верно понимаю?

Изменено htclog81 (17.11.2017 11:32:15)

Не в сети

#5 17.11.2017 14:45:11

htclog81
Откуда: Москва
Сообщений: 192
Сайт

Re: Как убрать eloquent запросы из blade в модель, что бы было меньше sql

Готово так

	
			<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)

Не в сети

Подвал раздела