对此没有单一的“正确”答案。不过,我通常采用几条一般准则/原则。
不要污染全局范围
为您的代码命名空间并保留所有功能是类。所以,而不是:
function myFunction($x) {
// do stuff with $x and return a value
}
我会的:
namespace MyVendorName\SomeComponent;
class SomeUtils
{
public static function myFunction($x)
{
// do stuff with $x and return a value
}
}
当时的用法是:
use MyVendorName\SomeComponent\SomeUtils;
$val = SomeUtils::myFunction($x);
为什么要为这一切烦恼?如果没有这种命名空间,当您将更多代码从其他来源带入您的项目时 - 当您共享/发布您的代码以供其他人在他们的项目中使用时 - 您最终会遇到他们的函数/变量与您的函数/变量之间的名称冲突。好栅栏造就好邻居。
使用自动加载器
拥有大量的过去:
require '/path/to/class.php';
在您的消费者代码中早已不复存在。更好的方法是告诉 PHP - 通常在一些引导过程中 - 在哪里可以找到类 MyVendor\MyComponent\MyClass。这个过程称为自动加载。
如今的大多数代码都符合 PSR-0/PSR-4 标准,该标准将名称间隔的类名映射到相对于文件根目录的文件路径。
在 ZF1 中,通常将 ./library 文件夹添加到 ./public/index.php 中的 PHP include_path,然后将您的供应商命名空间添加到 ./application/config.ini 中的 autoloaderNameSpaces 数组中:
autoloaderNameSpaces[] = 'MyVendor';
并在文件中放置一个类似MyVendor\MyComponent\MyClass 的类:
./library/MyVendor/MyComponent/MyClass.php
然后您可以简单地引用MyVendor\MyComponent\MyClass 形式的类:
// At top of consuming file
use MyVendor\MyComponent\MyClass;
// In the consuming page/script/class.
$instance = new MyClass(); // instantiation
$val = MyClass::myStaticMethod(); // static method call
确定使用范围
如果我的功能仅适用于特定类,那么我将该功能作为方法(或方法的集合)保留在使用它的类中。
如果我的某些功能将在单个项目的多个位置使用,那么我可能会将其分解为我自己的库命名空间中的单个类,可能是MyVendor。
如果我认为一个函数/类将被多个项目使用,那么我将其分解为具有自己的 repo 的自己的项目(例如在 Github 上),通过Composer 访问它,以最佳方式注册它与Packagist,并密切关注semantic versioning,以便我的包裹的消费者收到稳定且可预测的产品。
当然,将文件夹从一个项目复制到另一个项目是可行的,但是当您修复错误、添加功能和(有时)破坏向后兼容性时,它经常会遇到问题。这就是为什么通常最好将这些函数/类放在一个单独的、语义版本化的项目中,作为该代码的单一真实来源。
结论
将功能分解为以标准方式自动加载的单独的命名空间类,为开发更容易使用、更容易重用和更容易测试的自定义功能提供了充足的“空间”(一个大主题再来一次)。