We are developing an application with Laravel framework, it is supposed to be a RESTful Application which is implemented via the resources of Laravel framework, given the following example:
class CategoryController extends Controller
{
public function __construct() {
}
public function index()
{
return response()->json($this->getAll());
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
Let's take the following example:
Some methods like store and create are only permitted by the admin of the website but index method is permitted by all the users and there are so many cases like this example-different type of users can only access some methods of a Contrller.
In this case we can either benefit from Multi Auth of Laravel and create different tables for the storing the users or define different type for users in the same table and handle users' access with middleware that apply to some specific functions
Question:
which way do you recommend and please provide the reasons behind your suggestion as well
So, the answer depends on various parameters. The goal you're trying to achieve can be achieved using Laravel Multi-Auth or any RBAC (Role Based Access Control) system.
Situations where you should use RBAC: If your application is small you should go for any Role Based thing.
For Example.. Let's say you're working on some CMS then you won't create tables for each position (Manager, Developer, Marketing Head etc..) hence the RBAC is good option for you.
Situations Where you should use Multi-Auth: If your goal is big and you want to separate user login table and admin login table for any reason you can go for it.
What I suggest
What I suggest is to go for both, Multi auth as well as RBAC ( only if you're working on or trying to build very large scale application )
But as you're described, just keeping that in mind I would suggest you to go with RBAC not multi auth.
Some Useful links
Laravel Docs
RBAC (One of the Most Popular RBAC package for laravel)
If you feel like going for Multi Auth please follow This blog post Multi-Auth with Laravel 5.2
If I'm missing something or the answer can be improved any way, feel free to comment.
Related
I'm currently just starting on porting a large Yii2 application to Laravel and I'm considering using repositories to solve my current problem of messy controllers and bloated models.
I've looked at a ton of examples of repositories but most them only cover simple CRUD. For example in my current app a User can created in multiple places and must be created with like 5 related records in other tables, for example a User must be added to Groups and must have Permission records created based on their role.
Currently almost all of my models have a custom Create function that can reused anywhere. Here is a very basic Yii2 example of what I'm talking about.
Example User creation in User model:
public static function create(array $attributes, array $group_ids)
{
$user = new User;
$user->attributes = $attributes;
$user->save();
$role = $user->role;
foreach ($role->rolePermissions as $role_permission) {
UserPermission::create($user->id, $role_permission);
}
foreach ($group_ids as $group_id) {
GroupUser::create($user->id, $group_id)
}
if ($role->admin_mode) {
// send welcome email
}
return $user;
}
Is it good practice to simply inject the UserPermission and GroupUser Repositories into my UserRepository in this case? How do you handle saving related records in Repositories?
Does anyone have any more advanced examples of using Repositories with related models?
You need to understand that in Repository pattern, repository is not the place to store your business logic, that's why they are simple, doing CRUD only.
For what you need here is a business logic layer on top of the repositories. What I did to my recent projects is that I create a Services folder in my app root, and create all sort of services in it with my main business logic in it, like $userService->createUser(..), and in it will have checks on different roles, groups, emitting events, send emails.
So a typical calls could look like this:
calls UsersController->createUser
calls UserService->createUser
verifications, checks, throws errors
calls UserRepository->create
calls GroupUserRepository->create
emit UserCreated event
(disjointed: event listeners)
dedicated listeners listened UserCreated event
calls UserService->sendWelcomeEmail
send welcome emails
So services is almost identical to your fat models, but they are standalone php classes that understand your business logic, use whatever database it knows, and process requests and return results. It does not depend on anything to instantiate one, and so can be included by anyone to use it. They also can be instantiated as singleton or instances depending on your need.
Side note
I've wasted too much time on creating repositories when I could have just use Eloquent. They are not identical, but I could not foresee my project to change underlying DBMS so I would usually just use eloquent directly in my services layer.
This question already has answers here:
How can I implement an Access Control List in my Web MVC application?
(3 answers)
Closed 6 years ago.
I'm working on an MVC application with this structure:
Request
V
FrontController <-> Router
V
Controller <-> Model
V
View
I have two other components that I need to place in this structure:
Authentification: Logs the user in using the $_SESSION global variable;
RBAC: Role Based Access Control that can check if a role has access granted to a "ressource" (Controller method).
Every users can have any given number of roles (they can also have none).
Now, I need to place those two components in my applications, I need them to be able to:
If the User isn't authed and that the Request requires a authed User to be executed, the client should be redirected to a login page;
If the RBAC sees that the authed User doesn't have a role that has access granted to the required "ressource" to execute the Controller's method, the Controller's method should still be executed but with knowledge that the User did not have the permission to do so (Example: A User writes an article but doesn't have the right to publish it, so the article is saved as a draft and the User is told that a Moderator will have to publish it).
I already have a few ideas where to locate the Authentification and RBAC but I'm not sure:
Authentification could go in the FrontController or the Router;
RBAC could go in the FrontController or the Controller.
I saw someone putting the RBAC in the model but I don't understand why.
I'd like to have some insight on the subject please. Where should I put the Authentification and RBAC components?
Thank you!
In my experience, access control business logic changes as new features are added, so it pays to design flexibility and motility into your access control system. Thus, I would engineer Authentication and RBAC as separate traits, then incorporate those traits into the controller space as necessary.
As described, it sounds like the authentication trait would best be incorporated into your front controller: you know that all dependent controllers require authentication, so incorporate that check early in the life cycle to free up request sockets. If your requirements ever change to need some controllers to be ungated, you can push the trait down into specific controllers or into a base controller class.
As for RBAC, that may apply globally to all controllers as well as locally to some controllers. For example, your FrontController may query the RBAC to build the routing table, while dependent controllers would use the RBAC for their specific needs.
One thing to consider, though: you may also have some RBAC needs in the model. That is, some roles may have limited access to some fields in some models: role A can access all of model X, but role B can only read fields 1, 2, and 3 of model X. (Trust me, I have seen very, very complicated rules around roles that can see and act on what fields.)
Engineering RBAC as a controller trait may make porting to model space difficult. Thus, you may find it better to engineer RBAC as a service delegate and inject it on demand. With a well-provisioned IoC container, a service delegate is just as easy as compile-time traiting.
Finally, I'll add that you're going to want both of these under heavy test (they are important, after all). So whatever you choose, engineer so they can be tested. In my opinion, both traits and delegates are easy to test in isolation and either would be a good choice for implementing the necessary logic.
In a typical MVC application the authentication check (i.e. "if not auth, then stop and render the login page instead") is done very early in processing the request, while the business logic (i.e. "if user has this permission then this happens, otherwise that happens") is handled within the "C" (the controller).
Most frameworks have a mechanism in place for tests like the authentication check your are describing - names vary but I have often seen it called "middleware".
The role based access control is purely your implementation.
I am new to Laravel and not quite sure how to move my PHP code to Laravel
currently, I have an android app that communicates with the server with android volley throught a url www.example.com/test.php
android volley sends out some POST parameters ( example: userID, RestaurantId etc ) to the .php file
In the file it creates the correct .json structure from table(s) using PDO with prepared statements to connect to the db
then it returned a .json with json_encode()
how do I move this code to laravel?
do I really need an authorization/login page for this?
You will have to do a bunch of stuff to achieve this. You will probably not be able to transform your code since laravel will do all the database communication using eloquent. Routing is also a completely different concept than in plain php.
I still highly recommend using laravel since you will have less security issues.
Here's a list of topics and steps you will need to have a look at to achieve what you described.
Assuming you have a fresh laravel setup with the newest version you will have to look at the web middleware which you probably don't need for an api. It can be found in the RouteServiceProvider where it is defined to be used on every route in your routes.php file. If you have an older version of Laravel 5.2 it might be defined as group in the routes.php itself. Remove web middleware and maybe add api middleware if needed
Create routes in your routes.php file to define which "url" are used to respond to requests
Create controllers to handle those incoming requests. If you do not have a lot of code you can handle them directly in the routes.php as anonymous function
Models are basically your Tables. You should define a model for each of your tables. A user model is already defined by default. Have a look in it's code. You will also define relations between models. This will make CURD operators on linked models very easy.
Migrations are the definitions of your tables. It consists of "what should be done when the migration is run" (up function) and "what should be done in case of a rollback" (down function)
If you return classes / arrays in laravel it will automatically be parsed to json
Looking at your example I'd assume you will have a user model and a restaurant model if you for example have a vote system where a user votes / rates a restaurant you would have a many to many relationship between user and a restaurant.
if a restaurant belongs to an user it would be oneToMany since a user can have multiple restaurants.
Defining relations looks like this ( User.php Model )
public function restaurants() {
return $this->hasMany('App\Restaurants');
}
The Restaurant.php would look like this
public function user() {
return $this->belongsTo('App\User');
}
With this setup ensure your Restaurant table has a "user_id" foreign key field to the user table.
Querying all restaurants of a user will now look like this
return $user->restaurants;
But these are just some high level examples which should explain to you how laravel works and why you can benefit from it. It reduces your boilerplate code and provides you with a solid set of functions, helpers and concepts that will help you to easily enhance your application - once it was set up.
You can have a look into the docs for more details https://laravel.com/docs/5.2
And find awesome tutorials at http://laracasts.com
Cake's documentation says "Most commonly, controllers are used to manage the logic for a single model." I'm finding this is uncommon for most of my code, and I don't want to break convention unless it is proper to do so.
For example, my application sends a user to their account dashboard after they log in - this uses data from probably half a dozen tables, not all of which are even related. Do I create a "dashboard" controller for this (even though there is no dashboard model or table)? Or do I create a dashboard method in an existing controller?
Thanks, Brian
I have a similar situation and how I handle it is keeping the actions that connect a lot of models in the controller that is the most centric. For instance, my user can create voicenotes, comments, has settings, has twitter and facebook information. All this information I can get from my user model $this->User->Voicenotes->find('all'), for example.
I believe creating additional controllers might just confuse you, use what cake gives you, you can specify that models are to be used in a controller either by setting the $uses variable or using loadModel in the controller action, if you have your relations set up you can just do it the way i described before, no need to create additional controllers.
I guess it depends on how you want your own app to work and what comes easier in your situation.
the situation is this.
my client (who also is a programmer) asks me to develop an address book (with mysql database) with a lot of functions. then he can interact with some class methods i provide for him. kinda like an API.
the situation is that the address book application is getting bigger and bigger, and i feel like its way better to use CodeIgniter to code it with MVC.
i wonder if i can use codeigniter, then in some way give him the access to controller methods.
eg. in a controller there are some functions u can call with the web browser.
public function create_contact($information) {..}
public function delete_contact($id) {..}
public function get_contact($id) {..}
however, these are just callable from web browser. how can i let my client have access to these functions like an API?
then in his own application he can use:
$result = $address_book->create_contact($information);
if($result) {
echo "Success";
}
$contact = $address_book->get_contact($id);
in this way, my controller methods are handling the in and out with the Models. there will be no views, cause i just have to return the data/result from the Models. and he can just use my "API" functions.
is this possible?
cause i just know how to access the controller methods with the webbrowser. and i guess its not an option for him to use header(location) to access them.
all suggestions to make this possible are welcomed! even other approaches to let me use CI to develop. perhaps there already are best practices regarding this kind of cross framework collaboration?
thanks
MVC seems to have dispersed in its definition. This definition I will offer should be ideal for you.
Models are where you build your business end of the application. Operations such as create_contact, delete_contact, and get_contact belong in the model layer. The model layer is what builds your application API and should be entirely independent.
Consider the controllers purely as the user's puppeteers. Controllers accept user input - the validation, sanitation, and whatnot may be done elsewhere - and invokes the API you've already setup in the model layer. Also, controllers then specify what view to use - however complicated or simple your presentation layer is.
The presentation layer usually isn't the difficulty. As long as you are only using read operations in the view you should be fine.
To clarify, if a user wants to create a new contact, the controller may need a method called create_contact that accepts the appropriate input. However, the actual operation of creating the contact must be done in the model layer. This will allow your other developer to reuse that same operation in a completely different application by loading your model, which was already designed as an independent entity.