【问题标题】:Phalcon save() fails silentlyPhalcon save() 静默失败
【发布时间】:2017-05-13 05:22:13
【问题描述】:

我已经尝试了所有我能想到的方法,但无法让 model->save() 方法实际更新数据库中的某些列。我的用户模型如下所示(使用 Phalcon Cashier):

<?php
namespace Vokuro\Models;

use Phalcon\Mvc\Model;
use Phalcon\Validation;
use Phalcon\Cashier\Billable;
use Phalcon\Validation\Validator\Uniqueness;

/**
 * Vokuro\Models\Users
 * All the users registered in the application
 */
class Users extends Model
{

use Billable;

/**
 *
 * @var integer
 */
public $id;

/**
 *
 * @var string
 */
public $name;

/**
 *
 * @var string
 */
public $email;

/**
 *
 * @var string
 */
public $password;

/**
 *
 * @var string
 */
public $mustChangePassword;

/**
 *
 * @var string
 */
public $profilesId;

/**
 *
 * @var string
 */
public $banned;

/**
 *
 * @var string
 */
public $suspended;

/**
 *
 * @var string
 */
public $active;

/**
 *
 * @var string
 */
public $stripe_id;

/**
 *
 * @var string
 */
public $card_brand;

/**
 *
 * @var string
 */
public $card_last_four;

/**
 *
 * @var string
 */
public $trial_ends_at;

/**
 * Before create the user assign a password
 */
public function beforeValidationOnCreate()
{
    if (empty($this->password)) {

        // Generate a plain temporary password
        $tempPassword = preg_replace('/[^a-zA-Z0-9]/', '', base64_encode(openssl_random_pseudo_bytes(12)));

        // The user must change its password in first login
        $this->mustChangePassword = 'Y';

        // Use this password as default
        $this->password = $this->getDI()
            ->getSecurity()
            ->hash($tempPassword);
    } else {
        // The user must not change its password in first login
        $this->mustChangePassword = 'N';
    }

    // The account must be confirmed via e-mail
    // Only require this if emails are turned on in the config, otherwise account is automatically active
    if ($this->getDI()->get('config')->useMail) {
        $this->active = 'N';
    } else {
        $this->active = 'Y';
    }

    // The account is not suspended by default
    $this->suspended = 'N';

    // The account is not banned by default
    $this->banned = 'N';

}

/**
 * Send a confirmation e-mail to the user if the account is not active
 */
public function sendConfirmationEmail()
{
    // Only send the confirmation email if emails are turned on in the config
    if ($this->getDI()->get('config')->useMail) {

        if ($this->active == 'N') {

            $emailConfirmation = new EmailConfirmations();

            $emailConfirmation->usersId = $this->id;

            if ($emailConfirmation->save()) {
                $this->getDI()
                    ->getFlash()
                    ->notice('A confirmation mail has been sent to ' . $this->email);

            }
        }
    }
}

/**
 * Validate that emails are unique across users
 */
public function validation()
{
    $validator = new Validation();

    $validator->add('email', new Uniqueness([
        "message" => "The email is already registered"
    ]));

    return $this->validate($validator);
}

public function subscription()
{
  $users = Users::find();
  $user = $users->getLast();
  $result = $user->newSubscription('main', '2017 Online Individual')->create($this->getTestToken());
  return $result;
}

protected function getTestToken()
{
    return \Stripe\Token::create([
        'card' => [
            'number' => '4242424242424242',
            'exp_month' => 5,
            'exp_year' => 2020,
            'cvc' => '123',
        ],
    ], ['api_key' => 'sk_test_98CUmA7w2JTAp25qVyMZweM9'])->id;
}


public function initialize()
{

    $this->belongsTo('profilesId', __NAMESPACE__ . '\Profiles', 'id', [
        'alias' => 'profile',
        'reusable' => true
    ]);

    $this->hasMany('id', __NAMESPACE__ . '\SuccessLogins', 'usersId', [
        'alias' => 'successLogins',
        'foreignKey' => [
            'message' => 'User cannot be deleted because he/she has activity in the system'
        ]
    ]);

    $this->hasMany('id', __NAMESPACE__ . '\PasswordChanges', 'usersId', [
        'alias' => 'passwordChanges',
        'foreignKey' => [
            'message' => 'User cannot be deleted because he/she has activity in the system'
        ]
    ]);

    $this->hasMany('id', __NAMESPACE__ . '\ResetPasswords', 'usersId', [
        'alias' => 'resetPasswords',
        'foreignKey' => [
            'message' => 'User cannot be deleted because he/she has activity in the system'
        ]
    ]);
}

}

在创建 Stripe 用户/订阅并返回客户 ID (stripe_id)、Last 4 (card_last_four) 等...,这个函数,我想在转发到 IndexController 之前将所有这些保存到 SessionController 中的数据库.

public function subscribeAction($user)
{

  $subscribe = $user->subscription();

  $user->save();

  return $this->dispatcher->forward([
        'controller' => 'index',
        'action' => 'index'
  ]);

用户名、密码等都保存得很好,但我无法更新条带特定的列。除非我运行终端命令来更改它们,否则它们将保持为空。如果我等到创建用户,然后登录并运行类似的东西,我也可以使用 save 成功更新它们:

$user = $this->auth->getUser();

$user->stripe_id = "123";

$user->save();

【问题讨论】:

  • 尝试使用var_dump($user-&gt;save());die; 转储保存结果并查看错误消息的内容
  • 它只是给出一个布尔值 true。
  • 这对我来说有点奇怪。没有异常或错误。它只是没有做它应该做的事情。
  • save() 函数如果失败则返回布尔值false。要获取影响保存数据的 SQL 错误,可以打印getMessages()。如果它总是返回true,这意味着保存是正确的,但是您可能在模型中声明了一些东西,这会阻止保存stripe_id 部分。在尝试保存之前检查您是否已确定设置。

标签: phalcon


【解决方案1】:

试试这样的:

if ($user->save($_POST) === false) {
     $messages = $user->getMessages();

     $errorMsg = '';
     foreach ($messages as $message) {
         $errorMsg . "{$message} <br>";
     }
     $this->flashSession->error("Error: $errorMsg");
}

那么在你看来放

<?php $this->flashSession->output() ?>

【讨论】:

  • 我这样做了,得到“trial_ends_at is required”。因此,我进入并手动将该变量设置为保存之前的当前时间戳。
【解决方案2】:

很难说到底发生了什么,但在我看来,你几乎就像是在一个未提交的数据库事务中。您说在创建帐户时字段正在保存,但在您调用 Billable 特征上的方法作为 Cashier 的一部分之后没有。 save() 方法也返回 true,这意味着 Phalcon 认为记录已保存。我没有在 Cashier 中看到任何明确启动交易的代码,尽管我没有深入研究。

以下是测试我的理论的方法。使用 Phalcon 中的事务系统从隐式切换到显式

use Phalcon\Mvc\Model\Transaction\Manager as TxManager;

然后在你的 subscribeAction 方法中:

public function subscribeAction($user)
{
  $manager = new TxManager();

  // Request a transaction
  $transaction = $manager->get();

  $subscribe = $user->subscription();

  $user->save();

  $transaction->commit();

  return $this->dispatcher->forward([
        'controller' => 'index',
        'action' => 'index'
  ]);
}

事务系统旨在通过确保您在事务期间编写的所有内容在全有或全无的基础上可用,并且在您明确提交之前不可用,从而帮助避免冲突的写入或竞争条件。特别是在处理商务时,这可以帮助您避免让一张桌子说购买了,而另一张桌子在处理它的那一瞬间没有任何付款记录。

This page 有更多关于交易如何与 Phalcon 一起使用的详细信息。

【讨论】:

  • 所以,我实现了这个并转储了提交的结果,这是一个布尔值 TRUE。仍然在数据库中获取 NULL。也许我没有正确初始化模型或其他什么。
  • 您尝试插入的值是否曾添加到 $user 对象中?你说你在数据库中得到空值。在保存之前转储您希望看到的实际值,例如echo $user-&gt;stripe_id。从您的另一篇文章中,我认为您根本没有从数据库中获取任何内容。
  • 这是我运行的:public function subscribeAction($user) { $manager = new TxManager(); // Request a transaction $transaction = $manager-&gt;get(); $subscribe = $user-&gt;subscription(); $dump = $subscribe-&gt;stripe_id; var_dump($dump); $subscribe-&gt;save(); $trans = $transaction-&gt;commit(); exit; return $this-&gt;dispatcher-&gt;forward([ 'controller' =&gt; 'index', 'action' =&gt; 'index' ]); } subscription() 函数返回用户对象。转储给出了正确的值,但在数据库中仍为 NULL。
  • 你连接的是什么数据库?假设使用 Mysql,运行 SHOW CREATE TABLE users 并将结果粘贴到此处。这可能会更深入地了解为什么这不能节省。 (如果您不使用 mysql,请为您的数据库运行等效项)
【解决方案3】:

我也遇到过同样的问题。在对数据库进行一些调整后,问题是我们在同一张表上有两个自动编号字段。

通常第一个是主键。如果我们删除或将第二个自动编号字段更改为正常,那么问题就消失了。

【讨论】:

    【解决方案4】:

    moi jai une seurueux probleme avec save() mais lorsque je capture l'érreur il m'envois un false je ne comprend pas voici mon code initiale

      // Création du membre
             $membre = new Membre();    
              
            $membre->nom = $data['nom'];
            $membre->prenom = $data['prenom'];
            $membre->pseudo = $data['pseudo'];
            $membre->email = $data['email'];
            $membre->mdp = $data['mdp'];
            $membre->email = $data['email'];
            //$membre->civilite = $data['civilite'];
            $membre->ville = $data['ville'];
            $membre->code_postal = $data['code_postal'];
            //$membre->adresse = $data['adresse'];
    
    
           var_dump($membre->save());die;
    

    【讨论】:

    猜你喜欢
    • 2017-06-12
    • 2017-01-10
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-04
    相关资源
    最近更新 更多