Using AJAX in Laravel to interact with database
Asked Answered
S

3

6

I'm learning the Laravel PHP framework, based on the Model, View, Controller paradigm. I'm stuck on trying to incorporate AJAX into my simple starter application...a phonecall logger. This is where I normally give up. But I refuse!

So I have my Phonecall Model:

class Phonecall extends Eloquent
{
// Creates an instance of the database object 
}

Here's my phonecalls table:

mysql> desc phonecalls;
+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| id         | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| who        | varchar(200)     | NO   |     | NULL    |                |
| what       | varchar(200)     | NO   |     | NULL    |                |
| created_at | datetime         | NO   |     | NULL    |                |
| updated_at | datetime         | NO   |     | NULL    |                |
| initiator  | varchar(200)     | NO   |     | NULL    |                |
| info       | text             | NO   |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)

My View lists all calls (by who and what) currently in the database:

<!doctype html>
<html>
<head>
  <title>Title</title>
  <script type="text/javascript" 
           src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js">
</script>
</head>
<body>
<h1>Welcome</h1>
<p>Here's a list of recent phonecalls</p>
    <ul class="call-list">
    @foreach($phonecalls as $call)
        <li>{{ $call->who }} - {{ $call->what }} - 

        <a href="phonecalls/show/{{ $call->id }}">Show</a> | 

        {{ HTML::link('phonecalls/delete/'.$call->id, 'Delete') }} | 
        {{ HTML::link('phonecalls/update/'.$call->id, 'Update') }}
        </li>
    </ul>

    {{-- Placeholder for AJAX content --}}
    <div id="call-info">
    </div>
</body>
</html>

Here's my simple Controller:

 class Phonecalls_Controller extends Base_Controller {    

// Use $this within a method the same way you
// would use the object name outside of the class

public function get_index()
    {
            $phonecalls = Phonecall::all();
            return View::make('phonecalls.index')->with('phonecalls', $phonecalls);
    }    
// ************************************
// DISPLAY CALL INFO
public function get_show($call_id)
{
    $call = Phonecall::find($call_id);

            // WHAT GOES HERE?

}

I want the user to be able to click on "Show" in the view and have the call info display within the...

<div id="call-info">
</div>

tags in the View.


UPDATE:

Here's what did it...

My get_show() method

// ************************************
// SHOW CALL INFO
public function get_show($call_id)
{
$call = Phonecall::find($call_id);
return $call->info;
}

My Javascript

//************************************
// Phonecall AJAX Example
//************************************
$(document).ready(function() {
  $('.call-list > li > a').click(function(e) {  // e=event
     e.preventDefault();
     var id = $(this).attr('id');
     $.get(BASE+'/phonecalls/show/'+id, function(data) {
     $("#call-info").html(data);
  })
});
Serpentine answered 25/3, 2013 at 20:24 Comment(0)
D
5

This can be done in many various ways.

First, you can do this :

public function get_show($call_id)
{
    $call = Phonecall::find($call_id);

    return View::make('phonecalls.single')->with('phonecal', $call);

}

In which case you need to create a template for a single phonecall and put it in your phonecalls folder.

Another option is to return JSON response from the Laravel app :

public function get_show($call_id)
{
    $call = Phonecall::find($call_id)->first();

    return Response::eloquent($call);

}

Another option is to use javascript MVC framework to make things like fetching/updating AJAX data very easy, for example Backbone JS or Angular JS can do that.

Either way, if you want to do AJAX data you need to build an API to make a separation between regular site and AJAX data backend.

Here is my blog post with lots of details on how to accomplish this: http://maxoffsky.com/code-blog/building-restful-api-in-laravel-start-here/

Also, a great introduction for AJAX in Laravel is Code Happy by Dayle Rees, chapter AJAX content : codehappy.daylerees.com/ajax-content

Let me know if you have more questions, and approve this comment if you feel like I've helped. Thanks!

UPDATE:

To actually load stuff in from the controller (or a Laravel route) you need to use jQuery ajax, GET(to load data) or POST(to post form results) Here's an example:

 $('#get-info').click(function(e) {  // e=event
        e.preventDefault();
        var BASE = "<?php echo URL::base(); ?>";
        // attempt to GET the new content
        $.get(BASE+'phonecalls/show/2', function(data) {
            $('#content').html(data);
        });
Durango answered 25/3, 2013 at 21:48 Comment(8)
maxoffsky, I want to display the returned $call->info to the same view (the index view above) where the user clicked "Show" without the user having to refresh the page. I guess I'm missing how the $call->info makes it from the controller back to the index view and is put between the <div id="call-info></div> tags.Serpentine
Ahh, to load stuff in you need to use AJAX, in jQuery you can use .ajax or .get or .post (depending on what you need to do) In this case it can be a .get. let me update my answer a bit.Durango
Ok, great. This may be the piece I need to get it done. I'll let you know. Thanks @maxoffsky!Serpentine
Getting close @maxoffsky. I've added an update to my original question.Serpentine
If I do a dd($result) inside my controller get_show() function, I see the data array coming back to the index view.Serpentine
HA! All I needed to do in the controller is say return $call->info; and it displayed it in the view. No page refresh!Serpentine
Awesome! Glad to hear that!Durango
The final solution can be seen here: linkSerpentine
T
5

it took me a while to figure out as the examples in the webz are kind of confusing making reference to changing headers to account for csrf token and so on. Here is an example and I hope it helps someone else.

First: the form that goes in your view:

{{ Form::open(['id' => 'testForm']) }}

   <p>{{ Form::label('title', 'Title') }}
   {{ Form::text('title') }}</p>

   <p>{{ Form::label('description', 'Description') }}
   {{ Form::text('description') }}</p>

   <p>{{ Form::submit('Submit') }}</p>

{{ Form::close() }}

Second: write your route in route.php:

Route::post('ad', 'AdController@store');

Third: the Controller:

public function store()
{

if(Request::ajax()){

    $ad = new ad; 
    $ad -> title = Input::get('title');
    $ad -> description = Input::get('description');
    $ad -> save();

    $response = array(
        'status' => 'success',
        'msg' => 'Option created successfully',
    );

    return Response::json( $response );

    }

}

Fourth: The jquery ajax request:

$('form#testForm').submit(function(e){
  e. preventDefault();


  var str1 = $('input[name="title"]').val();
  var str2 = $('input[name="description"]').val();
  var str3 = $('input[name="_token"]').val();
  var data = {title:str1,description:str2, token:str3};
  //console.log(data);
  var request = $.ajax({
    url: "ad",
    type: "POST",
    data: data ,
    dataType: "html"
  });

  request.done(function( msg ) {
    var response = JSON.parse(msg);
    console.log(response.msg);
  });

  request.fail(function( jqXHR, textStatus ) {
    console.log( "Request failed: " + textStatus );
  });

  });

Thats, it. For protection you can set the Session::token() == Input::get('_token') in the controller as the if check. This is just an example that works fine to get you started. Using absolute URL might be necessary (in that case use http://www.pretty.url/ad) were www.pretty.url is your localhost or local private development url.

Thoroughfare answered 24/8, 2014 at 19:38 Comment(0)
L
0

You've to be able to intercept clicks on the "Show" link. If you make your controller restful, it should be easy to make an ajax request to your controller.

You've to send an ajax request when the user clicks on the Show link.

I suggest you to output the results as JSON, so it's pretty easy to later use js to output your results.

Lyudmila answered 25/3, 2013 at 20:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.