Laravel по-русски

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

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

#51 Re: Хорошие практики (FAQ) » Соглашения об именовании » 18.11.2017 13:30:02

Но все же наверное есть классы которые вообще дурной тон класть в общую папку с другими, например Нотификации или Провайдеры там же сама Ларавель папки создает...


В тоже время по мне так лучше на папки все побить. Но в то же время в конце класса не дописывать Service Helper Interface итд

#52 Re: Хорошие практики (FAQ) » Соглашения об именовании » 18.11.2017 11:49:11

А имеет ли смысл держать контракты, трейты, сервисы, интерфейсы каждые в своей папке? Или только часть этих классов заслуживает отдельной папки? должны ли все они так или иначе лежат в папке Models или типа того?

#53 Хорошие практики (FAQ) » Соглашения об именовании » 18.11.2017 11:19:42

htclog81
Ответов: 8

>Переменные    $articlesWithAuthor

Это сначала articles тк сначала их берем в запросе. Множественное число тк коллекция. Для каждого артикла один автор и потому он единственный. Те все исходит из здравого смысла и содержимого переменной.

"Контракт (интерфейс): прилагательное или существительное    Authenticatable"

То есть СhangePasswordContract ChangePasswordService те включающие контракт сервис названия плохие...

Сервис и репозиторий как называть я бы тоже внес в таблицу.

А сокращение Pass вместо Password Trans вместо Transaction плохо?

#55 Re: Хорошие практики (FAQ) » Вопросы по стилю » 17.11.2017 18:35:09

А если название модели PaymentMethod то во множественном метод ты бы назвал getPaymentMethods или getPaymentsMethods ?

#56 Re: Хорошие практики (FAQ) » Вопросы по стилю » 17.11.2017 18:16:15

Хорошо. А методы внутри модели которые не являются отношениями?

Например

public function paymentWithMethod()
{
		return $this->payments()->with('payment_method', 'subscription.plan')->get();
}


public function paymentMethodWithIsDefault()
{
    return $this->payment_methods()->withCount('defaultForUser')->get();
}	

Как лучше назвать в плане числа? Если первый возращает платежи вместе с картами. А второй карты с признаком какая умолчательная..

#57 Re: Хорошие практики (FAQ) » Вопросы по стилю » 17.11.2017 18:00:19

При этом названия классов в единственном - Subscription Payment PaymentMethod, а не Subscription, Payments, PaymentMethods??Почему? Там же hasMany.


Тут я не про отношения уже спрашиваю, а про сами классы как называть

#59 Re: Прочее » Дублирование тем на форуме » 17.11.2017 17:52:31

Или ты не про мою тему, а про тему именно с запросом по ошибке?

#60 Re: Прочее » Дублирование тем на форуме » 17.11.2017 17:52:00

Специально не создавал... Может форма два раза отправилась... Конечно надо одну оставить тему.

#61 Re: Хорошие практики (FAQ) » Вопросы по стилю » 17.11.2017 17:40:49

нужно именовать методы method_name или methodNamemethodName

И для отношений типа

    public function paymentMethods()
    {
        return $this->hasMany(AppPaymentMethod::class, $this->getForeignKey())->orderBy('created_at', 'desc');
    }

Так?

в каком случае мы берем множественное число, а в каком единственноеЕдинственное число для hasOne и belongsTo, множественное для всех остальных.

При этом названия классов в единственном - Subscription Payment PaymentMethod, а не Subscription, Payments, PaymentMethods??

А методы не связанные с отношениями? Смотря что они возвращают? От этого зависит единственное или множественное число? Если возвращают коллекцию то множественное? Если один объект то единственное?

#62 Хорошие практики (FAQ) » Вопросы по стилю » 17.11.2017 15:39:02

htclog81
Ответов: 18

Первый вопрос

Допустим есть класс Eloquent модели. В нем есть отношения и свои какие то еще методы:

А в каком регистре или как правильно назвать, нужно именовать методы method_name или methodName

Дело в том что изначально и в том числе в пакетах вроде бы отношения пишут как method_name, в тоже время вроде бы хороший тон свои функции писать как methodName


Второй вопрос:

А в каком случае мы берем множественное число, а в каком единственное:

Например, вроде бы имя модели единственное число правильно писать... А имя отношения вроде бы множественное..

В общем что бы тут пофиксить и переименовать в указанном выше смысле


<?php

namespace App\Classes\Models;

use Illuminate\Notifications\Notifiable;
//use App\Notifications\CustomResetPassword;
use Illuminate\Foundation\Auth\User as Authenticatable;
use \Plunk\Mediable;
use Laravel\Cashier\Billable;
use \Plank\Mediable\Mediable as PlunkMediable;
use Braintree\PaymentMethod as BraintreePaymentMethod;
use Braintree\PayPalAccount as BraintreePayPalAccount;
use Braintree\Customer as BraintreeCustomer;
use Braintree\Transaction as BraintreeTransaction;
use Braintree\Subscription as BraintreeSubscription;
use Illuminate\Support\Arr;
use App\Classes\Models\PaymentMethod as AppPaymentMethod;

class User extends Authenticatable
{
    use Notifiable;
    use Billable;
    use PlunkMediable;
    
    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    public function subscriptions()
    {
        return $this->hasMany(Subscription::class, $this->getForeignKey())->orderBy('created_at', 'desc');
    }
	
	public function newSubscription($subscription, $plan)
    {
        return new SubscriptionBuilder($this, $subscription, $plan);
    }

	public function payments()
    {
        return $this->hasMany(Payment::class, $this->getForeignKey())->orderBy('created_at', 'desc');
    }
	
	public function payment_methods()
    {
        return $this->hasMany(AppPaymentMethod::class, $this->getForeignKey())->orderBy('created_at', 'desc');
    }	
		
	public function default_payment_method()
    {
        return $this->hasOne(AppPaymentMethod::class, 'id', 'default_payment_method_id');
    }

	
	public function paymentMethodWithIsDefault()
	{
		return $this->payment_methods()->withCount('defaultForUser')->get();
	}	
	
    public function getDefautPaymentMethod()
	{
		$paymentMethod = $this->default_payment_method()->first();
	
		return $paymentMethod;
	}

	
	public function paymentWithMethod()
	{
		return $this->payments()->with('payment_method', 'subscription.plan')->get();
	}

#63 Re: Laravel 5.x » Как убрать eloquent запросы из blade в модель, что бы было меньше sql » 17.11.2017 14:45:11

Готово так

	
			<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();
	}

Даже два отношения понадобилось. В целом все понятно и применена нетерпеливая загрузка

#64 Прочее » Дублирование тем на форуме » 17.11.2017 13:28:48

htclog81
Ответов: 5

Вот моя тема

https://laravel.ru/forum/viewtopic.php?pid=14907 тут есть ответы и вообще несколько сообщений. Эта ссылка из уведомления по мейлу.


https://laravel.ru/forum/viewtopic.php?id=3045  А тут только мой вопрос и нет почему то ответов. Эта ссылка в самом форуме. И еще и 0 ответов написано там в списке тем. Но это же неверно!

#65 Re: Laravel 5.x » Как убрать eloquent запросы из blade в модель, что бы было меньше sql » 17.11.2017 11:31:58

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


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

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

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

#66 Re: Laravel 5.x » Как убрать eloquent запросы из blade в модель, что бы было меньше sql » 17.11.2017 11:29:06

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

#67 Laravel 5.x » Как убрать eloquent запросы из blade в модель, что бы было меньше sql » 17.11.2017 10:34:47

htclog81
Ответов: 4

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

Модели

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

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

#68 Re: Laravel 5.x » Eloquent красиво выбрать есть ли для каждого объекта связаная запись » 16.11.2017 23:16:21

Нет.

Это вот

class User extends Authenticatable
{
 ....
	public function payment_methods()
    {
        return $this->hasMany(AppPaymentMethod::class, $this->getForeignKey())->orderBy('created_at', 'desc');
    }
	
	public function getPaymentMethods()
	{
		return $this->payment_methods()->withCount('defaultForUser')->get();
	}
  ....
}


class PaymentMethod extends Model
{
    ...  
	
	public function defaultForUser()
    {
        return $this->belongsTo(User::class, 'id', 'default_payment_method_id');
    }
	...
}

@foreach($user->getPaymentMethods() as $payment_method) 

@endforeach

#69 Re: Laravel 5.x » Eloquent красиво выбрать есть ли для каждого объекта связаная запись » 16.11.2017 22:05:21

Включил я в итоге debug bar

Запрос получился вот таким:


select `payment_method`.*, (select count(*) from `users` where `payment_method`.`id` = `users`.`default_payment_method_id`) as `default_for_user_count` from `payment_method` where `payment_method`.`user_id` = '1' and `payment_method`.`user_id` is not null and `payment_method`.`deleted_at` is null order by `created_at` desc


Помойму вполне терпимо. Я и на голом php так писал. Это же в не цикле подзапросы. select count со связкой по ключу норм

#70 Re: Laravel 5.x » Eloquent красиво выбрать есть ли для каждого объекта связаная запись » 16.11.2017 15:29:37

Но ты же делаешь $user->get_default_payment_method()->id а не $user->get_default_payment_method(). Т.е. просто так исполняешь кучу лишних запросов в БД. Установи Laravel Debugbar, чтобы наблюдать за запросами.


Я знаю понимаю. Я этот метод вроде бы и не использую в итоге? Посмотри, что я в итоге прислал... Debugbar скоро установлю. Я его удалил тк он мне портил ответы WebHook его js скрипты ответ сервера засоряли.

#71 Re: Laravel 5.x » Eloquent красиво выбрать есть ли для каждого объекта связаная запись » 16.11.2017 14:49:37

Отладил таким образом

class User extends Authenticatable
{
 ....
	public function payment_methods()
    {
        return $this->hasMany(AppPaymentMethod::class, $this->getForeignKey())->orderBy('created_at', 'desc');
    }
	
	public function getPaymentMethods()
	{
		return $this->payment_methods()->withCount('defaultForUser')->get();
	}
  ....
}


class PaymentMethod extends Model
{
    ...  
	
	public function defaultForUser()
    {
        return $this->belongsTo(User::class, 'id', 'default_payment_method_id');
    }
	...
}

@foreach($user->getPaymentMethods() as $payment_method) 

@endforeach

Конечно было бы наверное правильнее в PaymentMethod добавить метод который возвращает withCount('defaultForUser')->get(); и еще его вызывать в User через отношение... Но вроде и так норм..

А Scope в таких примерах никак не применимы?

Скажем для withCount('defaultForUser') и уже вызывать PaymentMethod с его использованием...

#72 Re: Laravel 5.x » Eloquent красиво выбрать есть ли для каждого объекта связаная запись » 16.11.2017 14:43:12

А разве $user->default_payment_method_id вернет не тоже самое, что $user->get_default_payment_method()->id?

не тоже самое $user->get_default_payment_method() вернет для юзера сам дефолтный пеймент метод, а то что ты указал вернет лишь строку с его id


Вот я думаю а как лучше поместить в модель... Чуть позже пришлю как сделал

#74 Re: Laravel 5.x » Eloquent красиво выбрать есть ли для каждого объекта связаная запись » 16.11.2017 12:31:35

Главный сейчас вопрос

$user->payment_methods()->withCount('defaultForUser')->get()

И другие подобные конструкции в views верно ли было бы спрятать в методы модели? И что бы в views обращаться через $user и его отношения к данным методом моделей?

#75 Re: Laravel 5.x » Eloquent красиво выбрать есть ли для каждого объекта связаная запись » 16.11.2017 12:29:16

В шаблонах вообще запросов не должно быть. Нужно заранее подгружать все данные и работать с результатом в представлении.

Хорошо, а как верно эту eloquent конструкцию спрятать? В контроллер не хочу, нет смысла.. он должен быть тонкий да и вообще контроллеров много,  а суть запроса одна. Почему бы не спрятать в модель?

Я говорю об отношении между User и PaymentType.

А оно не многое ко многим. Данный PaymentType не может принадлежать более чем одному юзеру

Это создаст дополнительно N запросов, мой код нет.

Да тк ты обращаешся просто к полю user

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