有不同的方法可以解決這個問題,這取決於你有多少時間要花費這樣做,以及如何「以及」你想這樣做。
離開它,因爲它是
您可以將方法就可以假設它們能否正常使用的方式。根據您對不想重寫所有內容的評論,這可能是您最好的方法。
在一天結束時,在所有函數中使用全局變量(在我看來)與包含50個不包含類的獨立函數的文件相比,沒有更多或更差的做法。
傳遞全局中
如果你改變了全局變量函數參數,而不是它給你的洞察力,能夠準確地知道什麼是變量的值是和它來自哪裏,當你打電話給你的方法,那麼你將該變量傳遞給方法並刪除全局變量的需要。
類使用依賴注入/繼承
這可能是「最好」的辦法,也是一個需要最長時間來實現。無論如何,我建議你這樣做,說實話。
所以假設你的50方法文件中包含了多種用於不同目的的方法,你可以決定你需要1,2或3的基類,並且有目的或作用5-10類,例如,你可能有一個抽象基類設置您的PDO(DB類)連接,然後您的Blog類(示例)可能會擴展基類。這樣,Blog類將繼承它生成Blog條目所需的所有外部依賴關係(外部意思是說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類只包含特定於博客文章的邏輯。任何格式化函數,安全函數等都可以在Base類中,或者在Base類與DB類似的另一個輔助類中使用,例如,一個Formatter類。
你應該能夠做到這一點,那麼:
<?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,則可以向您的數據庫類添加一些方法來提供基本的ORM。
作出共同的價值觀
一個類
另一個短/快速選擇是建立一個單一的類,它可以起到什麼共同點所有的,將在你的包含文件中的函數,在這種情況下,DB處理程序和博客帖子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;
}
}
你唯一的責任是設置在每個頁面上的博客文章編號,例如:
# 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
當然,使用一類是一個很好的點開始。但很少有一個班級是一個好主意。類是爲了描述一個特定的事物或特徵,而不僅僅是所有的。無論如何,使用一個類,你擺脫了全局。你甚至不必使用對象屬性。如果這些值真的是(僞)常量,那麼爲什麼不使用類常量? – arkascha
謝謝@arkascha,我不知道你可以使用類來使用對象屬性。你能指點我一個使用類常量的例子嗎? –
'$ db'本身沒有錯。這種習慣性和廣泛的做法並不是出於惡作劇,而是因爲它確實發生了適合普通情況的事情,並沒有引入無用的抽象。 - 現在'$ BLOG_ID'完全不同。如果它相當於一個配置設置或者實際上是恆定的,那麼就去掉它。 – mario