1

我要这个

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

要执行这样的事情

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

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

希望这是有道理的!!!提前感谢客栈

4

2 回答 2

3

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

我绝不会告诉您完全避免使用它们,但是在使用它们时需要考虑一些事项;

1.它们是“神奇”的方法

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

请注意;

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

2. 他们没有提供所有提供的find(xxx)功能

CakePHP 模型可能定义了很多“关系”。尽管简单地调用Model->find('all')会为您提供所需的所有数据,但在大多数情况下,它会为您提供比您需要的更多的数据。Model->find('all') CakePHP 中的这个查询相当于 SQL 中的这个查询;

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

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

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

CakePHP 有一个recursive选项,允许您指定检索数据的深度,例如,通过设置recursive = -1,CakePHP 将只从“主”表中检索数据,而不是从相关表中检索数据;

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 就不会做任何事情,因此默认情况下通过将其添加到$actsAsAppModel 的数组中来添加此行为是保存的

请明确点

无论您是否使用 ContainableBehavior,具体化始终是一种好习惯。始终检查 CakePHP 执行的 SQL 查询以检查它们是否有意义始终检查这些查询返回的数据;检查它们是否不包含您不会使用的数据。

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

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

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

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

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',
                )
            )
        );

    }
}

这可能看起来像很多代码,但是,如果您对 CakePHP 有更多的经验,这样的方法可以在不到 5 分钟的时间内编写出来。从积极的一面; 它们将使您完全控制将要检索的内容,并且可以轻松修改以满足您的需求。

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

// Search by email
$data = $this->User->searchByField('User.email', 'foo@example.com');

// Search by name
$data = $this->User->searchByField('User.name', 'admin');
于 2013-04-30T17:37:19.297 回答
1

您可以通过使用 Cakephp 中的变形器类来做到这一点,这是一个概念,因此可能需要充实但是......

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

$this->$model_name->$methodName($id);
于 2013-04-30T13:24:37.043 回答