Inserting with relationships in laravel - php

I am facing a problem in Laravel 5.3 that I looked the docs and also searched web but didn't find anything on it.
I am using Laravel Relationships to join two tables. Now I want the data to be inserted on both the tables at the same time after the user submits a form. The catch in this is the first table is the primary one say "users" and second one "xyz" belongsTo the first table. The table "xyz" contains "users_id" column that connects both the tables. And obviously "users_id" is the "id" column of "users" table.
Now the problem arriving is that I want to insert the data in "users" table (that is easily done) and "xyz" table at the same time. The User::create() function will create the user data easily and it is working also but for inserting the data in "xyz" table I will be needing the "user_id" column data and ID will not be generated until the user is created as ID column has Auto-Increment attribute activated.
Code:
$user = new User;
$inputArry = array('data1' => $request['field1'],
'data2' => $request['field2'],
'data3' => $request['field3'],
);
$user->create($inputArry);
$user->xyz()->create([
'user_id' => $user->id,
'name' => $request['name'],
'about' => $request['desc'],
'tag' => $request['tag'],
]);
Above is the code that I am using for this purpose but it is giving me a error.
Error:
QueryException in Connection.php line 761:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'soft_id' cannot be null (SQL: insert into `xyz` (`user_id`, `name`, `about`, `tag`, `updated_at`, `created_at`) values (, John, I am John, dev, 2016-11-09 21:01:29, 2016-11-09 21:01:29))

One way of inserting related table is using relations as:
$user = User::create($user_inputs);
$xyz = $user->xyz()->create($xyz_inputs);
It will automatically fills the user_id in the xyz table.

If you need insert many items, use createMany or saveMany method.
For example:
$post = App\Post::find(1);
$post->comments()->createMany([
[
'message' => 'A new comment.',
],
[
'message' => 'Another new comment.',
],
]);
In the offical laravel docs:
https://laravel.com/docs/5.6/eloquent-relationships#inserting-and-updating-related-models

You can create them like this instead of saving them on same time...
$id = User::create($input_arr)->id;
Xyz::create([
'user_id' => $id,
...
]);

Related

Laravel 8 unique validation rule doesn't work with user_id

I'm using Laravel 8 and the unique validation rule to ensure that a record remains unique, I'm now trying to extend this so that it's unique per user as well, but when expanding the functionality and using the rule in array form it doesn't seem to validate the user ID and instead gives me a integrity constraint violation.
So I have a table called brands, and this table contains two columns in question: brand and user_id, I need to ensure that when storing a record that the brand is unique against the brand column and that the logged in in user's ID the one making the request, e.g:
Two users can have the same brand, but a single user can't have multiples of the same brand.
$validator = Validator::make($request->all(), [
'brand' => [
'required',
'string',
Rule::unique('brands')->where(function ($query) {
return $query->where('user_id', Auth::id());
})
],
'url' => 'required|string',
'telephone' => 'required|string|min:11|max:11'
]);
I've also tried:
'brand' => 'required|string|unique:brands,brand,user_id,' . Auth::id()
What am I missing?
According to the documentation you have to use the ignore() function:
Rule::unique('users')->ignore($user->id),
on your case:
Rule::unique('brands')->ignore($user->id, 'user_id'),

How can i UPDATE all records using associative array?

I have this table that contains my site settings:
I would want to update all records at once with data that comes from a form.
The data looks like this:
$data = [
"brand" => "bbb"
"mail" => "kontakt#aaa.pl"
"phone" => "111"
"site-name" => "test"
];
Now I would like to update that with key of the associative array and with it value.
I tried:
DB::table('settings')->update($data);
But there is an error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'brand' in 'field list' (SQL: update `settings` set `brand` = bbb, `mail` = kontakt#aaa.pl, `phone` = 111, `site-name` = test)
Obviously it thinks that brand is a column name.
So I transformed the $data to this array:
$data = [
0 => [
"name" => "brand"
"value" => "bbb"
]
1 => [
"name" => "mail"
"value" => "kontakt#aaa.pl"
]
2 => [
"name" => "phone"
"value" => "111"
]
3 => [
"name" => "site-name"
"value" => "test"
]
];
and now the error is:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '0' in 'field list' (SQL: update `settings` set `0` = {"name":"brand","value":"bbb"}, `1` = {"name":"mail","value":"kontakt#aaa.pl"}, `2` = {"name":"phone","value":"111"}, `3` = {"name":"site-name","value":"test"})
So now it thinks that index of each row in array is column name and at this place i have no idea how to do this...
Can anyone help me please?
I came to this solution although i think it looks ugly and there should be a better way to do this, if no better answers will be given i will mark my answer as correct
$data = [
"brand" => "bbb"
"mail" => "kontakt#aaa.pl"
"phone" => "111"
"site-name" => "test"
];
foreach($data as $key=>$d) {
DB::table('settings')->where('name','=',$key)->update(['value' => $d]);
}
Your table looks something like you can only take a set of data and update it with time. Why because there are no foreign key relations.
if that is the case then why not have brand_name, mail, phone and site_name for settings columns,
Your migrations
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->string('brand_name');
$table->string('mail');
$table->string('phone');
$table->string('site_name');
$table->timestamps();
});
}
In your model?
protected $fillable = ['brand_name', 'mail', 'phone', 'site_name'];
or
protected $guarded = [];
In your controller
public function method(Request $request)
{
// You can also abstract this in to a custom request class
$request->validate([
'brand_name' => 'required',
'mail' => 'required',
'phone' => 'required',
'site_name' => 'required',
]);
// Add data if record doesn't exist, update when it does
// To use the validated method on request all needed fields must be required
Settings::updateOrCreate($request->validated())
}
Should in case I was wrong you can still check out Laravel Mass Update
https://laravel.com/docs/8.x/eloquent#mass-updates
Laravel Upserts
https://laravel.com/docs/8.x/eloquent#upserts
You can use upsert to update multiple records
First transform data to add column name using collection
$data=collect($data)->transform(function ($value,$name){
return ["name"=>$name,"value"=>$value];
})->values()->toArray();
and here i used model
Setting::upsert($data,["name"],["value"]);
To understand Upserts
Upsert perform multiple "upserts" in a single query
first argument consists of the values to insert or update
second argument lists the column(s) that uniquely identify records within the associated table.
third and final argument is an array of the columns that should be updated if a matching record already exists in the database.
Also important point
All databases systems except SQL Server require the columns in the
second argument provided to the upsert method to have a "primary" or
"unique" index.
It means in your mysql table settings column name to be unique index or else it will insert as new row
Ref:https://laravel.com/docs/8.x/eloquent#upserts

Is there a common way for updating two joined tables in Laravel?

I'm trying to update two tables in Laravel. But I don't know if you can do this while using an associative array with the help of Object->update($associative-array);
I have made an update sequence in laravel which updates a user and a location in two separate tables with a foreign key in the user table. I tried to update both tables doing update statements with the objects of the tables. I tried this in the following way:
$user->update($attributes);
$user->update($attributes); $location->update($attributes);
But this will only update the user table and skips the location table. The $attributes array contains multiple column data of the table user and location. The array is in order of the first column from the user table to the last column of the location table.
But neither of those tries updated both the tables. They only update user and skips location. As far as I know, is that you can do it this way with an associative array if the array contains the column data in the same order of a table and Laravel does the rest. With only updating the user table it does work, But I want it to work with two tables in the way It works using the update function with the object.
MySQL tables
users:
id
firstname
middlename
lastname
active
email
password
phone
mobile_work
phone_work
gender
position_id
settling_id
location_id
locations:
id
street
house_number
addition
zipcode
city
province
country
public function update(Request $request, User $user, Location $location)
{
$attributes = request()->validate([
'firstname' => 'min:3|max:50',
'middlename' => 'max:50',
'lastname' => 'min:3|max:50',
'active' => 'required',
'email' => 'min:3|max:100',
'gender' => '',
'phone' => 'numeric|min:8',
'mobile_work' => 'numeric|min:8',
'phone_work' => 'numeric|min:8',
'position_id' => '',
'settling_id' => '',
'location_id' => '',
'street' => 'required|min:3',
'house_number' => 'required|numeric',
'addition' => '',
'zipcode' => 'required|min:6|max:7',
'city' => 'required|min:3',
'province' => 'required|min:3',
'country' => '',
]);
$user->update($attributes);
}
If the way I'm trying to do it is impossible, I'd like to hear what the standard approach is in updating two tables within one update sequence.
What you try to do is not quite right. You should try to update the relation as well, and preferably first like
$location->update($locationAttributes);
$user->update($userAttributes);
By the way, it is not quite clear you want to update Location record or you want to associate a new Location to User. If it is latter then you can associate the Location to user like
$user->locations()->attach($locationId);
I made the mistake to not include the locations function from the model User into the update sequence.
User model:
public function locations()
{
return $this->hasOne(Location::class, 'id', 'location_id');
}
I fixed the problem by simply deviding the $attribute array to 2 arrays with their own table column data. I also made a second statement which calls the location function from the model and updates it accordingly.
$user->locations()->update($locationAttributes);
$user->update($attributes);
With $attributes only containing the user information and $locationAttributes only containing the location information.
$locations() refers to the row in the table locations. It knows which row to pick by taking the location_id from the selected user.

Database Relationship - Laravel

I am having issues inserting data into my database tables. I have users table which is has a relation of one to many to school table and region table. That is, users table has foreign keys of school and region tables.
I have created the relations correctly but then when i try to insert values into the database, i get the error.
PS: I have one user(admins) in the user table (the school_id and region_id was inserted accurately) already which i saved through RegisterController. Now, when i sign in with the user(admin) already saved, i want to save other users through the UserController but then i get the error above.
What am i not doing right?. I am only a beginner with database relationship and laravel
General error: 1364 Field 'school_id' and `region_id`doesn't have a default value
meaning the field cannot be empty.
UserController
public function store(UserFormRequest $request)
{
$user = new User(array(
'name' => $request->get('name'),
'email' => $request->get('email'),
'password'=> $request->get('password'),
'phone' => $request->get('phone')
));
$user->save();
}
there are three solutions to your problem.
1
public function store(UserFormRequest $request)
{
$user = new User(array(
'name' => $request->get('name'),
'email' => $request->get('email'),
'password'=> $request->get('password'),
'phone' => $request->get('phone'),
'school_id'=>'you must pass value here',
'region_id'=>'you must pass value here'
));
$user->save();
}
2 Go to phpmyadmin make your school_id,region_id default value NULL. so you are good to go.
MySQL is telling you that those fields can't be empty because they aren't nullable.
To make those fields nullable() in your users migration:
// Your create users table migration
$table->integer('school_id')->nullable();
$table->integer('region_id')->nullable();
(You can add any other properties to these - like index(), unsigned(), or foreign keys, etc.)

Yii Relations with non-Primary keys

I have a mysql table and a mysql view I'm trying to build relations for.
The table(commissions) is as follows:
--commissions--
id(primary Key)
date_added
order_id
salesrep_id
customer_id
commission_total
status
The view(rep_view_customer) is as follows:
--rep_view_customer--
entity_id
email
first_name
last_name
company
I'm trying to relate rep_view_customer to commissions on commissions.customer_id = rep_view_customer.entity_id.
I've tried using the on option:
'rep_view_customer' => array(self::HAS_ONE, 'RepViewCustomer', '', 'on'=>'rep_view_customer.entity_id = t.customer_id')
I also tried setting the primary key for the rep_view_customer model using:
public function primaryKey(){
return 'entity_id';
}
But I always seem to end up with an error similar to:
CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]:
Column not found: 1054 Unknown column 't.customer_id' in 'where
clause'. The SQL statement executed was: SELECT
rep_view_customer.entity_id AS t1_c0,
rep_view_customer.email AS t1_c1,
rep_view_customer.first_name AS t1_c2,
rep_view_customer.last_name AS t1_c3,
rep_view_customer.company AS t1_c4 FROM rep_view_customer
rep_view_customer WHERE (rep_view_customer.entity_id =
t.customer_id)
I'm at my wit's end what to try next
You will have to create a foreign key inside repview_customer to relate to commissions. You won't be able to do it with just a primary key.
I did it this way and it works:
so in the commissions model you put: (it does the relation through itself within the model, then the join output will be the same as the normal relation but with other unique key in commission model)
public function relations()
{
return array(
'commission' => array(self::HAS_ONE, 'Commission', 'entity_id', 'on' => 'commission.customer_id=rep_view_customer.entity_id'),
'rep_view_customer' => array(self::HAS_MANY, 'RepViewCustomer', '', 'through' => 'commission', 'condition' => '...'),
),
}

Categories