CakePHP HATBM无法正常工作

时间:2011-02-16 15:27:12

标签: php cakephp

我正在开始一个cakephp应用程序,我从来没有在现实世界中使用它所以我有点困惑HABTM如何工作,即使我阅读文档我甚至无法得到$this->User->Subscription和没有看到任何额外的物品被倾倒

我想要的是在用户和订阅之间创建HATBM

所以我创建了三个表(用户,订阅,users_subscribers)

然后在我的User.php模型中我做了这个

var $hasAndBelongsToMany =
    array(
        'Subscription' =>
            array('className'=>'Subscription',
                'joinTable' => 'users_subscribers',
                'foreignKey'             => 'user_id',
               'associationForeignKey'  => 'subscription_id',
                'unique' => true,
               )
        );

SUbscription.php

    var $hasAndBelongsToMany = array(
        'User'=>array('className'=>'User',
                    'joinTable' => 'users_subscribers',
        'foreignKey' => 'subscription_id',
        'associationForeignKey' => 'user_id',
        'unique' => true));

即使有标签示例并且跟随它,我也无法获得关系集,我还添加了行<?php echo $this->element('sql_dump'); ?>以查看它是否正在运行它不是......

有人可以指导我如何让HATBM正常工作,还需要验证哪些内容?

完整代码: pages_controller.php http://sao.pastebin.com/PWQMhE2z

用户模型: http://sao.pastebin.com/PWqwAj1v

订阅模式: http://sao.pastebin.com/MfVFR4Kw

订阅SCHEMA: http://sao.pastebin.com/mLRcEp1c

用户SCHEMA: http://sao.pastebin.com/UeTRHh3u

users_subscriptions SCHEMA: http://sao.pastebin.com/4UeSDZte

4 个答案:

答案 0 :(得分:4)

实现这项工作的最简单,最快捷的方法是遵循CakePHP的配置规则而不是自定义。

这意味着遵循CakePHP约定,除非你有充分的理由不这样做。

我强烈建议您从已知的基本设置开始,然后根据需要进行修改。这是一种快速简便的启动和运行方式。

数据库表

从三个数据库表开始:users,subscriptions和subscriptions_users。你已经拥有的模式还可以,但我会做一些修改以确保顺利进行:

  1. nametitle列添加到users表。要么是这样,要么您必须将$displayField属性添加到您的用户模型中。如果你不这样做,你会错过CakePHP提供的一些“自动化”。 More info on $displayField
  2. 将联接表的名称更改为subscriptions_users。这是CakePHP的惯例,没有理由不节省时间和担心跟随它。 : - )
  3. 对连接表使用以下架构:
    CREATE TABLE subscriptions_users (
    subscription_id int(11) NOT NULL,
    user_id int(11) NOT NULL
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
    
  4. 请注意,没有定义任何键。从CakePHP手册:“为避免任何问题 - 不要为这两个字段定义组合主键,如果您的应用程序需要它,您可以定义唯一索引。”

    模特

    尽量保持代码清洁。 CakePHP中实现了许多合理的默认值,并且在定义它们时没有必要定义它们。

    以下型号适合您:

    <强> user.php的

    <?php
    class User extends AppModel {
        var $hasAndBelongsToMany = array('Subscription');
    }
    ?>
    

    <强> subscription.php

    <?php
    class User extends AppModel {
        var $hasAndBelongsToMany = array('User');
    }
    ?>
    

    非常简单。只需确保您的模型文件名称正确:user.php和subscription.php,全部小写。

    另外,请注意,您不必设置任何关系选项(classNamejoinTable等),除非它们必须是默认值之外的其他选项。百分之九十的默认值应该可以为你服务。

    你应该立即开始运作。您可以确保正在加载模型对象,并且可以在控制器中访问它们,如下所示:

    <强> users_controller.php中

    <?php
    class UsersController extends AppController {
        var $name = 'Users';
    
        function index() {
            $this->autoRender = false;
            var_dump(is_object($this->User));
            var_dump(is_object($this->User->Subscription));
        }
    }
    ?>
    

    <强> subscriptions_controller.php

    <?php
    class SubscriptionsController extends AppController {
        var $name = 'Subscriptions';
    
        function index() {
            $this->autoRender = false;
            var_dump(is_object($this->Subscription));
            var_dump(is_object($this->Subscription->User));
        }
    }
    ?>
    

    / users和/ subscriptions的输出都应为bool(true) bool(true)

    您可以通过执行pr($this->User);来查看完整模型。

    删除记录

    如果使用例如$this->User->delete($user_id)删除单个记录,则连接表中具有该用户ID的所有记录也将自动删除。

    如果要从HABTM连接表中删除单个记录,而不删除它链接到的记录,实际上“取消连接”这两个记录,则可以通过SubscriptionsUser模型执行此操作。这是一个在有HABTM关系的情况下即时创建的模型。

    请点击此处查看示例:CakePHP hasAndBelongsToMany (HABTM) Delete Joining Record

答案 1 :(得分:1)

我做了一个带有基本架构的测试应用程序,我得到了所有关系。我怀疑你的困境与你所做的事实有关$uses = array('User', 'Subscription');为什么不尝试使用$uses = $uses = array('User');然后尝试

$this->User->find('all');
$this->User->Subscription->find('all');

答案 2 :(得分:0)

您还需要在Subscription.php模型中定义相同的HABTM关系。如果我没记错的话,CakePHP会在内部从其他方面的HABTM配置中提取一些必要的信息。

答案 3 :(得分:0)

我总是使用两个“hasMany”关系和一个“belongsTo”关系来获得CakePHP中更多控件的HABTM效果。

试试这个:

用户模型(user.php)

class User extends AppModel {
  public $name = 'User';
  public $actsAs = array('Containable');
  public $hasMany = array('UserSubscription');
}

订阅模型(subscription.php)

class Subscription extends AppModel {
  public $name = 'Subscription';
  public $actsAs = array('Containable');
  public $hasMany = array('UserSubscription');
}

UserSubscription模型(user_subscription.php)

class UserSubscription extends AppModel {
  public $name = 'UserSubscription';
  public $belongsTo = array('User','Subscription');
}

pages / home action(pages_controller.php)

public function home() {
  $data = array(
    'User' => array(
      'id' => 1, 'user_email' => 'allenskd@gmail.com', 'user_password' => 'fdfdkert', 'user_salt' => 'haha', 'user_displayname' => 'David'
    ),
    'UserSubscription' => array(
            'user_id' => '1', 'subscription_id' => '1'
    ),
    'Subscription' => array(
      'id' => 1, 'title' => 'My first plan', 'price' => '30.00', 'subscriber_count' => '1'
    ),
  );
  $this->Subscription->save($data);
  $this->User->saveAll($data);
  $test = $this->User->find('all', array('contain' => array('UserSubscription' => array('Subscription'))));
  pr($test);
}