Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Посоветуйте по структуре приложения на php laravel 5 / 1 сообщений из 1, страница 1 из 1
06.08.2017, 16:48
    #39500969
alonecat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Посоветуйте по структуре приложения на php laravel 5
Добрый день! Учусь ларавель, делаем тестовый проект типа облачного хостинга файлов, который возможно станет реальным.

На данный момент все в стадии развернули ларавель, система авторизации (ларавельная) с активацией и сменой мейла (своими), также загрузка и вывод аватара (свои на основе Mediable). Далее в планах подключения биллинга и работа с файлами пользователей.

Все, что сейчас сделано работает. Но хотелось бы советов, по оптимальному проектированию классов.

Для начала примерно показываю что сделал.

Для авторизации и смены мейла написал похожие друг на друга сервисы. И сделал для них интерфейсы и зарегил сервис провайдер. Они включают в себя методы для обработки как запроса на отсылку письма с подтвержением регистрации/нового мейла, так и обработку клика по ссылке из данных писем.

Токены подтвержения регистрации и смены мейла и сам новый мейл, храню в двух отдельных табличках, не в users. И для каждой этой табличке по модели элоквент и по репозиторию.

Привожу код для случая смены мейла:

Роуты

Код: php
1.
2.
3.
4.
5.
    Route::get('home/account/email', ['middleware' => ['auth', 'isVerified'], 'uses' => 'Auth\ChangeEmailController@showForm'])->name('home.account.email');
    
    Route::post('home/account/email_save', ['middleware' => ['auth', 'isVerified'], 'uses' => 'Auth\ChangeEmailController@saveForm'])->name('home.account.email_save');
    
    Route::get('home/account/email_set/{token}', ['middleware' => ['auth', 'isVerified'], 'uses' => 'Auth\ChangeEmailController@emailSet'])->name('home.account.email_set');



Методы контроллера запроса на смену и смены по ссылке из письма


Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
   

     public function saveForm(Request $request, ChangeEmailContract $changeEmailService)
        {
            $user = Auth::user();
            
            $rules = [
                'email' => 'required|email|unique:users',
                'password' => 'required|checkpassword:'.$user->email,
            ];
            
            $messages = [
                'email.required' => 'Please enter an email address',
                'email.email' => 'Please enter a valid email address',
                'email.unique' => 'This e-mail is already taken. ',
                'password.required' => 'Please enter your password',
                'password.checkpassword' => 'Your enter wrong password',
                
            ];
            
            
            Validator::make($request::all(), $rules, $messages)->validate();
            
            $changeEmailService->sendChangeEmailMail($user, Request::get('email'));
            
            return redirect()->route('home')->with('status', "Confirmation change E-mail link send to ".Request::get('email'));
        }
        
        public function emailSet($token, ChangeEmailContract $changeEmailService)
        {
            $email = Request::get('email');
            
            try {
               $user = $changeEmailService->setEmail($token, $email);
            }
            catch (\App\Exceptions\ChangeEmailNotFoundException $e) {
                return redirect()->route('home')
                    ->with('status', $e->getMessage());
            }
            
            Auth::login($user);
           
            return redirect()->route('home')
                ->with('status', 'You successfully activated your new email!');
        }



Сервис
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
    namespace App\Services\Auth;
    
    use \App\Models\User;
    use \App\Contracts\Auth\ChangeEmailContract;
    use \App\Contracts\Auth\ChangeEmailRepositoryContract;
    use \App\Exceptions\ChangeEmailNotFoundException;
    use Illuminate\Mail\Mailer;
    use Illuminate\Mail\Message;
    
    class ChangeEmailService implements ChangeEmailContract
    {
    
        protected $mailer;
        
        protected $changeEmailRepo;
        
        public function __construct(ChangeEmailRepositoryContract $changeEmailRepo)
        {
           $this->changeEmailRepo = $changeEmailRepo;
        }
      
        public function sendChangeEmailMail($user, $email)
        {
            $token = $this->changeEmailRepo->createEmailChange($user, $email);
            
            \Mail::to($email)->send(
                new \App\Mail\ChangeEmail(array(
                    'email' => $email,
                    'token' => $token,
                ))
            );
        }
        
        public function setEmail($token, $email)
        {
            $changeEmail = $this->changeEmailRepo->getChangeEmailByTokenAndEmail($token, $email);
            
            if ($changeEmail === null) {
                throw new ChangeEmailNotFoundException();
            }
            
            $user = User::find($changeEmail->user_id);
            
            if (!$user) {
                throw new ChangeEmailNotFoundException();
            }
    
            $user->email = $email;
    
            $user->save();
    
            $this->changeEmailRepo->deleteChangeEmail($token);
    
            return $user;
    
        }
        
    }



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

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
    namespace App\Repositories\Auth;
    
    use \App\Contracts\Auth\ChangeEmailRepositoryContract;
    use \App\Models\EmailChange;
    use Carbon\Carbon;
    use Illuminate\Database\Connection;
    use Illuminate\Support\Facades\DB;
    
    
    class ChangeEmailRepository implements ChangeEmailRepositoryContract
    {
        public function createEmailChange($user, $email)
        {
            $email_change = $this->getEmailChange($user);
            
            if (!$email_change) {
                return $this->createEmailChangeRecord($user, $email);
            }
            
            return $this->updateEmailChangeRecord($user, $email);
            
        }
        
        public function getEmailChange($user)
        {
            return EmailChange::where('user_id', $user->id)->first();
        }
        
        public function getChangeEmailByTokenAndEmail($token, $email)
        {
            return EmailChange::where(array('token' => $token, 'email' => $email))->first();
        }
        
        public function deleteChangeEmail($token)
        {
            EmailChange::where('token', $token)->delete();
        }
        
        private function updateEmailChangeRecord($user, $email)
        {
            $token = $this->getToken();
            
            EmailChange::where('user_id', $user->id)->update([
                'token' => $token,
                'email' => $email,
                'created_at' => new Carbon()
            ]);
            
            return $token;
        }
        
        private function getToken()
        {
            return hash_hmac('sha256', str_random(40), config('app.key'));
        }
        
        private function createEmailChangeRecord($user, $email)
        {
            $token = $this->getToken();
            
            EmailChange::insert([
                'user_id' => $user->id,
                'token' => $token,
                'email' => $email,
                'created_at' => new Carbon()
            ]);
            
            return $token;
        }
    }


Модель таблицы
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class EmailChange extends Model
    {
        protected $table = 'email_change';
        
        public function user()
        {
            return $this->belongsTo(User::class);
        }
    
    }



Моделька юзера. Метод отправки письма, связан не с данным, функционалом, а со сменой пароля, которая встроенная используется.

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
    namespace App\Models;
    
    use Illuminate\Notifications\Notifiable;
    use App\Notifications\CustomResetPassword;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    use \Plunk\Mediable;
    class User extends Authenticatable
    {
        use Notifiable;
        use \Plank\Mediable\Mediable;
    
        protected $fillable = [
            'name', 'email', 'password',
        ];
    
        protected $hidden = [
            'password', 'remember_token',
        ];
    
        public function sendPasswordResetNotification($token)
        {
    
            $this->notify(new CustomResetPassword($token));
        }
    }


Сервис провайдеры для сервиса и репозитория
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
    namespace App\Providers\Auth;
    
    use Illuminate\Support\ServiceProvider;
    
    class ChangeEmailProvider extends ServiceProvider
    {
        protected $defer = false;
    
        public function register()
        {
           
            $this->app->bind('App\Contracts\Auth\ChangeEmailContract', function ($app) {
              
                return new \App\Services\Auth\ChangeEmailService(
                   $app -> make("\App\Contracts\Auth\ChangeEmailRepositoryContract")
                );
            });
            
        }
    
        public function provides()
        {
            return ['\App\Contracts\Auth\ChangeEmailContract'];
            
        }
        
        public function boot()
        {
         
            
        }
    }
    

    namespace App\Providers\Auth;
    
    use Illuminate\Support\ServiceProvider;
    
    class ChangeEmailRepositoryProvider extends ServiceProvider
    {
        protected $defer = false;
    
        public function register()
        {
            $this->app->bind('\App\Contracts\Auth\ChangeEmailRepositoryContract', function ($app) {
                return new \App\Repositories\Auth\ChangeEmailRepository();
            });
        }
    
        public function provides()
        {
            return ['\App\Contracts\Auth\ChangeEmailRepositoryContract'];
            
        }
        
        public function boot()
        {
              
        }
    }




Как я хочу все это отрефакторить?

Я думаю нужно создать UserRepository, его явно не хватает. В него конечно нужно будет добавить саму регистрацию, смену аватара, а из данного функционала, пожалуй те небольшие процедуры которые относятся все же именно к таблице users например постановка, статус активирован, установка нового мейла...

Тогда получится для каждой таблицы свой репозиторий. В общем то логично. Но кажется более практично было бы, так как активация и смена мейла, в общем то также тесно связанные именно с юзеров вещи и все обращения к таблицам ChangeEmail и Activation а так же генерацию и проверку токена перенести в UserRepository. Да он будет толще зато смогу убрать два репозитория ChangeEmailRepository и ActivateEmailRepository и также два контракта и два сервис провайдера..

Тогда получится юзеру и связанным тесно с ними табличкам общий репозиторий, а вот сервисы отдельные для смены емайла, активации и аватара оставить.

Как считаете, так было бы оптимальнее?

Так же прошу подсказать есть в моем уже существующем и приведенном коде какие то явные ошибки?

И еще вопрос. А даже если ChangeEmailRepository и ActivateEmailRepository оставить отдельными и не переносить их содержимое в UserRepository, то нужны ли для этих репозиториев контракты и сервис провайдеры, учитывая что подменять реализацию я ведь вряд ли буду....
...
Рейтинг: 0 / 0
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Посоветуйте по структуре приложения на php laravel 5 / 1 сообщений из 1, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]