Laravel Model Binding - laravel

I have issue with model binding in routes and controller. Here is my routes:
Route::group(['prefix'=>'services/devops/domain-names'], function () {
Route::group(['middleware'=>'auth'], function () {
Route::get('/editAutoRenew/{domainname}', 'EnomController#editAutoRenew');
});
Route::post('/', 'EnomController#checkDomainName');
});
And here is function
public function editAutoRenew(DomainName $domainname)
{
dd($domainname);
}
But this gives me empty model. Why? How can I get my model?
I tried to route:list and there it shows {domainname}

You get in argument integer type, not object. Try to rewrite your function with:
public function editAutoRenew($domainname)
{
$domainnameObj = DomainName::findOrFail($domainname);
}
When you use:
DomainName::first();
You get all entries from your table domain_name, then command first() - get first of this records.

Related

Doesn't work route model binding in laravel 8

My route:
Route::get('/users/{user}', function(App\Models\User $user) {
dd($user);
});
where {user} - id of model. A user with this name is in the database.
I check so:
Route::put('/users/{user}', function(int $id) {
dd(App\Models\User::find($id)->toArray());
});
I tried to bind in RouteServiceProvider:
Route::bind('user', function ($value) {
return App\Models\User::where('id', $value)->firstOrFail();
});
UPDATE
When binding, I get an empty instance
What could be the problem?
its been awhile, if anyone still need it try route:clear

Inconsistency with 'show' function

I've been working on a project for a few months now and I feel like I am seeing some inconsistency with how the public function show is working
I have a model and controller for a Location that has
public function show(Location $Location)
{
$Loc = Location::with('company:id,name')->findOrFail($Location);
return response()->json($Loc,200);
}
and that works just fine. Note the parameters.
I just made a new model and controller for Asset and it has this:
public function show(Asset $asset)
{
$AssetReturn = Asset::with('location:id,name,address')->findOrFail($asset);
return response()->json($AssetReturn,200);
}
but that does not work. it just returns empty. If i remove the class name from the parameters so its just
public function show($asset)
then it works as intended.
relation from asset model to location:
public function location()
{
return $this->belongsTo(Location::class);
}
According to the documentation, 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('/assets/{asset}', function (App\Asset $asset) {
$asset->load('location:id,name,address');
return response()->json($asset);
});
Since the $asset variable is type-hinted as the App\Asset Eloquent model and the variable name matches the {asset} 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.
If you don't want this behavior and want to use findOrFail manually:
Route::get('/assets/{asset}', function ($assetId) {
$asset = App\Asset::with('location:id,name,address')->findOrFail($assetId);
return response()->json($asset);
});

Eloquent: get changed columns

I need to log updated columns using Eloquent getChanges, It works just fine when use it in the same code context right after ex: updateOrCreate, but when call it from the "provider" it returns empty array, example of boot in service provider:
public function boot()
{
User::updating(function ($user) {
dd($user->getChanges()); //empty array
});
}
I get the problem I should use User::updated instead, ex:
public function boot()
{
User::updated(function ($user) {
dd($user->getChanges());
});
}

laravel: how to pass a parameters to a function in model?

I'm using laravel 5.5 / php 7.2 /
for example, I have a function like this in a model:
public function featuredTopSight($count=8)
{
return $this->hasMany(Sight::class)
->wherePublish(1)
->latest()
->take($count);
}
and then, In view:
$sight->featuredTopSight(8);
But I got this error:
"htmlspecialchars() expects parameter 1 to be string, object given
but with $sight->featuredTopSight; I got right answer. but I can not pass the parameter.
In that function you're defining a relationship.
You can't call a relationship with arguments.
First you need to declare the relation, and then the query or method to retrieve results.
Your method should be something similar to:
public function sights()
{
return $this->hasMany(Sight::class);
}
public function getFeaturedTopSights($count = 8)
{
return $this->sights()->wherePublish(1)->latest()->take($count)->get();
}

How to condition route model bindings by actions in RouteServiceProvider

I have an application which needs to accomplish this in RouteServiceProvider.php:
//in \App\Providers\RouteServiceProvider.php
public function boot(Router $router)
{
//
parent::boot($router);
//somehow can get the current action
$action = $router->getCurrentAction();
if($action == 'edit'){
$router->model('articles','App\Article');
} else{
$router->bind('articles', function($id){
return Article::published()->findOrFail($id);
});
}
}
Here is my route:
Route::resource('articles', 'ArticlesController');
Here is my Controller:
public function show(Article $article){
return view('articles.show',compact('article'));
}
public function edit(Article $article){
return view('articles.edit',compact(['article','tags']));
}
The reason I want to do it because I want show action only shows published articles while edit action can change both published and unpublished articles.
if there is any better solution, please teach me. Thank you !
Why don't you make a middleware, that will work only for 'published' routes, where you will check if your Article is published?
Based in your route, I assume that you have the following paths:
example.com/edit
example.com/3 - article ID
So, you could use a pattern to bind the article:
public function boot(Router $router)
{
parent::boot($router);
// bind
$router->bind('article', function($id){
return Article::published()->findOrFail($id);
});
// id pattern
$router->pattern('id', '[0-9]+');
}
Now, just declare the respective routes:
Route::get('articles', 'ArticlesController#showAll');
Route::get('{id}', 'ArticlesController#edit');
Finally, your controller could looks like this:
class ArticlesController{
public funcion showAll(){
// show a list of articles
}
public function edit(Article $article){
// selected article
}
}
Try to get the best of Laravel using class injection and keeping cleaning code.

Resources