I created an API and made customizations. Looking through the documentation, I tried a few ways, but somehow I could not do the pagination. Can you help me?
PostResource.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'image' => $this->image,
'description' => $this->description,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'user' => new UserResource($this->user),
'comments' => CommentResource::collection($this->comment),
];
}
}
PostController.php
public function res() {
$post_all_item = Posts::all();
return response()->json(PostResource::collection($post_all_item),200);
}
This is how you can paginate collections in laravel:
$post_all_item = Posts::paginate(15); //will paginate 15 posts per page
return PostResource::collection($post_all_item); //will be converted to Json automatically
Note1: Model names should be singularis eg. Post instead of Posts
Note2: Its not necessary to convert a resource collection to json response, Laravel will do that automatically
Note3: In resource files, check if relationships exists by using whenLoaded:
'user' => new UserResource($this->whenLoaded('user')), //with resource
'comments' => $this->whenLoaded('comments'), //without resource
Related
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
Sometimes I need to return some specific key instead whole resource.
How to return a specific array of key from JsonResource toArray()? like Request with only(['key1', 'key4']) function.
From your controller, when you pass data to your view or API, you simply specify the exact key you want to access.
For example, in your controller
public function store(Request $request){
//You other logic here
$post = new PostResource( $request->all() );
//Here, you return only the specific key you want to access
return response([
'title' => $post->title,
]);
}
All the best
I am developing A web Application using Laravel-5.8 framework. I have a Model Class as shown below:
<?php
namespace App;
use App\Model;
class Gradesystem extends Model
{
protected $table = 'grade_systems';
}
Also my Controller is shown below:
public function store(Request $request){
$request->validate([
'grade_system_name' => 'required|string|max:255',
'point' => 'required',
'grade' => 'required',
'from_mark' => 'required',
'to_mark' => 'required',
]);
$gpa = new Gradesystem;
$gpa->grade_system_name = $request->grade_system_name;
$gpa->point = $request->point;
$gpa->grade = $request->grade;
$gpa->from_mark = $request->from_mark;
$gpa->to_mark = $request->to_mark;
$gpa->save();
}
How do I validate, probably from the Model or the Controller between from_mark and to_mark. Also, from_mark should not be greater that or equal to to_mark.
It must not allow a number that falls in the range of already existing value. For example if from_mark is 0 and to_mark is 49 are already in database. So, if a user enters from_mark or to_mark to be 30, it must not allow it.
How do I achieve this?
Thank you.
For custom Validations its better use Rule Objects, where you can implement the logic of your validation.
An Example:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class Uppercase implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return strtoupper($value) === $value;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The :attribute must be uppercase.';
}
}
You can see the info in the Laravel documentation
Hope this can help you
I did not understand entire validation you asked but this will help. With same way you can write any other validation on from_mark and to_mark.
$validator = Validator::make($request->all(), [
'grade_system_name' => 'required|string|max:255',
'point' => 'required',
'grade' => 'required',
'from_mark' => 'required',
'to_mark' => 'required',
]);
if ($validator->fails()) {
return redirect()->back()->withInput()->withErrors();
}
if ($request->get('from_mark') < $request->get('to_mark')) {
return redirect()->back()->withInput()->withErrors();
}
i have Post and User model with one to one relation and it works good:
//User.php
public function post(){
return $this->hasOne(Post::class);
}
// Post.php
public function user() {
return $this->belongsTo(User::class);
}
now i create API resources:
php artisan make:resource Post
php artisan make:resource User
I need to return all post with an api call then i set my route:
//web.php: /resource/posts
Route::get('/resource/posts', function () {
return PostResource::collection(Post::all());
});
this is my Posts resource class:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
use App\Http\Resources\User as UserResource;
class Posts extends Resource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'bodys' => $this->body,
'users' => UserResource::collection($this->user),
'published' => $this->published,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
this is the error:
Call to undefined method Illuminate\Database\Query\Builder::mapInto()
if i remove:
'users' => UserResource::collection($this->user),
it's work but i need to include relations in my api json, i have read and followed the doc at https://laravel.com/docs/5.5/collections.
this is my User resource class:
```
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class User extends Resource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'user_id' => $this->user_id,
'name' => $this->name,
'lastname' => $this->lastname,
'email' => $this->email
];
}
}
any ideas where am i wrong?
The problem is that you use UserResource::collection($this->user) and you have just one element not a collection so you can replace it with new UserResource($this->user) like this :
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'bodys' => $this->body,
'users' => new UserResource($this->user),
'published' => $this->published,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
In Laravel 8.5.*, you can use the static method make on the collection to get the same result. It would be like UserResource::make($this->user)
this problem is that you use UserResource::collection($this->user) it mean you have many users but and you have just one element for the a single resource and not a collection so you can replace it with new UserResource($this->user)
when you have just one element and not a collection use new Resouce
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'user' => new UserResource($this->whenLoaded('user')),
];
and give a try to use the eager loading for better perfomance not just this.
using the method whenLoaded and put the relations name in ( ).
Resource::collection is used when the model has hasMany relation. If your model has hasOne relation use Resource::make(Book::all())
I am begginer, and trying to create a referral system. following is sample url
http://dev.lea.com/register?ref=mh2HPLpVSn
I try to get referral string. how can i get separately? is there need of middleware for getting cookies? if yes then what will be code of middleware? and how can i get referral reference in RegisterController?
Here is my Register Controller.
<?php
namespace Lea\Http\Controllers\Auth;
use DB;
use Lea\User;
use Lea\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
use Cookie;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'fname' => 'required|string|max:255',
'lname' => 'required|string|max:255',
'referral' => 'string|max:255',
'username' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
// 'tracking_id' => 'required',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \Lea\User
*/
protected function create(array $data, Request $request)
{
// printing here referral Link
echo $request()->ref;
// $referred_by = Cookie::get();
// print_r($referred_by);
die;
return User::create([
'fname' => $data['fname'],
'lname' => $data['lname'],
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'affiliate_id' => str_random(10),
// 'referred_by' => $referred_by,
'identity' => $data['identity'],
'dob' => $data['dob'],
'board_id' => $data['board_id'],
'class_id' => $data['class_id'],
'subject_id' => $data['subject_id'],
'institute' => $data['institute'],
'address' => $data['address'],
'city' => $data['city'],
'std_mobile' => $data['std_mobile'],
'father_name' => $data['father_name'],
'father_mobile' => $data['father_mob'],
'ipadress' => \Request::ip(),
]);
}
}
When you have an URI such as /register?ref=mh2HPLpVSn you can retrieve ref like this:
$request()->ref
in your controller! I believe you can also use $request()->has('ref') to determine if it's present in the URI.
Hope this helps you!!
In laravel 6+ inside controller you can use like
$request->get('ResourcePath')
You can get your parameters using Request access.
Here one example for get your ref code:
public function register(Request $request)
{
$allParams = $request->all();
$refParam = $request->ref;
dd($allParams, $refParam);
...
}
public function showRegister(Request $request) {
var_dump(request->ref)
}
then you can do things like validation and so on, another possiblity is to change the template of your register form and add a hidden field with the refcode from the ref param and handle the whole request in your register method.
So I am trying to group all my validation rules into its respective files in folders for easy maintenance. Below is how my folder structures look:
Project
--app
--config
--(more folders)
--domains
----App
--------Entities
--------Repositories
--------Services
--------Validators
----Core
--------Validators
So what I wanted to achieve is under Core\Validators I created a LaravelValidator.php which look like this
<?php namespace Core\Validators;
use Validator;
abstract class LaravelValidator {
/**
* Validator
*
* #var \Illuminate\Validation\Factory
*/
protected $validator;
/**
* Validation data key => value array
*
* #var Array
*/
protected $data = array();
/**
* Validation errors
*
* #var Array
*/
protected $errors = array();
/**
* Validation rules
*
* #var Array
*/
protected $rules = array();
/**
* Custom validation messages
*
* #var Array
*/
protected $messages = array();
public function __construct(Validator $validator)
{
$this->validator = $validator;
}
/**
* Set data to validate
*
* #return \Services\Validations\AbstractLaravelValidator
*/
public function with(array $data)
{
$this->data = $data;
return $this;
}
/**
* Validation passes or fails
*
* #return Boolean
*/
public function passes()
{
$validator = Validator::make(
$this->data,
$this->rules,
$this->messages
);
if ($validator->fails())
{
$this->errors = $validator->messages();
return false;
}
return true;
}
/**
* Return errors, if any
*
* #return array
*/
public function errors()
{
return $this->errors;
}
}
Then in my App\Validators I created a file name RegistrationFormValidator.php which look like this
<?php namespace App\Validators\Profile;
class RegistrationFormValidator extends \Core\Validators\LaravelValidator
{
protected $rules = array(
'first_name' => 'required',
'last_name' => 'required',
'username' => 'required',
'password' => 'required',
'rTPassword' => 'required',
'profile_url' => 'required',
'email' => 'required|email',
'gender' => 'required',
'dob' => 'required',
);
}
so usually in laravel 4.2, to validate something all i do is construct the validation rules and then call it in services which look like this
<?php namespace App\Services\Profile;
/*
|-----------------------------------------------------------
| This section injects the repositories being used
| in this service.
|-----------------------------------------------------------
*/
use App\Repositories\Profile\ProfileRepository;
use Core\ValidationFailedException;
use App\Validators\Profile\RegistrationFormValidator;
use Validator;
class ProfileService implements ProfileServiceInterface
{
protected $_profile;
protected $v;
/*
|-----------------------------------------------------------
| All construsted models variables must carry
| the '_' sign to identify it as a model variable
|-----------------------------------------------------------
*/
public function __construct(ProfileRepository $_profile, RegistrationFormValidator $v)
{
$this->_profile = $_profile;
$this->v = $v;
}
/*
|-----------------------------------------------------------
| 1. All try and catch error handling must be done
| in the respective controllers.
|
| 2. All data formattings must be done in this section
| then pass to repository for storing.
|
| 3. No controller actions allown in this section
|-----------------------------------------------------------
*/
public function createProfile($array)
{
if($this->v->passes())
{
//save into db
}
else
{
throw new ValidationFailedException(
'Validation Fail',
null,
$this->v->errors()
);
}
}
}
But the problem is once i upgraded into laravel 5 i did the same thing and when i try to execute the code it returns me with this error
ErrorException in ProfileService.php line 26:
Argument 2 passed to App\Services\Profile\ProfileService::__construct() must be an instance of App\Validators\Profile\RegistrationFormValidator, none given
My code works absolutely fine in L4.2 but once i upgraded it wont work anymore. I also know that i can do validation like such
public function createProfile($array)
{
$v = Validator::make($array, [
'first_name' => 'required',
'last_name' => 'required',
'username' => 'required',
'password' => 'required',
'rTPassword' => 'required',
'profile_url' => 'required',
'email' => 'required|email',
'gender' => 'required',
'dob' => 'required',
]);
if($v->passes())
{
}
else
{
throw new ValidationFailedException(
'Validation Fail',
null,
$v->errors()
);
}
}
But the problem is if i would have more validation rules or scenario it will flood the whole service file.
Any suggestions or solutions that will guide me? thanks in advance!
In Laravel 5 you have something similar, which handles better the validation and makes validation clean and easy. It is called Form Request Validation. The idea there is the same - to have different classes that handle validation in different scenarios.
So whenever you need a validation you can create new FormRequest, like this:
php artisan make:request RegisterFormRequest
A new class will be generated under app/Http/Requests. There you can see it has two methods authorize and rules. In the first one you can make a check if given user is allwed to make this request. In the second method you can define your rules, just like in the validator.
public functions rules() {
return array(
'first_name' => 'required',
'last_name' => 'required',
'username' => 'required',
'password' => 'required',
'rTPassword' => 'required',
'profile_url' => 'required',
'email' => 'required|email',
'gender' => 'required',
'dob' => 'required',
);
}
Then you can change your controller method like this:
public function postCreateProfile(RegisterFormRequest $request) {
// your code here
}
The are a few cool things here. First one - the class will be automatically constructed in injected in your controller method by the IoC container, you don't need to do something special. The second cool thing is that the validation check is done before the Request object is passed to the controller, so if any validation error occurs you will be redirected back with all errors according to your rules set. This means that writing your code in the postCreateProfile method you can assume if this code get executed the validation is passed at this position and no additional check are needed by you.
I suggest you to migrate your code to use Laravel 5 Form Requests, because what you need is already implemented in the framework, and yes basically this is the point of the migration of one version to another. You can also check the documentation for more examples.