Make an Ajax request in Symfony2 - ajax

My problem is that the method doesn't return a true result.
I want to test if the email of input exists in my entity or not.
Here is the controller:
public function verificationAction(Request $request)
{
if ($this->container->get('request')->isXmlHttpRequest()) {
$email=$request->request->get('email');
$em=$this->getDoctrine()->getEntityManager();
$resp= $em->getRepository("CMSiteBundle:Prospect")->findBy(array('email'=>$email));
$response =new Response(json_encode($resp));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
}

You could try an old-trick. Since in Symfony Controller Actions, You must return a Response why not fake a DEAD RESPONSE like so:
<?php
class ABCController {
public function verificationAction(Request $request) {
if ($this->container->get('request')->isXmlHttpRequest()) {
$email = $request->request->get('email');
$em = $this->getDoctrine()->getEntityManager();
$resp = $em->getRepository("CMSiteBundle:Prospect")
->findBy(array('email' => $email));
//$response = new Response(json_encode($resp));
//$response->headers->set('Content-Type', 'application/json');
// THE TRICK IS THAT DIE RUNS FIRST
// THUS SENDS YOUR RESPONSE YOU THEREBY
// STOPPING THE RETURN FROM FIRING... ;-)
return die(json_encode($resp));
}
}
}
Perhaps this very Old Trick still works for you... ;-)

Related

Laravel Create a request internally Resolved

I need to recreate a resquest so that it behaves like a call via api to go through the validator, but my $request->input('rps.number') always arrives empty, although I can see the data in the debug
I also couldn't get it to go through the laravel validator
I can't use a technique to make an http call, because I need to put this call in a transaction
<?php
$nota = new stdClass();
$rps = new stdClass();
$rps->numero = (int)$xml->Rps->IdentificacaoRps->Numero;
$rps->serie = (string)$xml->Rps->IdentificacaoRps->Serie;
$rps->tipo = (int)$xml->Rps->IdentificacaoRps->Tipo;
$nota->rps = $rps;
$controller = new NotaController(new Nota());
$content = new StoreNotaRequest();
$content->request->add($nota);
$result = $controller->store($content);
StoreNotaRequest
<?php
class StoreNotaRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
$request = $this->request;
return [
'rps.numero' => 'required_with:rps|numeric|between:1,999999999999999',
'rps.serie' => 'required_with:rps|string|min:1|max:5',
'rps.tipo' => 'required_with:rps|integer|in:1,2,3'
];
}
}
NotaController
<?php
class NotaController extends Controller
{
private Nota $nota;
public function __construct(Nota $nota)
{
$this->nota = $nota;
}
public function store(StoreNotaRequest $request): JsonResponse
{
// $validated = $request->validated();
try {
$nota = DB::transaction(function () use ($request) {
$request->input('rps.numero');
});
return response()->json($nota);
} catch (Throwable $e) {
return response()->json($data, 409);
}
}
}
Solution
the solution was a little too verbose, I believe it is possible to solve with less code.
more does what it needs to go through the validation of the data contained in the StoreNotaRequest
and it returns an http response, in addition to being able to put all these isolated calls in a single transaction
DB::beginTransaction();
$errors = [];
foreach ($itens as $item) {
$controller = new NotaController(new Nota());
$request = new StoreNotaRequest();
$request->setMethod('POST');
$request->request->add($nota);
$request
->setContainer(app())
->setRedirector(app(Redirector::class))
->validateResolved();
$response = $controller->store($request);
if ($response->statusText() !== 'OK') {
$errors[$item->id] = 'ERROR';
}
}
if (count($errors) === 0) {
DB::commit();
} else {
DB::rollBack();
}

How to compare otp number without reload page which send in sms?

I want to compare otp numbers, which i type in textbox and sms otp sent to the number through api calling controller in laravel.
i use laravel5.6 and php 7.2.3
public function otpverify(Request $req)
{
$otpenter=$req->txtotp;
if ($otpenter==$otp)
{
return redirect()->action('JaincountController#create')
}
else
{
return view('jaincount_user/verification');
}
}
public function makeRequest(Request $req)
{
$client = new Client();
$otp=rand(10000,4);
// $data=
$data = array('adhar'=>$req->txtadharnumber,'drp'=>$req->drpcode,'mobilenumber'=>$req->txtnumber);
$response = $client->request('POST','http://192.168.1.9/jaincountapi/public/api/otpsms',[
'form_params'=>[
'adharcardnumber'=>$req->txtadharnumber,
'mobilecode'=>$req->drpcode,
'mobilenumber'=>$req->txtnumber,
'otp'=>$otp
]
]);
$response = $response->getBody();
return json_decode($response,true);
}
i want to compare textbox otp number and sms otp number sent through api calling and redirect with another controller in laravel5.6
The thing is you must store your otp in database or in session variable.
(Documentation: https://laravel.com/docs/5.8/eloquent)
You can store otp in database like
public function makeRequest(Request $req)
{
$client = new Client();
$otp=rand(10000,4);
// $data=
$data = array('adhar'=>$req->txtadharnumber,'drp'=>$req->drpcode,'mobilenumber'=>$req->txtnumber);
//CHANGES
User::where('phone_number',$req->txtnumber)->update(['otp'=>$otp]);
$response = $client->request('POST','http://192.168.1.9/jaincountapi/public/api/otpsms',[
'form_params'=>[
'adharcardnumber'=>$req->txtadharnumber,
'mobilecode'=>$req->drpcode,
'mobilenumber'=>$req->txtnumber,
'otp'=>$otp
]
]);
$response = $response->getBody();
return json_decode($response,true);
}
you can retrieve it using eloquent in Laravel using
public function otpverify(Request $req)
{
$otpenter=$req->txtotp;
//CHANGES
$otp = User::where('phone_number', $phone_number)->first()->otp;
if ($otpenter==$otp)
{
return redirect()->action('JaincountController#create')
}
else
{
return view('jaincount_user/verification');
}
}
after entering the correct otp clear that in database.
Or you can use session.you can use session in two ways
1.php default session
2.Laravel Session
let us see php default session
(documentation:https://www.php.net/manual/en/book.session.php)
public function makeRequest(Request $req)
{
$client = new Client();
$otp=rand(10000,4);
// $data=
$data = array('adhar'=>$req->txtadharnumber,'drp'=>$req->drpcode,'mobilenumber'=>$req->txtnumber);
//CHANGES
session_start();
$_SESSION['otp'] = $otp
$response = $client->request('POST','http://192.168.1.9/jaincountapi/public/api/otpsms',[
'form_params'=>[
'adharcardnumber'=>$req->txtadharnumber,
'mobilecode'=>$req->drpcode,
'mobilenumber'=>$req->txtnumber,
'otp'=>$otp
]
]);
$response = $response->getBody();
return json_decode($response,true);
}
you can retrieve it by
public function otpverify(Request $req)
{
$otpenter=$req->txtotp;
//CHANGES
session_start();
$otp = $_SESSION['otp']
if ($otpenter==$otp)
{
return redirect()->action('JaincountController#create')
}
else
{
return view('jaincount_user/verification');
}
}
let us use laravel session
(documentation: https://laravel.com/docs/5.2/session)
//important
use Illuminate\Support\Facades\Session;
public function makeRequest(Request $req)
{
$client = new Client();
$otp=rand(10000,4);
// $data=
$data = array('adhar'=>$req->txtadharnumber,'drp'=>$req->drpcode,'mobilenumber'=>$req->txtnumber);
//CHANGES
Session::put('otp',$otp)
$response = $client->request('POST','http://192.168.1.9/jaincountapi/public/api/otpsms',[
'form_params'=>[
'adharcardnumber'=>$req->txtadharnumber,
'mobilecode'=>$req->drpcode,
'mobilenumber'=>$req->txtnumber,
'otp'=>$otp
]
]);
$response = $response->getBody();
return json_decode($response,true);
}
you can retrieve it by
//important
use Illuminate\Support\Facades\Session;
public function otpverify(Request $req)
{
$otpenter=$req->txtotp;
//CHANGES
$otp = Session::get('otp') //best way to use is flash. see the full documentation
if ($otpenter==$otp)
{
return redirect()->action('JaincountController#create')
}
else
{
return view('jaincount_user/verification');
}
}

How to produce API error responses in Laravel 5.4?

Whenever I make a call to /api/v1/posts/1, the call is forwarded to the show method
public function show(Post $post) {
return $post;
}
in PostController.php resourceful controller. If the post does exist, the server returns a JSON response. However, if the post does not exist, the server returns plain HTML, despite the request clearly expecting JSON in return. Here's a demonstration with Postman.
The problem is that an API is supposed to return application/json, not text/html. So, here are my questions:
1. Does Laravel have built-in support for automatically returning JSON if exceptions occur when we use implicit route model binding (like in show method above, when we have 404)?
2. If it does, how do I enable it? (by default, I get plain HTML, not JSON)
If it doesn't what's the alternative to replicating the following across every single API controller
public function show($id) {
$post = Post::find($id); // findOrFail() won't return JSON, only plain HTML
if (!$post)
return response()->json([ ... ], 404);
return $post;
}
3. Is there a generic approach to use in app\Exceptions\Handler?
4. What does a standard error/exception response contain? I googled this but found many custom variations.
5. And why isn't JSON response still built into implicit route model binding? Why not simplify devs life and handle this lower-level fuss automatically?
EDIT
I am left with a conundrum after the folks at Laravel IRC advised me to leave the error responses alone, arguing that standard HTTP exceptions are rendered as HTML by default, and the system that consumes the API should handle 404s without looking at the body. I hope more people will join the discussion, and I wonder how you guys will respond.
I use this code in app/Exceptions/Handler.php, probably you will need making some changes
public function render($request, Exception $exception)
{
$exception = $this->prepareException($exception);
if ($exception instanceof \Illuminate\Http\Exception\HttpResponseException) {
return $exception->getResponse();
}
if ($exception instanceof \Illuminate\Auth\AuthenticationException) {
return $this->unauthenticated($request, $exception);
}
if ($exception instanceof \Illuminate\Validation\ValidationException) {
return $this->convertValidationExceptionToResponse($exception, $request);
}
$response = [];
$statusCode = 500;
if (method_exists($exception, 'getStatusCode')) {
$statusCode = $exception->getStatusCode();
}
switch ($statusCode) {
case 404:
$response['error'] = 'Not Found';
break;
case 403:
$response['error'] = 'Forbidden';
break;
default:
$response['error'] = $exception->getMessage();
break;
}
if (config('app.debug')) {
$response['trace'] = $exception->getTrace();
$response['code'] = $exception->getCode();
}
return response()->json($response, $statusCode);
}
Additionally, if you will use formRequest validations, you need override the method response, or you will be redirected and it may cause some errors.
use Illuminate\Http\JsonResponse;
...
public function response(array $errors)
{
// This will always return JSON object error messages
return new JsonResponse($errors, 422);
}
Is there a generic approach to use in app\Exceptions\Handler?
You can check if json is expected in the generic exception handler.
// app/Exceptions/Handler.php
public function render($request, Exception $exception) {
if ($request->expectsJson()) {
return response()->json(["message" => $exception->getMessage()]);
}
return parent::render($request, $exception);
}
The way we have handled it by creating a base controller which takes care of the returning response part. Looks something like this,
class BaseApiController extends Controller
{
private $responseStatus = [
'status' => [
'isSuccess' => true,
'statusCode' => 200,
'message' => '',
]
];
// Setter method for the response status
public function setResponseStatus(bool $isSuccess = true, int $statusCode = 200, string $message = '')
{
$this->responseStatus['status']['isSuccess'] = $isSuccess;
$this->responseStatus['status']['statusCode'] = $statusCode;
$this->responseStatus['status']['message'] = $message;
}
// Returns the response with only status key
public function sendResponseStatus($isSuccess = true, $statusCode = 200, $message = '')
{
$this->responseStatus['status']['isSuccess'] = $isSuccess;
$this->responseStatus['status']['statusCode'] = $statusCode;
$this->responseStatus['status']['message'] = $message;
$json = $this->responseStatus;
return response()->json($json, $this->responseStatus['status']['statusCode']);
}
// If you have additional data to send in the response
public function sendResponseData($data)
{
$tdata = $this->dataTransformer($data);
if(!empty($this->meta)) $tdata['meta'] = $this->meta;
$json = [
'status' => $this->responseStatus['status'],
'data' => $tdata,
];
return response()->json($json, $this->responseStatus['status']['statusCode']);
}
}
Now you need to extend this in your controller
class PostController extends BaseApiController {
public function show($id) {
$post = \App\Post::find($id);
if(!$post) {
return $this->sendResponseStatus(false, 404, 'Post not found');
}
$this->setResponseStatus(true, 200, 'Your post');
return $this->sendResponseData(['post' => $post]);
}
}
You would get response like this
{
"status": {
"isSuccess": false,
"statusCode": 404,
"message": "Post not found"
}
}
{
"status": {
"isSuccess": true,
"statusCode": 200,
"message": "Your post"
},
"data": {
"post": {
//Your post data
}
}
}
You just use use Illuminate\Support\Facades\Response;.
then, make the return as am:
public function index(){
$analysis = Analysis::all();
if(empty($analysis)) return Response::json(['error'=>'Empty data'], 200);
return Response::json($analysis, 200, [], JSON_NUMERIC_CHECK);
}
And now you will have a JSON return....

API REST don't work routes

I'm using codeigniter, for make an api rest, with the library that provide the oficial web site.
The problem is: the file routes.php doesn't redirect well. When i put localhost/API/1 into my browser apear the 404 error.
Here my controller "Apicontroller":
public function __construct() { //constructor //no tocar
parent::__construct();
$this -> load -> model("Modelocontrolador");
}
public function index_get() { //get all the info
$datos_devueltos = $this->Modelocontrolador->getPrueba(NULL, "Usuarios");
if(!is_null($datos_devueltos)){
$this->response(array("response" => $datos_devueltos), 200);
}else{
$this->response(array("response" => "No date"), 200);
}
}
public function find_get($id){ //select where
$datos_devueltos = $this->Modelocontrolador->getPrueba($id, "Usuarios");
if($id != NULL){
if(!is_null($datos_devueltos)){
$this->response(array("response" => $datos_devueltos), 200);
}else{
$this->response(array("response" => "No date"), 200);
}
}else{
$this->response(array("response" => "No dates for search"), 200);
}
}
public function index_post() { //insert in la table
if(! $this -> post("dato")){
$this->response(array("response" => "No enought info"), 200);
}else{
$datoID = $this -> Modelocontrolador -> save($this -> post("dato"),"UsuariosJJ");
if(!is_null($datoID)){
$this->response(array("response" => $datoID), 200);
}else{
$this->response(array("response" => "No found it"), 200);
}
}
}
public function index_put($id) { //"update"
if(! $this -> post("dato") || ! $id){
$this->response(array("response" => "No ha mandado informacion correcta para el update"), 200);
}else{
$datoID = $this -> Modelocontrolador -> update("Uid",$id,$this -> post("dato"),"UsuariosJJ");
if(!is_null($datoID)){
$this->response(array("response" => "Dato actualizado"), 200);
}else{
$this->response(array("response" => "Error modify"), 200);
}
}
}
public function index_delete($id) {
if(! $id){
$this->response(array("response" => "Not enought info"), 200);
}else{
$delete = $this-> Modelocontrolador -> delete("Uid",$id,"UsuariosJJ");
}
if(!is_null($delete)){
$this->response(array("response" => "Date delete"), 200);
}else{
$this->response(array("response" => "Error delete"), 200);
}
}}
And my routes file:
$route['default_controller'] = 'Apicontroller';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
/*sub-rutas*/
/*---------*/
$route["Apicontroller"]["get"] = "Apicontroller/index"; //basico
$route["Apicontroller/(:num)"]["get"] = "Apicontroller/find"; //select
$route["Apicontroller"]["post"] = "Apicontroller/index"; //insert
$route["Apicontroller/(:num)"]["put"] = "Apicontroller/index/$1"; //update
$route["Apicontroller/(:num)"]["delete"] = "Apicontroller/index/$1"; //delete
If the browser request literally uses /API then routing needs to 'see' exactly that. Also, the route rules must be explicit with the method to be called. (Hopefully the code shown reflects the mapping you had in mind.)
/*sub-rutas*/
/*---------*/
$route["API"]["get"] = "Apicontroller/index_get"; //basico
$route["API/(:num)"]["get"] = "Apicontroller/find_get/$1"; //select
$route["API"]["post"] = "Apicontroller/index_post"; //insert
$route["API/(:num)"]["put"] = "Apicontroller/index_put/$1"; //update
$route["API/(:num)"]["delete"] = "Apicontroller/index_delete/$1"; //delete
Using the above routes I created some test code. Here are those files.
The much simplified Apicontroller.
class Apicontroller extends CI_Controller
{
function __construct()
{
parent::__construct();
}
function index_get()
{
echo "API index";
}
public function find_get($id)
{ //select where
echo "API find_get $id";
}
public function index_post()
{
echo 'API index_post';
}
public function index_put($id)
{ //"update"
echo "API put $id";
}
}
I don't believe that because your Apicontroller is extending a different Class the results would change. That may be a drastic assumption.
In order to test POST calls I used these two files.
First a Testpost.php controller
class Testpost extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->helper('form');
}
public function index()
{
$this->load->view("test");
}
}
The very simple view (test.php) loaded by the above.
<?php
echo form_open("API");
echo form_submit('mysubmit', 'Submit Post!');
echo form_close();
Directing the browser to localhost/testpost shows a page with a single submit button. Pressing the button results in a screen with the text "API index_post".
Sending the browser to localhost/API/3 produces a screen with the text "API find_get 3".
localhost/API produces "API index".
Now the interesting thing (not related to your problem, but interesting).
Given the default
$route['default_controller'] = 'Apicontroller';
and the route
$route["API"]["get"] = "Apicontroller/index_get";
I expected that directing the browser to the home page localhost would produce "API index". But it doesn't. It results in a 404. Due to that behavior it might be wise to be more explicit with default_controller
$route['default_controller'] = 'Apicontroller/index_get';
Or add an index() function to Apicontroller that calls $this->index_get().
I did not test PUT or DELETE as my server isn't setup to handle them. But as GET and POST seem to function, in a righteous world, they will work.
seems like you are using PHil's REST_Controller library with CI 2.x, correct ?
If so, I would recommend you to use what I like to call an "index gateway" because you can't do per-Method routing with CI2:
class Apicontroller extends REST_Controller
{
function index_gateway_get($id){
$this->get_get($id);
}
function index_gateway_put($id){
$this->put_put($id);
}
// This is not a "gateway" method because POST doesn't require an ID
function index_post(){
$this->post_post();
}
function get_get($id = null){
if(!isset($id)){
// Get all rows
}else{
// Get specific row
}
}
function put_put($id = null){
if(!isset($id)){
// a PUT withtout an ID is a POST
$this->post_post();
}else{
// PUT method
}
}
function post_post(){
// POST method
}
}
The routing to make this work is really easy:
$route["API/(:num)"] = "Apicontroller/index_gateway/$1";
That's all you need. Phil's REST Library will redirect to the correct index_gateway_HTTPMETHOD depending on which method is used.
Each index_gateway_HTTPMETHOD will then redirect to the correct method.
As far as I know, this trick is the only way to have CI2 use a single /API/ entry point that works for all HTTP Methods.

Controller must return a response in Symfony2

I have an ajax call in my code. What I want to achieve with the call works fine. I want to delete some records from the database which is actually deleted when the method is called via ajax but as in symfony method it must return a response and thats why when the method is executed its gives me the error
My Ajax call is
$.ajax({
type: "POST",
data: data,
url:"{{ path('v2_pm_patents_trashpatents') }}",
cache: false,
success: function(){
document.location.reload(true);
}
});
And the method that is executed is
public function trashpatentAction(Request $request){
if ($request->isXmlHttpRequest()) {
$id = $request->get("pid");
$em = $this->getDoctrine()->getEntityManager();
$patent_group = $em->getRepository('MunichInnovationGroupPatentBundle:PmPatentgroups')->find($id);
if($patent_group){
$patentgroup_id = $patent_group->getId();
$em = $this->getDoctrine()->getEntityManager();
$patents = $em->getRepository('MunichInnovationGroupPatentBundle:SvPatents')
->findBy(array('patentgroup' => $patentgroup_id));
if($patents){
foreach($patents as $patent){
if($patent->getIs_deleted()==false){
$patent->setIs_deleted(true);
$em->flush();
}
}
}
$patent_group->setIs_deleted(true);
$em->flush();
}
else{
$em = $this->getDoctrine()->getEntityManager();
$patent = $em->getRepository('MunichInnovationGroupPatentBundle:SvPatents')->find($id);
if ($patent) {
$patent->setIs_deleted(1);
$em->flush();
}
}
return true;
}
}
How can I successfully return from this method ?
Any ideas? Thanks
Replace return true; with return new Response();. Also don't forget to write use Symfony\Component\HttpFoundation\Response; at the top.
You can also pass error code 200 and the content type like below.
return new Response('Its coming from here .', 200, array('Content-Type' => 'text/html'));
Here is the full example of the controller
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class WelcomeController extends Controller
{
public function indexAction()
{
return new Response('Its coming from here .', 200, array('Content-Type' => 'text/html'));
}
}

Resources