多角色仪表盘应用目录结构最佳实践咨询:管理员/学生/教师端
Great question—this is such a common pain point as Laravel apps grow beyond basic role-based setups. Let’s walk through a scalable, maintainable structure that’ll save you headaches down the line, while keeping your role-specific dashboards organized.
Core Idea: Move from Role-First to Domain-First Organization
Your current structure splits everything by role first, which works for small apps but gets messy fast when roles share overlapping business logic (like lessons, articles, or user management). Instead, organize your code around business domains (e.g., Lessons, Users, Dashboard) and nest role-specific logic within those domains. Here’s how it might look:
app/ |- Domains/ | |- Admin/ | | |- Dashboard/ | | | |- Controllers/AdminDashboardController.php | | | |- Views/ # Admin-specific dashboard views | | | |- routes.php | | |- UserManagement/ | | |- Controllers/AdminUserController.php | | |- Views/ # Admin user CRUD views | | |- routes.php | |- Student/ | | |- Dashboard/ | | | |- Controllers/StudentDashboardController.php | | | |- Views/ | | | |- routes.php | | |- Lessons/ | | |- Controllers/StudentLessonController.php | | |- Views/ # Student lesson views (enrollments, progress) | | |- routes.php | |- Teacher/ | | |- Dashboard/ | | | |- Controllers/TeacherDashboardController.php | | | |- Views/ | | | |- routes.php | | |- Lessons/ | | |- Controllers/TeacherLessonController.php | | |- Views/ # Teacher lesson views (create, grade) | | |- routes.php | |- Shared/ # Cross-role core business logic | |- Lessons/ | |- Models/Lesson.php | |- Services/LessonService.php | |- Policies/LessonPolicy.php | |- Articles/ | |- Models/Article.php | |- Services/ArticleService.php |- Console/ |- Events/ |- Exceptions/ |- Http/ | |- Middleware/ | | |- CheckAdminRole.php | | |- CheckStudentRole.php | | |- CheckTeacherRole.php | |- Providers/ |- Models/ # Base shared models | |- User.php | |- Role.php | |- Permission.php database/ |- factories/ |- migrations/ |- seeders/ config/ routes/ |- admin.php # Just imports Admin domain routes |- student.php # Imports Student domain routes |- teacher.php # Imports Teacher domain routes resources/ |- assets/ |- lang/ |- views/ |- admin/ | |- dashboard/ | |- user-management/ |- student/ | |- dashboard/ | |- lessons/ |- teacher/ | |- dashboard/ | |- lessons/ |- shared/ # Reusable components (navbars, forms, alerts)
Key Benefits of This Structure
- Easy to locate code: When you need to update lesson logic, you go straight to
Domains/Shared/Lessons/for core logic, and the role-specific controllers/views are nested under their respective domain folders. No more jumping between three different role directories for the same business feature. - Avoids code duplication: The
Sharedfolder holds core services, models, and policies that all roles can use. For example,LessonServicehandles creating/updating lessons, and the Teacher/Admin controllers just call this service instead of rewriting logic. - Scales cleanly: Adding a new feature (like Assignments) means creating a new
Shared/Assignmentsfolder, then adding role-specific controllers/views underAdmin/Assignments,Teacher/Assignments, etc.
Additional Best Practices to Reinforce Maintainability
1. Centralize Authorization with Policies & Middleware
- Use Laravel’s Policy classes (in
Shared/[Domain]/Policies/) to define role-specific permissions for each model. For example,LessonPolicycan specify that only teachers can create lessons, students can only view enrolled lessons, and admins can view everything. - Use role-checking middleware (like
CheckAdminRole) to protect entire route groups, so you don’t repeat authorization checks in every controller.
2. Keep Controllers Thin
Controllers should only handle request input, call service classes, and return responses. All business logic belongs in the Shared service classes. For example:
// app/Domains/Teacher/Lessons/Controllers/TeacherLessonController.php public function store(Request $request) { $validated = $request->validate([/* rules */]); $lesson = app(LessonService::class)->create($validated, auth()->user()); return redirect()->route('teacher.lessons.show', $lesson); }
3. Organize Routes by Domain
Your root route files (routes/admin.php, etc.) should be minimal—just import the route files from each domain:
// routes/admin.php require base_path('app/Domains/Admin/Dashboard/routes.php'); require base_path('app/Domains/Admin/UserManagement/routes.php');
This keeps each domain’s routes self-contained and easy to manage.
4. Reuse Shared Views
Put common UI components (like navigation bars, form inputs, or alert messages) in resources/views/shared/ and include them in role-specific views. This cuts down on duplicate HTML and makes styling changes easier.
When to Consider Going Further
If your app grows extremely large (hundreds of routes/controllers per role), you could split each role into a separate Composer package (in a packages/ directory). But for most apps, the domain-driven structure above is more than sufficient and avoids overcomplicating things.
内容的提问来源于stack exchange,提问作者rook

