Laravel по-русски

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

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

#1 30.06.2015 08:27:14

Простая авторизация Laravel 5.1.1

версия Laravel:
php artisan -V
Laravel Framework version 5.1.1 (LTS)

Читаю доки-уроки по аутентификации в 5-м и натыкаюсь на несоответствия.
Ввиду малого опыта, процесс обучения затягивается.

Итак. Создал миграцию с таблицей users:

public function up()
{
	Schema::create('users', function(Blueprint $table) {
            // ID пользователя
            $table->increments('id');
 
            // E-Mail (уникальный)
            $table->string('email')->unique();
 
            // Пароль. Для используемой в Laravel хэш-функции требуется не меньше 60 символов
            $table->string('password', 60);
 
            // Никнейм
            $table->string('username')->unique();
 
            // Админ?
            $table->boolean('isAdmin');
 
            // Активирован?
            $table->boolean('isActive')->index();
 
            // Код активации аккаунта
            $table->string('activationCode');
 
            // Токен для возможности запоминания пользователя
            $table->rememberToken(); // remember_token
 
            // created_at, updated_at
            $table->timestamps();
        });
}

В БД таблица появилась.
Дальше создаю по уроку:
https://laracasts.com/series/laravel-5- … pisodes/15 - создаю путь:
Route::controller(['auth' => 'Auth\AuthController']);

php artisan route:list - вываливает ошибку:
Missing argument 2 for Illuminate\Routing\Router::controller(), called in F
  :\OpenServer\domains\project\vendor\laravel\framework\src\Illuminate\Suppor
  t\Facades\Facade.php on line 210 and defined

Смотрю доки: упоминается шаблон resources/views/auth - у себя не нахожу каталог auth

Потом в уроке ссылаются на trait AuthenticatesAndRegistersUsers
у меня он не такой как в уроке:
namespace Illuminate\Foundation\Auth;

trait AuthenticatesAndRegistersUsers
{
    use AuthenticatesUsers, RegistersUsers {
        AuthenticatesUsers::redirectPath insteadof RegistersUsers;
    }
}

Собственно как создать простую авторизацию в 5.1.1?

Не в сети

#2 30.06.2015 11:41:07

Re: Простая авторизация Laravel 5.1.1

php artisan|grep table

потом генеришь дефолтные миграции.
затем правишь их.

своих оверрайдов не надо писать, а то напонатыкаешься на несоответствий.
корректируй существующие.

+

5.1 отличается от 5.0, не серьёзно, но уже от многих старых рнр-фишек отказались в пользу новых.

Не в сети

#3 30.06.2015 23:05:11

Re: Простая авторизация Laravel 5.1.1

Пришлось ковырять инглиш
Route::controller(['auth' => 'Auth\AuthController']); - это похоже в 5.1 не работает.

рекомендуют так:
Route::get('auth/login', 'Auth\AuthController@getLogin');
Route::post('auth/login', 'Auth\AuthController@postLogin');
Route::get('auth/logout', 'Auth\AuthController@getLogout');

// Registration routes...
Route::get('auth/register', 'Auth\AuthController@getRegister');
Route::post('auth/register', 'Auth\AuthController@postRegister');

ну и дальше тоже есть отличия от 5.0.
http://laravel.com/docs/5.1/authentication

Не в сети

#4 01.07.2015 08:47:05

Re: Простая авторизация Laravel 5.1.1

Хотелось бы немного изменить дефолтную регистрацию. В частности, нужно отсылать пользователю email с предложением подтвердить регистрацию, после подтверждения пользователь может входить. Стандартный механизм регистрации описан в трейте \project\vendor\laravel\framework\src\Illuminate\Foundation\Auth\RegistersUsers.php
согласно логике, пользователь при отправке формы регистрации проходит валидацию контроллера \project\app\Http\Controllers\Auth\AuthController.php, и если все ок, система сразу его логинит.

Я могу переделать метод postRegister RegistersUsers.php - но меня смущает, что придется ковырять файл движка.
Или отказаться от стандартного механизма и написать свой с нуля используя Ручную аутентификацию и метод attempt? Как обычно принято делать в таких случаях?

Не в сети

#5 01.07.2015 08:58:12

Re: Простая авторизация Laravel 5.1.1

Route::controller(['auth' => 'Auth\AuthController']);

если ты передаёшь массив, должно быть ::controllers

Не в сети

#6 01.07.2015 09:03:16

Re: Простая авторизация Laravel 5.1.1

если ты в контроллере объявляешь метод, который совпадает с именем из трейта — метод контроллера перекроет метод из трейта. т.е. его можно просто скопипастить оттуда и переделать как считаешь нужным.

PHP
    /**
     * Handle a registration request for the application.
     *
     * @param Request   $request
     * @param MailQueue $mailer
     *
     * @return array|Response
     */
    
public function postRegister(Request $requestMailQueue $mailer)
    {
        
$validator $this->registrar->validator($request->all());

        if (
$validator->fails()) {
            
$this->throwValidationException($request$validator);
        }

        
/** @var User $user */
        
$user $this->registrar->create($request->all());
        
$url action('Auth\AuthController@getConfirm', [ $user->confirmation_code ]);

        
$mailer->queue('emails.confirm'compact('url''user'), function ($message) use ($user$url)
        {
            
$message->to($user->email)->subject('Подтверждение регистрации');
        });

        return ...;
    }

    
/**
     * Подтверждение регистрации пользователем
     *
     * @param Request     $request
     * @param User        $user
     * @param string|null $token
     *
     * @return Response
     */
    
public function getConfirm(Request $requestUser $user$token null)
    {
        if (
is_null($token)) {
            throw new 
NotFoundHttpException;
        }

        
/** @var User $user */
        
$user $user->whereConfirmationCode($token)->first();

        if (!
$user) {
            return 
view('auth.noconfirm')->withMessage('Пользователь с таким кодом подтверждения не найден. Если это ошибка, свяжитесь с нами.');
        }
        if (
$user->confirmed) {
            return 
view('auth.noconfirm')->withMessage('Ваш пользовательский аккаунт уже активирован. Нажмите "Войти" и введите свой логин и пароль, или воспользуйтесь восстановлением пароля.');
        }

        
$user->confirmed true;
        
$user->save();

        return ...;
    }

Изменено constb (01.07.2015 09:05:53)

Не в сети

#7 01.07.2015 09:17:51

Re: Простая авторизация Laravel 5.1.1

забыл дописать PHP$this->auth->login($user); в getConfirm, а редактировать уже не даёт.

Не в сети

#8 01.07.2015 11:29:03

Re: Простая авторизация Laravel 5.1.1

Спасибо. Попробую внедрить.

Не в сети

#9 02.07.2015 05:10:24

zloadmin

Re: Простая авторизация Laravel 5.1.1

Сделал заготовку с стандартной авторизацией (вход, выход, восстановление пароля)
https://github.com/zloadmin/laravel51_with_auth

#10 02.07.2015 11:06:08

Re: Простая авторизация Laravel 5.1.1

а зачем весь проект форкнул?

Не в сети

#11 03.07.2015 08:33:02

zloadmin

Re: Простая авторизация Laravel 5.1.1

hzone пишет:

а зачем весь проект форкнул?

Почему нет?

#12 03.07.2015 10:20:05

Re: Простая авторизация Laravel 5.1.1

Попробую прокомментировать Ваш код.

    public function postRegister(Request $request, MailQueue $mailer)
    {
        $validator = $this->registrar->validator($request->all());  //"registrar->" - для 5.1 это убрать

   // проверяем правильность введенных данных.
        if ($validator->fails()) {
            $this->throwValidationException($request, $validator);
        }

        /** @var User $user */
       
       //записываем в базу нового пользователя
       $user = $this->registrar->create($request->all()); //"registrar->" - для 5.1 это убрать
      //генерируем URL подтверждения 
      $url = action('Auth\AuthController@getConfirm', [ $user->confirmation_code ]); //я понимаю генерация кода происходит в функции create(). Очень хотелось бы увидеть код !!!
      //ставим письмо в очередь на отправку
        $mailer->queue('emails.confirm', compact('url', 'user'), function ($message) use ($user, $url)
        {
            $message->to($user->email)->subject('Подтверждение регистрации');
        });
    //возврат после регистрации придумайте сами   
        return ...;
    }

    /**
     * Подтверждение регистрации пользователем
     *
     * @param Request     $request
     * @param User        $user
     * @param string|null $token
     *
     * @return Response
     */
    public function getConfirm(Request $request, User $user, $token = null)
    { //эта проверка для меня не понятна, пробел знаний:
        if (is_null($token)) {
            throw new NotFoundHttpException;
        }

        /** @var User $user */
       //находим в БД пользователя
       $user = $user->whereConfirmationCode($token)->first();  //буду признателен за комментарий по поводу связи кода подтверждения и токена. Имею пробел знаний.
       //если не найден:
        if (!$user) {
            return view('auth.noconfirm')->withMessage('Пользователь с таким кодом подтверждения не найден. Если это ошибка, свяжитесь с нами.');
        }
       //если уже подтвержден
        if ($user->confirmed) {
            return view('auth.noconfirm')->withMessage('Ваш пользовательский аккаунт уже активирован. Нажмите "Войти" и введите свой логин и пароль, или воспользуйтесь восстановлением пароля.');
        }
        //поднимаем флаг пользователь подтвержден
        $user->confirmed = true;
       //записываем в БД
        $user->save();
      // тут пишем возврат на свой вкус
        return ...;
  //Ламерский вопрос. Почему не используется конструкция if - else? return обрывает выполнения кода?
    }

Не в сети

#13 03.07.2015 11:29:30

Zloadmin

Re: Простая авторизация Laravel 5.1.1

Чей? Мой? Ну как бы там кроме view всё стандартное. Тоесть там Laravelий контролер и модель. А вьюхи я делал по документации.

#14 03.07.2015 11:36:22

Re: Простая авторизация Laravel 5.1.1

Gaint пишет:

$validator = $this->registrar->validator($request->all());  //"registrar->" - для 5.1 это убрать

возможно. копипастил из проекта на 5.0. там используется App\Services\Registrar, который реализует Illuminate\Contracts\Auth\Registrar и даёт методы validator и create.

Gaint пишет:

$url = action('Auth\AuthController@getConfirm', [ $user->confirmation_code ]); //я понимаю генерация кода происходит в функции create(). Очень хотелось бы увидеть код !!!

код генерирует create в Registrar, он заполняет данные пользователя из полей формы, а код - это просто рандомная строка:

    public function create(array $data)
    {
        $user = new User;

        $user->fill([
            'login' => $data['login'],
            'name' => $data['first_name'] . ' ' . $data['last_name'],
            'email' => $data['email'],
            'phone' => $data['phone'],
            'password' => bcrypt($data['password']),
        ]);
        $user->confirmed = false;
        $user->confirmation_code = str_random(128);
        $user->save();

        return $user;
    }

Gaint пишет:

    { //эта проверка для меня не понятна, пробел знаний:
        if (is_null($token)) {
            throw new NotFoundHttpException;
        }

тут дело в том, что AuthController в маршутах подключен хелпером Route::controllers. При таком способе его параметры передаются в порядке очерёдности. Если сделать php artisan route:list, мы увидим для getConfirm:

/auth/confirm/{one?}/{two?}/{three?}/{four?}/{five?}

знак вопроса означает что параметр опционален, поэтому для токена задано значение по умолчанию = null. то есть если пользователь откроет /auth/confirm без токена, вместо крэша он получит осмысленное сообщение об ошибке. в данном случае - ошибка 404, потому что такой страницы, без токена, вроде как не существует.

Gaint пишет:

$user = $user->whereConfirmationCode($token)->first();  //буду признателен за комментарий по поводу связи кода подтверждения и токена. Имею пробел знаний.

особенности нейминга. $token - это и есть код подтверждения. в модели он хранится в поле confirmation_code. whereConfirmationCode($token) - это в Eloquent синоним для where('confirmation_code', '=', $token)

Gaint пишет:

//Ламерский вопрос. Почему не используется конструкция if - else? return обрывает выполнения кода?

да. на ларакастах есть отдельный каст из серии "simple rules for simpler code" с названием "don't use else". логика такая, что зачастую мы возвращаем значения в условиях и else только увеличивает уровень вложенности кода, что снижает его читаемость. также else - признак того, что функция становится слишком сложной и для лучшей читаемости кода, какую-то его часть, включающую этот if лучше вынести в отдельный метод и дать ему осмысленное название, описывающее что в этом месте кода делается.

это не значит, что else также плох как goto, но часто бывает, что он является признаком того, что код пора рефакторить. один из code smells - это слишком большой уровень вложенности.

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

    if ($condition = true)
        return $this->error();

    $this->doSomething();
    $this->doSomethingElse();

    return $this->generateResult();

это кажется чушью, но на самом деле, когда я начал следовать этой рекомендации, я заметил, что мой код стал лучше. опять же повторю, это не абсолютное правило, но зачастую да - else не нужен.

Изменено constb (03.07.2015 11:40:24)

Не в сети

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