Laravel 5 firstOrCreate 保持创建甚至设置唯一的字段

Posted

技术标签:

【中文标题】Laravel 5 firstOrCreate 保持创建甚至设置唯一的字段【英文标题】:Laravel 5 firstOrCreate keep create even set unique to the field 【发布时间】:2015-08-09 04:05:04 【问题描述】:

下面是我的应用\Cart.php

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Cart extends Model 
    use SoftDeletes;
    protected $table = 'cart';
    protected $fillable = ['sess','uid'];

下面是我的应用\Http\Controllers\CartController.php

public function cart($id=0, $act, Request $request)
    
        $sessId = Session::getId();
        switch($act)
            case 'Add':
                $quantity = $request->only('p_quantity');
                $data = $request->except('p_quantity');
                $cartId =  Cart::firstOrCreate(['sess' => $sessId,'status' => 1]);
            break;

            case 'Delete':

            break;
        

        return response()->json(['success' => true,'message' => 'Success', 'act' => $act, 'id' => $id ,'data' => $data, 'quantity'=> $quantity, 'cart'=>$cartId->id]);
    

如果会话密钥存在于表 cart.sess 中,我想要检查数据库,否则创建新的并获取 id。

问题是,当它不断为数据库创建新的重复会话时。

我可以知道我哪里做错了吗?

谢谢

更新 [2015-05-27 16:02]: 在我 TRUNCATE 表并将 sess 字段设置为 Unique 后,第一次提交它看起来没问题,当第二次提交时显示以下错误:

更新 [2015-05-27 16:16] 我用来创建数据库的代码:

CREATE TABLE IF NOT EXISTS `cart` (
  `id` int(11) NOT NULL,
  `uid` int(11) DEFAULT NULL,
  `sess` varchar(40) NOT NULL,
  `status` int(11) DEFAULT '1',
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `deleted_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

【问题讨论】:

因为它是你自己的会话 ID,除非你的会话发生变化,否则它不会改变 @user1578359 你可以执行以下 Cart::whereSess($sessId)->whereStatus(1)->firstOrCreate() 并告诉我们这是否有效。 +shaddy 在这里放了一个 arg,让你的 'sess' 列也独一无二。 【参考方案1】:

我解决了这个问题。 在哪里 因为在我的模态中我使用了 SoftDeletes; 如何解决 它不能在此字段内具有默认值, 但是我将其设置为 Default 0000-00-00 00:00:00 ,默认情况下将其设置为 null 。

CREATE TABLE IF NOT EXISTS `cart` (
  `id` int(11) NOT NULL,
  `uid` int(11) DEFAULT NULL,
  `sess` varchar(40) NOT NULL,
  `status` int(11) DEFAULT '1',
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',

deleted_attimestamp NOT NULL DEFAULT '0000-00-00 00:00:00'

) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

deleted_at时间戳

为什么 firstOrCreate 做了这个查询(检查下面的图片)

上面的插件是:https://github.com/barryvdh/laravel-debugbar谁需要它。

谢谢

【讨论】:

【参考方案2】:

在您创建此购物车表的数据库架构中,sess 列应该是唯一的,但事实并非如此。你应该改变它,让它变得独一无二:

$table->unique('sess');

在此之前不要忘记删除所有记录,否则会出错。

编辑在您发布表架构后,我发现了问题

sess varchar(40) NOT NULL

您必须将sess 的长度设置为至少 255 个字符或会话 ID 的大小,因为您的会话 ID 超过 40 个符号。 Laravel 尝试查找包含 64 个字符(或会话 id 长度)的字符串,例如:

8a9f119eaea027def7268d12e4e4d680

但没有,所以它会尝试插入新的。由于您的列长度为 40,因此 sess id 被截断为 40 个符号:

8a9f119eaea

在下一次检查中它不会匹配,因为它正在搜索8a9f119eaea027def7268d12e4e4d680,但在您的数据库中您得到了8a9f119eaea

【讨论】:

您好,感谢您的回答,但是当我将字段更改为唯一时,它会显示重复错误。我更新了我的问题。 @user1578359 您能否在问题中发布您创建此表的代码(数据库模式),以便我可以尝试重现您的问题? 嗨,@shaddy 我使用 mysql 代码手动创建数据库。更新为问题。 我找到了问题,请看我编辑的答案:) 嗨@shaddy,在我截断并将varchar更改为255并尝试更改为文本后,问题仍然存在重复错误。还是我的 firstOrCreate() 函数有什么问题?

以上是关于Laravel 5 firstOrCreate 保持创建甚至设置唯一的字段的主要内容,如果未能解决你的问题,请参考以下文章

laravel中firstOrCreate的使用

在 Laravel 中,有没有办法找出是不是创建了 `firstOrCreate` 或者是不是找到了行?

Laravel 8 - firstOrCreate() 不返回数据库中设置的默认值

laravel中firstorcreate和updateorcreate的操作区分

Laravel firstOrNew 与 firstOrCreate 的区别

Laravel FirstOrCreate和Save()重复输入