Laravel eloquent api resource remove `data` key (no collection) - laravel

I have custom eloquent api resource for user. For example when I use this resource
Code
$user = $request->user();
return new UserResource($user);
Then on response I get:
{
"data": {
"name": "Margarete Daniel",
"email": "goldner.berniece#example.net",
"verified": "2020-03-20T07:15:56.000000Z"
}
}
How I can change api resource and get example response:
{
"name": "Margarete Daniel",
"email": "goldner.berniece#example.net",
"verified": "2020-03-20T07:15:56.000000Z"
}

Add this to your resource
public static $wrap = null;

You can disable data wrapping by calling the withoutWrapping static method of your resource in the AppServiceProvider. In your case it will be:
public function boot()
{
UserResource::withoutWrapping();
}
You can refer to Laravel documentation about data wrapping for more explanation.

Answering as I keep stumbling on the same problem myself.
The easiest way to return a Laravel resource without the data wrap is to simply return it in a JSON response. So instead of doing:
return new UserResource($user);
You would do:
return response()->json(new UserResource($user));
This way you also don't have to worry about stuffing your AppServiceProvider with a lot of calls to the withoutWrapping method.

To remove the data wrapper for all resources inside your project just add:
use Illuminate\Http\Resources\Json\JsonResource
public function boot()
{
JsonResource::withoutWrapping();
}
Inside the boot method of your AppServiceProvider.php.

this worked for me
return UserResource::make($user)->toArray($request);
and for collection
return UserResource::collection($users)->collection;

For some reason this works:
$user = User::find(1);
return UserResource::make($user)->resolve();
Without ->resolve() it's not working.

Related

Route not defined when passing parameter to a route

I have a named route with a parameter which looks like this...
Route::get('/profile/{user_id}', [ProfileController::class, 'profile'])->name('profile');
Now in one of my controller,
I have a function that calls this route like this
public function _myFunction($some_data) {
return redirect()->route('profile', [$some_data->user_id]);
}
and in my ProfileController's profile() function, I have this.
public function profile() {
return view('modules.profile.profile');
}
I've followed the documentation and some guides I found in SO, but I got the same error,
"Route [profile] not defined."
can somebody enlighten me on where I went wrong?
Here's what my routes/web.php looks like...
Route::middleware(['auth:web'])->group(function ($router) {
Route::get('/profile/{user_id}', [ProfileController::class, 'profile'])->name('profile');
});
When calling the route, you should pass the name of the attribute along with the value (as key vaue pairs). In this case, your route is expecting user_id so your route generation should look like this:
return redirect()->route('profile', ['user_id' => $some_data->user_id]);
Read more on Generating URLs To Named Routes in Laravel.
I solved the issue, and its really my bad for not providing a more specific case information and made you guys confused.
I was using socialite and called _myFunction() inside the third party's callback..
After all, the problem was the socialite's google callback, instead of placing the return redirect()->route('profile', [$user->id]) inside _myFunction(), what I did was transfer it to the callback function.
So it looked like this now...
private $to_pass_user_id;
public function handleGoogleCallback()
{
try {
$user = Socialite::driver('google')->user();
$this->_myFunction($user);
return redirect()->route('profile', [$this->to_pass_user_id]);
} catch (Exception $e) {
dd($e->getMessage());
}
}
public function _myFunction($some_data) {
... my logic here
$this->to_pass_user_id = $some_value_from_the_logic
}

Laravel pagination & get all

I have an API endpoint api/users that returns Users in paginated form:
public function index()
{
return User::latest()->paginate(10);
}
I also need to have access to ALL users as well, however the pagination makes this not possible.
For example I want to get all users as well using:
return User::latest()->get();
How can I use both without creating another endpoint? e.g. api/allusers
public function index($page)
{
if($page=='All')
{
return User::latest();
}
return User::latest()->paginate($page);
}

Automatically Load/Show Laravel View File

I am thinking of any techniques of autoloading the view files according to url.
For example:
public function addProducts()
{
return view('admin.addProducts');
}
public function editProducts()
{
return view('admin.editProducts');
}
public function allProducts()
{
return view('admin.allProducts');
}
Here, the Controller's method name is identical to view file name. So, I am thinking, if it is possible to load the view files without writing same kind of method again and again.
Enlighten me.
If your route only needs to return a view, you may use the Route::view method.
For example:
Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
read more here
It's the call PHP magic, man. https://repl.it/#Piterden/PHP-call-magic?language=php
public function __call($method, $parameters)
{
if (str_contains($method, 'Product')) {
return view("admin.{$method}");
}
}
btw, it's not a good practice for controller.

Returning same variable to every controller in laravel

I need to send the same result to almost every view page, so I need to bind the variables and return with every controller.
My sample code
public function index()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.index', compact('drcategory','locations'));
}
public function contact()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.contact', compact('drcategory','locations'));
}
But as you see, I need to write same code over and over again. How can I write it once and include it any function whenever I need?
I thought about using a constructor, but I cannot figure out how I can implement this.
You are able to achieve this by using the View::share() function within the AppServicerProvider:
App\Providers\AppServiceProvider.php:
public function __construct()
{
use View::Share('variableName', $variableValue );
}
Then, within your controller, you call your view as normal:
public function myTestAction()
{
return view('view.name.here');
}
Now you can call your variable within the view:
<p>{{ variableName }}</p>
You can read more in the docs.
There are a few ways to implement this.
You can go with a service, a provider or, like you said, within the constructor.
I am guessing you will share this between more parts of your code, not just this controller and for such, I would do a service with static calls if the code is that short and focused.
If you are absolutely sure it is only a special case for this controller then you can do:
class YourController
{
protected $drcategory;
public function __construct()
{
$this->drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
}
// Your other functions here
}
In the end, I would still put your query under a Service or Provider and pass that to the controller instead of having it directly there. Maybe something extra to explore? :)
For this, you can use View Composer Binding feature of laravel
add this is in boot function of AppServiceProvider
View::composer('*', function ($view) {
$view->with('drcategory', DoctorCategory::orderBy('speciality', 'asc')->get());
$view->with('locations', Location::get());
}); //please import class...
when you visit on every page you can access drcategory and location object every time
and no need to send drcategory and location form every controller to view.
Edit your controller method
public function index()
{
return view('visitor.index');
}
#Sunil mentioned way View Composer Binding is the best way to achieve this.

Laravel Backpack - getting current record from crud controller

In my crud controller I am trying to get the name of the person who is currently being edited.
so
http://192.168.10.10/admin/people/93/edit
In the people crud controller
public function setup() {
dd(\App\Models\People::get()->first()->name)
}
This returns the first person not the person currently being edited.
How do I return the current person (with an id of 93 in this example)
Ok, So since you use backpack look into CrudController to see how the method looks:
public function edit($id)
{
$this->crud->hasAccessOrFail('update');
$this->data['entry'] = $this->crud->getEntry($id);
$this->data['crud'] = $this->crud;
$this->data['fields'] = $this->crud->getUpdateFields($id);
$this->data['id'] = $id;
return view('crud::edit', $this->data);
}
So now you can overwrite the edit function and change whatever you want. You can even create a custom edit page if you so wish.
Setup on the other hand is usually used to add things like
$this->crud->addClause(...);
Or you can even get the entire constructor and put it in the setup method because setup call looks like this:
public function __construct()
{
// call the setup function inside this closure to also have the request there
// this way, developers can use things stored in session (auth variables, etc)
$this->middleware(function ($request, $next) {
$this->setup();
return $next($request);
});
}
So you could do something like \Auth::user()->id;
Also it's normal to work like this. If you only use pure laravel you will only have access to the current id in the routes that you set accordingly.
Rahman said about find($id) method. If you want to abort 404 exception just use method findOrFail($id). In my opinion it's better way, because find($id)->name can throw
"Trying to get property of non-object error ..."
findOrFail($id) first fetch user with specified ID. If doesn't exists just throw 404, not 500.
The best answer is:
public function edit($id)
{
return \App\Models\People::findOrFail($id);
}
Good luck.
you need person against id, try below
public function setup($id) {
dd(\App\Models\People::find($id)->name);
}

Resources