laravel - why function call with no parentheses?
Asked Answered
F

2

12

I see this in a laravel tutorial :

Auth::user()->item;

where item is a function, inside models\User.php :

function item() { return $this->hasMany('Item', 'owner_id'); }

where Item is for models\Item.php

So why the parentheses is not needed when item function is called ? Like : Auth::user()->item(); If I put the parentheses, the browsers goes crazy and crash.

Also, if I rename Item.php to Item2.php, rename class Item to Item2, and I do hasMany('Item2', 'owner_id'), it won't work. But why ? Where does 'Item' came from ?

Thanks,

Patrick

Fraunhofer answered 22/10, 2014 at 16:17 Comment(1)
Can you give us the context of Auth::user()->item? My preliminary conclusion is that somewhere needs the reference of the function.Riles
B
11

Laravel uses the magic function __get to handle arbitrary attributes.

This calls Illuminate\Database\Eloquent\Model's getAttribute function, which checks the model's relations and returns the related item(s) if a relationship is present with that name.

The parentheses are not needed because getAttribute automatically executes the function items() when the attribute items is requested. You can, by the way, request Auth::user()->item(); which will return a query builder you can work with.

Burlesque answered 22/10, 2014 at 16:23 Comment(9)
But then, why this works : Auth::user()->itemszo; public function itemszo(){ return $this->hasMany('Item', 'owner_id'); } There's nothing 'itemszo' in my app.Fraunhofer
@Fraunhofer When you request the attribute itemszo, it executes the function itemszo(), which does exist. That function creates a relationship with the Item model, which exists too.Burlesque
Then, why if I do Auth::user()->getAuthPassword , without no final (), it won't execute the getAuthPassword() function ?Fraunhofer
@Fraunhofer Because it's not coded that way. The getAttribute function looks for relationships specifically. The source for all this is freely available - github.com/laravel/framework/blob/4.2/src/Illuminate/Database/… - so I suggest you look there for further answers.Burlesque
Thank you ceejayoz! I know understand that while Laravel is looking for an attribute, it is also executing the function with the same name. This function is returning a big object of type "Illuminate\Database\Eloquent\Relations\HasMany". By asking for the attribute, I get what hasMany is specifically meant for : a "Illuminate\Database\Eloquent\Collection" object.Fraunhofer
I really hate all this Laravel magic; makes it hard to follow the flow of the code, and simply makes too many things implicit, and often just to save a couple keystrokes.. (╯°□°)╯︵ ┻━┻Slayton
@Slayton It's well documented, and a few keystrokes a bunch of times adds up. It's popular for a reason.Burlesque
@Burlesque sure, it is documented, that doesn't mean the framework shouldn't be as clear as possible. The programming language "Brainfck" is also documented... And code editors / IDEs already help with the extra typing. I haven't had to manually type a full for-loop in 17 years or more.. so why would saving a parenthesis be worth modifying the obvious behaviour an object's method call?Slayton
@Slayton It's quite clear, and saving a parenthesis isn't why this exists. item and item() in Laravel where item is a relationship do importantly different things.Burlesque
O
2

The method item() is setting up a relationship for the Eloquent ORM on how to prepare a query. calling ->item is telling Eloquent through its Dynamic Properties that you want Item and then Eloquent will use the method. You can only call the method directly if it is compatible with Query Builder. The example you give should work either way but there may be something I am missing.

Oeillade answered 22/10, 2014 at 16:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.