ranto's avatar

ranto wrote a reply+100 XP

2mos ago

I second this. It really a matter of taste.
Sometimes you cannot avoid writting a large function and then never have the time to really write a readable function.

I prefer small functions and this is what I do when I encounter a massive function inside the codebase:

  1. I make sure all the task I had to do are done. I never refactor old code when I have business things to ship.
  2. Identify code blocks on the larger function that do a single task. Eg: check for some condition, do a business logic, etc
  3. Move those to a separate function. This could be a private function on the Repository or an action if you like the action pattern, etc. This might heavely deppend on your preferences or codebase standars.
  4. Make sure I don't break any test.

Just don't overcomplicate things. Write code for the person who is going to read it 3 months lated.

ranto's avatar

ranto liked a comment+100 XP

2mos ago

It is totally a matter of taste. However 900 lines seems far too many.

Some say a class/method/function should fit a screen without scrolling.

ranto's avatar

ranto liked a comment+100 XP

2mos ago

Great questions! Here’s a systematic approach to planning permissions for your Laravel ticketing app:

1. Start With User Stories & Actions:
List all user actions (based on real scenarios), not just CRUD. For a ticketing system, actions might include: create, view, update, delete, assign, escalate, comment, upload_attachment, change_status, export_report, view_sla, etc.

2. Map Actions to Permissions:
Decide on permission granularity. For fields that require distinct access patterns (like assigning vs updating status), create separate permissions:

update_ticket_details
update_ticket_status
assign_ticket
add_ticket_comment
upload_ticket_attachment
escalate_ticket

Start granular; you can always group in roles later.

3. Controller/Route Analysis:
Walk through each controller and route method. For each, mark the user action required and map to a permission. Build a spreadsheet or mindmap—this exposes gaps and avoids overlaps.

4. Permissions Generator:
Consider a custom command to yank all controllers, reflect on their methods, and suggest permission names (e.g., analyze methods prefixed with CRUD verbs). This isn’t perfect but can highlight missing ones.

Example basic seeder using arrays

$permissions = [
    'view_any_ticket', 'view_ticket', 'create_ticket', 'update_ticket_details', 'update_ticket_status',
    'assign_ticket', 'add_ticket_comment', 'upload_ticket_attachment', 'escalate_ticket',
    'view_report', 'view_sla', /* etc. */
];

foreach ($permissions as $perm) {
    Permission::findOrCreate($perm);
}

5. Patterns & Recommendations:

  • Permissions per action, not per field unless your workflow demands deep granularity.
  • Permissions for meta-actions: assign_role, revoke_role, manage_permissions.
  • Use Policies for complex logic (e.g., "can update ticket if agent assigned"), but simple can() for basic permissions.
  • Audit log access should have its own permission.

6. Tools:
No definitive auto-generator, but laravel-permission works well with simple arrays. For semi-automatic discovery, try spatie/laravel-route-discovery for insight.

Summary:

  • List app-specific user stories.
  • Extract every meaningful action.
  • Map each to a permission.
  • Review by controller.
  • Use Policies where logic gets hairy.
  • Simple scripts or arrays suffice for seeding.
  • Err on the side of "too many" fine-grained permissions—roles glue them together anyway.

And don’t stress too much! This stuff is iterative—add to your set as you find new workflows or edge cases.

ranto's avatar

ranto liked a comment+100 XP

3mos ago

Splitting your API routes into separate files for better organization is a common and recommended approach, especially as your application grows. It’s perfectly fine to include those files directly within routes/api.php using PHP’s native require or require_once functions—there’s no need to register them via a service provider unless you have advanced requirements.

Here’s a simple and effective way to do it:

Suppose you create sub-files like:

  • routes/api/auth.php
  • routes/api/users.php
  • routes/api/products.php

Your routes/api.php can look like:

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

// Main routes
Route::get('/status', fn () => ['status' => 'OK']);

// Grouped or included routes
require __DIR__.'/api/auth.php';
require __DIR__.'/api/users.php';
require __DIR__.'/api/products.php';

Each included file should contain only route definitions—just as you’d write them in api.php, for example:

routes/api/users.php:

<?php

use Illuminate\Support\Facades\Route;

Route::middleware('auth:sanctum')->group(function() {
    Route::get('/users', 'UserController@index');
    Route::get('/users/{user}', 'UserController@show');
});

Key points:

  • All middleware, groups, etc., are available just as in the main api.php.
  • Route caching (php artisan route:cache) works seamlessly since you're not dynamically loading routes (like via globbing with scandir in production).
  • This keeps your routes organized and maintainable.
  • No need to use a service provider or do anything special for Laravel to pick them up.

Conclusion:
Including route files directly in api.php is a simple, effective, and recommended approach for organizing large sets of routes in Laravel.