2016-07-06 73 views
0

我已經更改了我的authController.php文件來完成我的項目所需的一些操作。它工作得很好,只需要再做一次改變。眼下控制器看起來是這樣的:Laravel 5.2在註冊後發送密碼重置

<?php 

namespace App\Http\Controllers\Auth; 

use App\User; 
use App\Role; 
use Mail; 
use Validator; 
use App\Http\Controllers\Controller; 
use Illuminate\Foundation\Auth\ThrottlesLogins; 
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; 
use Illuminate\Http\Request; 

use Illuminate\Foundation\Auth\ResetsPasswords; 

class AuthController extends Controller 
{ 
    /* 
    |-------------------------------------------------------------------------- 
    | Registration & Login Controller 
    |-------------------------------------------------------------------------- 
    | 
    | This controller handles the registration of new users, as well as the 
    | authentication of existing users. By default, this controller uses 
    | a simple trait to add these behaviors. Why don't you explore it? 
    | 
    */ 

    use AuthenticatesAndRegistersUsers, ThrottlesLogins, ResetsPasswords; 

    /** 
    * Where to redirect users after login/registration. 
    * 
    * @var string 
    */ 
    protected $redirectTo = '/add'; 

    /** 
    * Create a new authentication controller instance. 
    * 
    * @return void 
    */ 
    public function __construct() 
    { 
     $this->middleware($this->guestMiddleware(), ['except' => 'logout']); 


    } 


    /** 
    * Overwrite the Laravel 5.2 standard registration 
    * so user will not be logged in automatically. 
    * 
    * @param array $request 
    * @return Register 
    */ 
    public function register(Request $request) 
    { 
     $validator = $this->validator($request->all()); 

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

     $this->create($request->all()); 

     return redirect($this->redirectPath()); 
    } 

    /** 
    * Extend password reset email to user for when registering 
    */ 

    public function sendResetLinkEmail(Request $request) 
    { 
     $this->validateSendResetLinkEmail($request); 

     $broker = $this->getBroker(); 

     $this->subject = "First Time User Setup"; 
     $broker->emailView = "auth.emails.password"; 

     $response = Password::broker($broker)->sendFirstTimeSetup(
      $this->getSendResetLinkEmailCredentials($request), 
      $this->resetEmailBuilder() 
     ); 

     switch ($response) { 
      case Password::RESET_LINK_SENT: 
       return $this->getSendResetLinkEmailSuccessResponse($response); 
      case Password::FIRST_TIME_SETUP: 
       return $this->getSendFirstTimeSetupEmailSuccessResponse($response); 
      case Password::INVALID_USER: 
      default: 
       return $this->getSendResetLinkEmailFailureResponse($response); 
     } 
    } 

    public function getSendFirstTimeSetupEmailSuccessResponse($response) 
    { 
     return redirect()->back()->with('status', trans($response)); 
    } 


    /** 
    * Get a validator for an incoming registration request. 
    * 
    * @param array $data 
    * @return \Illuminate\Contracts\Validation\Validator 
    */ 
    protected function validator(array $data) 
    { 
     return Validator::make($data, [ 
      'first-name' => 'required|max:255', 
      'last-name' => 'required|max:255', 
      'phone' => 'required|max:255', 
      'form' => 'max:255', 
      'email' => 'required|email|max:255|unique:users', 
      'password' => 'required|min:6|confirmed', 
     ]); 
    } 

    /** 
    * Create a new user instance after a valid registration. 
    * 
    * @param array $data 
    * @return User 
    */ 
    protected function create(Request $request, array $data) 
    { 
     //Create the user 
     $user = User::create([ 
      'first_name' => $data['first-name'], 
      'last_name' => $data['last-name'], 
      'phone' => $data['phone'], 
      'email' => $data['email'], 
      'password' => bcrypt($data['password']), 
     ]); 

     return $this->postEmail($request); 

     /* 
     Mail::send('auth.emails.registered', ['user' => $user], function ($m) use ($user) 
     { 
      $m->to($user->email, $user->first_name)->subject('You Have Been Added'); 
     });*/ 

     //Is it a User? Then give them that role 
     if ($data['user-role'] == 'user') 
     { 
      $role = Role::where('name', '=', 'user')->firstOrFail(); 
      $user = User::find($user->id); 
      $user->roles()->attach($role->id); 
     } 

     //Is it an Admin? Then give them that role 
     if ($data['user-role'] == 'admin') 
     { 
      $role = Role::where('name', '=', 'owner')->firstOrFail(); 
      $user = User::find($user->id); 
      $user->roles()->attach($role->id); 
     } 

     return $user; 
    } 





} 

它停在創建用戶自動登錄,分配角色基於表單上的用戶,併發送密碼重置電子郵件。麻煩不是我得到的錯誤Trait method guestMiddleware has not been applied, because there are collisions with other trait methods on App\Http\Controllers\Auth\AuthController

回答

4

這個技巧之一是瞭解Auth工廠工作的traits內部如何工作。

首先,我們需要使用use Illuminate\Foundation\Auth\ResetsPasswords;特徵以及AuthenticatesAndRegistersUsersThrottlesLogins特徵。

use AuthenticatesAndRegistersUsers, ThrottlesLogins, ResetsPassword; 

接下來,我們需要確保我們有一個$request實例被傳遞給我們的create方法:

protected function create(Illuminate\Http\Request $request, array $data) 

阿里納斯 - 我建議遠離一個$data物體通過爲移動一個參數,而不是與$request一起工作。您可以讓您的數據是這樣的:$request->get('first-name')

最後,我們通過我們的$requestpostEmail()功能:

return $this->postEmail($request); 

這將管道中的$請求ResetsPasswords\postEmail功能:

public function postEmail(Request $request) 
{ 
    return $this->sendResetLinkEmail($request); 
} 

這將導入管道到ResetsPasswords\sendResetLinkEmail功能:

public function sendResetLinkEmail(Request $request) 
{ 
    $this->validateSendResetLinkEmail($request); 

    $broker = $this->getBroker(); 

    $response = Password::broker($broker)->sendResetLink(
     $this->getSendResetLinkEmailCredentials($request), 
     $this->resetEmailBuilder() 
    ); 

    switch ($response) { 
     case Password::RESET_LINK_SENT: 
      return $this->getSendResetLinkEmailSuccessResponse($response); 
     case Password::INVALID_USER: 
     default: 
      return $this->getSendResetLinkEmailFailureResponse($response); 
    } 
} 

哪個最終會發出電子郵件。

使整個事情工作的關鍵是Illuminate\Http\Request的實例總是包含一個email字段。

注意

將從sendResetLinkEmail函數返回可能不是你送出的相同反應的response。也許用戶在創建帳戶時會被Password Reset請求所困惑。相反,也許你想發送一個First Time Setup。爲了做到這一點,您需要創建自己的Password BrokerPassword Facade

接下來,讓我們做了2名新的目錄:

App\Brokers 
App\Facades 

接下來,建立一個新的文件App\Facades裏面並調用它Password.php。命名空間相應的文件並擴展現有的密碼門面。此外,我們還會添加另一個const作爲我們的FIRST_TIME_SETUP的可觀察響應類型。

<?php 

namespace App\Facades; 

class Password extends \Illuminate\Support\Facades\Password { 
    /** 
    * Constant representing a successfully sent reminder. 
    * 
    * @var string 
    */ 
    const FIRST_TIME_SETUP = 'passwords.first_time_setup'; 
} 

現在我們又增加響應類型,我們可以switch上,這將有助於決定我們如何發送我們的電子郵件。

接下來,我們需要使我們的Password Broker和建立我們的sendFirstTimeSetup功能。

namespace App\Brokers; 

class PasswordBroker extends Illuminate\Auth\Passwords\PasswordBroker { 
    public function sendFirstTimeSetup(array $credentials, Closure $callback = null) 
    { 
     // First we will check to see if we found a user at the given credentials and 
     // if we did not we will redirect back to this current URI with a piece of 
     // "flash" data in the session to indicate to the developers the errors. 
     $user = $this->getUser($credentials); 

     if (is_null($user)) { 
      return static::INVALID_USER; 
     } 

     // Once we have the reset token, we are ready to send the message out to this 
     // user with a link to reset their password. We will then redirect back to 
     // the current URI having nothing set in the session to indicate errors. 
     $token = $this->tokens->create($user); 

     $this->emailResetLink($user, $token, $callback); 

     return static::FIRST_TIME_SETUP; 
    }   
} 

現在我們需要複製我們前面看到的sendResetLinkEmail功能,並將其移動到我們AuthController。這將允許我們修改Password門面,我們使用和修改我們的switch語句來支持我們的First Time Setup

public function sendResetLinkEmail(Request $request) 
{ 
    $this->validateSendResetLinkEmail($request); 

    $broker = $this->getBroker(); 

    $response = Password::broker($broker)->sendFirstTimeSetup(
     $this->getSendResetLinkEmailCredentials($request), 
     $this->resetEmailBuilder() 
    ); 

    switch ($response) { 
     case Password::RESET_LINK_SENT: 
      return $this->getSendResetLinkEmailSuccessResponse($response); 
     case Password::FIRST_TIME_SETUP: 
      return $this->getSendFirstTimeSetupEmailSuccessResponse($response); 
     case Password::INVALID_USER: 
     default: 
      return $this->getSendResetLinkEmailFailureResponse($response); 
    } 
} 

隨後,同樣在AuthController,我們會讓其他功能來回報廣大response

public function getSendFirstTimeSetupEmailSuccessResponse($response) 
{ 
    return redirect()->back()->with('status', trans($response)); 
} 

最後,如果要覆蓋所使用的函數發送出去時view,只需調用->sendFirstTimeSetup()功能之前覆蓋$broker->emailView屬性:

//... 

$broker->emailView = "emails.user.first_time_setup"; 
$response = Password::broker($broker)->sendFirstTimeSetup(
    $this->getSendResetLinkEmailCredentials($request), 
    $this->resetEmailBuilder() 
); 

//... 

如果你想改變電子郵件的subject,覆蓋->subject()財產的內部發射的->sendFirstTimeSetup()功能您AuthController之前:

//... 
$this->subject = "First Time User Setup"; 
$broker->emailView = "emails.user.first_time_setup"; 
$response = Password::broker($broker)->sendFirstTimeSetup(
    $this->getSendResetLinkEmailCredentials($request), 
    $this->resetEmailBuilder() 
); 

//... 

我可以繼續下去,但我認爲這會讓你朝着正確的方向前進。希望它能幫助其他幾個人。

+0

這是我得到的最有效的解釋,但是現在我得到錯誤'Trait方法guestMiddleware尚未應用,因爲App \ Http \ Controllers \ Auth \ AuthController '與其他特徵方法發生衝突。我更新了我的代碼。 – Packy

+0

@Packy您可能需要直接覆蓋該函數的用法。看看AuthenticatesAndRegistersUsers特性;你會注意到有一個有趣的'use'語句...'AuthenticatesUsers :: redirectTo而不是RegistersUsers'。所以你會爲你的'guestMIddleware'做同樣的事情。 – Ohgodwhy

+0

對不起,我很困惑如何「爲您的guestMIdware做同樣的事情」。你能多解釋一下嗎? – Packy

0

您可以通過改變use塊以下解決您的特質碰撞的問題:

use ThrottlesLogins, 
    ResetsPasswords, 
    AuthenticatesAndRegistersUsers { 
    AuthenticatesAndRegistersUsers::guestMiddleware insteadof ResetsPasswords; 
    AuthenticatesAndRegistersUsers::getGuard insteadof ResetsPasswords; 
    AuthenticatesAndRegistersUsers::redirectPath insteadof ResetsPasswords; 
} 

這是醜陋的,但它會解決所有相關的碰撞,從而使您可以只使用預建照亮方法如果你這樣選擇。