php - 这是在 PHP mvc 中缓存查询和构建页面的可接受方式吗?

标签 php oop caching model-view-controller

下面的代码是否显示了一种可接受的方式来缓存完全构建的页面和数据库查询?

构建页面的缓存从 Controller 中的 __construct 开始,然后以 __destruct 结束,在此示例中,所有页面都默认缓存 15 分钟到一个文件。

查询缓存是使用 apc 完成的,它们会在每次查询指定的时间内存储在内存中。在实际站点中,apc 缓存会有另一个类,以便在需要时可以更改它。

我的目标是尽可能构建最简单的 mvc,我是失败了还是在正确的轨道上?

Controller

//config
//autoloader
//initialiser - 

class controller {

    var $cacheUrl;

    function __construct(){

        $cacheBuiltPage = new cache();
        $this->cacheUrl = $cacheBuiltPage->startFullCache();
    }

    function __destruct(){

        $cacheBuiltPage = new cache();
        $cacheBuiltPage->endFullCache($this->cacheUrl);
    }
}

class forumcontroller extends controller{

    function buildForumThread(){

        $threadOb = new thread();
        $threadTitle = $threadOb->getTitle($data['id']);

        require 'thread.php';
    }
}

型号

class thread extends model{

    public function getTitle($threadId){

        $core = Connect::getInstance();
        $data = $core->dbh->selectQuery("SELECT title FROM table WHERE id = 1");

        return $data;
    }
}

数据库

class database {

    public $dbh;
    private static $dsn  = "mysql:host=localhost;dbname=";
    private static $user = "";
    private static $pass = '';  
    private static $instance;

    private function __construct () {
        $this->dbh = new PDO(self::$dsn, self::$user, self::$pass);
    }

    public static function getInstance(){
        if(!isset(self::$instance)){
            $object =  __CLASS__;   
            self::$instance = new $object;
        }
        return self::$instance;
    }

    public function selectQuery($sql, $time = 0) {

        $key = md5('query'.$sql);

        if(($data = apc_fetch($key)) === false) {

            $stmt = $this->dbh->query($sql);
            $data = $stmt->fetchAll();

            apc_store($key, $data, $time);
        }
        return $data;
    }
}

缓存

class cache{

    var url;

    public function startFullCache(){

        $this->url = 'cache/'.md5($_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']);   

        if((@filesize($this->url) > 1) && (time() - filectime($this->url)) < (60 * 15)){
            readfile($this->url);
            exit;
        }

        ob_start();

        return $this->url;
    }

    public function endFullCache($cacheUrl){

        $output = ob_get_contents();
        ob_end_clean();

        $output = sanitize_output($output);

        file_put_contents($cacheUrl, $output);

        echo $output;
        flush();
    }

}

查看

<html>
<head>
<title><?=$threadTitle[0]?> Thread - Website</title>
</head>
<body>

    <h1><?=$threadTitle[0]?> Thread</h1>

</body>
</html>

最佳答案

“外包”缓存

首先,您必须了解 GET 请求的缓存通常在整个 Internet 上进行。特别是如果您的用户通过某种代理连接。

然后还可以设置较长的过期时间,以便用户的浏览器缓存 HTML 页面和/或媒体文件。

要开始研究这个,您应该阅读 these two文章。

你的目标是什么?

在您开始尝试添加缓存之前,请确保您确实需要它。做一些基准测试,看看你的瓶颈是什么。 为了优化而优化是没有意义的,而且通常是有害的

如果您知道(并且有数据支持它.. 这与“感觉”无关)您的应用程序进行了过多的 SQL 查询,而不是跳转到查询缓存,您应该首先检查这些查询是什么为。

For example:
If you see, that you are performing slow query each page-view just to generate a tag cloud, you instead should store the already completed tag cloud (as HTML fragment) and update it only, when something has changed.

此外,“添加缓存” 绝不应该是您尝试提高性能的第一步。如果您的查询速度很慢,请使用 EXPLAIN 查看它们是否正确使用了索引。确保您没有多次查询相同的数据。还要看看查询是否真的有意义。

这不是MVC

我不确定,你是从哪里学会这样写的,但你似乎错过了 MVC 的全部要点:

  • “ View ”不是模板
  • “模型”不是数据库抽象
  • “ Controller ”不是应用程序逻辑

您似乎还缺少“层”一词的含义。它不是“类”的同义词。层是在类似情况下可重用的可重用组件组 [1] .

您可能会从阅读中受益 thisthis邮政。它们应该可以帮助您理解这种架构模式的基础知识。

在MVC架构中缓存在哪里?

当使用 MVC(或受 MVC 启发的)架构时,基本上有两点可以进行缓存: View 和持久性逻辑。

缓存 View 主要需要重用一次渲染过的模板(MVC 中的每个 View 都将兼顾多个模板和相关的 UI 逻辑)。请参阅前面带有标签云的示例。

持久化逻辑中的缓存将取决于您的实现。

  • 您可以缓存应该传递给 domain objects 的数据。 , 有服务:

    Note: in real application the new instances would not be here. Instead you would be using some factories

    $user = new User;
    $user->setId( 42 );
    
    $cache = new Cache;
    
    if ( !$cache->fetch( $user ))
    {
        $mapper = new UserMappper;
        $mapper->fetch( $user );
    }
    
    $user->setStatus( User::STATUS_BANNED );
    $cache->store( $user );
    $mapper->store( $user );
    
    // User instance has been populated with data
    
  • 缓存的另一点是存储库和/或身份映射,如果您将持久层扩展到使用简单映射器之外。这将很难用一个简单的代码示例来解释。相反,您应该阅读 Patterns of Enterprise Application Architecture书。

.. 您代码中的一些其他不良做法:

  • 请停止使用单例建立数据库连接。它使编写单元测试变得不可能,并导致与类的特定名称紧密耦合。我建议改用 this approach并在需要它的类中注入(inject)数据库连接。

  • 另外,如果您的查询没有参数,那么准备它就没有意义了。准备好的语句用于将数据传递给 SQL ..但是您的示例都没有任何参数。

    出现此问题的主要原因是您神奇的 Database 类。相反,您应该将持久性逻辑分成多个 data mappers .这样您就不会面临对所有查询使用单一方法的问题。

  • var 关键字是 PHP4 的神器。现在我们使用 publicprivateprotected

  • 您正在对代码中的连接详细信息进行硬编码。基本上是违反了OCP (精简版:here)。

关于php - 这是在 PHP mvc 中缓存查询和构建页面的可接受方式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14982434/

相关文章:

php - 占位符的 PDO 有效字符

php - 从 session ID 所在的两个表中获取选择数据

php - 使用 jQuery 按行和列插入值

c++ - 在 C++ 中,float 值被从 double 中截断

php - 使用 Laravel HasManyThrough 关系获取模型 ID 和更新字段时出错

c++ - 如何在不导出对象的情况下自动删除对象

PHP运行时类修改

performance - 如果您正在使用 Service Workers,您还需要缓存控制 header 吗?

Java 内存感知缓存

java - 通过 setter 或服务使缓存失效?