如何在Phalcon中处理动态生成的数据库表?

时间:2014-05-27 13:47:12

标签: phalcon

我为我们的承保经理创建一个网络应用程序,以创建和测试各种保险产品的评级方案。

编辑器允许用户在计算过程中添加和删除步骤,并且每个这样的步骤可以取决于几个不同的评级因素(驾驶员的年龄,车辆的年龄等)。每步的因子数量不固定,因此第一步可能只取决于一个评级因子,而下一步可能取决于四个不同的评级因子。

我的实现使用数据库表来存储表中的每个步骤,结构如下:

 id  | schemeId  | stepnumber  |  stepname  |  calculationtable
-----------------------------------------------------------------
     |           |             |            |

id是主键,schemeId是此步骤所属的方案的ID,stepnumber用于订购步骤(它们可以重新订购)在编辑器中,stepname只是步骤的标签,`计算表包含保存此步骤的实际评级因子信息的表的名称。

在Phalcon中为此表创建模型是一件轻而易举的事情。问题是计算表。创建新步骤时,会在此步骤表中插入一行,并创建一个名为scheme1step10的全新表。此表的结构是动态的,具体取决于此步骤在计算中所依赖的因子数。编辑器将允许用户在每个步骤中添加和删除评级因子,因此每个表中的列数将不同并且将随时间而变化。由于这些表的动态特性,我无法看到如何为它们创建模型。

我有几年前我正在尝试的这个编辑器的早期版本没有使用框架,这个表的数据检索看起来像这样:

public function getSteptable()
{
    $returnval=false;
    $result=mysql_query("SHOW COLUMNS FROM ".$this->getCalculationtable());
    if($result!=false)
    {
        for($loop=0;$loop<mysql_num_rows($result);$loop++)
        {
            $row=mysql_fetch_array($result);
            $colnames[$loop]=$row['Field'];
        }
        $rowsresult=mysql_query("SELECT * FROM ".$this->getCalculationtable());
        if($rowsresult!=false)
        {
            for($loop=0;$loop<mysql_num_rows($rowsresult);$loop++)
            {
                $row=mysql_fetch_array($rowsresult);
                foreach($colnames as $colname)
                {
                    $returnval[$loop][$colname]=$row[$colname];
                }
            }
        }
    }
    return $returnval;
}

请忽略此代码使用已弃用的mysql_函数的事实。

所以我的问题是如何在Phalcon中重现这种东西?看起来我无法使用PHQL,因为它似乎依赖于相关表格中存在的模型 - 当我尝试Model 'scheme1step1' could not be loaded时出现错误$steptable=$this->modelsManager->executeQuery("SELECT * FROM $steptablename")$steptablename是从另一个表中获取并且最初是由应用程序生成的,所以应该是安全的,我认为SQL注入的可能性)。我是否需要使用如here所示的原始SQL,还是依赖于现有的模型呢?或者我是否需要创建自己的模型来避免Phalcon的动态表格的ORM?如果是这样的话,我可以使用存储在DI容器中的数据库连接而不会造成任何问题吗?

1 个答案:

答案 0 :(得分:0)

这是一个非常有趣的问题。

我认为应该可以通过“动态”模型,modelsManager和自定义元数据策略来实现,尽管这只是我的理论,可能会或可能根本不起作用,或者只是引导您进入正确的方向。


  1. 创建一个自动加载器,它将通过使用eval()或类似于Zend_CodeGenerator_Php_Class()的方式为您动态创建scheme1step1类 - 使其简单如下:

      

    eval('class scheme1step1 extends \ Phalcon \ Mvc \ Model {}');

  2. 创建一个类似于Introspection的自定义MetaData策略(可能会扩展它),它将作为“全部捕获”代理对象

  3. 如果策略检测到已调用常规模型,则将其传递给Introspection父级
  4. 如果检测到scheme1step1模型,请正确指示表的列映射,可能使用\ Phalcon \ Db \ Dialect \ Mysql或再次使用Introspection(取决于其他需要)
  5. 或者只是在步骤1中执行步骤2,3,4:D 祝你好运!

    PS。我已经停止评论动态“分割”这样看起来不正确的表格的想法,而是专注于真正的问题