Can we pass a model to updateOrCreate method of eloquent Laravel? - php

Is there anyway to pass a model to updateOrCreate method of Eloquent laravel? My current code is working fine, in which i am passing array to updateOrCreate method.
$ud = UserDetail::updateOrCreate(
['user_id' => $user->id],
[
'father_name' => $request['fname'], 'dob' => $request['dob'],
'contact_no' => $request['contactNumber'], 'img_url' => $url,
'postal_address' => $request['postalAddress'],
'permanant_address' => $request['permanantAddress'],
'gender' => $request['gender'], 'religion' => $request['religion'],
'marital_status' => $request['maritalStatus'],
'district_id' => $request['district'], 'profile_status' => $status]);
I am using updateOrCreate method multiple times. So i want to create a model once, assign these values to the model, then pass it to updateOrCreate method instead of passing a large array.
//Create model and assign values
$user_d = new UserDetail;
$user_d->father_name = $request['fname'];
$user_d->dob = $request['dob'];
//pass the model to updateOrCreate method
$ud = UserDetail::updateOrCreate(
['user_id' => $user->id], $user_d );

You could use attributesToArray method
//Create model and assign values
$user_d = new UserDetail;
$user_d->father_name = $request['fname'];
$user_d->dob = $request['dob'];
$user_d->save();
//pass the model to updateOrCreate method
$ud = UserDetail::updateOrCreate([
'user_id' => $user->id
], $user_d->attributesToArray());

Related

How to properly update a model on laravel? Method Illuminate\Database\Eloquent\Collection::update does not exist

I made a page for a user to update his company information, all companies default values are null, when a user is created. When a user fills the information, i get this error:
Method Illuminate\Database\Eloquent\Collection::update does not exist
I am sure this error is because of my CompanyController#edit
public function edit(Request $request)
{
$this->validate($request, [
'company_name' => 'alpha|max:50',
'phone' => 'integer|max:50',
'gst_hst_number' => 'integer|max:50',
'country' => 'alpha|max:50',
]);
$companies = Company::where('id', Auth::user()->id)->get();
$companies->update([
'company_name' => $request->input('company_name'),
'phone' => $request->input('phone'),
'gst_hst_number' => $request->input('gst_hst_number'),
'country' => $request->input('country')
]);
return redirect()->route('company.index')->with('info', 'Company information was updated.');
}
I am stuck quite some time on this issue, would gladly apriciate help and information how to properly update my company models fillable fields.
‌As the error message says, you are using the update method on a collection, you have to change the select query to this:
$companies = Company::where('id', Auth::user()->id)->first();
Because the get() method returns a collection, not a single record.
Try this. ->get() is for multiple collections here you can directly update your records.
$companies = Company::where('id', Auth::user()->id)->update([
'company_name' => $request->input('company_name'),
'phone' => $request->input('phone'),
'gst_hst_number' => $request->input('gst_hst_number'),
'country' => $request->input('country')
]);;
Your using update method on collection, but collection doesn't have update method,
what you need is remove the get(), so you can use update method on eloquent builder:
$companies = Company::where('id', Auth::user()->id);
$companies->update([
'company_name' => $request->input('company_name'),
'phone' => $request->input('phone'),
'gst_hst_number' => $request->input('gst_hst_number'),
'country' => $request->input('country')
]);

Trying to understand how to make a UpdateOrCreate

I have a model with the following code:
public static function insertSent($itemId, $currentPackId)
{
$itemHistory = new ItemHistory([
'item_id' => $itemId,
'pack_id' => $currentPackId,
'status' => self::SENT,
'returned_by' => Auth::id()
]);
$itemHistory->save();
}
public static function insertReturned($itemId, $currentPackId)
{
$itemHistory = new ItemHistory([
'item_id' => $itemId,
'pack_id' => $currentPackId,
'status' => self::RETURNED,
'returned_by' => Auth::id()
]);
$itemHistory->save();
}
I just added the insertSent and I want to change the insertReturned to a function where it updates a record if it exists or creates it so UpdateOrCreate.
I'm using laravel php
You can adjust your method to use updateOrCreate pretty easily:
public static function insertReturned($itemId, $currentPackId)
{
ItemHistory::updateOrCreate([
'item_id' => $itemId,
'pack_id' => $currentPackId,
], [
'status' => self::RETURNED,
'returned_by' => Auth::id(),
]);
}
The first array is what you are looking for. If a record is found fill it with the second array and save. If no record is found merge the first and second array and create the new record.
Laravel 6.x Docs - Eloquent - Other Creation MethodsupdateOrCreate

Laravel generate object using model factory with parameter

I have this model factory that generates new contact, it uses random company_id:
$factory->define(App\Models\Contact::class, function (Faker\Generator $faker)
{
$company_id = Company::all()->random()->id;
return [
'firstname' => $faker->firstName,
'lastname' => $faker->lastName,
'phone' => $faker->phoneNumber,
'email' => $faker->email,
'company_id' => $company_id,
'lead_id' => \App\Models\Lead::where('company_id', $company_id)->get()->random()->id,
];
});
It is ok when I use it in seeds:
factory(App\Models\Contact::class)->create();
But for testing I need somehow to pass $company_id to factory, create contact for concrete company_id (I know that I can do ->create(['company_id', $company_id])) but this will rewrite only company_id from Contact.
When I select lead_id, I also need to know current company_id.
How to pass company_id to factory as parameter?
Try to use this example:
$factory->define(App\Models\Contact::class, function ($faker, $params) {
$company_id = $params['company_id'];
....
});
and this to make a new object:
$newContact = factory(App\Models\Contact::class)->make(['company_id' => $current_company_id]);
Depends on your Laravel version it will be different.
For laravel 5.1
https://github.com/laravel/framework/issues/9245
You will need to check if is passed manually
// Testcase
$company = factory(App\Models\Company::class)->create();
factory(App\Models\Contact::class)->create(['company_id' => $company->id]);
// Factory
$factory->define(App\Models\Contact::class, function (Faker\Generator $faker, $attribues) {
// Manually check if id is passed
$company_id = (isset($attribues['company_id'])) ?: Company::all()->random()->id;
return [
'firstname' => $faker->firstName,
'lastname' => $faker->lastName,
'phone' => $faker->phoneNumber,
'email' => $faker->email,
'company_id' => $company_id,
'lead_id' => \App\Models\Lead::where('company_id', $company_id)->get()->random()->id,
];
});
For Laravel 5.2 and above you can simply pass id
https://laravel.com/docs/5.5/database-testing#relationships
// Testcase
$company = factory(App\Models\Company::class)->create();
factory(App\Models\Contact::class)->create(['company_id' => $company->id]);
// Factory
$factory->define(App\Models\Contact::class, function (Faker\Generator $faker, $attribues) {
// Manually check if id is passed
$company_id = (isset($attribues['company_id'])) ?: Company::all()->random()->id;
return [
'firstname' => $faker->firstName,
'lastname' => $faker->lastName,
'phone' => $faker->phoneNumber,
'email' => $faker->email,
'company_id' => function(){
return factory(\App\Models\Company::class)->create()
},
'lead_id' => \App\Models\Lead::where('company_id', $company_id)->get()->random()->id,
];
});
So, for your case, get your random company_id first and pass it to factory. Depends on your Larval version change the ContactModel factory. Or if you have relation that you can query, you can do it as well.
// If you have a relation
$contact = factory(App\Models\Contact::class)->create();
$company_id = $contact->company->id;

Laravel DB table and eloquent method updateOrCreate

DB::table("mytable")->updateOrCreate([
'user_id' => $user_id,
'active' => 1,
'created_at' => Carbon::now()
]);
But this code return me error:
Call to undefined method
Illuminate\Database\Query\Builder::updateOrCreate()
So, according to this answer link (user stanb) I added:
protected $table = 'mytable';
And change code:
DB::table($this->table)->updateOrCreate([...
But still I have this same error
DB::table('table name')
->updateOrInsert(
['email' => 'admin#admin.com', 'name' => 'Admin'],
['id' => '7']
);
I disagree with the other answer, we can use query builder to insert or update.
It's Eloquent method, so you need to use model. Also, you need to pass two arrays as parameters:
Model::updateOrCreate([
'user_id' => $user_id
],
[
'active' => 1,
'created_at' => Carbon::now()
]);
In this example, if there is a record where user_id = $user_id, the record will be updated.

Using Fractal's $defaultIncludes

I am trying to use a $defaultIncludes() and am getting an exception --
ErrorException in ViewoptionTransformer.php line 8:
Argument 1 passed to App\Transformers\ViewoptionTransformer::transform() must be an instance of App\Viewoption, boolean given
Following the tutorial (http://laravelista.com/build-an-api-with-lumen-and-fractal/) except I am using Laravel 5.1 not Lumen:
in User model, I have the hasOne relationship with Viewoption called viewoptions
In the UsersController, I eager load viewoptions
public function index(Manager $fractal, UserTransformer $userTransformer)
{
$records = User::with(['locations', 'viewoptions'])->get();
$collection = new Collection($records, $userTransformer);
$data = $fractal->createData($collection)->toArray();
return $this->respondWithCORS($data);
}
In the UserTransformer, I have the $defaultInclude and the includes method
protected $defaultIncludes = ['viewoptions'];
`public function transform(User $user)
{
return [
'id' => $user->id,
'name' => $user->name,
'is_active' => (boolean)$user->is_active,
'is_admin' => (boolean)$user->is_admin,
'is_manager' => (boolean)$user->is_manager,
'role_id' => (integer) $user->role_id,
'email' => $user->email,
'phone' => $user->phone,
'full_sidebar' => (boolean)$user->full_sidebar
];
}
public function includeViewoptions(User $user)
{
$viewoptions = $user->viewoptions;
return $this->collection($viewoptions, new ViewoptionTransformer);
}`
Have a ViewoptionTransformer
`
use App\Viewoption;
use League\Fractal\Resource\Collection;
use League\Fractal\TransformerAbstract;
class ViewoptionTransformer extends TransformerAbstract {
public function transform(Viewoption $item)
{
//return $item;
return [
'id' => $item->id,
'user_id' => $item->user_id,
'voAgency' => (boolean)$item->voAgency,
'voBalanceDue' => (boolean)$item->voBalanceDue,
'voCloseDate' => (boolean)$item->voCloseDate,
'voCommitTotal' => (boolean)$item->voCommitTotal,
'voDistributor' => (boolean)$item->voDistributor,
'voDueDate' => (boolean)$item->voDueDate,
'voFeePercentage' => (boolean)$item->voFeePercentage,
'voRegion' => (boolean)$item->voRegion,
'voSeason' => (boolean)$item->voSeason,
];
}
}`
Worked with these and slight variations of these throughout the day yesterday and I can't rid myself of that exception.
Not all of your users.id corresponds to some viewoptions.user_id.
Just check it:
$records = User::with(['locations', 'viewoptions'])->get();
dd($records);
some viewoptions will be null or false or just undefined
Instead of using collection use item like so
public function includeViewoptions(User $user){
$viewoptions = $user->viewoptions;
return $this->item($viewoptions, new ViewoptionTransformer);
}`
I had a similar issue today, all my other uses of transformers had been with hasMany relationships. I was always instantiating the transformer with a collection of objects.
However, when using a transformer with a belongsTo relationship and instantiating the transformer with only one object (similar to how you are passing only one object from a hasOne relationship) I would get the same boolean given error.
In the end I solved the issue by using 'item' instead of 'collection' when instantiating the transformer.
Within your includeViewoptions function
Instead of using
return $this->collection($viewoptions, new ViewoptionTransformer);
try
return $this->item($viewoptions, new ViewoptionTransformer);

Categories