从CakePHP框架内自动创建数据库表

时间:2009-10-31 04:26:46

标签: php sql mysql cakephp model

我正在尝试使用CakePHP编写一个webapp,并且像大多数webapps一样,我想创建一个安装程序来检测数据库是否已经初始化,如果没有,则执行安装过程。

此过程将完全自动化(它假设数据库本身已存在,并且通过匿名帐户授予完全管理访问权限且无密码...这适用于沙箱环境,因此无需担心安全性),所以它需要能够检测(无论请求!)数据库表是否已创建和初始化,如果没有,则透明地执行初始化,然后仍然提供用户的原始请求。

我考虑编写一种Bootstrap控制器,通过该控制器路由所有请求,并运行单个SQL查询来确定数据库表是否存在,但这看起来很麻烦(并且控制器需要相应的模型,不需要是这样的情况)。另一种可能性是覆盖AppModel并在其中放置相同的测试,但我不确定如何做到这一点,因为这些行没有任何文档。

提前致谢!

tl; dr version :什么是J2EE servlet的“init()”方法的CakePHP等价物(或者如何为CakePHP编写等效物)?

4 个答案:

答案 0 :(得分:3)

查看AppError类 - 可能是否存在缺少的数据库表错误,您可以从那里覆盖并运行创建数据库表SQL?

答案 1 :(得分:2)

您真的想让每个请求检查数据库是否存在?这看起来非常浪费。

第一次检查它将设置数据库,然后对于下一个百万个请求中的每一个,它将再次检查,即使数据库当然已经被设置了!

最好是要求安装应用程序的人进行一些设置。您应该在每个请求期间提供一个单独的运行的脚本,但是在安装过程中由该人员手动运行。


关于使用CakePHP执行此操作的最佳方法的评论,您是否看过Cake对数据库模式迁移的支持?

http://book.cakephp.org/view/734/Schema-management-and-migrations

答案 2 :(得分:2)

像这样的东西可以做你正在寻找的东西,但每个模型需要额外的查询。

<?php
class AppModel extends Model {
    var $create_query = false;

    function __construct($id = false, $table = null, $ds = null) {
        parent::__construct($id, $table, $ds);

        if (!empty($this->create_query)) {
            $this->query($this->create_query);
        }
    }
}
?>

然后你只需要在模型中添加var $create_query = 'CREATE TABLE IF NOT EXISTS ...;`。 MySQL CREATE TABLE documentation有关于IF NOT EXISTS的更多信息。

然而,我不确定这是不是太早尝试调用query()。或者在检查表之前是否已经存在, 。否则,CakePHP将错误而不是创建您的表。没有太多关于这个主题的文档,你最好的选择是直接看看cake / libs / model / model.php。

更新:上面的代码无效。

在深入研究Model类之后,Model :: __构造调用了Model :: setSource()。 Model :: setSource()检查表是否存在,如果不存在则抛出错误。要使用此方法,您必须覆盖并插入查询。下面的代码可能需要有所不同,具体取决于您使用的CakePHP版本。

<?php
function setSource($tableName) {
    // From Model::setSource().  I believe this is needed to make query() work.
    $this->setDataSource($this->useDbConfig);

    // Create our table if we have a create query
    if (!empty($this->create_query)) {
        $this->query($this->create_query);
    }

    // Now call the parent
    parent::setSource($tableName);
}
?>

答案 3 :(得分:1)

我想过在某个时间点做这件事,想出了一个很好的方法。

首先,请注意:我相信您的应用需要对app / config / database.php进行写访问,因此您可以编写正确的信息。我有一个解决方法,但让我解释一下安装程序的工作方式。

PHP脚本可以动态地重写(或删除自己)。由于脚本被加载到内存中,然后执行字节码,因此一旦完成工作,它就不依赖于文件。所以理论上你可以用一些东西覆盖AppError类来运行一个特定的控制器(比如你的SetupWizardController),加载所有常规的CakePHP东西。完成整个向导后,编写database.php文件/ setup所需的任何内容,覆盖AppError和AppController文件(如果在某些情况下没有安装应用程序,我可以看到你需要AppController以不同的方式工作)那些存储在app / vendors / myapp中的地方。该脚本已完成执行,现在您的检查不会在后续运行中发生。

这将解决Bill Karwin提出的问题,利用AppError并制作安装程序。

另一种方法是在您的应用程序中包含Environments的概念。假设您将环境存储在app / config / environment.php中。该文件将被授予写入权限(并且在安装结束时将删除该访问权限),或者可以覆盖该文件。无论何时,只要有人试图部署您的应用程序,它就会存在,而database.php会自动从environment.php文件中导入数据库。然后,database.php类的构造函数将使用environment.php中指定的数据覆盖它的$ default数据库。 database.php中的$ default将引用NoDB数据源,您可以在AppController中检查(我认为您将能够实例化虚拟模型并检查它的数据源),然后推送所需的安装程序。显然你也会在此之后覆盖AppController。