I've created an observer to complete the user_id when a user adds a new department.
The created method in the DepartmentObserver:
public function created(Department $department)
{
//
if (auth()->check())
{
$department->created_by_user_id = auth()->id();
$department->save();
}
}
The model:
protected $fillable = [
'deptname',
'created_at',
'updated_at',
'deleted_at',
'created_by_user_id'
];
public function user()
{
return $this->belongsTo(User::class,'created_by_user_id');
}
Then registered the obeserver in the AppServiceProvider Class
public function boot()
{
//
Department::observe(DepartmentObserver::class);
}
I get the following error:
SQLSTATE[HY000]: General error: 1364 Field 'created_by_user_id' doesn't have a default value (SQL: insert into departments (deptname, updated_at, created_at)
I think the oberserver is not firing on the create event. I also tried composer dump and php artisan config:cache
and it didn't work. I'm on laravel 8 (Breeze, not Jetstream)
Related
Hello i am trying to make a simple delete function but its showing an error
This is the code from the controller:
public function destroy($id)
{
$clientOrder = ClientHasOrder::where('order_id',$id)->firstOrFail();
$clientOrder->delete();
return redirect('/')->with('msg','Order Deleted successfully!');
}
This is the model code:
class clientHasOrder extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = [
'order_id',
'product_id',
'amount',
];
}
This is the migration file:
public function up()
{
Schema::create('client_has_orders', function (Blueprint $table)
{
$table->string('order_id')->constrained();
$table->foreignId('product_id')->constrained();
$table->string('amount')->default('200');
});
}
And when i click delete button this is the error im getting:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'where clause'
delete from
`client_has_orders`
where
`id` is null
showing this line in red: $clientOrder->delete();
When i change the name of column from order_id to id the code works but i dont want to call it id
try it without firstorfail() because you table dose not have an ID.
public function destroy($id)
{
$clientOrder = ClientHasOrder::where('order_id', $id)->delete();
return redirect('/')->with('msg', 'Order Deleted successfully!');
}
I would like to store the corresponding logged in user when adding a new School data. What I'm trying to do is store the logged in user_id in the schools table, in order to know on who added the school data. I have a users table already, which will establish the relation in the schools table.
My goal is when an admin is logged in, he/she can see all of the School records, otherwise if it's a user, then only fetch the records he/she added. The problem is that I can't figure out on when and where to insert the user_id data during the store request as I'm getting an error "user id field is required". Here's what I've tried so far:
Migration:
class CreateSchoolsTable extends Migration
{
public function up()
{
Schema::create('schools', function (Blueprint $table) {
$table->id();
$table->string('school_name');
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->timestamps();
});
}
}
School Model:
class School extends Model
{
use HasFactory;
protected $fillable = ['school_name', 'user_id'];
public function User() {
return $this->belongsTo(User::class);
}
}
Store Request:
class StoreSchoolRequest extends FormRequest
{
public function rules(): array
{
return [
'school_name' => 'required|string|max:255',
'user_id' => 'required|exists:users,id'
];
}
}
Controller:
class SchoolController extends Controller
{
public function store(StoreSchoolRequest $request) {
$school_data = $request->validated();
$user_id = \Auth::user()->id;
$school_data['user_id'] = $user_id;
School::create($school_data );
return Redirect::route('schools.index');
}
}
Any inputs will be of big help! Thanks.
Laravel has elegant way to bind authenticated user_id. Remove user_id from request class and chaining method. Also setup relationship from User model to School Model
Form Request Class
class StoreSchoolRequest extends FormRequest
{
public function rules(): array
{
return [
'school_name' => 'required|string|max:255',
];
}
}
User Model
protected $fillable = ['school_name', 'user_id'];
...
// new line
public function schools() {
return $this->hasMany(School::class);
}
Your Controller
class SchoolController extends Controller
{
public function store(StoreSchoolRequest $request) {
auth()->user()->schools()->create($request->validated());
return Redirect::route('schools.index');
}
}
UPDATE ANSWER
Since user_id value is school name (based on image link from comment), probably there's something wrong either in User or School model. Here the quick fix
Your Controller
class SchoolController extends Controller
{
public function store(StoreSchoolRequest $request) {
auth()->user()->schools()->create(
array_merge(
$request->validated(),
['user_id' => auth()->id()]
)
);
return Redirect::route('schools.index');
}
}
You can add 'created_by' and 'updated_by' fields to your table. so you can register in these fields when additions or updates are made.
Then you can see who has added or updated from these fields.
class School extends Model
{
use HasFactory;
protected $fillable = ['school_name', 'user_id', 'created_by', 'updated_by'];
public function User() {
return $this->belongsTo(User::class);
}
}
Your controller part is correct but since you get the logged in user, you wont be having user_id in the request. So you should remove the rules about user_id from your StoreSchoolRequest.
class StoreSchoolRequest extends FormRequest
{
public function rules(): array
{
return [
'school_name' => 'required|string|max:255'
];
}
}
Problem is here ..
$school_data = $request->validated();
Since you are using $request->validated()..
You have to safe()->merge user_id into it , here Docs : .
$validated = $request->safe()->merge(['user_id' => Auth::user()->id]);
Then put this $validated into create query , Thanks. –
I have a Recipe and Review model:
class Recipe extends Model
{
use HasFactory;
protected $guarded = ['id'];
public function reviews(): MorphToMany
{
return $this->morphToMany(Review::class, 'reviewable');
}
}
class Review extends Model
{
use HasFactory;
protected $guarded = ['id'];
}
Each has a factory:
class RecipeFactory extends Factory
{
protected $model = Recipe::class;
public function definition()
{
return [
'name' => $this->faker->sentence(5, true),
];
}
}
class ReviewFactory extends Factory
{
protected $model = Review::class;
public function definition()
{
return [
'review' => $this->faker->paragraphs(1, true),
];
}
}
When I try to seed new test records using this:
Recipe::factory()->hasAttached(
Review::factory()
->count(5)
);
I get the SQL error:
SQLSTATE[HY000]: General error: 1364 Field 'reviewable_type' doesn't have a default value
How do I get Laravel to fill in the correct morph reviewable_type and reviewable_id values when seeding the related records?
In my case, I have a program, and a form, the form can be attached to various tables.
When I created my seeder I would grab a program, create a form, and then got the error General error: 1364 Field 'formable_type' doesn't have a default value
I fixed this by updating my migration to use nullableMorphs.
$table->nullableMorphs('formable');
Hope that will help someone.
I have a polymorphic relation in a Laravel application. I want a user of the website to be able to give a rating to both a User model as well as Product model.
I have following models and relations
class Rating extends Model
{
public function ratable()
{
return $this->morphTo();
}
}
class User extends Authenticatable
{
public function ratings()
{
return $this->morphMany('App\Rating', 'ratable');
}
}
class Product extends Model
{
public function ratings()
{
return $this->morphMany('App\Rating', 'ratable');
}
}
and the following database migration:
class CreateRatingsTable extends Migration
{
public function up()
{
Schema::create('ratings', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('ratable_id');
$table->string('ratable_type');
$table->double('rating');
$table->text('comment');
$table->timestamps();
});
}
}
I have defined two routes:
1) Route::post('products/{product}/rating', 'ProductController#setRating')->name('products.rating');
2) Route::post('users/{user}/rating', 'UserController#setRating')->name('users.rating');
I have the following code in the controller (will only show the Product example)
public function setRating(Request $request, Product $product)
{
$rating = new Rating();
$rating->rating = $request->rating;
$rating->comment = $request->comment;
$product->ratings()->save($rating);
}
The above works perfectly and the correct records get inserted in the database depending on whether the Product route or the User route is called.
Now, all the rest of my code is using Laravel Resources, and for consistency reasons, I have also defined a resource for Rating:
class RatingResource extends JsonResource
{
public function toArray($request)
{
return [
'ratable_id' => $this->ratable_id,
'ratable_type' => $this->ratable_type,
'rating' => $this->rating,
'comment' => $this->comment
];
}
}
I'm also changing the ProductController code to use this resource
public function setRating(Request $request, Product $product)
{
return new RatingResource(Rating::create([
'ratable_id' => $product->id,
'ratable_type' => $product,
'rating' => $request->rating,
'comment' => $request->comment,
]));
}
In postman, I'm calling the REST API:
http://{{url}}/api/products/1/rating with body:
rating: 4
comment: "Test"
Yet, I always get following error message
"SQLSTATE[HY000]: General error: 1364 Field 'ratable_id'
doesn't have a default value (SQL: insert into ratings (rating,
comment, updated_at, created_at) values (4, test, 2019-09-07
13:44:22, 2019-09-07 13:44:22))"
I'm not passing the ratable_id and ratable_typeas I'm filling these in already in the controller code.
I somehow need to pass the resource that it's a Productor a UserI'm giving a rating for.
How can I make this work?
The problem probably is that ratable_id is missing from $fillable.
Try $product->ratings()->create([...data...]) so you don't have to set ratable_id and ratable_type yourself:
public function setRating(Request $request, Product $product)
{
return new RatingResource(
$product->ratings()->create([
'rating' => $request->rating,
'comment' => $request->comment,
])
);
}
I have a model
class Foo extends Model
{
protected $fillable = [
'name',
'user_id'
];
}
I would like to set Auth::user()->id by default to user_id column. So I added:
class Foo extends Model
{
protected $fillable = [
'name',
'user_id'
];
public function setUserIdAttribute()
{
$this->attributes['user_id'] = Auth::user()->id;
}
}
And from my controller I'm calling for Foo::create($data) without user_id key.
But it doesn't work as expected. store() gives Integrity constraint violation because of user_id is missing. (User already logged in to achieve create page)
i cannot find official documentation about model-observers for Laravel 5.6. but you can still do it by this code
public static function boot()
{
parent::boot(); // TODO: Change the autogenerated stub
// it will automatically add authenticate user to created_by column of selected model
static::creating(function ($model){
$model->created_by = auth()->user()->id;
});
}
You provide an example where you used accessors.
https://laravel.com/docs/5.1/eloquent-mutators#accessors-and-mutators
From official doc:
The accessor will automatically be called by Eloquent when attempting to retrieve the value of first_name:
If you want to set default value for some attributes you need to use Observers.
<?php
// file app/models/Foo.php
namespace App\Models;
use App\Observers\FooObserver;
class Foo extends Model
{
protected $fillable = [
'name',
'user_id'
];
public static function boot() {
parent::boot();
parent::observe(new FooObserver);
}
}
<?php
// file app/observers/FooObserver.php
namespace App\Observers;
use App\Models\Foo;
class FooObserver {
public function creating(Foo $model) {
$this->user_id = Auth::user()->id;
}
}
About model observers in official doc:
https://laravel.com/docs/5.0/eloquent#model-observers