How to get and validate application/json data in Laravel? - laravel

I send data from client to server in application/json content type.
Then I try to take this information in server side like as:
public function register(Request $request)
{
$data = $request->json()->all();
var_dump($data); die();
}
It returns me empty array()
Also I tried to validate incoming POST using this:
$validator = Validator::make($request->json()->all(), []);
How to get and validate application/json data in Laravel?
I get POST data like as:
dd($_POST);
array:1 [▼
"application/json" => "{"id":6,"unique_code":null,"name":"О","secondname":"П","lastname":"Валерьевич","datebirth":"14/10/1991 00:00:00","taxcode":"4545","gender":"1","created_at":null,"file":"C:\\db\\tests\\22-07-2017\\MMM1.TXT","orders":{"profession":"Директор","pacient_id":null,"payment":"1","kind_work":"1,2","factory_name":"FALKO","factory_edrpou":"2020","factory_departament":"IT","status_pass":"1","office_address":"Kiev","unique_code":"0","enterprise_id":"12","status":null},"http_code":null}"
]

I have an api I post json to. I have an api end point where I post this json
{
"email":"youremail#triumworks.com",
"phone": "phone",
"name": "name",
"password": "password"
}
The corresponding controller that handles the request looks like
public function create_account(Request $request){
$data = json_decode(file_get_contents('php://input'));
$response = new Responseobject;
$array_data = (array)$data;
$validator = Validator::make($array_data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6',
'phone' => 'required|string|min:12|max:12|unique:users',
]);
if($validator->fails()){
$response->status = $response::status_failed;
$response->code = $response::code_failed;
foreach ($validator->errors()->getMessages() as $item) {
array_push($response->messages, $item);
}
}
else{
$api_token = str_random(60);
$user = new User();
$user->api_token = $api_token;
$user->name = $data->name;
$user->email = $data->email;
$user->phone = $data->phone;
$user->password = bcrypt($data->password);
if($user->save()){
$response->status = $response::status_ok;
$response->code = $response::code_ok;
$response->result = $user;
}
}
return Response::json(
$response
);
}
This does the same thing as the one above.
public function create_account(Request $request){
$response = new Responseobject();
$validator = Validator::make($request->json()->all(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6',
'phone' => 'required|string|min:12|max:12|unique:users',
]);
if($validator->fails()){
$response->status = $response::status_failed;
$response->code = $response::code_failed;
foreach ($validator->errors()->getMessages() as $item) {
array_push($response->messages, $item);
}
}
else{
$api_token = str_random(60);
$user = new User();
$user->api_token = $api_token;
$user->name = $data->name;
$user->email = $data->email;
$user->phone = $data->phone;
$user->password = bcrypt($data->password);
if($user->save()){
$response->status = $response::status_ok;
$response->code = $response::code_ok;
$response->result = $user;
}
}
return Response::json(
$response
);
}

The posted data will end up in the request body parameter bag. You get the data either via $request->all() or $request->request->all().
So the Validator looks like this:
$validator = Validator::make($request->all(), []);
Dive deeper:
Or you can use the validate() method in your controllers. Which look like this:
$this->validate($request->all(), []);
Read more about this in the Laravel docs.
To make things even more complicator, you don't even need to inject the Request instance to your controller. You can use the request() helper function. The register method then looks like this:
public function register()
{
$this->validate(request()->all(), [
'email' => 'required|email',
'password' => 'required|min:6|confirmed',
]);
}

Related

How to validate a string in laravel

I have a textarea where a user can bulk add clients. In the textarea they would add the clients like this
client 1,client1#domain.com,client username 1
client 2,client2#domain.com,client username 2
client 3,client3#domain.com,client username 3
Here is what I have so far
public function bulkClients()
{
$bulk = request('bulk_clients');
$split = explode("\n",$bulk);
foreach($split as $row)
{
$split_row = explode(",", $row);
$name = $split_row[0];
$email = $split_row[1];
$username = $split_row[2];
$validate = Validator::make($email, [
$email => 'email',
$username => 'unique:App\User,username'
]);
if($validate->fails())
{
$messages = $validate->messages();
return response()->json([
'messages' => $messages
]);
}
}
}
What I would like to know is how can I validate that $email is an email or that $username is unique.
The first param of Validator::make should be an array and the second is the rules for the keys of the array.
public function bulkClients()
{
$bulk = request('bulk_clients');
$split = explode("\n",$bulk);
foreach($split as $row)
{
$split_row = explode(",", $row);
$client['name'] = $split_row[0];
$client['email'] = $split_row[1];
$client['username'] = $split_row[2];
$validate = Validator::make($client, [
'email' => 'email',
'username' => 'unique:App\User,username'
]);
if($validate->fails())
{
$messages = $validate->messages();
return response()->json([
'messages' => $messages
]);
}
}
}
You find all available rules in the docs:
$validate = Validator::make([ 'email' => $split_row[1],
'username' => $split_row[2]
], [
'email' => 'string',
'username' => 'unique:App\User,username'
]);
However, for email, I would rather check if its a valid email instead of a string. Thus,
'email' => 'email'
would be recommended.
I would suggest using the validator for the whole array instead of validating it row by row:
$clients = Str::of(request()->get('bulk_clients'))
->explode("\n")
->map(fn ($value) => Str::of($value)->explode(','))
->toArray();
$validator = Validator::make(compact('clients'), [
'clients' => 'array',
'clients.*.0' => 'required|string',
'clients.*.1' => 'required|email',
'clients.*.2' => 'required|unique:App\User,username',
]);

How to generate access_token without username and password

I am trying to make an API with Passport. If a user tries to login or signs up with Socialite, find user than generate access_token then redirect to the frontend with access_token in URL parameters.
I tried to register and login than generate access_token with user email and the default password, which is not suitable for security.
try {
$serviceUser = Socialite::driver($service)->stateless()->user();
} catch (\Exception $e) {
return redirect(config('app.client_url').'/auth/social-callback?error=Unable to login using '.$service.'. Please try again'.'&origin=login');
}
$email = $serviceUser->getEmail();
$name = $serviceUser->getName();
$user = $this->getExistingUser($serviceUser, $email, $service);
$newUser = false;
if (!$user) {
$newUser = true;
$user = new User;
$user->name = $name;
$user->email = $email;
$user->username = Str::random(10);
if ($service === 'facebook') {
$user->image = $serviceUser->avatar;
}
$user->verify = true;
$user->save();
}
if ($this->needsToCreateSocial($user, $service)) {
Social::create([
'user_id' => $user->id,
'social_id' => $serviceUser->getId(),
'service' => $service
]);
}
$http = new Client;
$response = $http->post(config('app.url').'/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => '2',
'client_secret' => 'oBKWxgF2fDvrxwA05ciapwy4JYKaHxzhGzr6D24X',
'username' => $email,
'password' => 'gebdandi',
'scope' => '',
],
]);
$body = json_decode((string) $response->getBody(), true);
$accessToken = $body['access_token'];
return redirect(config('app.client_url').'/social-callback?token='.$accessToken.'&origin='.($newUser ? 'register' : 'login'));
I can't find any solution in the documentation.
after reading all documentation i found solution in this documentation
i did like this
edit authserviceprovider like this
public function boot()
{
$this->registerPolicies();
Passport::routes();
Passport::personalAccessClientId(1);
Passport::tokensExpireIn(now()->addDays(15));
Passport::refreshTokensExpireIn(now()->addDays(30));
}
added code in controller like this
$accessToken = $user->createToken('access_token')->accessToken;
thanks for laravel Team for provide good documentation

Validation error in api response in laravel 5.6

I want to store data through api. It's working but problem is when I add validation it does not give me corresponding message . How can I fix it? Thanks in advance
Here is my route
Route::post('api/add_user', 'TestApiController#store');
Here is my controller
public function store(Request $request)
{
$validation = Validator::make(Request::all(), [
'name' => 'required',
'phone' => 'required',
'email' => 'required'
]);
if ($validation->errors()) {
return $errors->toJson();
} else {
$testApi = new testApi();
$testApi->name = $request->name;
$testApi->phone = $request->phone;
$testApi->email = $request->email;
$testApi->save();
return "ok";
}
}
to handle that your method should be like this :
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required',
'phone' => 'required',
'email2' => 'required|email'
]);
if($validator->fails()){
// here we return all the errors message
return response()->json(['errors' => $validator->errors()], 422);
}
$testApi = new testApi();
$testApi->name = $request->name;
$testApi->phone = $request->phone;
$testApi->email = $request->email;
$testApi->save();
// 201 http code means that the server has proceced your request correctly
return response()->json([], 201);
}
You don't have to manually do this. simply
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'phone' => 'required',
'email' => 'required'
]);
$testApi = new testApi();
$testApi->name = $request->name;
$testApi->phone = $request->phone;
$testApi->email = $request->email;
$testApi->save();
return "ok";
}
this will automatically handles validation and returns error message when invalid.
Update
if you wanna stick with your approach. this is where you need to change.
if ($validation->fails()) {
return $validation->errors();
}

How to display array data after store & email sent?

UPDATE
I have contact form. it works good. I would like to display $data array at
final page which is admintemp.blade.php.
I can display $data array at one step before final page. but I would like to display those at last page too.
I thoguht just add this
return view('mail.complete', ['data' => $data]);
is fine. but I got this error
Invalid argument supplied for foreach()
Could you teach me right way please?
Here is my code
/*
*confirm page
*/
public function confirm(Request $request)
{
$rules = [
'orderer' => 'required'
];
$this->validate($request, $rules);
$data = $request->all();
$request->session()->put('data',$data);
return view('mail.confirm', compact("data"));
}
/*
* complete page
*/
public function complete(Request $request)
{
$data = $request->session()->pull('data');
$token = array_shift($data);
$Contact = Contact::create($data);
$data = session()->regenerateToken();
return view('mail.complete', ['data' => $data]);
}
UPDATES 2
complete.blade.php
#foreach ($data as $val)
{{ $val->id }}
{{ $val->tel }}
#endforeach
for example you have two step form
first step post method:
public function postCreateStep1(Request $request)
{
$validatedData = $request->validate([
'name' => 'required',
]);
if (empty($request->session()->get('contact'))) {
$contact = new Contact();
$contact->fill($validatedData);
$request->session()->put('contact', $contact);
} else {
$contact = $request->session()->get('contact');
$contact->fill($validatedData);
$request->session()->put('contact', $contact);
}
return redirect('/create-step2');
}
second step post method:
public function postCreateStep2(Request $request)
{
$validatedData = $request->validate([
'family' => 'required',
]);
if (empty($request->session()->get('contact'))) {
$contact = new Contact();
$contact->fill($validatedData);
$request->session()->put('contact', $contact);
} else {
$contact = $request->session()->get('contact');
$contact->fill($validatedData);
$request->session()->put('contact', $contact);
}
$created_contact = Contact::create([
'name' => $contact->name,
'family' => $contact->family,
]);
// Do whatever you want with $created_contact
return redirect('/');
}

Lumen: update records via json body

I have a Laravel Lumen API. I'm seeing an issue with the update functionality.
In my controller, the code for updating an item is:
public function update(Request $request, $id)
{
$this->validate($request, [
'name' => 'required',
'description' => 'required',
'completed' => 'required',
]);
$todo = Todo::find($id);
$todo->name = $request->name;
$todo->description = $request->description;
$todo->completed = $request->completed;
$todo->save();
return response()->json(['status' => 'success']);
}
I can update the todo item using:
http://lumen-todo.app/api/51?name=test&description=test&completed=1
however was hoping I could send the parameters in a json body, like this
PUT http://lumen-todo.app/api
{
"id": 1
"name": "Test",
"description": "Test",
"completed": 1,
}
For adding items, it works via a json body, so don't understand why it does not work for updates. For info, the 'add item' controller code is here:
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required',
'description' => 'required',
'completed' => 'required'
]);
$todo = new Todo();
$todo->name = $request->name;
$todo->description = $request->description;
$todo->completed = $request->completed;
$todo->save();
return response()->json(['status' => 'success']);
}
If you want to get the json data from request payload, validate and store it, use
public function store(Request $request)
{
$data = $request->json()->all();
$this->validate($data, [
'name' => 'required',
'description' => 'required',
'completed' => 'required'
]);
$resource = $this->model->find($id);
$resource->fill($request);
$resource->save();
return response()->json(['status' => 'success']);
}
Instead of doing this:
$todo = new Todo();
$todo->name = $request->name;
$todo->description = $request->description;
$todo->completed = $request->completed;
$todo->save();
Do, this:
use App\Todo;
protected $model;
public function __construct(Todo $model) {
$this->model = $model;
}
$resource = $this->model->find($id);
$resource->fill($request);
$resource->save();
Also, you can do json_decode() function to change your json params to array and use that to validate and save data.

Resources