Laravel Model binding including SoftDeleted values - laravel

I have a Route::resource('sheeps', 'SheepsController') with a show function returning a resource:
public function show(Sheep $sheep)
{
return new SheepResource(
$sheep->load('farm')
);
}
So when I call /api/sheeps/123 should I get Sheep 123, but... I don't get it, because it's softdeleted.
How to fix the resource that it also searches in softdeleted results?

You should use this :
in your RouteServiceProvider :
/**
* Define your route model bindings, pattern filters, etc.
*
* #return void
*/
public function boot()
{
parent::boot();
Route::bind('sheep', function ($value) {
return Sheep::withTrashed()->find($value);
});
}

Try this:
public function show($id)
{
$sheep = Sheep::withTrashed()->findOrFail($id);
and update your route
or
public function show(int $sheep)
{
$sheep = Sheep::withTrashed()->findOrFail($sheep);
or
use Explicit Binding

Related

My authorize function is always failing in laravel-5.8?

I created one policy inside create function i am checking weather this user can able to create records and i am registering the Model and policy in the AthServiceProvider.php after that i am checking inside the controller by using $this->authorize('create') it's failing always even the user is valid,can you please help me how to resolve this issue
Error:- This Action is unathorized
restaurentContoller.php
class RestaurentsController extends Controller
{
protected $repository;
public function __construct(RestaurentRepository $repository){
$this->repository = $repository;
}
public function postRestaurent(RestaurentRequest $request){
$data = $request->all();
$data['admin_id'] = $this->getAccountId($request);
$this->authorize('create');
$rest = $this->repository->create($data);
return response()->json(fractal($rest,new RestuarentTransformer));
}
}
RestaurentPolicy.php
public function create(User $user)
{
return ($user->admin_id=1) ? true : false;
}
api.php
Route::post('/postRest',[RestaurentsController::class,'postRestaurent'])->middleware(['CheckAdmin']);
If you use Request Classes you have to change authorize method return false to true
class RestaurentStoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return false;
}
}

Laravel 8 vendor class `Illuminate\Database\Eloquent\Factories\Factory` can't resolve name of ModelNameFactory class

Laravel 8 has the default App/Models directory for Model classes. The Illuminate\Database\Eloquent\Factories\Factory has static function resolveFactoryName() to resolve name of ModelNameFactory class
public static function resolveFactoryName(string $modelName)
{
$resolver = static::$factoryNameResolver ?: function (string $modelName) {
$modelName = Str::startsWith($modelName, 'App\\Models\\')
? Str::after($modelName, 'App\\Models\\')
: Str::after($modelName, 'App\\');
return static::$namespace.$modelName.'Factory';
};
return $resolver($modelName);
}
The function works properly only for App/ModelName or App/Models/ModelName
if name of Model class, for example, is the Domain/Customers/Models/ModelName, that function doesn't work properly. What is the best way to fix it?
As you can see here, there is a method called guessFactoryNamesUsing which lets you tell Laravel how it should guess the name of your factories.
Add the following to your AppServiceProvider:
use Illuminate\Database\Eloquent\Factories\Factory;
public function register()
{
Factory::guessFactoryNamesUsing(function ($class) {
return 'Database\\Factories\\' . class_basename($class) . 'Factory';
});
}
Source:
/**
* Specify the callback that should be invoked
* to guess factory names based on dynamic relationship names.
*
* #param callable $callback
* #return void
*/
public static function guessFactoryNamesUsing(callable $callback)
{
static::$factoryNameResolver = $callback;
}
Please put this in your model class in App\Models\ModelName.
Make sure the ModelFactory is the factory name.
protected static function newFactory()
{
return \Modules\Module\Database\Factories\ModelFactory::new();
}

Laravel Nova metrics filtering

I have a model called Property which has an 'active' flag. I want a metric at the top of my resource which shows a count of active Properties.
My calculate method is exactly as in the doc but this shows all Properties rather than active ones:
public function calculate(Request $request)
{
return $this->count($request, Property::class);
}
How can I add a filter?
I've tried a where clause:
public function calculate(Request $request)
{
return $this->count($request, Property::class)->where('active','=',1);
}
And a query scope:
public function calculate(Request $request)
{
return $this->count($request, Property::class)->active();
}
I thought I might be able to use the Nova filter I set up on the resource list page but that didn't seem to work either. I'm sure it's really easy but I haven't worked it out. Thanks for your help!
Your can use every type of Eloquent\Builder instance in the $model param.
Instead of:
public function calculate(Request $request)
{
return $this->count($request, Property::class);
}
Set a Scope on your Model
App\Property.php
...
public function scopeActive($query)
{
return $query->where('active', 1);
}
public function scopeInactive($query)
{
return $query->where('active', 0);
}
And use this scope as the $model param in your calculate method, because the call of the scope returns a Eloquent\Builder Instance
public function calculate(Request $request)
{
return $this->count($request, Property::active());
// return $this->count($request, Property::inactive());
}
Edit
Of course you can make the Eloquent Builder call inline:
public function calculate(Request $request)
{
return $this->count($request, Property::where('active', 1));
}

Laravel Model Controller Dependency injection

I have the following problem. I hope my approach is not completely wrong, feel free to advice.
I have a Model class Chat.php
protected $skip;
protected $take;
protected $agreements;
protected $chat;
public function getSkip()
{
return $this->skip;
}
public function setSkip($skip)
{
$this->skip = $skip;
}
public function getTake()
{
return $this->take;
}
public function setTake($take)
{
$this->take = $take;
}
public function __construct(array $attributes = array())
{
parent::__construct($attributes);
$this->setTake(8);
$this->setSkip(8);
}
I set properties skip and take here.
Then, I have the DashboardController
class DashboardController extends Controller
{
private $chat;
/**
* DashboardController constructor.
* #param $chat
*/
public function __construct(Chat $chat)
{
$this->chat = $chat;
}
/**
* Display a listing of the authenticated resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$chats = Chat::orderBy('created_at','desc')->skip($this->chat->getSkip())->take($this->chat->getTake())->get();
$agreements = AgrType::orderBy('created_at','desc')->take(10)->get();
return view('sections.dashboard', compact('chats','agreements'));
}
public function loadMore()
{
$this->chat->setSkip($this->chat->getSkip() - 1 );
$this->chat->setTake($this->chat->getTake() - 1);
return redirect('/dashboard');
}
My approach is as follows:
After a user clicks on button, route /loadmore get him to this controller and triggers loadMore function.
LoadMore function then gets values through accessors and sets values with mutator.
Index method then simply reads this values.
So the meaning is: I show chat window (rather maybe comments window cause this si not really a chat), index method is called.
Index method reads the values and displays comments according to query. -> this one is OK
Now, what does NOT work:
When I click button, loadMore function gets called, sets the values which index method then reads and reloads according to them.
What did I try: I tried loadMore method to display its own values (changed) and return them, but then I have a new route for reloaded chat and it is not what I want.
What do I miss? Is my approach OK? (I know javascript is maybe better for this, but I want a Laravel way, get and post.)
Thanks in advance.
Your controller functions get executed within in completely separate requests.
All return redirect('/dashboard'); does in loadMore() send your browser to the dashboard route. Your browser then makes a new request to index() on which your controller gets instantiated again, its __construct() function run again and a new empty Chat model gets instantiated.
I recommend you put the take and skip parameters into your url like this:
$router->get('/dashboard/{skip}/{take}', 'DashboardController#index');
And change your index() function to this:
public function index($skip, $take)
That way it will work, however the even better way of doing it would be to use Laravel's paginate() function: https://laravel.com/docs/5.6/pagination
public function index()
{
$chats = Chat::orderBy('created_at','desc')->paginate();
$agreements = AgrType::orderBy('created_at','desc')->take(10)->get();
return view('sections.dashboard', compact('chats','agreements'));
}

Laravel eloquent save

I am trying to change a value on save
public static function boot()
{
static::saving(function ($formRow) {
$formRow->sales = 1;
});
}
But the weird part is that its not changing the sales to 1, any idea why ?
You're missing the call to the parent's boot method:
public static function boot()
{
// add this
parent::boot();
static::saving(function ($formRow) {
$formRow->sales = 1;
});
}
You can just override the save method on the model itself:
public function save(array $options = [])

Resources