【问题标题】:CakePHP 3: get a list of all table objectsCakePHP 3:获取所有表格对象的列表
【发布时间】:2017-08-25 09:33:35
【问题描述】:

我正在寻找一种方法来获取所有可用table objects 的列表。这些是(默认情况下)位于App/Modal/Table 下并由TableRegistry 处理的所有类。如何获取所有这些对象的列表?

我知道可以获取数据库的所有表:

$tables = ConnectionManager::get('default')->schemaCollection()->listTables();

然后使用TableRegistry::get()获取表格对象。

但这对于我的解决方案是不可能的,因为有两种情况不起作用:

  1. 与表对象名称不同的自定义表名称
  2. 插件表对象

有什么想法吗?


编辑:为什么?我需要所有使用行为 X 的表对象。在我的例子中是自定义 SearchableBehavior,它会在每个 afterSave 事件上更新已保存实体的 searchindex 表。要更新所有表的所有实体的 searchindex,我需要知道哪些表正在使用 SearchableBehavior 并手动调用它们的更新方法。

【问题讨论】:

  • I need a list of all table objects that use a behavior X - 为什么?我确信有更好的方法来做任何你尝试的事情。
  • 请查看更新后的问题,我添加了更多背景信息。
  • 为什么需要更新all?当Model.afterSave 被触发时,我们对相关表进行索引更新。一种行为就是这样做的。该行为还检查获取数据的方法,如果不存在,则回退到 Table::get()。顺便说一下,该插件是开源的,但使用 Elastic Search github.com/World-Architects/cakephp-elastic-index 来索引数据。
  • update all 是搜索索引的初始创建或表结构发生更改并且需要重新创建索引时所必需的。你的插件看起来很棒,谢谢!它的行为类似于我的解决方案。我是否理解正确,每次保存单个数据集时,您的行为都会为表重新创建索引?还是只是这个单一数据集的索引数据?
  • 不,因为这很愚蠢,因为它很慢而且需要时间。重新创建整个索引绝对没有意义。我们有一个外壳(包含在插件中)并通过配置指定可以索引的表列表。这就是我们重新创建索引的方式,但仅在架构更改后且仅在新索引上执行此操作,然后在索引编制完成后切换索引。您不会在运行时重建整个索引。

标签: cakephp cakephp-3.x


【解决方案1】:
$tables = glob(APP."Model".DS."Table".DS."*Table.php"); $tablesNames = []; foreach ($tables as $name){ $item = explode('Table.php', basename($name)); $tablesNames[] = $item[0]; } 公关(表名);

【讨论】:

  • 欢迎来到 Stack Overflow,非常感谢您愿意帮助他人!但是,在发布答案时,请务必包含一些关于您的代码为何有效的信息。它有什么作用?它与原始问题有何关系?为什么这个解决方案是一个好的解决方案?
【解决方案2】:

编写一个监听Model.initialize的事件监听器,然后检查主题,如果表有你的行为,它就是表对象。然后用那个列表做点什么。

如果这对你不起作用 - 你给 背景信息 - 遍历应用程序模型/表文件夹和插件文件夹以及供应商文件夹并搜索模型文件夹并检查 @987654322 @ 文件。然后尝试根据路径/命名空间和文件名实例化表对象并检查模型。但这不是很快,您应该缓存结果列表。

【讨论】:

  • 感谢您的回答。我会检查Model.initialize 解决方案,也许这行得通。我在我的问题中添加了一些额外的信息,让您知道我想做什么。
【解决方案3】:

我最近有一个类似的用例,我需要访问所有表对象,以在控制台命令中初始化数据库中的数据一次。

我首先构建了一个包含表对象类可以驻留的所有路径的数组,然后遍历所有文件并使用以“Table.php”结尾的文件。请注意,根据您的用例,此方法可能需要稍作修改。

<?php

use Cake\Core\Plugin;
use Cake\ORM\TableRegistry;
use Cake\Filesystem\Folder;

// Building an array of all possible paths. Firstly the src directory:
$tableClassPaths = [
    APP . 'Model' . DS . 'Table' . DS,
];

// Secondly, all loaded plugins:
foreach(Plugin::loaded() as $plugin) {
    $dir = Plugin::classPath($plugin) . 'Model' . DS . 'Table' . DS;
    if(is_dir($dir)) {
        $tableClassPaths[$plugin] = $dir;
    }
}

// Iterating over each file in each folder.
$tableObjects = [];
foreach($tableClassPaths as $plugin => $dir) {
    foreach(new \FilesystemIterator($dir) as $file) {
        // All Files ending in Table.php might be relevant
        if($file instanceof \SplFileInfo && $file->isFile()
            && mb_substr($file->getFilename(), -9) === 'Table.php'
        ) {
            $className = mb_substr($file->getFilename(), 0, -9);
            if(is_string($plugin)) {
                $className = $plugin . '.' . $className;
            }
            
            $tableObject = TableRegistry::getTableLocator()->get($className);
            // Here you can use / filter the Tables, for example by checking for the presence of a behavior "Indexable":
            if($tableObject->hasBehavior('Indexable')) {
                $tableObjects[] = $tableObject;
            }
        }
    }
}

?>

请记住,这仅适用于非常狭窄的环境,因为这完全避开了 CakePHP 的常规 MVC 模式。

【讨论】:

    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多