I am using Laravel/Passport and already can get data by id:
api.php/Controller.php
Route::get('members/{member}', 'MemberController#show');
public function show(Member $member)
{
return $member;
}
This just return all data by id, now I want to get member by phone number, so I created:
Route::get('members/{phone}', 'MemberController#phone');
public function phone(Member $member)
{
return $member;
}
Error:
exception:
"Symfony\Component\HttpKernel\Exception\NotFoundHttpException" file:
"C:\Users\xx\xx\xx\xx\vendor\laravel\framework\src\Illuminate\Foundation\Exceptions\Handler.php"
line: 204 message: "No query results for model [App\Member]
2929292222"
route
Route::get('members/{phone}', 'MemberController#phone');
controller
public function phone(Member $member)
{
return $member;
}
Go to Member.php model
and add this method getRouteKeyName
public function getRouteKeyName()
{
return 'phone';
}
Laravel by default it will automatically inject the model instance that has an ID matching the corresponding value from the request URI.
If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model:
for more information check the documentation
Related
Am fetching data with javascript to a yii2 api which i would like to also return model relations.
I have the following
In my user class i have
class User{
//relationship
public function getAuthOptions(){
return $this->hasMany(UserAuthOption::className(),["user_id"=>"id"]);
}
}
Am fetching the data as follows
$users = User::find()->with(['authOptions'])->all();
return $users.
The above returns an array of objects which doesnt contain the authOptions.
I understand that you can access the relationship data via
$users[0]->authOptions
But is there a way the relationship data can be returned on the $users query for javascript api requests which cannot access the $users[0]->authOptions
Currently am able to achieve this by adding a custom field like
class User{
public function fields()
{
$fields = parent::fields();
$fields["authOptions"]=function ($model){
return $model->authOptions;
};
return $fields;
}
public function getAuthOptions(){
return $this->hasMany(UserAuthOption::className(),["user_id"=>"id"]);
}
}
But the above is not optimal because it returns authOptions in all requests but i would like to controll which requests require authOptions to be returned.
class User extends ActiveRecord
{
public function extraFields()
{
return [
'authOptions',
];
}
public function getAuthOptions() {
return $this->hasMany(UserAuthOption::class, ['user_id' => 'id']);
}
}
After that you can use expand param when you need in your API query like this:
/api/controller/action?expand=authOptions
->with(['authOptions']) is not necessary in REST Controller.
Previously i have this code working in laravel 5.2
RouterServiceProvider
public function boot(Router $router)
{
parent::boot($router);
// Model binding
$router->model('house', 'App\house');
}
and in controller
public function show(House '$house')
{
return view('house.show', compact('house'));
}
and when i upgrade to Laravel 5.4 this code doesn't work.
So i change my code to this in RouterServiceProvider
public function boot()
{
//
parent::boot();
Route::model('house', App\House::class);
}
But I dont know what to change in the controller codes below
public function show(House '$house')
{
return view('house.show', compact('house'));
}
, when I run the code I got this error
(1/1) FatalThrowableError
Parse error: syntax error, unexpected ''$house'' (T_CONSTANT_ENCAPSED_STRING), expecting variable (T_VARIABLE)
I need Route Model Binding to simplify my code-> (house = House::FindOrFail($id);)
Thanks for the help!
Change this
public function show(House '$house')
{
return view('house.show', compact('house'));
}
to this
public function show(House $house)
{
return view('house.show', compact('house'));
}
Implicit binding works out of the box:
Implicit Binding
Laravel automatically resolves Eloquent models defined in routes or
controller actions whose type-hinted variable names match a route
segment name. For example:
Route::get('api/users/{user}', function (App\User $user) {
return $user->email;
});
Since the $user variable is type-hinted as the App\User Eloquent
model and the variable name matches the {user} URI segment, Laravel
will automatically inject the model instance that has an ID matching
the corresponding value from the request URI. If a matching model
instance is not found in the database, a 404 HTTP response will
automatically be generated.
But in case you want to declared explicitly, you can check the Explicit Binding of the documentation:
Explicit Binding
To register an explicit binding, use the router's model method to
specify the class for a given parameter. You should define your
explicit model bindings in the boot method of the
RouteServiceProvider class:
public function boot()
{
parent::boot();
Route::model('user', App\User::class);
}
Next, define a route that contains a {user} parameter:
Route::get('profile/{user}', function (App\User $user) {
//
});
Since we have bound all {user} parameters to the App\User model, a
User instance will be injected into the route. So, for example, a
request to profile/1 will inject the User instance from the
database which has an ID of 1.
If a matching model instance is not found in the database, a 404
HTTP response will be automatically generated.
So, in your case:
RouteServiceProvider.php
public function boot()
{
parent::boot();
Route::model('house', App\House::class);
}
Then in your controller:
HousesController.php
public function show(House $house)
{
return view('house.show', compact('house'));
}
I have the following table structure in my database:
products
id
product_formats
id
product_id
product_prices
id
product_format_id
When I'm trying to do $this->format->product; inside my ProductPrice class, I get an error:
LogicException: App\ProductPrice::product must return a relationship instance.
When I perform a dd inside my function:
dd($this->format()->first()->product);
I get the instance of the product. However, removing the dd would still throw the exception.
Why am I getting the LogicException?
ProductPrice
class ProductPrice extends Model
{
public function format()
{
return $this->belongsTo(ProductFormat::class, 'product_format_id');
}
public function product()
{
return $this->format->product;
}
}
ProductFormat
class ProductFormat extends Model
{
public function product()
{
return $this->belongsTo(Product::class);
}
}
Update
The result of dd($this->format); returns an instance of ProductFormat.
After investigating the HasAttributes::getRelationshipFromMethod(), I've noticed that if the property does not exist in the properties attribute of the class, it will try to retrieve a relation, hence the error.
To fix it, I had to add the following to my class:
protected $attributes = ['product'];
Otherwise, I could call product as a function instead of attribute:
$price->product();
Hey i have three table like this
--table plan--
id
name
....
----table letter---
id
plan_id
....
---table person----
id
plan_id
name
.....
Model i have :
---Model plan---
class plan extends Model
{
protected $table = 'plan';
public function letter(){
return $this->hasOne('App\letter');
}
public function person(){
return $this->hasMany('App\person');
}
}
--Model person--
class person extends Model
{
public function plan(){
return $this->belongsTo('App\plan');
}
}
--Model letter--
class letter extends Model
{
public function plan(){
return $this->belongsTo('App\plan');
}
}
And in controller i write code like this :
$letter = letter::find($id) // $id from url parameter and it's work
return view('letter',['letter' => $letter]);
Nah in view i wanna acces person name from letter model as distinct , so i write code like this
{{ #foreach ($letter->plan()->person()->groupBy('name')->get) as $person }}
but it return error like this :
Call to undefined method Illuminate\Database\Query\Builder::person()
Where is my mistake(s)?
There is a difference between $letter->plan() and $letter->plan. If you call it like a method, Laravel will return the Query Builder. If you call it like an attribute Laravel will return the model from that relation.
So you're trying to call your model on the Query Builder, which is a method that doesn't exists and creates the error. This will fix your problem:
$letter->plan->person()->groupBy('name')->get()
In your controller you can do:
$letter = letter::find($id) // $id from url parameter and it's work
$persons = $letter->plan->person()->groupBy('name')->get();
return view('letter', compact('letter', 'persons'));
And in your view:
#foreach($persons as $person)
Hi I'm using Laravel 4 and I have three models, Project (table name projects), Status (tables name: statuses) and AssignedProjectBoardStatus (table name: assigned_project_board_statuses). Now when I create a project statuses are automatically assigned if they are not selected from a list. The assigned_project_board_statuses table has two foreign keys the table schema is below:
id|project_id|status_id|order|created_at|updated_at
project_id and status_id are the foreign keys. Now I have a model as so:
app/models/AssignedProjectBoardStatus.php
class AssignedProjectBoardStatus extends AbstractModel {
public function projects() {
return $this->belongsTo('Project');
}
public function statuses() {
return $this->belongsTo('Status');
}
}
app/models/Project.php
class Project extends AbstractModel
{
public function assignedProjectBoardStatus() {
return $this->hasMany('AssignedProjectBoardStatus');
}
app/models/Status.php
class Status extends AbstractModel {
public function assignedProjectBoardStatus() {
return $this->hasMany('AssignedProjectBoardStatus');
}
There when I am fetching the projects and I want to see the statuses assigned I would call this as follows:
Project::assignedScrumBoardStatuses();
However this throws the following error:
Non-static method Project::assignedProjectBoardStatuses() should not be called statically, assuming $this from incompatible context
So I've changed the function as follows:
app/models/Project.php
class Project extends AbstractModel
{
public **static** function assignedProjectBoardStatus() {
return $this->hasMany('AssignedProjectBoardStatus');
}
However this then threw the following error:
Using $this when not in object context
So i then changed the function as follows:
public **static** function assignedScrumBoardStatuses() {
return **static::**hasMany('AssignedScrumBoardStatus');
}
And this then threw this error:
Non-static method Illuminate\Database\Eloquent\Model::hasMany() should not be called statically
Any ideas what I'm doing wrong and how I can get the assigned statuses from the model??
You can’t call Project::assignedScrumBoardStatuses() because when you do, the Project model doesn’t know which record you’re trying to fetch the assigned scrum board status for. It has no context.
Instead, find a record so you have a model instance, and you can then call your relation methods on that:
$project = Project::find($id)->assignedScrumBoardStatuses();