Why last id is lost while creating process? - laravel

I have a create method that works fine, but it fails trying to create its relation:
public function create(array $article, string $note)
{
$art = $this->article->create($article);
print($art->id) // this line is for helping me to know if id is successfully generated. It works!
$this->article->note()->create([
'article_id' => $art->id, // the id desapears
'note' => $note
])
}
Console logs:
Integrity constraint violation: 1048 Column 'article_id' cannot be null (SQL: insert into notes (article_id, note, updated_at, created_at) values (?, TESTING, 2019-11-13 13:03:07, 2019-11-13 13:03:07))"

The field article_id is probably not a fillable attribute on the Note model.
You could also create the note like this, without adding article_id as a fillable attribute:
$art->note()->create([
'note' => $note
]);
Also make sure that the relations are defined correctly on the models. If an article can have many notes, there might be something wrong with your definitions, since note is currently singular. If it is a one to one relation everything might be fine.

You need to save your article. $art->save()

Related

Save HasMany and asscoiate BelongsTo in Eloquent

There is following table structure:
Users
HasMany Pages
Pages
BelongsTo User
HasMany Notes
Notes
BelongsTo User
To create a note I do:
$note = new Note([
'page_id': $this->page->id,
'user_id': auth()->id(),
'title': 'Foobar'
]);
$note->save();
Easy. Because of mass assignment vulnerability I want to avoid having foreign keys inside fillable of the note model. The code changes to:
$note = $this->page->notes()->create([
'title': 'Foobar'
]);
$note->user()->associate(auth()->user());
$note->save();
Fuzzy. For this to work I have to make the user_id of note nullable in the migration. This feels wrong because a note should never exist without a user. How would you solve this problem?
You can do this instead:
$note = new Note([
'title' => 'your_title_here' //works if title is in the fillable attributes
]);
$note->page()->associate($this->page);
$note->user()->associate(auth()->user());
$note->save();
Here, you don't need any nullable column and there are no risks about mass assignment.
Another advantage, there is only one database query instead of two when you are doing create first then another save.

OctoberCMS belongsTo relationship saving problem

I have two models:
Brands
Mods
I can display all brands via belongsTo function. Problem is when I try to save same brand two times, I get error duplicated entry.
This belongsTo is causing duplicated entry error when saving to DB two same brands.
Mods.php
public $belongsTo = [
'brand' => [\Slasher\Farming\Models\Brands::class, 'key' => 'id'],
];
This belongsToMany works, and save's data to DB, but is generating checkbox field (I only want to select one brand at one mod enty). I'm using pivot table for this relation.
Mods.php
public $belongsToMany =[
'brand' =>[
'Slasher\Farming\Models\Brands',
'table' => 'slasher_farming_mods_brands',
'order' => 'brand_name'
],
];
BelongsTo example: (Brands are visible and I can save them. But problem is when saving same brand for more than two times).
Error I get when saving with belongsTo.
I tried also creating inverse relationships on Brands model with (belongsTo and belongsToMany), but still getting this error.
What type of relation should I make, to save Brands as dropdown list and to fix this duplicate error?
If you're using a pivot table for your relation, then you should use $belongsToMany. Pivot table is only used for many-to-many relations.
I fixed this problem with changing column in the mods name brand to brand_id and also changing belongsTo relation. I just removed key, and it works like a charm. No need for pivot table here.
Mods.php
public $belongsTo = [
'brand' => ['Slasher\Farming\Models\Brands']
];
"SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '3' for key 'PRIMARY' (SQL: update liam_blog_blogs set id = 3, liam_blog_blogs.updated_at = 2022-07-26 09:30:09 where id = 2)"

Column Shows 'id' Number Instead of Foreign Key Attribute

When using the select2 field/column type in Laravel Backpack, the list view displays the 'id' of the foreign entity instead of the foreign key required (in this case the 'name' of the Session).
Laravel 5.8.4, Backpack 3.4. I asked in GitHub and the response was that my relationships were incorrect in my models. I don't think that's the problem as the name loads in the edit view.
GradeCrudController
$this->crud->addColumn([
'label' => "Session",
'type' => 'select2',
'name' => 'session_id', // the db column for the foreign key
'entity' => 'session', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => "App\Models\Session" // foreign key model
]);
Grade (Model)
public function session()
{
return $this->belongsTo('App\Models\Session');
}
Session (Model)
public function grades()
{
return $this->hasMany('App\Models\Grade');
}
As it's been a few days and nobody has responded, I thought I'd post the answer I came up with. Note that I highly doubt that this is the correct solution, but for my project it will do.
I added a Laravel Observer for the Grade Model. Once a user adds a new record, the observer visits the session table, pulls the name of the session using the key and adds it as a column to the Grades table.
Then in backpack I just display the 'name' column.
There has to be a better way than this... But for now it will do.
I see you're using a "select2" column type. That's not something Backpack provides by default - it only has a "select" column.
Most likely what happened is that Backpack loaded the "text" column, since it couldn't find a "select2" column. Hence, the ID.
Try changing "select2" to "select". It should work for you without any observers/anything else.
I was having a similar issue. I could not get the foreign key attribute to show up no matter what. I finally got it working by doing to following.
Add the foreign key to the belongsTo method. It should be the name of the column in that model that has the ID that is associated with in the belongsTo model.
public function session()
{
return $this->belongsTo('App\Models\Session','name');
}
One other item that I suggest is to make sure all columns that have foreign keys are set to the same data types in the database.

Laravel, Can't update a soft-deleted value

I have this values in my db:
id - name - created_at - updated_at - deleted_at
------------------------------------------------
1 - John - 2018-11-11 - 2018-11-11 - (NULL)
2 - John - 2018-11-11 - 2018-11-11 - 2018-11-11
If I search for "John" with my Datatable (Yajra) I only see the John with id=1 because I'm using softdeletes. My model is this:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class MyModel extends Model
{
use SoftDeletes;
protected $fillable = ['name'];
protected $dates = ['deleted_at'];
}
When I delete (destroy) a registry it puts a date at deleted_at which is correct. But when I want to edit (update) John the Validator is giving me the error that that value is already in use. My update method is this:
public function update(Request $request, $id)
{
$rules = array(
'name' => 'unique:my_table'
);
$validator = Validator::make($request->all(), $rules);
if ($validator->passes()) {
MyModel::find($id)->update($request->input());
return redirect()->route('myroute')->withFlashSuccess('Ok!');
} else {
return redirect()->back()->withInput()->withErrors($validator);
}
}
What I'm doing wrong?
This person has written a blog post that looks like it would solve your problem:
https://wisdmlabs.com/blog/laravel-soft-delete-unique-validations/
I'm not 100% sure you want to do this though as you may later wish to use the restore() method to bring the soft-deleted data back. At which point, you'll have a collision.
The problem has nothing to do with the SoftDeletes, it is a validation issue. The unique validation rule is very special, because in case of an update it needs to know which entry it may ignore when performing the validation. In the background, the rule is performing an SQL query like
IF EXISTS (
SELECT id
FROM my_table
WHERE name = 'some value'
)
SELECT 1
ELSE
SELECT 0
(it may not be the exact query, but similar).
As you can see, the query does not take into account if you perform an update or not. Because your entity already exists, it will return 1 and therefore fail the validation because it thinks that the value under validation is not unique.
But there is actually a way to make the validation work for updates. You simply have to add the id of the existing entity (which is being validated) as third parameter to the validation rule. So your rules should look something like this:
$rules = [
'name' => 'unique:my_table,name,'.$id
];
Please be aware that there is also a second parameter for the unique validation rule - the column of the database table you want to search in.
Edit:
In case the unique constraint does only relate to not deleted entries, meaning that a unique value may be reused if other occurences of the same value are flagged as deleted, then it may be necessary to add an additional where() clause to the unique validation rule. For this, the fourth parameter needs to be set to the identifier column name and then we can add the additional where clauses as pairs of two parameters.
$rules = [
'name' => 'unique:my_table,name,'.$id.',id,deleted_at,NULL'
];
This will add where('deleted_at', 'NULL') (or whereNull('deleted_at')) to the query.

Timestamps (updated_at, created_at) are null in Laravel 5

I have a problem with updated_at, created_at fields in Laravel 5.
Here is my migration:
Schema::create('lots', function (Blueprint $table) {
$table->increments('id');
$table->integer('lot');
$table->integer('is_active');
$table->timestamps();
});
But when I insert some data into this table, updated_at and created_at fields are null. How make them auto-complete with current timestamps?
I insert data like this:
\DB::table('admin_lots')->insert([
'lot' => $request->cycle_lot,
'is_active' => '1',
]);
Thanks.
You have to use the create method instead of the insert method in Laravel.
The create method automatically adds timestamps for created_at and updated_at fields:
// GOOD:
User::create(array(
'name' => 'John'
));
On the contrary, the insert method bypasses Eloquent, (it uses the query builder) and does not update updated_at/created_at columns!
// BAD:
User::insert([
'name' => '[[ test name ]]',
]);
dd(
User::where(['name' => '[[ test name ]]'])->first()->create_date
);
You probably do not use Eloquent when inserting data, in this case you should add timestamps manually.
If you do not want to do this, but you still need filled timestamps, use this hack:
$table->timestamp('created_at')->default(\DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(\DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
Update
Based on your updated code, here's another solution:
\DB::table('admin_lots')->insert([
'lot' => $request->cycle_lot,
'is_active' => '1',
'created_at' = \Carbon\Carbon::now()->toDateTimeString(),
'updated_at' = \Carbon\Carbon::now()->toDateTimeString()
]);
Check if your model has this line.
public $timestamps = false;
If it has, delete it.
When you instert data directly, Laravel won't know about your timestamps.
You can either set the timestamps manually in the insert statement, or switch to using Eloquent models , which handle many things out of the box for you, including timestamps. It's also way easier to maintain than straight queries, where applicable.
Eloquent ORM
You need to use Laravel's awesome Eloquent feature to make timestamps written to the Database automatically...
As by seeing your example the code for eloquent will go something like this:
$lot_inputs = array(
'lot' => $request->cycle_lot,
'is_active' => 1
);
$new_lot = Lot::create($lot_inputs);
Please note that you should have the Model for the table = 'lots' (and it must extend Eloquent) so that you can easily use Eloquent methods and its properties...
It would be great if you use Eloquent ORM as much as possible so that if in future you want to change your DB technology then you won't need to specify the written eloquent queries again (e.g: the conversion of query to different DB languages is automatically done by Eloquent)
Thanks I hope this will help you to resolve your issue..!!

Resources