有不同的方法可以解决这个问题,具体取决于你想花多少时间做这件事,以及你想做得有多“好”。
保持原样
您可以按照他们假设它们正常工作的方式保留该方法。根据您关于不想重写所有内容的评论,这可能是您最好的方法。
归根结底,在所有函数中使用全局变量(在我看来)与拥有一个包含 50 个没有类的单独函数的文件一样多或少是不好的做法。
将全局变量传入
如果您将全局变量更改为函数参数,它可以让您在调用方法时能够准确地知道变量的值是什么以及它来自哪里,然后您将变量传递给方法并消除对全局变量的需求。
使用具有依赖注入/继承的类
这可能是“最好的”方法,但也是需要最长时间才能实现的方法。老实说,我还是建议你这样做。
因此假设您的 50 个方法文件包含用于不同目的的各种方法,您可能会决定需要 1、2 或 3 个基类和 5-10 个具有目的或角色的类,例如,您可能有一个抽象设置您的 PDO(DB 类)连接的基类,然后您的 Blog 类(示例)可能会扩展 Base 类。这样,Blog 类将继承生成博客条目所需的所有外部依赖项(外部意思是,Blog 类可能假设其目的只是检索、格式化和输出博客文章 - 应该已经处理了 DB 连接)。
一个实际的例子可能是这样的:
/**
* Handle your database connection, querying etc functions
*/
class DB {
protected $_pdo;
public function getPdo() {
if (is_null($this->pdo)) {
$this->_pdo = new PDO(...);
}
return $this->_pdo;
}
public function __construct() {
return $this->getPdo();
}
public function query($sql, $binds = []) {
// write a function that executes the $sql statement on the
// PDO property and return the result. Use $binds if it is not
// empty
$eg = $this->getPdo()->prepare($sql);
return $eg->execute((array) $binds);
}
/**
* Create a basic framework for all purpose-classes to extend
*/
abstract class Base {
/**
* "DB" property might be broad here to cover other DBs or connection
* methods (in theory)
*/
protected $_db;
public function __construct() {
$this->_db = new DB;
}
public function db($sql, $binds) {
return $this->_db->query($sql, $binds);
}
// insert other common methods here that all type-specific classes
// can use
}
现在执行一个特定的动作/角色:
class Blog extends Base {
public function get($blogId = null) {
// Basic error check
if (empty($blogId)) {
throw new UnexpectedValueException('Blog post ID was missing!');
}
return $this->db('SELECT * FROM `blogposts` WHERE blog_id = ?', $blogId);
}
}
注意我没有测试过这个,但现在的原则是 Blog 类只包含特定于博客文章的逻辑。任何格式化函数、安全函数等都可以在基类中,也可以在基类使用类似于 DB 的另一个辅助类中,例如格式化程序类。
你应该能够做到这一点:
<?php
# blogPost.php
# - Gets a blog post
require_once 'common.php'; // <--- include your class files, or an autoloader
// Instantiate the class for this role
$blog = new Blog;
// Get the blog post
$id = (isset($_GET['id'])) ? (int) $_GET['id'] : null;
$post = $blog->get($id);
// now other methods:
$post->toHTML(); // example - function might call a template file, insert the
// DB results into it and output it to the browser
这只是一个粗略的例子,但展示了如何构造一组类以实现类具有单一角色和方法具有单一目的的原则(例如“获取博客通过其 ID 发布”)。
这样,扩展 Base 的所有内容都将自动访问数据库(通过继承)。如果您想尝试从实现中删除 SQL,可以向您的 DB 类添加一些方法来提供基本的 ORM。
为通用值创建一个类
另一个简短/快速的选择是创建一个单一的类,它可以为您包含的文件中的所有函数提供任何通用的东西,在这种情况下是数据库处理程序和博客文章 ID。例如:
class Common {
protected static $_db;
protected static $_blogId;
public function getDb() {
if (is_null(static::$_db)) {
static::$_db = new PDO(...);
}
return static::$_db;
}
public static function getBlogId() {
return (int) static::$_blogId;
}
public static function setBlogId($id) {
static::$_blogId = (int) $id;
}
}
现在您只需在开始调用函数之前实例化这个类,并设置博客文章 ID(如果需要)。 PDO 连接将在需要时延迟创建。
# functions.php
require_once 'common.php';
function getWidgets($widget_id) {
$stmt = Common::getDb()->prepare('SELECT * FROM widget_assoc WHERE bid = ? AND aid = ?');
$stmt->execute(array(Common::getBlogId(), $widget_id));
$matches = $stmt->rowCount();
if ($matches !== 0) {
for($i = 0; $path[$i] = $stmt->fetch(); $i++);
array_pop($path);
return $path;
}
}
您唯一的职责是在每个页面上设置博客文章 ID,例如:
# blogPost.php
require_once 'common.php';
// Manual dependency blog ID needs to be set before processing:
$blogId = isset($_GET['blog_id']) ? (int) $_GET['blog_id'] : null;
Common::setBlogId($blogId);
// now you call your processing methods and perform your logic flow