framework: firstOrNew/firstOrCreate not working with json data type.

  • Laravel Version: 5.3.28
  • PHP Version: 7.1.0
  • Database Driver & Version: mysql 5.7.11

Description:

firstOrNew/firstOrCreate not working on tables containing json data type fields.

Steps To Reproduce:

Migration:

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Test extends Migration
{
    public function up()
    {
        Schema::create('tests', function (Blueprint $table) {
            $table->increments('id');
            $table->char('title', 50);
            $table->json('lines')->nullable();
        });
    }
    public function down()
    {
        Schema::drop('tests');
    }
}

Model:

namespace App;

use Illuminate\Database\Eloquent\Model;
class Test extends Model
{
    public $timestamps = false;
    protected $casts = [
        'lines' => 'array',
    ];
}

Seeder:

use Illuminate\Database\Seeder;

class TestTableSeeder extends Seeder
{
    public function run()
    {
        \App\Test::firstOrCreate([
            'title' => 'title',
            'lines' => ['line1', 'line2'],
        ]);
    }
}

Running TestTableSeeder multiple times will produce duplicates.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 13
  • Comments: 17 (2 by maintainers)

Most upvoted comments

@ThaDaVos I think I found a better solution for your example (when json field property has a simple value but not array or object as in the initial example of @John-Ciuchea)

Something::firstOrCreate(
    [
        'some_identifier' => 'XXX',
        'some_json->a' => 1
    ],
    [
        'some_json' => [
            'a' => 1
        ]
    ]
);

Tested on Laravel Version 8.x

Unfortunately the same example with array as a value doesn’t seem to be working

Something::firstOrCreate(
    [
        'some_identifier' => 'XXX',
        'some_json->a' => ['line1', 'line2']
    ],
    [
        'some_json' => [
            'a' => ['line1', 'line2']
        ]
    ]
);

im facing this issue as well pls reopen this

I am facing the same issue like this and would like to know if anyone got this problem solved?

Why is this issue closed?

Have the same issue “firstOrCreate” is not able to detect array object and creates a new entry.

Here I want to check if keyword has already been created:

  public function store($data)
  {
      return Keywords::firstOrCreate(
          [
              'name' => $data['name'],
          ],
          [
              'created_by' => $data['created_by'],
          ]
      );
  }
//$data looks like this
array:3 [
  "name" => array:2 [
    "en" => "Italian Pizza 6"
    "de" => "Italienische Pizza 6"
  ]
  "created_by" => 1
]

Workaround for me looks like this:

  public function store($data)
  {
      $query = Keywords::query();

      return ($query->where('name->en', $data['name']['en'])
      ->orWhere('name->de', $data['name']['de'])->first()) ?? $query->create($data);
  }

im facing this issue as well pls reopen this

It’s not about my data structure, it’s about this methods that doesn’t work as expected when we have a json field. I know I should write some tests and create a pull request to report a bug but I’m not familiar with database testing (I know that laravel makes it easy) and I didn’t have much time.