You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无框架PHP项目组件组织及依赖控制器存储位置咨询

Hey there! Since you’re coming from a framework background, building a framework-less PHP project can feel a little unstructured at first—totally get that confusion. Let’s break down how to organize your components properly, especially where to put those dependent controllers/reusable logic.

1. Where to Store Dependent Controllers & Reusable Components

First, let’s clarify terms to avoid mixing responsibilities:

  • Base Controllers: If you have a controller that other route-specific controllers inherit from (e.g., it handles view rendering, request validation, or shared auth checks), stick it in a subdirectory like controllers/Base/ (e.g., BaseController.php). This keeps your route controllers clean and focused.
  • Reusable Business Logic: If you’re talking about components that aren’t directly tied to a route (like user authentication logic, order processing, or data fetching), these don’t belong in the controllers/ folder at all. Instead, use a services/ directory—this is where your core business logic lives, and route controllers will call these services to get work done.
  • Middleware: For code that runs before/after your controllers (like logging, auth checks, or request sanitization), create a middleware/ directory. This keeps cross-cutting concerns separate from your core app logic.
  • Core Infrastructure: If you have foundational components (like a router, database connection wrapper, or request/response handlers), put them in a core/ directory. These are the "framework-like" bits you’re building yourself.
2. A Scalable, Clean Directory Structure

Here’s a standard, maintainable structure that aligns with separation of concerns:

your-project/
├── public/              # Web root (only this folder is accessible to the web)
│   └── index.php        # Single entry point for all requests
├── app/                 # Your application's core code
│   ├── controllers/     # Route-specific controllers (only handle request/response)
│   │   ├── Base/
│   │   │   └── BaseController.php
│   │   ├── HomeController.php
│   │   └── UserController.php
│   ├── services/        # Business logic layer (called by controllers)
│   │   ├── UserService.php
│   │   └── OrderService.php
│   ├── models/          # Data models (map to database tables, handle ORM/CRUD)
│   │   ├── User.php
│   │   └── Order.php
│   ├── middleware/      # Pre/post request handlers
│   │   ├── AuthMiddleware.php
│   │   └── LoggingMiddleware.php
│   ├── views/           # Template files (HTML/PHP for rendering)
│   │   ├── layouts/     # Reusable page layouts (header, footer)
│   │   │   ├── header.php
│   │   │   └── footer.php
│   │   ├── home/
│   │   │   └── index.php
│   │   └── user/
│   │       └── profile.php
│   └── core/            # Custom framework-like tools
│       ├── Router.php
│       ├── Database.php
│       ├── Request.php
│       └── Response.php
├── config/              # Configuration files (DB settings, routes, env vars)
│   ├── database.php
│   ├── routes.php
│   └── env.php
├── vendor/              # Composer dependencies (if you use Composer)
└── logs/                # Application logs
3. Key Practices to Keep Things Maintainable
  • Separation of Concerns: Never let controllers handle business logic. Controllers should only accept requests, call the right service, and send back responses. All "heavy lifting" goes to services.
  • Use Autoloading: Ditch manual require_once calls by using Composer’s PSR-4 autoloading. Add this to your composer.json:
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    }
    
    Run composer dump-autoload to set it up, and you’ll be able to reference classes like App\Services\UserService without manual includes.
  • Dependency Injection: Instead of instantiating services directly in controllers, inject them via the constructor. This makes your code easier to test and modify:
    class UserController extends BaseController {
        private $userService;
    
        public function __construct(\App\Services\UserService $userService) {
            $this->userService = $userService;
        }
    
        public function profile($userId) {
            $user = $this->userService->getUserById($userId);
            return $this->render('user/profile', ['user' => $user]);
        }
    }
    
  • Centralize Routing: Keep all route definitions in config/routes.php instead of scattering them in controllers. Example:
    return [
        'GET /' => 'App\Controllers\HomeController@index',
        'GET /user/{id}' => 'App\Controllers\UserController@profile',
        'POST /user/login' => 'App\Controllers\UserController@login',
    ];
    
    Then build a core/Router.php to parse these routes and dispatch requests to the right controller methods.

By following this structure, you’ll keep your project organized, scalable, and easy to maintain—even without a full framework.

内容的提问来源于stack exchange,提问作者bulicud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:43:18