cakephp 3.0 注册与现有用户问题关联的帐户

Posted

技术标签:

【中文标题】cakephp 3.0 注册与现有用户问题关联的帐户【英文标题】:cakephp 3.0 Registering an account associated to an existing user issue 【发布时间】:2015-04-18 07:46:06 【问题描述】:

Accounts 表有外键 user_id,它引用了 Users 表 id。

我一直在尝试完成我的 AccountsController 的添加功能。目前,如果它是不存在的用户,它可以将记录添加到我的 Accounts 表和 Users 表(关联)中。当我尝试将帐户添加到现有用户时出现问题(错误我得到“在主键 [NULL] 的表“帐户”中找不到记录”;有关以下内容的更多信息)。 我有一个用户表的原因是因为它将包含公共用户(通过提供电子邮件订阅;没有帐户)和注册用户(注册用户将有一个帐户)。 我认为出现此问题的原因是电子邮件在 UsersTable(规则)中不是唯一的。

AccountsController

    public function add()
    
        $account = $this->Accounts->newEntity();
        if ($this->request->is('post')) 
            $account = $this->Accounts->patchEntity($account, $this->request->data);
            if ($this->Accounts->save($account)) 
                $this->Flash->success('The account has been saved.');
                return $this->redirect(['action' => 'index']);  
            else 
                $this->Flash->error('The account could not be saved. Please, try again.');
            
       
        $users = $this->Accounts->Users->find('list', ['limit' => 200]);
        $this->set(compact('account', 'users'));
        $this->set('_serialize', ['account']);
    

add.ctp(帐户)

        <?= $this->Form->create($account); ?>
        <fieldset>
            <legend><?= __('Add Account') ?></legend>
            <?php
                echo $this->Form->input('user.name');
                echo $this->Form->input('user.email');
                echo $this->Form->input('password');
                echo $this->Form->input('phonenumber');
                echo $this->Form->input('address');
                echo $this->Form->input('user.postcode');
            ?>
        </fieldset>
        <?= $this->Form->button(__('Submit')) ?>
        <?= $this->Form->end() ?>
    </div>

注意:有关表格中哪些字段的信息,因此我不会详细介绍它们。但是accounts表也会有id和user_id;用户表将具有与 user_id 关联的 id 和用户类型(管理员、客户端或公共)。

我一直在尝试通过使用 user.email 从 Users 表中检索行来解决此问题,但我无法访问它。如果我可以访问它,我应该能够从 Users 表中检索关联的行,从 Users 表中获取 id,然后以某种方式将我的 Accounts 记录的 user_id 设置为该 id。 我曾尝试从表单中请求数据,但它仅适用于与帐户模型相关的输入(至少我认为它是这样工作的)。

我们将不胜感激。请告诉我我的想法是否错误。如果我的问题的答案能以通俗易懂的方式解释,我将不胜感激(不是要求)。

编辑:用户表将包含管理员、拥有注册帐户以购买服务的用户和只想订阅的用户。后者只需要提供比注册用户更少的信息,因此为什么同时存在用户表和帐户表。登录的唯一方法是使用用户表(包含电子邮件)和帐户表(包含密码)。

编辑 2:我基本上想这样做。

AccountsController报错地址(主键约束)

 public function add()
    
        $account = $this->Accounts->newEntity();
        if ($this->request->is('post')) 
            $account = $this->Accounts->patchEntity($account, $this->request->data);
            if ($this->Accounts->save($account)) 
                $this->Flash->success('The account has been saved.');
                return $this->redirect(['action' => 'index']);          
            else 
                $this->Flash->error($this->request->data['address']);
             

        
        $users = $this->Accounts->Users->find('list', ['limit' => 200]);
        $this->set(compact('account', 'users'));
        $this->set('_serialize', ['account']);
    

上述工作并报告输入的地址。

AccountsController 报告错误时的电子邮件(主键约束)

 public function add()
    
        $account = $this->Accounts->newEntity();
        if ($this->request->is('post')) 
            $account = $this->Accounts->patchEntity($account, $this->request->data);
            if ($this->Accounts->save($account)) 
                $this->Flash->success('The account has been saved.');
                return $this->redirect(['action' => 'index']);          
            else 
                $this->Flash->error($this->request->data['user.email']);
             

        
        $users = $this->Accounts->Users->find('list', ['limit' => 200]);
        $this->set(compact('account', 'users'));
        $this->set('_serialize', ['account']);
    

这不起作用并给我错误: 注意(8):未定义索引:user.email [APP/Controller\AccountsController.php, line 68]

我想获取 user.email,这样我就可以在我的用户表中搜索该行并检索它的主键(插入我尝试创建的帐户的 user_id)。

表的sql

 CREATE TABLE users (
          id INT AUTO_INCREMENT PRIMARY KEY,
          name VARCHAR(255),
          email VARCHAR(255),
          postcode VARCHAR(255),
          usertype VARCHAR(20) DEFAULT 'Public',
          created DATETIME,
          updated DATETIME
    );

CREATE TABLE accounts (
      id INT AUTO_INCREMENT PRIMARY KEY,
      user_id INT NOT NULL,
      password VARCHAR(255),
      phonenumber VARCHAR(10),
      address VARCHAR(255),
      created DATETIME,
      updated DATETIME,         
      FOREIGN KEY user_key (user_id) REFERENCES users(id)
);

编辑 3我发现了通过 $account->user->email 从表单(或更准确地说,修补的实体 $account)中检索相关数据的方法。 我正在取得进展,但这是为现有用户(公共)注册帐户的一种非常肮脏的方式。

AccountsController 更新

public function add()
    

        $account = $this->Accounts->newEntity();
        if ($this->request->is(['post', 'patch', 'put'])) 
            $account = $this->Accounts->patchEntity($account, $this->request->data);

            if ($this->Accounts->save($account)) 
                $users = $this->Accounts->Users;
                $query = $users->query();
                $query->update()
                    ->set([
                        'usertype'=>'Client'
                    ])
                    ->where(['email' => $account->user->email])
                    ->execute();
                $this->Flash->success('The account has been saved.');
                return $this->redirect(['action' => 'index']);          

            else 
                $users = $this->Accounts->Users;
                $query = $users->query();
                $usertype = $query->select('usertype')
                    ->where(['email' => $account->user->email]);

                    if(true)
                        $query->update()
                            ->set(['name'=>$account->user->name,
                                'postcode'=>$account->user->postcode,
                                'usertype'=>'Client'
                                ])
                            ->where(['email' => $account->user->email])
                            ->execute();
//everything up to this point works

                        $userid = $query->select('id')
                            ->where(['email' => $account->user->email]);

                        $accounts = $this->Accounts;
                        $query = $accounts->query();
                        $query->insert(['user_id', 'password', 'phonenumber', 'address'])
                            ->values([
                                'user_id' => $userid,
                                'password' => $this->request->data['password'],
                                'phonenumber' => $this->request->data['phonenumber'],
                                'address' => $this->request->data['address']
                            ])
                            ->execute();


                        $this->Flash->success('The account has been saved.');
                        return $this->redirect(['action' => 'index']);          
                    
                    else
                        $this->Flash->error('The account could not be saved.');
                    
             

        
        $users = $this->Accounts->Users->find('list', ['limit' => 200]);
        $this->set(compact('account', 'users'));
        $this->set('_serialize', ['account']);
    

现在的问题是通过查询构建器将 user_id 输入到我的帐户行中。目前,它成功地更改了我的用户的用户类型,但是当我尝试在我的帐户表中插入一行时,我得到了这个。错误:SQLSTATE[21000]:基数违规:1241 操作数应包含 1 列。

另外 sql 错误是这个 -> INSERT INTO accounts (user_id, password, phonenumber, address) VALUES ((SELECT Users.usertype AS Users__usertype, Users.id AS Users__id FROM users Users WHERE (email = : c0 AND 电子邮件 = :c1 AND 电子邮件 = :c2)), :c3, :c4, :c5)

我不知道为什么它试图将两列放在一个字段中。很多帮助表示赞赏。 在写这篇文章时,我意识到有 3 个查询执行到存在电子邮件条件的那一点。似乎查询已加入。

【问题讨论】:

收到错误时,请始终显示完整的错误消息,包括堆栈跟踪!此外,“我无法访问它”不是正确的问题描述,它可能意味着任何事情,如果您尝试过某些事情,那么请将代码添加到您的问题中并解释究竟出了什么问题。顺便说一句,谁在添加这些“帐户”,即“用户”自己?如果是,他们当时是否已经通过身份验证/登录? 用户没有登录。用户唯一可用的功能是添加他们的详细信息以订阅时事通讯。帐户将具有登录功能。说明一下,目前还没有登录功能(待账户添加功能完成后实现)。尝试从我的帐户表单请求用户 (user.email) 数据时出现的错误是 Notice (8): Undefined index: user.email [APP/Controller\AccountsController.php, line 68] 【参考方案1】:

AccountsController 更新 2

公共函数add()

    $account = $this->Accounts->newEntity();
    if ($this->request->is(['post'])) 
        $account = $this->Accounts->patchEntity($account, $this->request->data);
        $users = $this->Accounts->Users;
        $query = $users->find();    
        $query->delete()
            ->where(['email' => $account->user->email])->where(['usertype' => 'Public'])
            ->execute();
        //the above query will delete a user if the email provided matches and their usertype is public
        //subsequently, this code will delete and add a user; not update user. ie. their id will change.    
        if ($this->Accounts->save($account)) 
            $users = $this->Accounts->Users;
            $query = $users->query();
            $query->update()
                ->set([
                    'usertype'=>'Client'
                ])
                ->where(['email' => $account->user->email])
                ->execute();
            $this->Flash->success('The account has been saved.');
            return $this->redirect(['action' => 'index']);          

        else 
            $this->Flash->error('The account could not be saved.');
        
    
    $users = $this->Accounts->Users->find('list', ['limit' => 200]);
    $this->set(compact('account', 'users'));
    $this->set('_serialize', ['account']);

新功能将删除用户类型为“Public”的提供电子邮件的用户;它只会删除 1,因为电子邮件是唯一的。然后它将像默认添加功能一样正常运行,并将新用户(或删除然后添加)的用户类型编辑为“客户端”。

【讨论】:

以上是关于cakephp 3.0 注册与现有用户问题关联的帐户的主要内容,如果未能解决你的问题,请参考以下文章

cakephp 3.0 - 保存独特的关联

在 CakePHP 3 中为文章添加评论

我可以从 cakephp 中的视图重定向吗

Cakephp 3 保存关联属于ToMany

在 CakePHP 3 中保存 belongsToMany 关联

CakePHP 1.3 关联