【问题标题】:Automate database table creation from within CakePHP framework在 CakePHP 框架内自动创建数据库表
【发布时间】:2009-10-31 04:26:46
【问题描述】:

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

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

我考虑编写一种引导所有请求的控制器,通过它来路由所有请求,并运行单个 SQL 查询来确定数据库表是否存在,但这似乎很麻烦(并且控制器需要相应的模型,不需要就是这里的情况)。另一种可能性是覆盖 AppModel 并在其中放置相同的测试,但我不确定如何执行此操作,因为没有任何文档。

提前致谢!

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

【问题讨论】:

    标签: php sql mysql cakephp model


    【解决方案1】:

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

    【讨论】:

    • 这实际上正是我正在研究的 - 要么在错误页面中提供一个指向将自动填充表格的脚本的链接,要么在错误类中执行它,如果这是错误的话生成。谢谢!
    • @Magsol 你是如何实现这个的?我很好奇。
    • 很难确定——这是不久前的事了——但我有理由确定我创建了一个 AppError 类并使用生成数据库模式的代码覆盖了 missingTable 错误函数.对此持保留态度:我怀疑 CakePHP 在 5 年内发生了很大变化!
    【解决方案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::__construct 调用 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】:

      你真的想让每个请求检查数据库是否存在吗?这似乎非常浪费。

      第一次检查时,它会设置数据库,然后对于接下来的一百万个请求中的每一个,它都会再次检查,即使此时数据库当然已经设置好了!

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


      您对使用 CakePHP 的最佳方式发表评论,您是否查看过 Cake 对数据库模式迁移的支持?

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

      【讨论】:

      • 我非常喜欢那个;我想我正在寻找与 J2EE servlet 的“init()”方法等效的 CakePHP,如果这样的东西存在或可以编写的话。虽然单独的脚本也可以工作,但仍需要在主应用程序中检查数据库表是否存在,如果不存在,建议用户运行脚本。
      • 我认为对不存在的表的任何查询都会很好地揭示这一事实。
      • 看,我的重点是我不熟悉 CakePHP 框架。我了解网络编程的原理和范例;我只是不确定如何在 CakePHP 环境中实现它们。这方面的任何建议都是我正在寻找的。​​span>
      • 是的,我看过那篇文章,但我仍然必须将 Bake 过程变成只运行一次的批处理过程,我仍然不确定如何在CakePHP 框架(因为这些方面似乎没有任何文档)。
      • 您无需在 Cake 框架中运行它,您只需在安装、升级或部署应用程序时在 命令行 中运行它。从框架内运行它——也就是说,在每个请求上运行它——将是每个请求的不必要开销。听起来您太专注于实施而忽略了目标。
      【解决方案4】:

      我曾一度考虑过这样做,并想出了一个好方法。

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

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

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

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

      【讨论】:

        猜你喜欢
        • 2016-01-09
        • 1970-01-01
        • 2019-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-22
        • 2020-06-01
        • 1970-01-01
        相关资源
        最近更新 更多