0

I'll try to simplify the question a little more. In index.blade.php I have this AJAX call that gets routed to my controller. I added a "name" to the select element so that the form serialization is easier, and I've omitted the form. It POSTS with parameters:

command
_token
value1
value2

$( "#apiselection" ).submit(function( event ) {
alert( "Handler for .submit() called." );
event.preventDefault();
var formParams = $("#apiselection").serialize();
var data = formParams;
    $.post("dicomgrid", data, function(result){
        alert(result);
        $("#APIresults").html(result);
    });
});

In routes.php I have this:

Route::post('dicomgrid', 'DicomGridController@apiCall');

which is handled by the Contoller, which is now this. I had to add use Illuminate\Http\Request to make it work.

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;

class DicomGridController extends AppBaseController
{

    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public  function apiCall(Request $request) {
        if ($request->input('command') == "Login") {
            return "test2";
        }
        else {
            return "test";
        }
    }
}

That part works.

However, what I then want to do is essentially make an AJAX call (not sure you can do that within a Controller class using jQuery or some other method, so that what I return to the original call is what I get back through that second request. There must be a better way to do that, but I do like the idea of having a controller to service all of the requests for that particular application. I am really just getting started with this, so it is mostly a learning exercise.

To elaborate, the PHP page that has some of my functions is like this, cut down version:

<?php
$option = $_POST["APICall"];
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$curl = curl_init();
curl_setopt($curl, CURLOPT_VERBOSE, TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$APIBase = 'xxx';
$userName = "xxx";
$passWord = "xxx";
$sid =null;
$studyUUID;

function CallAPI($method, $API_command, $data = false)
{
   global $curl;  // curl object
   global $APIBase;  //  base url for API calls
   global $sid;  // session id, null initially, but after login it is set for the session, 
    switch ($method)
    {
        case "POST":
            curl_setopt($curl, CURLOPT_POST, 1);

            if ($data)
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            break;
        case "PUT":
            curl_setopt($curl, CURLOPT_PUT, 1);
            break;
        default:
            if ($data)
                $url = sprintf("%s?%s", $url, http_build_query($data));
    }

    curl_setopt($curl, CURLOPT_URL, $APIBase . $API_command );
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

    if ($sid == null)  {
        curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($curl, CURLOPT_USERPWD, "login:password");
    }

    $result = curl_exec($curl);
    return $result;
}

There are other functions on that same page that depend on the initialized variable and $curl in particular. Bottom line though is that I retrieve some results, either in JSON format or some other text (like formatted Array print_f), mostly for development and testing. That is why I want a controller to handle that feature set.

So I guess my question is how do I call my functions on that page within the Controller and return the results back to my original AJAX call.

It that a stupid question or method ?

Maybe this is what I need ?

Calling a function within a Class method?

Community
  • 1
  • 1
SScotti
  • 2,158
  • 4
  • 23
  • 41

3 Answers3

2

I'm not exactly sure what your trying to perform, but here's an example of a sign in form using AJAX.

The javascript:

$("#signupForm").on('submit', function(event) {
    event.preventDefault(); 

    var formData = new FormData();
    formData.append('username', $('#username').val());
    formData.append('email', $('#email').val());
    formData.append('password', $('#password').val());
    formData.append('password_confirmation', $('#password_confirmation').val());

    $.ajaxSetup({
        headers: {'X-CSRF-Token': $('#_token').val()}
    });

    $.ajax({
        url: $("#signupForm").attr('action'),
        method: 'POST',
        processData: false,
        contentType: false,
        cache: false,
        data: formData,
        success: function(data) {
           if(data.success) {
               window.location = //Desired location for redirect
            } else {
                // If the signin wasn't successful.
            }
        },
        error: function(data) {
            // If you got an error code.
        }
    }); 
});

Here's what's happening: The code detects when the form is submitted, than prevents the default action. It creates the form data to be sent over ajax. It sends the data, and when it's returned, it checks whether or not the data's success key is true. If so, it redirects, or else, it does whatever it needs to do for an unsuccessful signin.

PHP code:

if($request->ajax()) {
    $validator = Validator::make($request->all(), /*List of rules*/);
    if($validator->fails()) {
        return response()->json([
            'success' => false,
            'message' => '' // Desired return message, normally something like "You username or password is incorrect".
        ]);
    }
    if(Auth::attempt(['email' => $request->input('email'), 'password' => $request->input('password')], $request->input('remember'))) {
        /*
         * When the javascript redirects, you may need to flash data to the next page, do it here.
         * Example: $request->session()->flash(/*Name here*/, /*What you want to flash*/)->reflash();
         */
        return response()->json([
            'success' => true,
            'route' => // If you desire you can put the route you want to redirect to.
        ]);
    }
    return response()->json([
        'success' => false,
        'message' => '' // Desired return message, normally something like "You username or password is incorrect".
    ]);
}
// Handle if the user doesn't support javascript.

Here's what's happening: First off, the code detects whether the request came through ajax or not. If it did, it creates a validator than checks if it failed. By doing that we can format our JSON response with the success set to false. If it hadn't failed, it attempts to authenticate the user. When the user was authenticated successfully, it returns "success" => true to the browser. When doing something like this, make sure to implement the code of what to do if the request didn't come through ajax to properly support clients with Javascript turned off.

Hope this helps.

Edit:

What your trying to do is really confusing, so ill try and understand. From what I can see, your attempting to make a helper file with a load of functions that you need to access in your controller. There are a few ways to do this, one is with making a global helper file.

In your composer.json, add the following:

"autoload": {
    "files": [
        // Path to the file with your helper functions.
    ]
}

Than in your controller you can use CallAPI(/*Your params*/). When declaring a helper class, please don't declare variables, only use functions. Anything you need in your function from elsewhere either use dependency injection, or inject the value into the function with example($test = 5). When you need class from elsewhere use the class at the top of the file: use Session;.

Your other option is using facades. Facades are a good way to divide up your functions into there respected categories. For example, let's make a color facade for all of our color functions.

First, you need to create the class with all your functions in it:

namespace App\Helpers\Color;

class ColorContract
{
    public function foo() {
        echo "foo";
    }
}

Next, you need to create your facade class:

namespace App\Helpers\Facades;

use Illuminate\Support\Facades\Facade;

class ColorFacade extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'Color';
    }
}

Now, you need to bind your Color class the service container. I would recommend doing this in your own service provider.

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelperServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind("Color", function() {
            $this->app->make("App\\Helpers\\Color\\Color");
        });
    }
}

Lastly, add the alias and the service provider in the app.php config file.

'providers' => [
    // Path to your service provider...
]

'aliases' => [
    'Color' => // Path to your color facade.
]

Now in your controller you would add use Color;. In your controller method using Color::foo() will echo foo.

I hope this helps.

Dastur
  • 684
  • 6
  • 23
  • there are simpler ways to serialize a form than this. Example is overly complex to be used as a base when not uploading files – charlietfl Jul 22 '16 at 00:51
  • What would you suggest otherwise? – Dastur Jul 22 '16 at 01:24
  • I edited my original question. Let me digest your initial response and I'll post follow-up. – SScotti Jul 22 '16 at 01:38
  • Thank you for the edit (Dastur). That is confusing, especially for a beginner, but that actually does make some sense. The helper solution seems a little easier to implement than using facades, which I know nothing about. It is complicated but if I can figure it out, will be helpful in learning about Laravel, which I really would like to learn. It seems very nice, uses MVC model, is well supported and has a future. All new to me. – SScotti Jul 22 '16 at 20:08
  • Glad to help sscotti – Dastur Jul 22 '16 at 20:28
  • That actually works as far as using a global helper function, although I had to read a bit to get it to work. I do have to inject the needed parameters into the call, and I initialize the curl and values in the controller. I did have to do a couple of other things, like create a service provider, HelperServiceProvider.php. I'll have to go back over the whole thing and write a procedure for that down as I wasn't takin noted along the way, but yes, it does what I need. Question about putting code in comments, how do you do that. I may want to add the solution as an answer just for reference. – SScotti Jul 22 '16 at 22:34
  • Not sure I want to figure out how to use facades as another exercise, but could be helpful in the future. I really like the Helper thing. – SScotti Jul 22 '16 at 22:37
  • As far as I know, you can't put code in comments. ´Test´. – Dastur Jul 22 '16 at 22:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/118069/discussion-between-sscotti-and-dastur). – SScotti Jul 22 '16 at 23:36
0

maybe you want

return response()->json(['something'=>'somevalue']);

with $.ajax

$.ajax({
   url:yourUrl,
   method:"POST",
   data:{
     as:'object',
   }
}).done((response)=>{
  //do something with response
});
neuronet
  • 1,139
  • 8
  • 19
0

If it's a POST request you do not need to create more arguments in the route, (that would be useful for GET requests), instead take them from the Request facade in the controller side.

Route::post('dicomgrid', 'DicomGridController@apiCall'); // good

you'll need to use Laravel's Request class, Make sure you have included the namespace in the top of controller:

use App\Http\Requests;

and bind the Request class in the controller action:

public function apiCall(Request $request){

}

And you should be able to view all the passed data using:

public function apiCall(Request $request){   
    dd($request->all())   
}    

or get them by their input name:

$request->name  || $request->input('name')

If you are using PHPStorm i'd recommend to download Laravel Plugin for namespace and classes autocompletion.

Hope this helps you, cheers.

Manuel Azar
  • 853
  • 2
  • 14
  • 24