I've got a function in my User model (I use Laravel's default User model) that is a relationship with the Player model.
I want to retrieve the id of the Player, but I can't. Is there anyway to do it? I've tried something like:
Auth::user()->players->id;
or
Auth::user()->id->players;
but it doesn't work. Any hints?
That depends on the type of your relationship. From the code you provided I can guess that the relationship is called 'players' and not 'player' (meaning you should have a players() function inside your User model). If this is the case, than your code
Auth::user()->players
returns a collections of players. You can loop through this collection and get IDs of the players:
foreach (Auth::user()->players as $player)
{
$playerId = $player->id;
// Do more stuff for a single player here
}
Hope this clarifies things a little bit. If not, please provide more details about your relationship between User and Player models.
You can also find more details here: http://laravel.com/docs/eloquent#relationships
Related
In relationship 1 -> 1.
(Whereas a person may have only one address)
Assuming I need to get all the people active in the system:
Person::where ('status', 'A') -> get ();
However, I need to get at least one address from each active person in the system, which in the end turns out to be a 1 to 1 relationship, but I will not get a single user, since, in 1 to 1, you would need to give a Fist () or find ().
One way to resolve would be:
Person::where ('status', 'A') -> with ('address') -> get ();
But in this example, where I search for all users, and I need to retrieve the address together (as if it were an inner join), the with method ends up being a good or bad practice?
I think it all depends on what we can agree a best practice is. I've learnt so far that best practices are not always synonim of convenience. And we have a choice to make due with what we've got or refactor/migrate it when possible.
It seems by your example that you are looking for a convenient way to gather certain information and for that we can use Laravel Scopes or some other techniques such as repositories.
class User extends Model
{
public function scopeWithAddress($query)
{
return $query->with('address');
}
public function scopeWithRoleAdmin($query)
{
return $query->withAddress()->where('role', 'admin');
}
}
And use it
$users = User::withRoleAdmin()->get();
Well of course it is always good to use eager loading (with() is used for eager loading).
Also if you just need to get all users that have at least an address. Then you might need to use the has() function.
User::has('yourRelationName')->get()
I have a variable $courses that in my debugger is shown as type App/Courses
In the model, there is a one to many relation and I retrieve these related items in the model and then access as $courses->relateditems
In the debugger, $courses->relateditems is shown as type Illuminate/Database/Eloquent/Collection
Ok, all makes sense.
I want to get last item in the $courses->relateditems collection. So I try
$courses->relateditems->last()->startdate
But this is not returning the value that I know exists. And when I evaluate the expression $courses->relateditems->last() in the debugger I get this in my laravel.log:
Symfony\Component\Debug\Exception\FatalErrorException: Cannot access self:: when no class scope is active in /app/Courses.php:68
I am just not sure what is going on. I know I can use DB queries to just get the data I need, but I have a model event triggering a function and that function receives the $courses object/model (or however we name it) and I am just trying to get this working as above.
Ideas on what I am doing wrong?
thanks,
Brian
The issue here based on the error you have at the bottom of your post is a mistake in your code.
However, I think you've misunderstood how Laravel relationships work. They essentially come in two forms on a model, that of a property and that of a method.
relateditems Is a magic property that will return the result of a simple select on the relationship if one has already been performed. If one hasn't been performed it will perform one and then return it, known as eager loading.
relateditems() Is a method that returns a query builder instance for that relationship.
By calling relateditems->last() you're loading ALL related items from the database and then getting the last, which is less than optimal.
The best thing for you to do is this:
$course->relateditems()->orderBy('id', 'desc')->first();
This will get the first item return, however, since we've ordered it by id in descending order, it'll be reversed from what could be considered its default ordering. Feel free to change the id to whatever you want.
i am implementing a backoffice system with many Models and Relations.
Now im stuck with my UI Stragegy:
Lets assume i have Houses and Rooms. One House has many Rooms.
I have created controllers for both Models the "Laravel" way.(Resource Controllers)
So i have routes for both of them
example.com/backoffice/house
example.com/backoffice/room
What i want to implement sounds simple:
I want an Button inside the Detail View of a House ("Create Room for this House") which redirects me to "room/create" but in the create view i want to set the value for "house_id" to the id of the House i am comming from. So i can normaly use the store method in the RoomController and then redirect back to the house.
I want a general way because i must use this function on many Models/Views. I am thinking about a session variable but i think eventually has someone a better way for generally handling such cases? Or a better idea for UI Handling?
Apparently, Laravel removed some of their awesome documentation for version 5.6, being nested resource controllers.
What you could do, is use nested routes.
Let's assume your current controllers are set up the following way:
Route::resource('houses', 'HouseController');
Route::resource('rooms', 'RoomController');
If you change this part to the following:
Route::resource('houses', 'HouseController');
Route::resource('houses.rooms', 'RoomController');
This couples every room to a house and is really easy to manage. It gives you URL's like houses/4/rooms/create, which gives you a house_id in your create method instantly:
public function create($houseId)
{
return view('houses.rooms.create', ['houseId' => $houseId]);
}
If you want to edit a room, it is exactly the same:
public function edit($houseId, $roomId)
The Laravel 5.1 documentation still has an example of this technique.
To do this, i would suggest the following way (there might be other ways also)
Change Route:
Route::get('room/create/{house_id?},'Controller#action')->name('room.create')
Add <a> tag in house_view.blade.php file.
Create Room for this House
Room Controller file.
public function formCreate($house_id)
{
return view('form.room_create', ['house_id' => $house_id]);
}
Add type hidden <input> tag in room_create.blade.php file
<input type="hidden" id="house_id" name="house_id" value="{{$house_id or ''}}">
I'm facing a situation where a I have to call a function from the controller of a relation instance. For better explanation I will write an example below
I have a Article controller in which I have a preview() function.
A User can have multiple Article.
Let's say that the preview() function parse a text and replace special pieces of text by the user's name.
So my function will looks like this
//In ArticleController
public function preview(Article $article , User $user){
return str_replace("username", $user->name , $article->text);
}
But for a specific situation I want to display a preview of the article when I list all the users
So in UserController
public function index(){
foreach( User::all() as $user){
echo $user->articles[0]->preview( ... );
}
}
Obviously this piece of code will not work.
But I'm more looking of the way to proceed when I face this kind demand.
Should I create a Repository? Use this preview() function somewhere else? Or Is it just a bad practice to do that? What's the best approach or way of thinking when we face this?
Or maybe I'm just missing something important in Laravel's ORM. :/
I assume Article is a model. So you have to add hasMany relation to User (user has many articles). Inside article you have to add preview function. In this case you will be able to find $user->article (or user->articles) and run ->preview function. This is the easiest solution I guess.
You can also add custom attribute like getPreviewAttribute and append it to article model. This way you would have $user->article->preview.
I currently work on a project where the User creates Models, that only he/she is allowed to see, edit or delete.
The Create Part done by Eloquent Relationships, but for the other operations I would like to combine it with Route Model binding and not manually in the controller. I tried solving it with middlewares, but I couldn't access the Ressource.
Can somebody point me to the right Direction, any best Practices are welcome!
Personally I use route model binding, but only allow the model to bind if the user owns the record.
This means that no matter what - people can never access someone elses record. So for example, in my route I can do
$router->get('property/{property}, ['uses' => PropertyController#show]);
Then in my RouteServiceProvider:
$router->bind('property', function($value) {
$property = \App\Property::findOrFail($value);
if ((int)$property->user_id !== (int)auth()->id()) {
abort (404);
}
return $property;
});
So in the example above - we have a property route, and it will try and find the property record given. It will then check that the user owns the record, otherwise it throws a 404 (but you could just redirect or something - up to you).