当前位置: 首页 > 知识库问答 >
问题:

丢失函数中的全局值

周翰池
2023-03-14

我有一个自定义的CMS系统,我已经写在PHP。我几乎完成了将所有旧的遗留mysql_函数转换为PDO。但是,我在一个文件中有大量的函数,没有类包装器。文件中只有大约50个函数,这实际上是运行CMS所需的所有函数。很多天前,我养成了这样使用全局值的坏习惯:

function getWidgets($widget_id){
 global $db, $BLOG_ID;
 $stmt = $db->prepare("SELECT * FROM widget_assoc WHERE bid=? AND aid=?");
 $stmt->execute(array($BLOG_ID, $widget_id));
 $matches = $stmt->rowCount();
 if($matches !== 0){
 for($i = 0; $path[$i] = $stmt->fetch(); $i++) ;
 array_pop($path);
 return $path;
 }
 }

共有1个答案

孔甫
2023-03-14

你可以用不同的方法来解决这个问题,这取决于你想花多少时间来做它,以及你想做得有多“好”。

您可以让方法保持它们假设正常工作的方式。正如你关于不想重写一切的评论,这可能是你最好的方法。

归根结底,在所有的函数中使用全局变量(在我看来)和一个包含50个独立函数而没有类的文件一样糟糕。

一个实际的例子可能是这样的:

/**
 * 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类只包含特定于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
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;
    }
}

现在您只需要在开始调用函数之前实例化这个类,并设置blog post 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
 类似资料:
  • 全局函数 返回上级 DirectDrawCreate DirectDrawCreateClipper DirectDrawEnumerate DirectDrawEnumerateEx DirectDrawCreate 返回目录 创建一个DirectDraw对象的实例。 HRESULT WINAPI DirectDrawCreate( GUID FAR *lpGUID, LPDIRECTDRAW

  • debug 调试打印PHP变量,并中断执行。等同于 var_dump($var1, $var2);die; table 将任意MySQL表构造成Model对象。 table($table_name, $db_object_id); model 创建模型对象。 model($model_name, $db_object_id);

  • Herosphp提供了一些全局辅助函数: //格式化打印变量(数据) __print($message); //终端高亮打印绿色(success) tprintOk($message); //终端高亮打印红色(error) tprintError($message); //终端高亮打印黄色(warning) tprintWarning($message); //计算字符串的hash值, 默

  • imigo 启动一个协程,自动创建和销毁上下文 imigo(function(){ $value = Redis::get('key'); // 无需手动释放任何资源 }); 传入参数: imigo(function($id, $name){ echo $id, ':', $name, PHP_EOL; // 1:test }, 1, 'test'); imiCalla

  • 问题内容: 什么是效用全球关键字? 有什么理由偏爱一种方法而不是另一种方法? 安全? 性能? 还要别的吗? 方法1: 方法2: 什么时候使用有意义? 对我来说,这似乎很危险 ……但可能只是缺乏知识。我对 文档化的 技术原因感兴趣(例如,带有示例代码,链接到文档…)。 提前致谢! 赏金 这是关于该主题的一个很好的一般性问题,我(@Gordon)会提供赏金以获取其他答案。您的答案是否与我的意见一致或给

  • MiniFramework 在初始化时,会自动加载一个全局函数库,你可以随时调用里面的全局函数,例如: $test = array('a', 'b', 'c'); //调用全局函数 pushJson() 输出一个 JSON 串并终止程序运行 pushJson($test); 提示:全局函数库位于 Mini/Functions/Global.func.php