Home > Enterprise >  Laravel model::create function doesn't insert data but doesn't throw any exception
Laravel model::create function doesn't insert data but doesn't throw any exception

Time:06-03

Edit: I tested with dd(), it reaches the function and everything runs correctly but doesn't insert the data.

I have a model named ProductCustomer, I can save this model with ProductCustomer::create() function in tests but I can not create it from the service class with the same method. It's not throwing exceptions while trying to save but doesn't insert the data.

My model

class ProductCustomer extends Model
{
    use HasFactory;
    protected $fillable = [
      'product_id',
      'name',
      'lastname',
      'city',
      'district',
      'address',
      'email',
      'phone'
    ];

    public function product()
    {
        return $this->belongsTo(Product::class);
    }
}

My model's migration.

public function up()
    {
        Schema::create('product_customers', function (Blueprint $table) {
            $table->id();
            $table->string("product_id");
            $table->string("name");
            $table->string("lastname");
            $table->string("city");
            $table->string("district");
            $table->string("address");
            $table->string("email");
            $table->string("phone");
            $table->timestamps();

            $table->foreign('product_id')->references('id')->on('products')
                ->onDelete('cascade');
        });
    }

My insertion test passes.

public function test_insert()
    {
        $product = Product::factory()->create();
        $pc = ProductCustomer::create([
        'product_id' => $product->id,
        'name' => $this->faker->name,
        'lastname' => $this->faker->lastName,
        'city' => $this->faker->city,
        'district' => $this->faker->city,
        'address' => $this->faker->address,
        'email' => $this->faker->email,
        'phone' => $this->faker->phoneNumber,
    ]);

        $this->assertModelExists($pc);
    }

So the mindblowing part is this test can insert the data into the database. But below, there is no exception, no error but no action.

private function insertCustomer($request, $productId)
    {
        try {
            return ProductCustomer::create([
                'product_id' => $productId,
                'name' => $request->name,
                'lastname' => $request->lastname,
                'city' => $request->city,
                'district' => $request->state,
                'address' => $request->address,
                'email' => $request->mail,
                'phone' => $request->phone,
            ]);
        } catch (QueryException $e)
        {
            dd($e);
        }
    }

 public function commitPayment(Request $request, $productId) {
        $this->insertCustomer($request,$productId);
        $response = $this->preparePayment($request,$productId)->save();

        return $this->isPaymentSuccess($response);
    }

You can see $request and $productId below. There is no problem.

     request: Symfony\Component\HttpFoundation\InputBag {#44 ▼
        #parameters: array:9 [▼
          "_token" => "lOI9cI4GQ9OWtciQgAWAQX3b48sw2KqcGmhKqXi2"
          "productId" => "99ef04f9-612f-43f1-a39e-56f94a96edf7"
          "name" => "John"
          "lastname" => "Doe"
          "city" => "Istanbul"
          "state" => "Uskudar"
          "address" => "Test address"
          "mail" => "[email protected]"
          "phone" => " 905555454545"
        ]
      }

^ "99ef04f9-612f-43f1-a39e-56f94a96edf7"

Edit 2: For testing, I added dd() for Product Customer::created event. It was triggered so it means Product Customer::create() works fine. But in the database, there is no record contrary of the test. Here is the dd($model) results.

App\Models\Payment\ProductCustomer {#1534 ▼
  #connection: "mysql"
  #table: "product_customers"
  #primaryKey: "id"
  #keyType: "int"
   incrementing: true
  #with: []
  #withCount: []
   preventsLazyLoading: false
  #perPage: 15
   exists: true
   wasRecentlyCreated: true
  #escapeWhenCastingToString: false
  #attributes: array:11 [▼
    "product_id" => "42d9e84e-7d4c-49c8-8ddf-2327300a3a64"
    "name" => "John"
    "lastname" => "Doe"
    "city" => "HATAY"
    "district" => "HASSA"
    "address" => "test address"
    "email" => "[email protected]"
    "phone" => "4445556677"
    "updated_at" => "2022-06-02 15:51:55"
    "created_at" => "2022-06-02 15:51:55"
    "id" => 12
  ]
  #original: []
  #changes: []
  #casts: []
  #classCastCache: []
  #attributeCastCache: []
  #dates: []
  #dateFormat: null
  #appends: []
  #dispatchesEvents: []
  #observables: []
  #relations: []
  #touches: []
   timestamps: true
  #hidden: []
  #visible: []
  #fillable: array:8 [▼
    0 => "product_id"
    1 => "name"
    2 => "lastname"
    3 => "city"
    4 => "district"
    5 => "address"
    6 => "email"
    7 => "phone"
  ]
  #guarded: array:1 [▼
    0 => "*"
  ]
}

Edit 3: Finally I found the problem. I trailed the non-test case way from route to end. And I noticed I have a DB:prepareCommit command at the start. In the end, everything works fine but I have an event that tries to get ProductCustomer which I tried to create but it wasn't committed yet with DB:commit. So the event is failing because the record doesn't exist and the database rolling back.

CodePudding user response:

Finally I found the problem. I trailed the non-test case way from route to end. And I noticed I have a DB:prepareCommit command at the start. In the end, everything works fine but I have an event that tries to get ProductCustomer which I tried to create but it wasn't committed yet with DB:commit. So the event is failing because the record doesn't exist and the database rolling back.

CodePudding user response:

Try to catch all errors using Throwable. Throwable is the base interface for any object that can be thrown via a throw statement, including Error and Exception.

<?php

try {
// your code
} catch (Throwable $e) {
   echo 'Catch Exception and Error exceptions';
}

A popular mistake is when you expect an error of type A but got an error with type B and can't understand why it doesn't fall into the catch block where you expect an error of type A.

CodePudding user response:

You shouldn't use DB::commit and DB:prepareCommit, better way how to use transaction:

DB::beginTransaction();

try {
    DB::insert(...);
    DB::insert(...);
    DB::insert(...);

    DB::commit();
    // all good
} catch (\Exception $e) {
    DB::rollback();
    // something went wrong
}

See the transaction docs.

  • Related