What prevents me from adding a row with foreign key value? - php

1452 Cannot add or update a child row: a foreign key constraint fails (`bpr`.`trips`, CONSTRAINT `trips_driver_user_id_foreign` FOREIGN KEY (`driver_user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE)
is the error.
Adding a row, manually, through MySQL works fine. If I do it through my application - nope.
The id that I am trying to insert is correct (it exists and is an integer). I checked the foreign keys and stuff, everything looks fine. I don't know what the problem might be...
Some code:
$input = Input::all();
Trip::create([
'route_from' => $input['route_from'],
'route_to' => $input['route_to'],
... adding other stuff ...
'driver_user_id' => Auth::user()->id
]);
When I var_dump(Auth::user()->id) I do get correct int number, which is the correctly corresponding ID of the certain user.
in the Trip model:
protected $hidden = [
'id'
];
protected $fillable = [
'route_from',
'route_to',
...
'driver_user_id'
];
public function Trip()
{
return $this->belongsTo('User', 'driver_user_id', 'id');
}
in the User model:
public function Trips()
{
return $this->hasMany('Trip');
}

I have the gut feeling the attributes are guarded. Your code seems correct, however the error you receive originates from the database. Could you try it like this and see if it works:
$trip = new Trip;
$trip->unguard();
$trip->fill([
'route_from' => $input['route_from'],
'route_to' => $input['route_to'],
... adding other stuff ...
'driver_user_id' => Auth::user()->id
]);
$trip->save();
Using the create method on the model makes it difficult to debug what is happening.

Related

Failing test that record saves to pivot table in laravel

I have a Board model and a Pin model, and they are many to many. I am testing to make sure that when a pin gets created and assigned a board, it saves to the pivot table. I am having trouble figuring this out since I am new to testing.
Here is my Test:
/** #test */
public function a_pin_can_belong_to_a_board()
{
$board = create('App\Board');
$pin = make('App\Pin');
$response = $this->post('/pins/create', $pin->toArray());
$pin->boards()->sync($board);
$this->assertDatabaseHas('board_pin', [
'board_id' => $board->id,
'pin_id' => $pin->id
]);
}
Here is my Error:
1) Tests\Unit\PinTest::a_pin_can_belong_to_a_board
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity
constraint violation: 19 NOT NULL constraint failed: board_pin.pin_id
(SQL: insert into "board_pin" ("board_id", "pin_id") values (1, ))
Caused by
PDOException: SQLSTATE[23000]: Integrity constraint violation: 19 NOT
NULL constraint failed: board_pin.pin_id
Here is my Controller:
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|max:200',
'link' => 'required|max:255'
]);
$pin = new Pin();
$pin->title = $request->title;
$pin->link = $request->link;
$pin->user_id = auth()->id();
$pin->save();
$pin->boards()->sync($request->boards);
return redirect("/pins/{$pin->id}");
}
Any help would be greatly appreciated! Thank you!
Here is the answer! Instead of just using the make method on the pin instance, I used the create method and persisted it to the database, then just removed the post action. See below:
/** #test */
public function a_pin_can_belong_to_a_board()
{
$board = create('App\Board');
$pin = create('App\Pin');
$pin->boards()->sync($board);
$this->assertDatabaseHas('board_pin', [
'board_id' => $board->id,
'pin_id' => $pin->id
]);
}
You should be careful about using sync. I would advise against using it and instead opt for attach. The reason being the following:
You may also use the sync method to construct many-to-many
associations. The sync method accepts an array of IDs to place on the
intermediate table. Any IDs that are not in the given array will be
removed from the intermediate table. So, after this operation is
complete, only the IDs in the given array will exist in the
intermediate table
Documentation see "Syncing associations".
$pin->boards()->attach([$board->id])
Alternatively, although I'm not sure why you would choose this route you can use syncWithoutDetaching which does what one would expect:
If you do not want to detach existing IDs, you may use the
syncWithoutDetaching method
The main issue seems to be that you are using make on your pin but then you do not save it. You are creating an instance by also posting to that endpoint but it is not the same as the instance you have created locally. In your case $pin does not have an ID because it was never saved. There is a separate pin that was created with the same attributes when you did the following:
$this->post('/pins/create', $pin->toArray());
If your response contains the pin's id, you could do something like follows:
$pin_id = $response->getContent()->id;
$pin = Pin::find($pin_id);
$pin->boards()->attach([$board->id]);

Yii2 delete() without primary key

I want to delete a data in database with delete, but the table doesn't have the primary key
Here's the code
Table::findOne(['name' => 'Andrew', 'Age' => '25'])->delete();
Then, it shows the error
app\models\Table does not have a primary key. You should either define a primary key for the corresponding table or override the primaryKey() method.
Help me to find the way to delete without a primary key.
Thanks
You could override primaryKey() model method, so the error should disappear.
Inside app\models\Table add this method (I think that primary key should be composed with 'name' and 'Age'):
public static function primaryKey()
{
return [
'name',
'Age',
];
}
Instead of using ActiveRecord, you could use a delete command with condition:
$myCommand = Yii::$app->db->createCommand()
->delete('your_table', 'name = "Andrew" AND Age = 25 ');
$myCommand->execute();
If you want to delete all the rows that match the condition, you can use:
deleteAll( ... ) ;
Try This :
$data=Table::find()->where(['name' => 'Andrew', 'Age' => '25'])->one();
$data->delete();

Newly created Eloquent object won't return attribute in separate create Eloquent call

The code below shows a method in my Eloquent Link class. After creating a new Link I want to create a related object LinkContact then associate() it with the new Link.
When creating LinkContact I experience an issue in accessing the Link's id attribute. The Link id value appears inaccessible only when performing the create method for the new related object (LinkContact).
Using Laravel Debugbar a line before the create method is called I've logged the Link id and I can see it just fine! Any ideas why this is happening and why I can't access the value?! Is it to do with scope?
Please take note of where the comments are
public function createActiveLink($students)
{
$links = [];
foreach ($students as $student) {
$newLink = $this->create([
'token' => $student->saudi_nid,
'status' => 'active',
'course_title' => $student->course_title,
'university_id' => $student->university_id,
'student_id' => $student->id,
'institution_id' => $student->institution_id,
'course_id' => $student->course_id,
]);
$studentContacts = $student->institutionContacts;
if ($studentContacts) {
foreach ($studentContacts as $studentContact) {
/* I get the value here, no problems */
\Debugbar::info($newLink->id);
$linkContact = $this->contacts()->create([
'type' => $studentContact->pivot->type,
'institution_contact_id' => $studentContact->pivot->institution_contact_id,
/* $newLink->id returns nothing here */
'link_id' => $newLink->id, here!!
]);
$newLink->contacts()->associate($linkContact);
$newLink->save();
}
}
$links[] = $newLink;
}
return $links;
}
The errors I receive when attempting the above code:
SQLSTATE[23000]: Integrity constraint violation: 1048
Column 'link_id' cannot be null
(SQL: insert into `link_contacts`
(`type`, `institution_contact_id`, `link_id`, `updated_at`, `created_at`)
values (1, 1, , 2015-11-24 10:26:32, 2015-11-24 10:26:32))
C:\...\vendor\laravel\framework\src\Illuminate\Database\Connection.php#631
SQLSTATE[23000]: Integrity constraint violation: 1048
Column 'link_id' cannot be null
C:\...\vendor\laravel\framework\src\Illuminate\Database\Connection.php#380
To reiterate I do get the value in Laravel Debugbar but not in the method call after it!
Edit:
In my LinkContact class link_id is in my fillable attributes:
class LinkContact extends Model
{
protected $fillable = ['type', 'link_id', 'institution_contact_id'];
// rest of the class
}
It's worth noting that:
$newLink->contacts()->associate($linkContact);
Would in this instance, run a query like:
UPDATE `link_contacts` SET `link_id` = 1 WHERE `id` = 4;
So if you're setting the link_id in the create, there's no need to run associate. If memory serves you may be able to run $newLink->contacts()->create([...]) instead of both the create() and associate().
Because of the way Eloquent works, a foreign key will always be updated/inserted from running any helper method designed to automatically insert this data but you're manually specifying the key, meaning that it's subject to $fillable so I would take a look at that, and if you don't currently have it in there, add link_id to that array.
Try
$newLink->save();
before calling
$newLink->id
The id is generated only after the data was saved in the database so there's no way of knowing it before that.

Laravel 4 eloquent create doesn't work and fill does

I want to create an instance of model called Property using method create with Input::all() as parameter. Input contains only fillable fields. When using create method laravel raise this exception:
alpha.ERROR: exception 'Illuminate\Database\QueryException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`propathai`.`properties`, CONSTRAINT `properties_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE) (SQL: insert into `properties` (`slug`, `updated_at`, `created_at`) values (, 2014-07-30 10:21:42, 2014-07-30 10:21:42))' in /home/ricardo/CHH/propathai/vendor/laravel/framework/src/Illuminate/Database/Connection.php:555
This exception is happening because insert query is not populated with all input params.
{"bedrooms":"4","title":"ricardo","room_type":"apartment","type":"rent","furnished":"fully_furnished","aging":"new","user_id":"3"}
I tried creating new Property object and using fill() method and it does work.
Code not working
public function store()
{
$input = Input::all();
$input['user_id'] = Auth::user()->id;
$property = Property::create($input);
return Response::json(array('success' => true, 'redirect' => '/dashboard/properties/'.$property->id.'/edit-details'));
}
Code working
public function store()
{
$input = Input::all();
$input['user_id'] = Auth::user()->id;
$property = new Property;
$property->fill($input);
$property->save();
return Response::json(array('success' => true, 'redirect' => '/dashboard/properties/'.$property->id.'/edit-details'));
}
Model
protected $guarded = array('id','services');
protected $fillable = array('user_id','bedrooms','title','room_type','type','furnished','aging');
If anyone knows why it's happening let me know please.
Thanks.
Your slug is not being filled.
SQL: insert into `properties`
(`slug`, `updated_at`, `created_at`) values (, 2014-07-30 10:21:42, 2014-07-30 10:21:42)
It may be one of those:
1- Your slug has a different name attribute on your input form.
2- It's not on your fillable array.
3- It's either empty, null or being filtered.
ex: to filter empty inputs I do:
$input = array_filter(Input::all(),'strlen');
By the way, the way you are doing this is not the nicest of ways. Check this out:
http://laravel.com/docs/eloquent
Click on "one to many"
What it would look like on your app?
Your model User
public function properties(){
return $this->hasMany('Property');
}
Your model Property
public function user(){
return $this->belongsTo('User');
}
On your controller:
$user = Auth::user();
$input = Input::all();
$input['user_id'] = $user->id;
$user->properties()->create($input);
That would be a more 'Laravel' way to approach it.
Also, if you really wanna go PRO watch Laracasts by Jeffrey Way.
It's the best online resource for Laravel4 I've seen online.

Make a Yii Dropdown default value be NULL

I have a dropdown in my Yii form created with CActiveForm->dropDownList.
I am using the array('empty'=>'Please select one') as the way to set the value when nothing is selected.
The field is constrained to another table, but it is set to allow NULL. When Yii shows the MySQL error, it says:
integrity constraint violation: 1452 Cannot add or update a child row: a foreign
key constraint fails (`imi_sales`.`ss_project`, CONSTRAINT
`fk_project_product_type` FOREIGN KEY (`product_type_id`) REFERENCES
`ss_product_type` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
It also shows that the value being inserted into ss_project.product_type_id is ''. If I copy the SQL out and change it to NULL, it works. How can I have Yii set it to NULL?
Add the following codes into beforeSave() method:
public function beforeSave(){
if(parent::beforeSave()){
if(empty($this->product_type_id)) {$this->product_type_id=NULL;}
return true;
}
}
By this, you tell Yii before saving new record, check whether product_type_id value is empty('') or not. If yes, set it NULL.
The selected answer works but I believe this is more elegant.
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
....................
array('product_type_id', 'default', 'setOnEmpty' => true, 'value' => null),
....................
);
}

Categories