接近动态 php 包括没有前端控制器的遗留项目


Approaching dynamic php includes on legacy projects without a front controller

php中通过Include s/require_once s进行依赖管理是一种痛苦。 每隔一段时间,我就会改变一些东西,东西就会中断,我必须重新考虑我在 php 中初始化第一个 include()/require() 的方法。 我觉得我错过了一种更强大的技术,可以解决我的所有问题,但我似乎还没有找到它。

使用 MVC 自动加载会很好! 但是对于遗留的程序项目,我认为这没有帮助吗?

过去的做法

可能和其他人一样,我从相对路径开始。 require_once('../../../core/core.php');例如。 不幸的是,当您开始需要具有自己所需依赖项的库时,这种情况会中断。 因此,我转向使用动态包含,该包含从层次结构中的任何位置解析出主项目文件夹:require_once(substr(dirname(__FILE__), 0, strpos(dirname(__FILE__), 'my_project')+8).'core/database/admin.database.connection.php');这意味着我可以在适当的权限任何地方通过它,并将其移动到项目中的任何地方,它仍然可以工作! 不幸的是,当我实现 CI 并且 CI 项目设置一个项目根时它中断了,例如:/home/rof/bitbucket.org/repo_name/clone/不包含特定的字符串"my_project",因此破坏了所有包含。所以在过去的一个小时左右的时间里,我一直在修复包含,这并不好玩。 我想找到一个"最终解决方案"。

当前使用

目前,我一直在将包含更改为:

require_once(realpath(__DIR__.'/../../').'/core/database/admin.database.connection.php');

不幸的是,如果我在目录中向上或向下移动一组脚本(例如将用户/订单/移动到管理员/订单或所有各种内务管理方法),则需要再次重写每个单独的脚本。更改目录。/../../'到目录。/../../../'或其他什么。 这很糟糕,因为它太复杂了,以至于尝试重写它项目或目录范围是可怕的,东西可能会崩溃。

我的目标

  • 第一简单,我想设置包含并确保它们会工作,忘掉他们。
  • 第二层系统使不同的区域可以包含具有不同访问级别的库
  • 第三,我不想在事情发生变化时重写包括。 理想情况下,我很乐意将包含写入一个位置以供管理员访问,将包含在一个位置供用户使用访问,以及一个公共访问位置。

对于具有复杂目录结构的非面向对象、过程/基于函数的 php 项目的最终解决方案是什么?

示例目录结构和脚本

这是一个几乎真实的目录结构,这是非常标准的,但只是为了给你一个想法:

core/
 - core.php
 - environment.php
 - database/
   - database.php
   - admin.database.connection.php
   - user.database.connection.php
   - public.database.connection.php
www/
 - index.php
 - contactus.php
 - map.php
 - ...
 - users/
   - login.php
   - logout.php
   - accountdetails.php
   - ...
 - admin/
   - login.php
   - logout.php
   - index.php
   - admin.php
   ...
   - reports/
     - revenue_report.php
     - orders.php
     - clientslist.php
   - orders/
     - orderslist.php
     - orderview.php
     ...

希望您能理解这个想法,一个旧的遗留系统,其中包含过程代码、许多复杂的脚本和多层数据库访问。

无论程序设计如何,您都必须有一些通用文件,例如包含数据库连接信息的config.php

因此,您可以在其中设置一些定义:

首先,应用相对于配置文件的基本路径...

define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../'); // or whatever

注意,从 PHP 5.3 开始,您可以使用 __DIR__ 而不是 dirname(__FILE__)

然后,您可以为每组文件设置单独的定义。或:

define('CORE_PATH', APPLICATION_PATH . '/core/');

然后在您的个人脚本中,您可以只做

include(CORE_PATH . 'database/admin.database.connection.php');

或者,如果您想对其进行微调,请为/core/database/定义一条路径,然后执行例如 include(CORE_DATABASE_PATH . '/admin.database.connection.php');

如果移动这些文件夹,则只需更新配置文件即可。

我现在经常

处理这类问题,以下是我在所有情况下强烈建议的:尽快通过前端控制器路由所有内容!

在 php 中,创建一个前端控制器并通过它处理所有脚本是非常有益的,只要您可以设置它。 如果您仍然有像 example.php 这样的旧脚本,请让您的前端控制器index.php以白名单方式包含它们! 因此,像 mydomain.com/example 这样的 url 将通过前端控制器路由,获取所有基本包含,然后才包含example.php脚本(如果列入白名单)!

其他任何事情都只是延迟了统一一个充满大量微小分离脚本的破碎代码库的不可避免的问题。