cakephp魔术查找功能与通用字段

时间:2013-04-30 13:21:47

标签: php cakephp model cakephp-2.0

我想要这个

$this->$model_name->findByProgram_id($id)

执行类似这样的事情

$this->$model_name->findBy.$field_id($id) 

其中$field_id = 'program_id$id是实际字段值。 这是动态调用函数所必需的。是否可以或我应该用硬编码的字段名称进行处理。

希望这会有意义! 谢谢客栈提前

2 个答案:

答案 0 :(得分:3)

尽管findByXXX魔术方法有时很方便,但它们并不总是检索数据的最有效方法。

通过 no not 我会告诉你完全避免使用它们,但使用它们时需要考虑几件事情;

1。他们是'神奇的'方法

魔术方法依赖于一种神奇的__call()方法,该方法由PHP调用(如果存在)。我不打算在这里开始另一场辩论,因为已有几场辩论exist。魔术方法确实有用,可以在很多情况下使用。

请注意;

  • 它们导致(某些)开销(我认为在大多数情况下这可以忽略)
  • 如果没有额外的PhpDoc,您的IDE将无法识别它们
  • 可能对其他程序员来说不太清楚,因为如果没有知道他们是魔术,他们将无法找到所调用方法的声明(即findById() 存在于您的源代码中)

2。它们不提供find(xxx)提供的所有功能

CakePHP模型可能定义了很多“关系”。虽然只需拨打Model->find('all')即可为您提供所需的所有数据,但在大多数情况下,它会为您提供超出您的需求。 CakePHP中的Model->find('all')等同于SQL中的此查询;

SELECT * FROM tableA JOIN tableB JOIN tableC.....

换句话说;它将获取tableA,tableB和tableC的所有相关字段和记录

在大多数情况下,您不需要所有数据,这样的查询效率低下,使用大量内存,导致您的网站效果不佳。

CakePHP有一个recursive选项,可让您指定检索数据的方式,例如通过设置recursive = -1,CakePHP将只检索'main'表中的数据,而不是相关的表;

SELECT * FROM tableA;

但是,如果你想从tableA和tableC中检索数据但是从tableB中而不是,那么在使用recursive

时你就不走运了

获得更好的控制

如果您想要更好的控制,请使用Containable behavior。此行为允许您准确指定应将哪些关系包含在结果中,例如;

$this->ModelA->find('all', array(
    'fields' => array(
        'ModelA.id',
        'ModelA.name',
        'ModelC.name',
    ),
    'contain' => array(
        'ModelC',
    )
));

只要您没有在contain选项中指定find键,ContainableBehavior将不会执行任何操作,因此默认情况下将其添加到{{ 1}} AppModel的数组

具体

无论您是否正在使用ContainableBehavior,具体是总是良好做法。 始终检查CakePHP执行的SQL查询,以检查它们是否有意义始终检查这些查询返回的数据 ;检查它们是否包含您不会使用的数据。

  • 默认情况下,在AppModel($actsAs)中将递归设置为-1。如果确实需要,只将递归设置为1或2。如果是这样,请在每个查询的基础上执行此操作。
  • 使用包含行为;它允许您更好地控制查询将检索的内容。
  • 始终准确指定所需的字段。如果关系中的多个表包含具有相同名称的字段(例如,使用public $recursive = -1;而不仅仅是'ModelA.name'),则优先使用模型别名为字段添加前缀,以防止出错。

将与数据相关的逻辑移到您的模型中 - 将它们放在一起

尝试将所有与数据相关的逻辑/代码移出控制器并将其移至模型中。

回到原来的问题;创建自己的“便利”方法,允许您通过任何字段搜索模型,例如;启用搜索用户模型并仅检索ID,名称和部门名称

'name'

这可能看起来像很多代码,但是,如果你对CakePHP更有经验,那么这样的方法将在不到5分钟的时间内完成。从积极的一面;它们将为您提供完整的控制权,并且可以轻松修改以满足您的需求。

在你的控制器中,代码量只有一行;像这样使用它;

User extends AppModel
{
    public $actsAs = array('Containable');

    public function searchByField($field, $value)
    {
        return $this->find('all',
            array(
                'fields' => array(
                    'User.id',
                    'User.name',
                    'Department.name',
                ),
                'conditions' => array(
                    // this will dynamically search by $field
                    $field => $value,
                ),
                'contain' => array(
                    'Department',
                )
            )
        );

    }
}

答案 1 :(得分:1)

你可以通过使用Cakephp中的inflector类来实现,这是一个概念所以可能需要充实但是......

$methodName = 'findBy' . Inflector:camelize($field_id);

$this->$model_name->$methodName($id);