Abstract a polymorphic 'save' on a model - laravel-4

I have a polymorphic record I want to create.
This works
$user->logs()->create(['message' => 'message', 'failed' => false]);
But how do I convert that to something like this:
$user->logs()->logSuccess('message');
In my logs model class I tried this:
public function scopeLogSuccess($query, $message)
{
$this->create(['message' => $message, 'failed' => false]);
}
But nothing happens. The query runs - but no data is inserted in the database and no error is thrown.
I also tried this:
public function scopeLogSuccess($query, $message)
{
$this->message = $message;
$this->failed = false;
$this->save();
}
A "record" is saved in the Logs table - but it doesnt have the "loggable_id" or "loggable_type" that should be generated on a polymorphic relationship - they are just blank.

You would need to extend the MorphTo class and add your custom methods - I don't see an easy way to achieve this. I would recommend just adding the logSuccess etc method on your user model.

Related

Returning a Modal with relationships after creating in Laravel

I have a modal for example User. The User has relationships to Country and Currency modal as well. I would like to return a JSON object of the User with their relationships. I can achieve that using the code below:
$user = User::create($request->all()); // request contains all the information to create the user
$userDetails = User::with('country', 'currency')->where('id', $user->id)->first();
return json_encode($userDetails);
It works. However, is there a better or more recommended way to achieve this? Thank you for your time.
I found out that creating a new Laravel Resource and using the following approach seems much cleaner:
// in UserResource.php:
public function toArray($request)
{
return [
'id' => $this->id,
'country' => $this->country, // relationship
'currency' => $this->currency // relationship
]
}
// In controller:
return new UserResource($user);
Thanks!

How to queue the logics in controller

I have used two logic in my controller in my laravel project
public function multiStore()
{
$user = User::create([
'name'=>$request->name,
'email'=>$request->email,
'password'=>Hash::make($request->name),
]);
$post = MyPost::create([
'name'=>$request->post_name,
'body'=>$request->post_body,
]);
return redirect()->to('/admin/home);
}
Is it possible to make like if user is created successfully only then the post will be created so that I can use post created by user relationship
I have tried something like if condition but it is not working
You can try the code bellow , I assume you have a user_id field in posts table since you mentio9ned a relation ship. This is not the best way but i try to keep things simple, so I just edited the code.
Note : make sure you listed all the table fields in protected $fillable in your model before using Create()
public function multiStore()
{
$user = User::create([
'name'=>$request->name,
'email'=>$request->email,
'password'=>Hash::make($request->name),
]);
if($user){
$post = MyPost::create([
'user_id' => $user->id
'name'=>$request->post_name,
'body'=>$request->post_body,
]);
}
return redirect()->to('/admin/home);
}
Enclose your query in database transaction
https://laravel.com/docs/5.8/database#database-transactions
Either you can:
DB::transaction(function() {
Model::create();
AnotherModel::create();
});
Or you can use the following to find and catch error...
DB::beginTransaction();
// Your queries here...
// Model::create();
// AnotherModel::create();
DB::commit();

laravel 5.6 Eloquent : eloquent relationship model creation issue

in my controller i create an Eloquent Model Instance passign throug a relation. The model is loaded on controller's __construct, that's why is present a $this->store and not a $store.
public function index()
{
if (is_null($this->store->gallery)) {
$this->store->gallery()->create([
'title' => 'gallery_title,
'description' => 'gallery_description',
]);
}
$gallery = $this->store->gallery;
dd($gallery);
return view('modules.galleries.index', compact('gallery'));
}
Simply if a store's gallery is not present yet, let's create it.
The first time i print out my dd() is ALWAYS null, if i reload the page the dd() show correctly my gallery model.
The things is weird for me, seems like the first time the creation is done but not ready... I can work around but why this code doesn't work the first time?
Help is very appreciate.
Relationship codes: on gallery ....
public function store()
{
return $this->belongsTo(Store::class);
}
on store...
public function gallery()
{
return $this->hasOne(Gallery::class);
}
When using the $this->store->gallery()->create() method, the original method is not hydrated with the new value, you can simply do a
$gallery = $this->store->refresh()->gallery;
OR
$gallery = $this->store->load('gallery')->gallery;
if you want to make your code cleanner you can do that in your Store Model:
public function addGallery($gallery){
$this->gallery()->create($gallery);
return $this->load('gallery')->gallery;
}
And that in your controller:
$gallery = $this->store->addGallery([
'title' => 'gallery_title',
'description' => 'gallery_description',
]);
and voila ! You have your gallery ready to be used :)
It's the lazy load part of Eloquent. basicly, when you tested for it with is_null($this->store->gallery) it sets it to that value.
when you tried to recover it again, it did not do the DB query, it just loaded the value already present (null).
after creation you need to force reload the relation:
$this->store->load('gallery');
or
unset($this->store->gallery);
or
$gallery = $this->store->gallery()->get();

Laravel 5.4 storing mass assignment model and relationship

I'm unsure of the best practice when inserting mass assignment relationships within Laravel 5.4 - I'm new to the framework. The below code is working correctly, however can you tell me is there a way to simply into one line (inserting relationships)?
I've tried to look at 'save()'and 'push()' but it's not working as expected. Would this have an impact if transactions would scale up?
I have a Listing model, with a hasOne relationship:
public function garage()
{
return $this->hasOne('App\Garage', 'post_id');
}
First of all I have some validation, then I use the following to store, which I want to simplify to one one line of code:
public function store(Request $request)
{
// Validation has passed, insert data into database
$listing = Listing::create($request->all());
$listing->Garage()->create($request->all());
}
Also if I wanted to return the data inserted, how would I do this as the following is only returning the Listing model and not the Garage relationship? Yes I know that I wouldn't do this in a real world application.
return \Response::json([
'message' => 'Post Created Succesfully',
'data' => $listing
]);
Any help is muchly appreciated
Method chaining
Your store method looks good. You could chain methods though, if you don't need the listing object itself:
public function store(Request $request)
{
// Validation has passed, insert data into database
$garage = Listing::create($request->all())
->garage()->create($request->all();
}
But if you need the listing object, it's fine as you did it before!
Returning relation models
If you want to return the garage relation model too, you can simply do that by accessing it like a normal class propery:
return \Response::json([
'message' => 'Post Created Succesfully',
'data' => [$listing, $listing->garage]
//Access collection of garage relation ship
]);

How to make shortest code?

I use the following code to insert multi array to database:
foreach($request->category as $k => $v){
$category[] = array(
"category_id" => $v,
"announcement_id" => $announcement->id
);
}
AnnouncementCategory::insert($category);
So, input data is POST array $request->category.
I need to refactoring this code
I tried this code:
$announcement->categories()->attach($request->category);
In model Announcement I have:
public function categories()
{
return $this->hasMany("App\AnnouncementCategory", "announcement_id", "id");
}
If you define in your Announcement model relationship like this:
public function categories()
{
return $this->belongsToMany(AnnouncementCategory::class);
}
you can do it like this:
$announcement->categories()->attach($request->category);
EDIT
I see you updated your question and added categories relationship. But looking at your code, AnnounceCategory is rather pivot table, so you should use belongsToMany as I showed instead of hasMany
You can do it in one line if the request matches the columns:
AnnouncementCategory::insert($request->all());
Then in your AnnouncementCategory model, make sure you declare the protected $fillable array where you specify which field could be populated.

Resources