public function children()
{
return $this->belongsTo('App\User', 'parent_id', 'id');
}
$item = Item::where([
'status' => '1',
'id' => $id
])->first();
$user = User::where([
id=>Auth::id()
])->with('children')->get()
return view('item.list')->with(compact('item', 'user'));
How can I get item and authenticated user along with children and send it to view in one query or is there any other best practise.
From your code, it looks like Item is not related in any way to the User model. If that is the case, there is likely no reason to try to do this in one query, and likely not efficient or even possible. There could be some relation that I don't know of, but you are probably better off doing the two queries.. One for the $item:
$Item = Item::where([
'status' => '1',
'id' => $id
])->first();
And then one to load the children on the User object. This one is potentially a little different. If you are manually loading the User object for some reason, you can eager load the children:
$user = User::where([
'id' => $someId
])->with('children')->first();
If you are within the auth middleware, you don't need to re-load the user, it is already provided by Laravel. You can just load the children if they are not already there:
$user->load('children');
or, even easier, from your blade page, just call the load on the page:
$user->children();
You have the code correct for sending to your view:
return view('item.list')->with(compact('item', 'user'));
Related
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!
I looking a way to avoid the duplicates in Laravel. For example, I have a table with 2 fields which are name and firstname.
How to manage the duplicates on the Controller? I am newbie...
Here is my function store().
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:25',
'firstname' => 'required|string|max:25'
]);
$exists = Auteur::where('name', $request->get('name'))->where('firstName', $request->get('firstName'))->count();
if (!$exists){
Auteur::create($request->all());
return redirect()->route('auteurs.index')
->with('success', 'save');
}
}
I thank you for your help and your explanations.
If it were one field, you could use validation, or make that field unique and that would take care of it with a little error handling. However, with two fields to have to check against, it might be easiest to check if the element is already in the database and deduplicate from there. So in the store() method:
$exists = Auteur::where('name', $req->get('name'))->where('firstname', $req->get('firstname')->count();
if (!$exists){
// create the new model, now that we know there is no duplicate in the database
Auteur::create($request->all());
}
Just add unique in your validation rule. If you would like to check unique validation each field separately.
$request->validate([
'name' => 'required|unique:auteurs,name|string|max:25',
'firstname' => 'required|unique:auteurs,firstname|string|max:25'
]);
Here I hope the table name is `auteurs`
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();
This is my store method to save a post.
public function store(CreatePostRequest $request)
{
$post = new Post([
'title' => $request['title'],
'content' => Crypt::encrypt($request['content']),
'published_at' => Carbon::now()
]);
$post->user()->associate(Auth::user());
$newPost=Post::create($post->toArray());
$this->syncTags($newPost, $request['tag_list']);
return redirect('posts')->withMessage('Post Saved Successfully !!!');
}
In laracasts tutorial he is just doing a
Article::create($request->all());
I need to do the extra stuff like encrypt, but am i cluttering the method? could it be cleaner?
Do it in the Model. I use the set/get*Attribute() method to change stuff on the fly.
So you could use Article::create($request->all()); then in the model use the fillable array to only autofill what is allowed (such as title, content and published_at).
then use something like (in the model)
function setContentAttribute( $value ){
$this->attributes['content'] = Crypt::encrypt($value);
}
In fact you could also adapt this approach so that the published_at attribute is set to today, or even better use your database to provide now()s time.
I have two tables.
message - id, title, content
user - id, name
I have a pivot table.
message_user - message_id, user_id_sender, user_id_receiver
A message can be sent by 1-0 (sender can be null) users, defined with user_id_sender
A message can be received by 1-N users, defined with user_id_receiver
I am trying to define this in Eloquent.
The only solution I have is:
class Message
public function users()
{
return $this->belongsToMany(
'User',
'message_user',
'user_id_sender',
'user_id_receiver');
}
// Somewhere in the code
$message = $this->messageRepository->store($message);
$message->users()->attach($message->id, array(
'message_id' => $message->id,
'user_id_sender' => $userSender->id,
'user_id_receiver' => $userReceiver->id
));
This is the only solution I could think of, but it feels like a workaround. Is there a proper way to achieve this?
You could put into your Message model this:
public function betweenUsers($sender, $receiver) {
return $this->users()->attach($this->id, [
'message_id' => $this->id,
'user_id_sender' => $sender->id,
'user_id_receiver' => $receiver->id,
]);
}
Then you could somewhere in the code do $message->betweenUsers($userSender, $userReceiver);
I understand it is not a exactly what you wanted, but since you are really uncommon kind of pivot table, this is probably sufficient too.