Laravel по-русски

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

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

#1 03.12.2017 01:23:49

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

Где лучше прописать дату по умолчанию

Хочу прописать дату окончания триального периода подписки по умолчанию.

Где это лучше сделать?

В конфиг дату прописать не получается.


'subscription' => [
   'trialEndsAt' => \Carbon::today()->addDays(1),
]

Не работает.

В класс Subscription прописать константу или статическую переменную имеющую значение Carbon::today()->addDays(1) не получается.

Как вообще принято даты по умолчанию прописывать?

Нет конечно можно прописать период по умолчанию через durationUnit и duration, но это две переменные и вообще хочется иметь все таки именно дату по умолчанию.

Как быть???

Не в сети

#2 03.12.2017 09:27:49

Re: Где лучше прописать дату по умолчанию

  1. Как вообще принято даты по умолчанию прописывать?

Я пишу в конфиге количество часов или дней, например.

PHP
'trial_ends_in_hours' => 24,

А логика должна быть только в коде:

PHP
'trialEndsAt' => Carbon::now()->addHours(config('subscription.trial_ends_in_hours')),

Не в сети

#3 03.12.2017 11:35:37

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

Re: Где лучше прописать дату по умолчанию

Спасибо так и сделаю.

А если я хочу из формы принимать дату. То преобразовать ее из того что прислала форма ну например html 5 поле с датой или js календарь итд в Carbon дату где лучше? Мне кажется модель не должна знать что там за дата в форм, значки в контроллере или в реквесте быть может?

Как красивее? В реквесте по любому дату ведь проверять

Не в сети

#4 03.12.2017 12:04:37

Re: Где лучше прописать дату по умолчанию

Мне кажется модель не должна знать что там за дата в форм

Почему нет? Я не задумывался об этом особо, но мне кажется, что это можно делать в модели, в контроллере/сервисе/трансформере, в преобразователе модели (mutator) и т.д.

Не в сети

#5 03.12.2017 12:10:11

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

Re: Где лучше прописать дату по умолчанию

Почему модель не должна знать?

Допустим есть метод

class ExampleModel
{
  function create($request) 
  {
      $request['trial_end'] = fromSomeFormatDate($request['trial_end']);
  }

И вот этот fromSomeFormatDate() зависит от того, что мы сделали в форме и интерфейсе? Кажется совсем не красиво. Тк в форме то мы захотим в таком формате у юзера брать дату, а затем заказчик скажет некрасиво давайте в чуть другом, а мы уже модель меняем. А в метод create модели данные могут и не только из данной формы поступать...

Про сервис понятно, но допустим его не приминяем... А как в мутаторе? Можешь пример привести?

Изменено htclog81 (03.12.2017 12:11:41)

Не в сети

#6 03.12.2017 12:27:33

Re: Где лучше прописать дату по умолчанию

  1. как в мутаторе? Можешь пример привести?
PHP
public function setTrialEndsAtAttribute($value)
{
    
$this->attributes['trial_ends_at'] = Carbon::now()->addHours(config('subscription.trial_ends_in_hours'));
}

Если из формы данные, то:

PHP
public function setSomeDateAttribute($value)
{
    
$this->attributes['some_date'] = Carbon::parse($value);
}

Если логика простая, как в последнем примере, то можно просто сделать так:

PHP
protected $dates = [
    
'created_at',
    
'updated_at',
    
'some_date'
];

Не в сети

#7 03.12.2017 18:43:48

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

Re: Где лучше прописать дату по умолчанию

Нет, посмотрел свой код мутатор мне не подходит, так как мне нужно менять формат даты не в момент создания объекта именно...

Мне нужно следующее:

1) Принять дату из формы или из конфига
2) Заслать через API дату. Причем там есть варианты и более чистый что ли это через TrialDuration и TrialDurationUnit, а не просто DateTime
3) Использовать дату при создании объекта Subscription

Очевидно что мутатор по крайней мере задачу 2 не решает. Можно конечно написать Хелпер который переводит дату из TimeStamp в TrialDuration и TrialDurationUnit. А перед этим то что в форме перевести в Timestamp

Не в сети

#8 03.12.2017 22:25:30

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

Re: Где лучше прописать дату по умолчанию

Сделал это таким образом

Конфиг

	'subscription' => [
		'trial_ends_in_days' => 4,
	]

Контроллер в случае если мы эту дату берем из конфига, а не из формы. Те если платит юзер, а не админ, то ему дату не выбирать.


$user-> createSubscription(array_merge(
	$request->all(), [
		"trial_ends_at" => config('services.subscription.trial_ends_in_days') ? Carbon::today()->addDays(config('services.subscription.trial_ends_in_days')) : null,
	]
));

Модель. Трейт юзера, где мы создаем для юзера подписку. От разных форматов даты удалось избавиться, тк я понял что через API можно и просто timestamp передать, узнал у саппорта.

public function createSubscription($request)
{
	if (isset($request['payment_method_nonce'])) {
		if ($this->gateway_id) {
			throw new \LogicException('When user have payment method add subscription only with this method');
		} else {
			$this->createGatewayCustomerWithPaymentMethod($request['payment_method_nonce']);
		}
	} else {
		if (!$this->gateway_id) {
			throw new \LogicException('When user have not payment method add subscription only with add payment data');
		} 
	
	}
	
	$plan = Plan::findOrFail($request['plan_id']);
	

	
	if (empty($request['trial_ends_at'])) {
		$response = GatewaySubscription::create([
			'planId' => $plan->gateway_id,
			'paymentMethodToken' => $this->defaultCard->gateway_id,
			'options' => ['startImmediately' => true]
		]);
		
	} else {
		
		$response = GatewaySubscription::create([
			'planId' => $plan->gateway_id,
			'paymentMethodToken' => $this->defaultCard->gateway_id,
			'firstBillingDate' => $request['trial_ends_at'],
		
		]);
		
	}
	
	if (! $response->success) {
		throw new Exception('Gateway failed to create subscription: '.$response->message);
	}

	return $this->subscriptions()->create([
		'gateway_id'   => $response->subscription->id,
		'card_id' => $this->defaultCard->id, 
		'current_period_end' => $response->subscription->billingPeriodEndDate,
		'plan_id' => $plan->id,
		'trial_ends_at' => $request['trial_ends_at'],
	 ]);
	
}

Ну а в случае с админом, я просто через js календарик в нужном формате дату запрашиваю и ничего так же преобразовывать не приходиться. Все что нужно в Request

	public function createSubscriptionByAdmin($request)
	{
		
		$plan = Plan::findOrFail($request['plan_id']);
		
		if ($this->hasCard()) {
			if (empty($request['trial_ends_at'])) {
				$response = GatewaySubscription::create([
					'planId' => $plan->gateway_id,
					'paymentMethodToken' => $this->defaultCard->gateway_id,
					'options' => ['startImmediately' => true]
				]);
				
			} else {
				
				$response = GatewaySubscription::create([
					'planId' => $plan->gateway_id,
					'paymentMethodToken' => $this->defaultCard->gateway_id,
					'firstBillingDate' => $request['trial_ends_at'],
				]);
				
			}
			
			if (!$response->success) {
					throw new Exception('Gateway failed to create subscription: '.$response->message);
			}
			
			return $this->subscriptions()->create([
				'gateway_id' => $response->subscription->id,
				'card_id' => $this->defaultCard->id, 
				'current_period_end' => $response->subscription->billingPeriodEndDate,
				'plan_id' => $plan->id,
				'trial_ends_at' => $request['trial_ends_at'],
			]);
		} else {
			return $this->subscriptions()->create([
				'plan_id' => $plan->id,
				'trial_ends_at' => $request['trial_ends_at'],
			]);
		}
		
	}

До сегодняшних изменений все это в двух сервисных классах SubscriptionBuilder и GenericSubscriptionBuilder было которыя у cashier пакета подсмотрел. Кода меньше стало.  Но осталось эти две метода createSubscription() и createSubscriptionByAdmin() зарефакторить на предмет повторного кода и меньше условий. Благодаря тому что с датой разобрался все куда лучше стало.

Изменено htclog81 (03.12.2017 22:28:23)

Не в сети

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