加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > PHP > 正文

PHP RedBean存储bean如果不存在的话

发布时间:2020-05-25 09:08:05 所属栏目:PHP 来源:互联网
导读:我有点困惑.我在我的直接邮件服务中主动使用 PHP RedBean作为ORM,我遇到了奇怪的情况 – 我有一个具有唯一键约束的表(即subscriber_id,delivery_id)和两个将数据写入此表的脚本. 有源代码插入或更新表: public static function addOpenPrecedent($nSubscribe

我有点困惑.我在我的直接邮件服务中主动使用 PHP RedBean作为ORM,我遇到了奇怪的情况 – 我有一个具有唯一键约束的表(即subscriber_id,delivery_id)和两个将数据写入此表的脚本.
有源代码插入或更新表:

public static function addOpenPrecedent($nSubscriberId,$nDeliveryId)
{
    $oOpenStatBean = R::findOrDispense('open_stat','delivery_id = :did AND subscriber_id = :sid',array(':did' => $nDeliveryId,':sid' => $nSubscriberId));

    $oOpenStatBean = array_values($oOpenStatBean);
    if (1 !== count($oOpenStatBean)) {
        throw new ModelOpenStatException(
            "Ошибка при обновлении статистики открытий: пара (delivery_id,subscriber_id) не является уникальной: ($nDeliveryId,$nSubscriberId).");
    }

    $oOpenStatBean = $oOpenStatBean[0];
    if (!empty($oOpenStatBean->last_add_dt)) {
        $oOpenStatBean->precedent++;
    } else {
        $oOpenStatBean->delivery_id   = $nDeliveryId;
        $oOpenStatBean->subscriber_id = $nSubscriberId;
    }

    $oOpenStatBean->last_add_dt = time('Y-m-d H:i:s');
    R::store($oOpenStatBean);
}

它从两个脚本中调用.我定期在此表上存在腐败唯一约束问题,因为竞争条件发生.我知道SQL“INSERT on duplicate key update”功能.但是如何才能使用我的ORM获得相同的结果呢?

目前,我知道,如果,Redbean不会发布
INSERT ON DUPLICATE KEY UPDATE

正如上面评论中引用的讨论所表明的那样,Redbean的开发人员认为upsert是一种商业逻辑,会污染ORM的间期.这就是说,如果一个人使用自定义查询编写器或插件来扩展Redbean很可能是可行的.我没有尝试过这个,因为下面的方法很容易实现这种行为而不会弄乱ORM的内部和插件但是,它确实需要您使用事务和模型以及一些额外的查询.

基本上,在调用R :: store()之前,使用R :: transaction()或R :: begin()启动事务.然后在“FUSE”d模型中,使用“update”FUSE方法运行检查重复的查询,并在锁定必要行时检索现有id(即SELECT FOR UPDATE).如果没有返回id,那么你很好,只需让你的常规模型验证(或缺少)继续照常并返回.如果找到了id,只需将$this-> bean-> id设置为返回值,Redbean将UPDATE而不是INSERT.所以,使用这样的模型:

class Model_OpenStat extends RedBean_SimpleModel{
  function update(){
     $sql = 'SELECT * FROM `open_stat` WHERE `delivery_id`=? AND 'subscriber_id'=? LIMIT 1 FOR UPDATE';
     $args = array( $this->bean->deliver_id,$this->bean->subscriber_id );
     $dupRow = R::getRow( $sql,$args );
     if( is_array( $dupRow ) && isset( $dupRow['id'] ) ){
        foreach( $this->bean->getProperties() as $property => $value ){
          #set your criteria here for which fields
          #should be from the one in the database and which should come from this copy
          #this version simply takes all unset values in the current and sets them
          #from the one in the database
          if( !isset( $value ) && isset( $dupRow[$property] ) )
            $this->bean->$property = $dupRow[$property];
        }
        $this->bean->id = $dupId['id']; #set id to the duplicates id
     }
     return true;
  }
}

然后,您将修改R :: store()调用,如下所示:

R::begin();
R::store($oOpenStatBean);
R::commit();

要么

R::transaction( function() use ( $oOpenStatBean ){ R::store( $oOpenStatBean ); } );

该事务将导致“FOR UPDATE”子句锁定找到的行,或者在没有找到行的情况下,锁定新行所在的索引中的位置,以便您不会遇到并发问题.

现在这不会解决一个用户对另一个用户的记录更新,但这是一个完全不同的主题.

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读