问题描述:

I need to display two different index pages to two different user groups. For example, a regular user should see one page, and a privileged user - another one. I see two ways of approaching this issue:

One index action with conditionals:

public function index()

{

// view for privileged users

if(request()->user()->hasRole('privileged')){

return view('index_privileged');

}

// view for regular users

if(request()->user()->hasRole('regular')){

return view('index_regular');

}

return redirect('/');

}

Multiple actions:

public function index_privileged()

{

return view('index_privileged');

}

public function index_regular()

{

return view('index_regular');

}

Which approach is more "restful-friendly" and generally better?

网友答案:

I'm a big fan of light controllers. This might be a little overboard for a simple problem but if something like this pops up again, you'd already have everything all setup.

With that said, it might be best to create a PrivilegedUser class and a RegularUser class and give them both an index method which returns their respective views. Code them both to an interface UserInterface and make sure they both implement that.

Here is what those looked like in my test.

class RegularUser implements UserInterface
{
    public function index()
    {
        return view('index_regular');
    }
}

class PrivilegedUser implements UserInterface
{
    public function index()
    {
        return view('index_privileged');
    }
}

interface UserInterface
{
    public function index();
}

Then you can add a listener which should run for the event Illuminate\Auth\Events\Login. Laravel will fire this event for you automatically when someone logs in. This goes into the file EventServiceProvider.php.

protected $listen = [
    'Illuminate\Auth\Events\Login' => [
        'App\Listeners\AuthLoginListener',
    ],
];

Now you can run php artisan event:generate to generate the new listener. Here is what my listener looks like, it should work for you.

namespace App\Listeners;

use Illuminate\Auth\Events\Login;
use Illuminate\Foundation\Application;

class AuthLoginListener
{
    /**
     * Create the event listener.
     *
     * @param Application $app
     */
    public function __construct(Application $app)
    {
        $this->app = $app;
    }

    /**
     * Handle the event.
     *
     * @param  Login  $event
     * @return void
     */
    public function handle(Login $event)
    {
        if ($event->user->hasRole('privileged')) {
            $this->app->bind('App\Repositories\UserInterface', 'App\Repositories\PrivilegedUser');
        } else if ($event->user->hasRole('regular')) {
            $this->app->bind('App\Repositories\UserInterface', 'App\Repositories\RegularUser');
        }
    }
}

Essentially what this is doing is telling Laravel to load up a certain class based on the type of user that just logged in. The User instance is available through the Login object which was automatically passed in by Laravel.

Now that everything is setup, we barely have to do anything in our controller and if you need to do more things that are different depending on the user, just add them to the RegularUser or PrivilegedUser class. If you get more types of users, simply write a new class for them that implements the interface, add an additional else if to your AuthLoginListener and you should be good to go.

To use this, in your controller, you'd do something like the following...

// Have Laravel make our user class
$userRepository = App::make('App\Repositories\UserInterface');

return $userRepository->index()->with('someData', $data);

Or even better, inject it as a dependency.

use App\Repositories\UserInterface;

class YourController extends Controller
{
    public function index(UserInterface $user)
    {
        return $user->index();
    }
}

Edit:

I just realized I forgot the part where you wanted to return redirect('/'); if no condition was met. You could create a new class GuestUser (I know this sounds like an oxymoron) which implements UserInterface but instead of using the AuthLoginListener, I'd bind it in a service provider when Laravel boots. This way Laravel will always have something to return when it needs an implementation of UserInterface in the event it needs this class if no one is logged in.

网友答案:

Well, its more like a refactoring "issue" than a rest-friendly issue. Check this guideline and you can see that most of the things that makes an api friendly is concerned to the url.
But, lets answer what you are asking. The thing you wanna do is a refactoring method but it is not only the move method but something like the extract variable.

The second option would make the code more readable, either ways are right but the second is more developer friendly. It enhances the code readability from any developer. I would recommend using the second option.

Refactoring is never enough, but read something like this, it will help you a lot writing more readable codes.

相关阅读:
Top