How to structure Laravel system with API / Frontend / etc - php

My currenct project consists of 4 main parts:
App shows data from API
API offers data for app
Dashboard Manages data of database (Twig, no SPA)
Website Shows some numbers from the database (readonly)
Should we just use a modules-library for Laravel to split the system into: API, Dashboard, Common, Web or are there better ideas? What is the best way?

Laravel by default is already split for you. Just looking at the routes directory you can see there are separate files for web routes and api routes, prefixed with api, though you can change the prefix yourself.
The part you will have to actually think the most is the Dashboard/Website part, where you will have to implement authorization to know who can access what.
Basically, you are just building a normal application, then you start adding different controllers that would respond to API routes since application controllers and api controllers do not return the same thing. Application controllers return mostly views and redirect, whereas api controllers return mostly JSON formatted data. You can split those controllers into 2 different directories like this
app/Http/controllers/web/
app/Http/controllers/api/
So when generating controllers in artisan you prepend the directory
php artisan make:controller web/DashboardController
php artisan make:controller api/UserController
And so on.
So to summarise:
1- API: use routes/api.php, controllers return JSON return response()->json($data);
2- Common: Some helpers, services & middlewares shared by web & api
3- Dashboard: Authentication + Authorization to limit access. Use a routes group here and apply middlewares
Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'admin']], function(){
//admin routes go in here
});
4- Web: Public data, read only. Not authorization require. Just basic pages with no authentication.

Regarding to #EddyTheDove's answer, I would build main controllers to extend in web and api controllers. You need the same data for each output anyways. You can transform your data Eloquent Resources in api controllers or view in web controllers.

Related

laravel user dashboard in react adminpanel in blade keeping DRY for controllers

In my project, we are making API's endpoints in Laravel for react app and admin panel in blades only.
So I had to create separate controller in API folder as endpoints for react app and another controller to render blade view for admin for the same table (say messages).
But I do not want to repeat code like common checks and condition I want to keep these things somewhere commonplace so I can use it in both API endpoints and admin controllers.
Can someone share the reference for the best approach or some ideas.
I had the same issue. and I resolved by using the Service Layer. This link may help you to understand in detail about service.
In simple words, service can be injected into your controller. Service will get a request from the controller with inputs(which could be an array) and can send you back response(Which could be boolean or object).
Service also can help with test cases.
Good Luck.

Laravel Passport - How do you disallow users from generating clients?

Passport provides a convenient way of registering routes for users to create their own clients by calling Passport::routes(); in the AuthServiceProvider.
I do not wish to allow my users to create clients, as I only want to manually create clients using php artisan passport:client command, as I only need passport for machine-to-machine authentication for internal services.
How do I customize routes for Passport to only expose the necessary routes for passing a client id and secret to gain an access_token? I understand that I can dig into the framework and expose my own routes to a series of \Laravel\Passport\Http\Controllers\PassportController#action, I just didn't know if that was the only way or the preferred way.
You can pass a closure to Passport::routes() in your AuthServiceProvider.
See here
In the closure you can define which routes should be registered.
Something like this:
Passport::routes(function ($router) {
$router->forAuthorization();
$router->forAccessTokens();
// etc.
);
Here are the available methods:
forAuthorization();
forAccessTokens();
forTransientTokens();
forClients();
forPersonalAccessTokens();

Proper way to route vue/ajax requests in laravel?

I'm new to laravel and making a web service that can function without javascript (if a user has it disabled or something.)
But it would be a better user experience to be able to perform certain actions without refreshing the whole page. I'd like to be able to say, send a form without reloading the page, or refresh notifications.
The options I can think of are:
1) Send the ajax to the same route as the pure html form, but with an extra variable and make my laravel respond with json when that variable is detected
2) Use the API route? Will this detect the currently logged in user?
3) Make new routes for everything ajax, even though they function the same as my current routes (aside from returning a view)
Also, does the CSRF token work multiple times in a row, or do I need to disable that to handle multiple ajax form posts in a row without page refreshes?
I recommend keeping the routes separate, both to prevent weird caching bugs and for your own sanity as the code changes over time.
Laravel is set up out of the box to let you define web routes in routes/web.php and api routes in routes/api.php. Routes defined in your api.php file will be available at /api/* by default. It's much easier to manage changing the application this way, rather than trying to make your controllers do both views and api responses.
With Laravel Passport, your API routes can detect the currently logged in user via the auth:api middleware when combined with adding the Laravel\Passport\Http\Middleware\CreateFreshApiToken to your web middleware group.
https://laravel.com/docs/5.7/passport#consuming-your-api-with-javascript
An easy way to manage the duplicated controllers (one for web and one for api) is to put Api controllers in their own namespace, with php artisan make:controller Api/FooController. You can even set up your Api routes to look for controllers in this namespace by default by editing RouteServiceProvider.php.

Laravel: Api.php in routes directory

I am a bit confused, I have a web application having a login, Register, Logout. Some dashboard views etc(CRUD), I want to make an api for this application too.
Like an api which third party will use, Can update records, Can delete records etc.
Actually there should be some way which can be use by mobile app for CRUD.
I know we have that routes/api.php, But i am pretty confused that when to use it. Please explain the scenario, I am blank.
Update:
Scenario
Application having views, authentication system etc, How an android app will be able to perform CRUD operations on the same application ?
1.web routing uses session state, CSRF protection. does it mean api routing not using session state, CSRF protection?
All it possible but not required. You still can using sessions etc, but this is a REST principles violation.
2.laravel 5.3 uses seperate web and api routing, is there any advantages ?
It's just for your convenience. In Laravel 5.2 you need specify middleware for routes like ['web'] or ['api'] but it doesn't required anymore. In 5.3 routes stored in separated files and specify routes middleware not required.
If you are specifying routes in api.php, you will need to use the auth:api middleware. For example:
Route::group(['middleware' => ['auth:api']], function () {
Route::get('/test', function (Request $request) {
return response()->json(['name' => 'test']);
});
});
Notes about Token auth and Laravel 5.3:
If you've setup laravel's default auth system, you will also need to add a column for api_token to the user table. If you are using DB seeders, you might want to add something like:
$table->char('api_token', 60)->nullable();
to your users table seeder. Alternatively just add the column manually and fill that column with a random 60-char key.
When making the request, you can add the api_token as a URL/Querystring parameter like so:
domain.com/api/test?api_token=[your 60 char key].
You can also send the key as a header (if using Postman or similar), i.e: Header: Authorization, Value: Bearer [your 60 char key].
I order to get a useful error if the token is incorrect, also send the following header with all requests:
Header: Accept, Value: application/json. This allows the expectsJson() check in the unauthenticated() function inside App/Exceptions/Handler.php to work correctly.

Best option in laravel to create multiple modules under different namespace

I am new to Laravel and need to know how can i structure my project in Laravel.
1) We have almost 21 different modules in the project all the modules are connecting with same database but each module should be register under different namespace.
for example - if i have admin and inventory, the admin should access from /admin and inventory should access from /inventory. Also it will be fine if i can write the routing for each namespace from the corresponding app folder.
2) Another thing we have a different level of user and the different URL will be accessible to those who have permission. So i am planning to write a middle ware for checking the permission before the user request is reaching each controller. So i need a top level middle ware also to check the permission of the login user for all the module.
What structure will be good to implement this type of application. I only need to connect only one database throughout the application.
Here are a few suggestions :
1) You must have a different controller for each module. Place the controllers further in subdirectories if needed.
For example, I keep my Admin-related controllers in the Admin directory under the App\Controllers directory, API-related in App\Controllers\API directory and similarly, App\Controllers\Web for web-only controllers.
2) Have a separate route-file (web.php) for each controller.
Name the route-file to something that matches with the name of the module you are dealing with. for example, 'inventory.php' for dealing with inventory-controller routes only. You need to register the routes as well, just like web.php,api.php, etc routes have been pre-registered out of the box.
3) Follow design patterns to keep your code clean. I would suggest taking a look at Service-Repository pattern.
The code flow then becomes as follows :
Routes pass on the request to a Controller. The controller does not handle the business logic and passes task specific requests to the Service Class where all the business logic will be handled. If any Database specific tasks (CRUD) are needed, the Service class then calls the methods defined in the Repository class.
Have a separate Service and Repository class for all your modules. For example, InventoryController -> InventoryService -> InventoryRepository.
This is just a practice that I follow and may not be the best
solution.

Categories