stigo-rigo's avatar

Can't save information to database via a form in laravel:SQLSTATE[23000]:error

I am really confused. I'm a beginner in laravel 8 and I'm working on a pet registration platform. I want the User to collect his/her pet's info through a form, but when I click on the submit button to save the info to the database, nothing seems to happen(meaning no error). And when I use the tinker command >>> Pet::all();, nothing gets save to the database. I also tried saving the info manually through tinker, but then I get this error: >>> $pet->save(); Illuminate/Database/QueryException with message 'SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: pets.user_id (SQL: insert into "pets" ("nickname", "species", "date_of_birth", "gender", "color", "description", "updated_at", "created_at") values (Tom, Domestic cat, 2012-11-10, male, blue, description, 2020-12-20 05:00:49, 2020-12-20 05:00:49))'

This is the PetsController:

<?php

namespace App\Http\Controllers;

use App\Models\Pet;
use App\Models\User;

class PetsController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }
    
    public function create()
    {
        return view('create');
    }

    public function store()
    {   
        $data = request()->validate([
            'nickname' => 'required',
            'species' => 'required',
            'date_of_birth' => 'required',
            'gender' => 'required',
            'color' => 'required',
            'description' => 'required',
        ]);

        auth()->user()->pets()->create([
            'nickname' => $data['nickname'],
            'species' => $data['species'],
            'date_of_birth' => $data['date_of_birth'],
            'gender' => $data['gender'],
            'color' => $data['color'],
            'description' => $data['description'],
        ]);
       
        return redirect('/');
    }
}

This is the Model for User:

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'username',
        'phone',
        'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function pets()
    {
        return $this->hasMany(Pet::class);
    }

This is model for Pet:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Pet extends Model
{
    protected $guarded= [];
    
    public function user()
    {
        return $this->belongsTo(User::class);
    }

}

This is the form view:

@extends('layouts.app')

@section('content')
<div class="container py-5">
    <form action="/register" method="post">
        @csrf

        <div class="row">
            <div class="col-10">
            
                <div class="row justify-content-center">
                    <h1><strong>Add A Pet</strong></h1>
                </div>

                <div class="form-group row py-4">
                    <label for="nickname" class="col-md-4 col-form-label text-md-right">Nickname</label>
                    <div class="col-md-6">
                        <input id="nickname" type="text" class="form-control @error('nickname') is-invalid @enderror" 
                            name="nickname" 
                            value="{{ old('nickname') }}"
                            placeholder="Enter the name of the animal" 
                            required autocomplete="nickname" autofocus>

                        @error('nickname')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                </div> 

                <div class="form-group row">
                    <label for="species" class="col-md-4 col-form-label text-md-right">Species</label>
                    <div class="col-md-6">
                        <select id="species" class="form-control @error('species') is-invalid @enderror" 
                            name="species"
                            value="{{ old('species') }}"
                            required autocomplete="species" autofocus>
                                <option disabled selected>Select species</option>
                                <option>Dog</option>
                                <option>Domestic cat</option>
                                <option>other</option>
                        </select>

                        @error('species')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                </div>

                <div class="form-group row py-4">
                    <label for="date_of_birth" class="col-md-4 col-form-label text-md-right">Date of birth</label>
                    <div class="col-md-6">
                        <input id="date_of_birth" type="date" class="form-control @error('date_of_birth') is-invalid @enderror" 
                            name="date_of_birth" 
                            value="{{ old('date_of_birth') }}"
                            placeholder="yyyy-mm-dd" 
                            required autocomplete="date_of_birth" autofocus>

                        @error('date_of_birth')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                </div> 

                <div class="form-group row justify-content-center" style="padding-left:108px">
                    <div class="form-group col-md-3">
                        <label for="gender">Gender</label>
                        <select id="species" class="form-control @error('species') is-invalid @enderror" 
                                name="species"
                                value="{{ old('species') }}"
                                required autocomplete="species" autofocus>
                                    <option>Unknown</option>
                                    <option>Male</option>
                                    <option>Female</option>
                        </select>
                        @error('species')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                    <div class="form-group col-md-3">
                        <label for="color">Color</label>
                        <input id="color" type="text" class="form-control @error('color') is-invalid @enderror" 
                            name="color" 
                            value="{{ old('color') }}"
                            placeholder="Select color" 
                            required autocomplete="color" autofocus>
                        @error('color')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                </div>

                <div class="form-group row py-4">
                    <label for="description" class="col-md-4 col-form-label text-md-right">Description</label>
                    <div class="col-md-6">
                        <textarea name="description" id="description" rows="3"
                            class="form-control @error('description') is-invalid @enderror"  
                            value="{{ old('description') }}"
                            placeholder="Enter a description of the animal"></textarea>

                        @error('description')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>
                </div> 
                <div class="row col-md-6" style="margin-left:300px">
                    <button class="btn btn-primary btn-lg btn-block">Finish</button>
                </div>
                <div class="row col-md-6 py-4" style="margin-left:430px">
                    <a href="#"><u><h4>Add Pet Later</h4></u></a>
                </div>

            </div>
        </div>
    </form>
</div>
@endsection

This is the Routes file:

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();


Route::get('/register/create', [App\Http\Controllers\PetsController::class, 'create']);
Route::post('/register', [App\Http\Controllers\PetsController::class, 'store']);

Route::get('/profile/{user}', [App\Http\Controllers\ProfilesController::class, 'index'])->name('profile.show');

And finally the migrations for pets table:

<?php

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

class CreatePetsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('pets', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->string('nickname');
            $table->string('species');
            $table->date('date_of_birth');
            $table->string('gender');
            $table->string('color')->nullable();
            $table->text('description')->nullable();
            $table->timestamps();

            $table->index('user_id');


            
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('pets');
    }
}

I'm confused and I've been struggling for quite a while now!

0 likes
43 replies
Maria30's avatar

You need to send the user_id also when submitting the form

MarianoMoreyra's avatar

Hi @stigo-rigo

You have your auth routes before the ones that you are trying to use:

Auth::routes();

And that line already declares a POST route with the same /register url for user registration.

So, try changing your route for pets registration to something else (remember to change it at the blade view too) and see if that works!

Hope this helps!

stigo-rigo's avatar

Thanks @marianomoreyra for your reply

I've changed the route to /r and in the blade view too, but its still returning the same thing.

MarianoMoreyra's avatar

You mean you are still getting a white page? No redirection to you home '/' url neither any errors on log?

MarianoMoreyra's avatar

So in this case goes back to '/register/create' and renders it's content without showing any validation errors for any field?

Or it goes back to that url but with a white page?

MarianoMoreyra's avatar

Please, do a

dd(request());

on the first line of your store() method, before your validation, to see if you are getting to that method, and what are you getting at the request

MarianoMoreyra's avatar

I think here is your problem:

                    <div class="form-group col-md-3">
                        <label for="gender">Gender</label>
                        <select id="species" class="form-control @error('species') is-invalid @enderror" 
                                name="species"
                                value="{{ old('species') }}"
                                required autocomplete="species" autofocus>
                                    <option>Unknown</option>
                                    <option>Male</option>
                                    <option>Female</option>
                        </select>
                        @error('species')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>

You are using 'species' again as the name of the select control, instead of 'gender', so you are probably getting a validation error saying that the gender is required, but is not showing because you don't have and @error('gender') anywhere to render that error.

1 like
stigo-rigo's avatar

This is what I get:

Illuminate\Http\Request {#43 ▼
  #json: null
  #convertedFiles: null
  #userResolver: Closure($guard = null) {#250 ▶}
  #routeResolver: Closure() {#259 ▶}
  +attributes: Symfony\Component\HttpFoundation\ParameterBag {#45 ▶}
  +request: Symfony\Component\HttpFoundation\ParameterBag {#44 ▶}
  +query: Symfony\Component\HttpFoundation\InputBag {#51 ▶}
  +server: Symfony\Component\HttpFoundation\ServerBag {#47 ▶}
  +files: Symfony\Component\HttpFoundation\FileBag {#48 ▶}
  +cookies: Symfony\Component\HttpFoundation\InputBag {#46 ▶}
  +headers: Symfony\Component\HttpFoundation\HeaderBag {#49 ▶}
  #content: null
  #languages: null
  #charsets: null
  #encodings: null
  #acceptableContentTypes: null
  #pathInfo: "/r"
  #requestUri: "/r"
  #baseUrl: ""
  #basePath: null
  #method: "POST"
  #format: null
  #session: Illuminate\Session\Store {#290 ▶}
  #locale: null
  #defaultLocale: "en"
  -preferredFormat: null
  -isHostValid: true
  -isForwardedValid: true
  -isSafeContentPreferred: null
  basePath: ""
  format: "html"
}
MarianoMoreyra's avatar

Just in case you didn't get to see it, check my last reply before yours, I'm almost sure that's your problem now, after fixing your routes problem

1 like
stigo-rigo's avatar

😞Still redirecting to the same page. I that was it too...

MarianoMoreyra's avatar

That's something different then! That's a third problem!

On which line is throwing that error? Please, rollback any changes you may had on your store() method.

It should work as it originally was.

stigo-rigo's avatar

I didn't change anything in my store() method. The error is at line 42 auth()->user()->pets()->create([

stigo-rigo's avatar

@maracaibo I did! Its given the following error: "Call to undefined function App\Http\Controllers\pets()"

Maria30's avatar

which one ? there are two versions of function store()

stigo-rigo's avatar

The second one. The first one is giving this error:"Class 'App\Http\Controllers\Auth' not found"

Maria30's avatar

Add on the top of your file where other use .... are


use Illuminate\Support\Facades\Auth;

and try again the first method

1 like
stigo-rigo's avatar

I did it that and it is giving the same : "Call to a member function pets() on null" error

Maria30's avatar

please do

public function store()
    {   
       dd(auth()->user()->pets());


$data = request()->validate([
            'nickname' => 'required',
            'species' => 'required',
            'date_of_birth' => 'required',
            'gender' => 'required',
            'color' => 'required',
            'description' => 'required',
        ]);

$pet = new Pet();

        pets()->user()->create($data);
       
        return redirect('/');
    }
MarianoMoreyra's avatar

Are you using any third-party package for Authentication by any chance?

MarianoMoreyra's avatar
Level 25

And what has changed since you were just getting back to the create page, without errors, to start getting this current error?

I see you have this at your controller:

    public function __construct()
    {
        $this->middleware('auth');
    }

So I assume you are logged in otherwise you shouldn't be having the chance to submit that form at all...

1 like
Maria30's avatar

@stigo-rigo You know what?

you have $data = request()->validate([.... but you dont pass the request....

so


public function store(Request $request)
    {   
     


$data = request()->validate([
            'nickname' => 'required',
            'species' => 'required',
            'date_of_birth' => 'required',
            'gender' => 'required',
            'color' => 'required',
            'description' => 'required',
        ]);



        auth()->user()->pets()->create($data);
       
        return redirect('/');
    }
1 like
stigo-rigo's avatar

@marianomoreyra See thats my fault! I removed auth middleware without realizing it. I added it, and its now perfectly working!

You are a life saver. Thank you very much!

1 like
MarianoMoreyra's avatar

Great!! I'm glad it's working!!

As I said before, it had to work as you've originally posted but I was going crazy about auth()->user() being null after seeing you had the middleware!

Anyway, I'm glad I asked hehe

Now I can finally go to sleep :)

1 like
stigo-rigo's avatar

I mistakenly removed the

public function __construct()
{
	$this->middleware('auth');
}

from my petsController.

It is now working perfectly fine.

Thank you very much @maracaibo God bless you...

1 like
stigo-rigo's avatar

You're the best! Have a good sleep..

Thank you so much once again!

Maria30's avatar

You can try passing the User to store method

public function store(User $user)

And also change the "register" to something else

MarianoMoreyra's avatar

Hi @maracaibo,

Actually, I believe the user_id error happens only on tinker because probably he must be calling the save() method directly on a Pet object, in which case it doesn't have a user associated.

But in the controller he's actually doing:

auth()->user()->pets()->create()

In which case, the user_id should be automatically provided to the create method because of the relationship.

Maria30's avatar

Yes you are right, I saw later the way he saves the data

What I'm thinking is maybe he needs pets()->user() to have the user_id.

Maria30's avatar

Do a dd(auth()->user()->pets());

after validation to see what you get

Maria30's avatar

run php artisan view:clear and try again

Maria30's avatar

@stigo-rigo

As @marianomoreyra mentioned you have to fix your form and try the functions below.

As you can see I have added $pet = new Pet();



 

public function store()
    {   
        $data = request()->validate([
            'nickname' => 'required',
            'species' => 'required',
            'date_of_birth' => 'required',
            'gender' => 'required',
            'color' => 'required',
            'description' => 'required',
        ]);

$pet = new Pet();

        Auth::user()->pets()->create($data);
       
        return redirect('/');
    }

Or

public function store()
    {   
        $data = request()->validate([
            'nickname' => 'required',
            'species' => 'required',
            'date_of_birth' => 'required',
            'gender' => 'required',
            'color' => 'required',
            'description' => 'required',
        ]);

$pet = new Pet();

        pets()->user()->create($data);
       
        return redirect('/');
    }
MarianoMoreyra's avatar

Just in case, because this thread is getting really big really quickly, I'll repeat this message here too:

I think here is your problem:

                    <div class="form-group col-md-3">
                        <label for="gender">Gender</label>
                        <select id="species" class="form-control @error('species') is-invalid @enderror" 
                                name="species"
                                value="{{ old('species') }}"
                                required autocomplete="species" autofocus>
                                    <option>Unknown</option>
                                    <option>Male</option>
                                    <option>Female</option>
                        </select>
                        @error('species')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>

You are using 'species' again as the name of the select control, instead of 'gender', so you are probably getting a validation error saying that the gender is required, but is not showing because you don't have and @error('gender') anywhere to render that error.

EDIT:

This is how it should be:

                    <div class="form-group col-md-3">
                        <label for="gender">Gender</label>
                        <select id="gender" class="form-control @error('gender') is-invalid @enderror" 
                                name="gender"
                                value="{{ old('gender') }}"
                                required autocomplete="gender" autofocus>
                                    <option>Unknown</option>
                                    <option>Male</option>
                                    <option>Female</option>
                        </select>
                        @error('gender')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                        @enderror
                    </div>

Hope this finally works now! :)

1 like
MarianoMoreyra's avatar

So, you've applied the code with all the changes I've provided and you still get redirected with no validation message showing anywhere?

That's weird

MarianoMoreyra's avatar

Please add this just below the @section('content') line, so you should end up with:

@section('content')
@if ($errors->any())
<div class="alert alert-danger">
  <ul>
      @foreach ($errors->all() as $error)
        <li>{{ $error }}</li>
      @endforeach
  </ul>
</div><br />
@endif

That should show ANY validation errors on top of that view

Please or to participate in this conversation.