RESTful services with jQuery, PHP and the Slim Framework

NOTE: This is the PHP version of this article and its companion app. A Java version is available here.

I have been looking for a lightweight framework to build a RESTful API in PHP. There are a number of good options out there: Slim, Epiphany, Tonic, Recess, and Frapi to name a few. They all seem like good frameworks. In the end, I chose Slim for this project for two main reasons:

  1. It’s very lightweight and focused on REST and nothing else.
  2. It supports all the HTTP methods (GET, POST, PUT, DELETE), which was a key requirement for my application.

This article (and its companion app) provides an example of building a complete RESTful API using the different HTTP methods:

  • GET to retrieve and search data
  • POST to add data
  • PUT to update data
  • DELETE to delete data

The application used as an example for this article is a Wine Cellar app. You can search for wines, add a wine to your cellar, update and delete wines.


You can run the application here. The create/update/delete features are disabled in this online version. Use the link at the bottom of this post to download a fully enabled version.

The REST API consists of the following methods:

Method URL Action
GET /api/wines Retrieve all wines
GET /api/wines/search/Chateau Search for wines with ‘Chateau’ in their name
GET /api/wines/10 Retrieve wine with id == 10
POST /api/wines Add a new wine
PUT /api/wines/10 Update wine with id == 10
DELETE /api/wines/10 Delete wine with id == 10

 

Implementing the API with Slim

Slim makes it easy to implement this API in PHP:

<?php

require 'Slim/Slim.php';

$app = new Slim();

$app->get('/wines', 'getWines');
$app->get('/wines/:id',	'getWine');
$app->get('/wines/search/:query', 'findByName');
$app->post('/wines', 'addWine');
$app->put('/wines/:id', 'updateWine');
$app->delete('/wines/:id',	'deleteWine');

$app->run();

function getWines() {
	$sql = "select * FROM wine ORDER BY name";
	try {
		$db = getConnection();
		$stmt = $db->query($sql);
		$wines = $stmt->fetchAll(PDO::FETCH_OBJ);
		$db = null;
		echo '{"wine": ' . json_encode($wines) . '}';
	} catch(PDOException $e) {
		echo '{"error":{"text":'. $e->getMessage() .'}}';
	}
}

function getWine($id) {
	$sql = "SELECT * FROM wine WHERE id=:id";
	try {
		$db = getConnection();
		$stmt = $db->prepare($sql);
		$stmt->bindParam("id", $id);
		$stmt->execute();
		$wine = $stmt->fetchObject();
		$db = null;
		echo json_encode($wine);
	} catch(PDOException $e) {
		echo '{"error":{"text":'. $e->getMessage() .'}}';
	}
}

function addWine() {
	$request = Slim::getInstance()->request();
	$wine = json_decode($request->getBody());
	$sql = "INSERT INTO wine (name, grapes, country, region, year, description) VALUES (:name, :grapes, :country, :region, :year, :description)";
	try {
		$db = getConnection();
		$stmt = $db->prepare($sql);
		$stmt->bindParam("name", $wine->name);
		$stmt->bindParam("grapes", $wine->grapes);
		$stmt->bindParam("country", $wine->country);
		$stmt->bindParam("region", $wine->region);
		$stmt->bindParam("year", $wine->year);
		$stmt->bindParam("description", $wine->description);
		$stmt->execute();
		$wine->id = $db->lastInsertId();
		$db = null;
		echo json_encode($wine);
	} catch(PDOException $e) {
		echo '{"error":{"text":'. $e->getMessage() .'}}';
	}
}

function updateWine($id) {
	$request = Slim::getInstance()->request();
	$body = $request->getBody();
	$wine = json_decode($body);
	$sql = "UPDATE wine SET name=:name, grapes=:grapes, country=:country, region=:region, year=:year, description=:description WHERE id=:id";
	try {
		$db = getConnection();
		$stmt = $db->prepare($sql);
		$stmt->bindParam("name", $wine->name);
		$stmt->bindParam("grapes", $wine->grapes);
		$stmt->bindParam("country", $wine->country);
		$stmt->bindParam("region", $wine->region);
		$stmt->bindParam("year", $wine->year);
		$stmt->bindParam("description", $wine->description);
		$stmt->bindParam("id", $id);
		$stmt->execute();
		$db = null;
		echo json_encode($wine);
	} catch(PDOException $e) {
		echo '{"error":{"text":'. $e->getMessage() .'}}';
	}
}

function deleteWine($id) {
	$sql = "DELETE FROM wine WHERE id=:id";
	try {
		$db = getConnection();
		$stmt = $db->prepare($sql);
		$stmt->bindParam("id", $id);
		$stmt->execute();
		$db = null;
	} catch(PDOException $e) {
		echo '{"error":{"text":'. $e->getMessage() .'}}';
	}
}

function findByName($query) {
	$sql = "SELECT * FROM wine WHERE UPPER(name) LIKE :query ORDER BY name";
	try {
		$db = getConnection();
		$stmt = $db->prepare($sql);
		$query = "%".$query."%";
		$stmt->bindParam("query", $query);
		$stmt->execute();
		$wines = $stmt->fetchAll(PDO::FETCH_OBJ);
		$db = null;
		echo '{"wine": ' . json_encode($wines) . '}';
	} catch(PDOException $e) {
		echo '{"error":{"text":'. $e->getMessage() .'}}';
	}
}

function getConnection() {
	$dbhost="127.0.0.1";
	$dbuser="root";
	$dbpass="";
	$dbname="cellar";
	$dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
	$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	return $dbh;
}

?>

Code Highlights

  1. Lines 7 to 12: Slim helps you route resource URIs to callback functions in response to specific HTTP request methods (e.g. GET, POST, PUT, DELETE).
  2. Lines 45 to 46 and 67 to 68: the request object makes it easy to access the request’s data: In this case the JSON representation of a wine object.
  3. The approach you use to actually retrieve the data is totally up to you. In this example, I use some simple PDO code, but you can of course use your own data access solution.

Testing the API using cURL

If you want to test your API before using it in a client application, you can invoke your REST services straight from a browser address bar. For example, you could try:

You will only be able to test your GET services that way, and even then, it doesn’t give you full control to test all the content types your API can return.

A more versatile solution to test RESTful services is to use cURL, a command line utility for transferring data with URL syntax.

For example, using cURL, you can test the Wine Cellar API with the following commands:

  • Get all wines:
    curl -i -X GET http://localhost/cellar/api/wines
    
  • Get all wines with ‘chateau’ in their name:
    curl -i -X GET http://localhost/cellar/api/wines/search/chateau
    
  • Get wine #5:
    curl -i -X GET http://localhost/cellar/api/wines/5
    
  • Delete wine #5:
    curl -i -X DELETE http://localhost/cellar/api/wines/5
    
  • Add a new wine:
    curl -i -X POST -H 'Content-Type: application/json' -d '{"name": "New Wine", "year": "2009"}' http://localhost/cellar/api/wines
    
  • Modify wine #27:
    curl -i -X PUT -H 'Content-Type: application/json' -d '{"id": "27", "name": "New Wine", "year": "2010"}' http://localhost/cellar/api/wines/27
    

The jQuery Client

Accessing your API through cURL is cool, but there is nothing like a real application to put your API to the test. So the source code (available for download at the end of this post) includes a simple jQuery client to manage your wine cellar.

Here is the jQuery code involved in calling the services:

function findAll() {
	$.ajax({
		type: 'GET',
		url: rootURL,
		dataType: "json", // data type of response
		success: renderList
	});
}

function findByName(searchKey) {
	$.ajax({
		type: 'GET',
		url: rootURL + '/search/' + searchKey,
		dataType: "json",
		success: renderList
	});
}

function findById(id) {
	$.ajax({
		type: 'GET',
		url: rootURL + '/' + id,
		dataType: "json",
		success: function(data){
			$('#btnDelete').show();
			renderDetails(data);
		}
	});
}

function addWine() {
	console.log('addWine');
	$.ajax({
		type: 'POST',
		contentType: 'application/json',
		url: rootURL,
		dataType: "json",
		data: formToJSON(),
		success: function(data, textStatus, jqXHR){
			alert('Wine created successfully');
			$('#btnDelete').show();
			$('#wineId').val(data.id);
		},
		error: function(jqXHR, textStatus, errorThrown){
			alert('addWine error: ' + textStatus);
		}
	});
}

function updateWine() {
	$.ajax({
		type: 'PUT',
		contentType: 'application/json',
		url: rootURL + '/' + $('#wineId').val(),
		dataType: "json",
		data: formToJSON(),
		success: function(data, textStatus, jqXHR){
			alert('Wine updated successfully');
		},
		error: function(jqXHR, textStatus, errorThrown){
			alert('updateWine error: ' + textStatus);
		}
	});
}

function deleteWine() {
	console.log('deleteWine');
	$.ajax({
		type: 'DELETE',
		url: rootURL + '/' + $('#wineId').val(),
		success: function(data, textStatus, jqXHR){
			alert('Wine deleted successfully');
		},
		error: function(jqXHR, textStatus, errorThrown){
			alert('deleteWine error');
		}
	});
}

// Helper function to serialize all the form fields into a JSON string
function formToJSON() {
	return JSON.stringify({
		"id": $('#id').val(),
		"name": $('#name').val(),
		"grapes": $('#grapes').val(),
		"country": $('#country').val(),
		"region": $('#region').val(),
		"year": $('#year').val(),
		"description": $('#description').val()
		});
}

 

Download the Source Code

The source code for this application is hosted on GitHub here. And here is a quick link to the source code download. It includes both the PHP and jQuery code for the application.

I’m interested in your feedback. Let me know what you think and what your experience has been building RESTful-based applications using PHP and jQuery

142 Responses to RESTful services with jQuery, PHP and the Slim Framework

  1. Daniel Wallace December 1, 2011 at 8:24 pm #

    Hey man this is a great article very similar to my methods. But I got some great ideas from this! Thanks for writing this.

  2. CambridgeSoftware December 9, 2011 at 5:56 am #

    Christophe,
    This is excellent write up. I have been using the Slim framework for some time now but I remember stuggling with it a little bit at the begining – shame that your tutorial wasn’t there back in September/October;).
    L

  3. Ian December 18, 2011 at 9:56 am #

    This is a *really* useful tutorial. I’ve only just started looking into using the Slim Framework and this really helps to break it down into a practical application. I didn’t even think it could be that useful for providing a full RESTful API.

    Doing a Backbone alternative version is even better. That’s another lightweight framework I’ve been learning and seeing both side-by-side on a practical example really helps to show the differences between the two and provides a lot of food for thought.

    Fantastic work! Thanks for the effort you’ve put in in putting together both tutorials. They’ve come at a good time for me.

  4. Brian Wigginton December 22, 2011 at 6:54 pm #

    Were you able to update the content-type headers to application/json for your api responses?

  5. twangi December 31, 2011 at 5:43 am #

    Very useful, succinct example thank you for posting Christophe.
    I was using a newly installed Mac OS x Lion client to run this example.
    For the benefit of any other users in a similar position I had to:
    1- tell Apache to permit PHP file execution by uncommenting this line (remove hash symbol) in /private/etc/apache2/httpd.conf:
    LoadModule php5_module libexec/apache2/libphp5.so

    2- install MySql via 64bit DMG at http://www.mysql.com/downloads/mysql/ and start service

    3- add a .htaccess file to the cellar/api folder as follows
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]

    4- add cellar.conf to the /private/etc/apache2/other folder as follows:

    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    Allow from all

    I initially started by trying to get the site working under my //Users/username/Sites directory following the “read me” instructions but eventually gave up and moved the project to the main WebServer/Documents folder after not being able to get rid of an error: ” File does not exist: /Library/WebServer/Documents/Users”, if anyone has any advice on that I’d be interested to hear it.

    • matt berwald January 10, 2012 at 10:52 pm #

      twangi:

      complete noob to slim and i’m running my LAMP stack on windows… any idea where i would add the cellar.conf to my windows apache ? i do not have an other folder but i do have an extra folder. any pointers are appreciated. thanks!

    • Robert Adams October 18, 2012 at 2:30 pm #

      Added this line to my .htaccess:

      RewriteBase /~adams/Cellar

      • Fany January 8, 2013 at 8:07 am #

        i just use wampserver. when open http://localhost/cellar/ it works well. While I click new wine, it alerts error.
        How to fix it? It can’t work to add RewriteBase /~adams/Cellar .
        I have other questions.
        First, when click ‘delete’,it can’t redirect.
        Second, when you modify name ,then save,it can’t display in the left at the same time.
        I have already read part3 and final, maybe I can rewrite it. But I really want to know the final version of php.

  6. Ron January 8, 2012 at 4:28 am #

    What php server did you run on?

  7. Kishan January 10, 2012 at 11:59 am #

    Well you online test application doesn’t seem to run!! shows no wines and when i deploy the source code over my sever results same. Help!

    • sachin tyagi February 18, 2014 at 2:10 am #

      if your app is not responding. Add the below line :
      var data =$.parseJSON(data);
      into renderList(data) function into main.js file

  8. Kishan January 10, 2012 at 12:02 pm #

    online testpage doesn’t seem to run it displays no content except the html part. and it results the same when i deploy the source code over my webserver

    • sachin tyagi February 18, 2014 at 1:46 am #

      if your app is not responding. Add the var data = JSON.parse(data); into renderList(data) function into main.js file

      • kinsay September 6, 2014 at 6:39 am #

        Hi! The Api works fine using curl, however, when tring to GET the info from the html it doesn´t work.

        I´ve tred adding var data = JSON.parse(data); or var data =$.parseJSON(data); and nothing worked. I have checked the rootURL in main.js and it´s ok…

        Any hints??

        • kinsay September 7, 2014 at 5:10 am #

          Solved: ‘www.’ was missing from the urlroot

    • Patrick July 17, 2014 at 12:01 pm #

      Kishan, did you figure out how to fix this? I am having the same issue.

  9. Farhan 'AlfaTrion' Jiwani January 13, 2012 at 9:42 pm #

    thank you so much. this was amazingly helpful :)

  10. captainaj January 18, 2012 at 10:35 am #

    Hi Christophe, I got the app *almost* running. After all settings, the database is imported but the wine data wouldn’t load (right on homepage). Any idea? Thanks for your help!

  11. captainaj January 18, 2012 at 10:43 am #

    I figured out: pay attention to rootURL and JSON, firebug is your friend! Thanks for the useful tutorial Christophe!

    • Amany June 22, 2012 at 2:58 am #

      the add function is not working any idea ?
      also the update function give me parser error any solution so far?

      • Sree July 19, 2012 at 5:50 am #

        @Amany:
        Please comment the line
        Line No. 46: error_log(‘addWine\n’, 3, ‘/var/tmp/php.log’); in addWine() function.
        I had the same problem. Now its working for me

    • Patrick July 17, 2014 at 12:03 pm #

      AJ, Any way you would post a little more info on how you fixed your issue here. I know it was a little while ago but hope you remember!

  12. Jason January 21, 2012 at 12:57 pm #

    this is great script, just a question, how do i go about getting this to support chinese, i had it all going but the json return ?????? and it displays correctly in phpmyadmin, any help would be great cheers

    Jason

  13. Fred February 16, 2012 at 11:24 pm #

    Hello,

    I’ve been struggling with Backbone and your example for 2 days now (no kidding… I’m getting crazy!) and still haven’t found a way to make it work. I’m sorry and I must agree I’m no real programmer, but I would really like to understand all this :
    - I’ve downloaded your app (part1) with the PHP back-end. I’ve installed it on my localhost, re-read the changes you mention in you readme file… and I still get a 404 error on …/…/api/wines (like file index.php doesn’t exists) in my Firebug console! Result : no wine in the list. I feel like the Slim framework doesn’t do its job. Isn’t it supposed to catch the call and redirect it to index.php which then looks in the database?
    - I’ve tried putting it on a web server (feeling my localhost might be wrong). I had a 500 internal error on a first server (on a free webserver). I had a 404 error again on my website server.

    Sorry for this long comment which is actually more a desperate call for help, but I did spend about 15 hours in 2 days on that and I am really getting crazy. I am actually totally unable to use Backbone with server side data saving (quite a shame…). Eventually I’d like to change your Slim usage by working on files instead of a Mysql database, (so my database is not set on my remote servers tests _although I set it on my localhost), but I don’t think this is the problem.
    If you (or anybody reading this) feel like helping me a little with that one, I’d greatly appreciate. I have the feeling I’m missing quite an important thing here…
    You can email me if you prefer.
    Thanks !

    Fred.

    • Fred February 18, 2012 at 5:14 pm #

      Well… After struggling with all those news things to me, I found out it was a mod_rewrite problem on the server…
      My bad….

    • dragan June 28, 2013 at 6:43 am #

      just put apiUrl:app/index.php instead app

    • Kingsley December 20, 2013 at 4:36 am #

      Hi Fred, Can you please explain what you did to fix this issue. In particular what needed change and how did you set mod_rewrite working again. This is my desperate call for help. Thanks in advance.

  14. Francois February 24, 2012 at 8:15 am #

    i use xampp and the server refuses the http delete method.
    Does anyone know how to enable the delet method on xampp.

    • James February 29, 2012 at 6:14 am #

      I’m not using Slim framework yet. I assumed your function contain PDO code to manage database, could you check if your database account has “delete” privilege?

  15. Ryan April 6, 2012 at 10:21 am #

    Fantastic example, thanks! There are lots of REST tutorials about, but few worked examples that really illustrate the concepts.

  16. Mulatto401 April 7, 2012 at 8:39 pm #

    Thanks for this post. You have helped me get started with Slim!!

  17. Titus April 13, 2012 at 5:34 am #

    Awesome tutorial.
    I am trying to adjust this to be able to upload an image, in the example you provided maybe like an image of a wine bottle, is this easy to add to the API?
    Thanks!!
    Titus

  18. العاب April 18, 2012 at 3:05 am #

    nice example but what about header for json and how to set http cache settings
    thanks

  19. silvioprog April 23, 2012 at 2:58 am #

    Very nice article, guy! :)

    Thank you for this powerfull REST+Ajax demonstration!

    []‘s

    Silvio Clécio.

  20. Francisc May 30, 2012 at 10:22 pm #

    Hi Christophe,
    Why did you choose to use $db=getConnection(); instead of a global $db variable?
    Thanks for the insight.

  21. Norman Rice June 2, 2012 at 7:55 pm #

    Excellent tutorial! I was able to adapt this to a project I had already started. Thank you so much!

  22. Pete June 5, 2012 at 7:53 pm #

    Excellent tutorial. Really taught me a lot about AJAX and JSON. One question. Any idea why it won’t work in IE9? I get just a page of blank fields in that browser. I get this is probably intended as an iOS Web app etc, but I’m just curious as to what the offender is in IE. Works great in Chrome, Safari (for iOS) and Firefox. I tried implementing this script [ http://www.json.org/js.html ] with no results.

    Thanks!

  23. Paul June 6, 2012 at 11:26 pm #

    I’m trying to implement this on my webserver I keept gettinga 404 in my console when the system first loads trying to call the initial findAll() function. I’ve double checked the rootURL variable. I’ve tried enabling and disabling RewriteBase. No matter what I do I can’t seem to get it to load. You can see it at http://dev.lonewolfdigital.com/winecellar/
    Any help would be greatly appreciated.

  24. Francisc June 19, 2012 at 10:06 am #

    Why have comments if you never answer them?

  25. Damian June 19, 2012 at 11:46 pm #

    Great article! thanks!!

  26. Kevin June 21, 2012 at 11:06 am #

    For the for the SlimPHP API to work on MacOS X 10.7 (Lion) I had to add Options +FollowSymlinks to my .htaccess file (and adjust the RewriteBase path accordingly). My .htaccess file:

    Options +FollowSymlinks
    RewriteEngine On

    # Some hosts may require you to use the `RewriteBase` directive.
    # If you need to use the `RewriteBase` directive, it should be the
    # absolute physical path to the directory that contains this htaccess file.
    #
    RewriteBase /api/

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]

  27. Amany June 22, 2012 at 5:33 am #

    the add fun is not working in the demo and the same when i install it on my machine as it gives
    internal server error although the update and delete are working perfrectly
    any solution so far?

  28. ravindranath Reddy July 11, 2012 at 6:14 am #

    Excellent script work.Really its very useful.Thank u so much……….

  29. Mike Garite July 18, 2012 at 5:35 pm #

    You sir, are a bad ass.

  30. amit July 24, 2012 at 4:09 pm #

    its a great tutorial but when trying to add new wine i am getting error “addWine error:parsererror”. i am using the code from the sample code. but still getting error any body resolved the issue.

  31. Eyal August 1, 2012 at 8:08 am #

    How can we also send with Post some parameters in the URL like xxxxx.com/5/?name=eyal

    so i want to transfer 5 as a URL parameter, and name=eyal as a query parameter

    how can i get those value

    • Arran November 22, 2012 at 9:08 am #

      Hi,
      Eyan I have the same problem…
      AddWine doesn’t work. Someone can tell us how he make it work ? only functions with GET work well.

      • Jefferson Salunga May 22, 2013 at 9:34 pm #

        $request = $app->request()

        $request->get(‘name’) // to get the value of eyal

  32. Eyal August 1, 2012 at 8:10 am #

    for add a new wine for example, how can i add query parameter like ?type=red&size=1.5

    ?

  33. Faisal September 22, 2012 at 10:05 am #

    How can I deploy project in PHP into my server with using the Slim framework ? I tried to solve the problem but I can’t find any clear solution ?

  34. Faisal September 25, 2012 at 4:34 pm #

    hello, i have problem with post function. it doesn’t work very well. I don’t know why ? can you help me please ?

  35. Bills October 2, 2012 at 2:27 am #

    Excellent tutorial!!!

    How does Slim framework handle load? Say 100 transactions/sec or more.

  36. Jefferson Salunga October 9, 2012 at 5:54 am #

    it works fine for me! thanks!

    my concern now is the security issue. because you can delete an item using command line.

  37. Drew October 30, 2012 at 1:08 pm #

    Great article. Are there any resources on how to best secure the API calls with Slim? I am not using user logins or OAuth, just need to generate secure keys to transfer the data on the backend.

  38. Gun November 7, 2012 at 2:20 pm #

    Hi, nice article. So far I’ve used only Tonic but I want to know about other PHP Restful frameworks. With Tonic we can setup our script to accept and provide certain mimetype. For example, a GET method to http://localhost/cellar/api/wines/5 which request ACCEPT array is set to contain image/png would give an image, text/html would give a html, application/pdf would give a pdf file, and so forth. Can Slim do this?

  39. Arran November 22, 2012 at 9:13 am #

    Same problem : How can we also send with Post some parameters in the URL like xxxxx.com/5/?name=eyal

    so i want to transfer 5 as a URL parameter, and name=eyal as a query parameter

    how can i get those value

    Someone found a solution ?

    Thanks

  40. Silvio Clécio December 9, 2012 at 11:19 pm #

    Nice post, thank you! :)

  41. Joe December 13, 2012 at 11:12 am #

    I really love this example. Clean, easy and the ajax makes it feel nice. The only problem I have is a massive hesitation when I click on a wine, even on localhost. How is it that with no latency it can take 2-3 seconds for the wine data to show up. I would think that it should load up in under a millisecond. Where is the bottleneck?

    • Joe December 14, 2012 at 10:43 am #

      So after a few hours of debugging and narrowing it down I discovered that the slowdown came from using “localhost” to connect to the db. By using “127.0.0.1″ the hesitation is cleared up.

  42. majun8cn December 14, 2012 at 7:25 am #

    I found that the ruby on rails based solution is also very simple and straightforward, the RESTful url looks slightly different.

    I create a similar solution by running a few commands. No single line of code.

    rails new wine_cellar
    rails generate scaffold Wine name:string grapes:string country:string region:stri
    ng year:number note:text imgsrc:string
    rake db:migrate
    rails server

    That is it.

    The RESTful interface looks like:
    curl -i -X GET http://localhost:3000/wines.json

  43. Ice December 14, 2012 at 7:52 am #

    The tutorial is great. I successfully deployed the working files to my localhost server and it works perfectly fine after I comment line 45 on index.php. Hopefully I can integrate Slim framework to my knockout js & jquery mobile project.

    I have only one question, how api/index.php called in our app? Since index.php was not declared in js/main.js.

  44. etrusco December 17, 2012 at 9:40 am #

    Wonderful tutorial …

  45. spiros January 29, 2013 at 1:24 pm #

    hello there! thanks for this nice post!

    for those having problem with the .htaccess file (http://localhost/cellar/api/wines 404 (Not Found) ), take a glance at httpd.conf file (you might have to change AllowOverride All)

    • Krishnan July 30, 2014 at 2:09 am #

      Thank you Spiros! Appreciated!

  46. vaibhav April 30, 2013 at 12:42 am #

    Thanks for the post. I am very new to php, mysql and REST but I could create my first working app exclusively using this article alone.

  47. Uwe May 7, 2013 at 1:17 pm #

    Hi,

    thx this is great, but i’ve one question (maybe off-topic). How to secure the access? Is there any simply way to implement (simple) authentication?

    Any Ideas?

    UR

  48. dlsooklb May 9, 2013 at 5:08 am #

    Hi! I’ve loved your article.

    I would like to leave two little suggestions.

    As other users has asked, you could set the encoding of the responses to json using this before your echo’s:

    $app = Slim::getInstance();
    $app->contentType(‘application/json’);

    And to get the correct response code you could use this in the catch block, just before your echo:

    $app = Slim::getInstance();
    $app->response()->status(500); //500 == internal server error or 400 == bad request

  49. Bart May 11, 2013 at 2:04 pm #

    Nice tutorial! Actually I just made my first (working) API with it. But now I want to hook my API up to a mobile app I am working on (phonegap etc). But it is not clear to me how I can load JSON data from the Slim Api. Do I actually need JSONP for this, and is Slim suited for that? It seems like quite a standard application, but I can’t find how to connect the API to my App.
    Thanks in advance for any help, tips & solutions!

  50. java question bank May 13, 2013 at 8:26 am #

    hi this is is very useful to me . thanq for giving this information.

  51. pure green coffee May 15, 2013 at 11:51 am #

    I tend not to leave a leave a response, but I browsed some remarks here RESTful
    services with jQuery, PHP and the Slim Framework |
    Christophe Coenraets. I do have a couple of
    questions for you if you do not mind. Is it just me or do a few of these comments look like they are left by brain
    dead people? :-P And, if you are posting at additional online sites,
    I’d like to keep up with you. Could you post a list of the complete urls of your shared sites like your Facebook page, twitter feed, or linkedin profile?

    • Jefferson Salunga May 23, 2013 at 4:15 am #

      i think they need to read also the Slim documentation.. i have many question too.. but after i read the documentation.. im very happy using slim now! and also some googling! =)

  52. Matt Dance May 21, 2013 at 4:19 pm #

    In using this code, I get Class ‘Slim” not found. Did I not install Slim right?

    • David June 1, 2013 at 8:03 am #

      It appears so. I have installed and it worked fine. Though, upgraded to the latest Slim package. If you need any help with getting this up and running just shout (d aaattt my domain).

  53. David June 1, 2013 at 7:59 am #

    Many thanks for a great tutorial. I have touched Slim a bit but struggled with implementing authentication and rating. Therefore, ended up using Laravel instead although still think Slim is much more lightweight and probably better for my app. Oh well, I might go back one day and try again once have learned more about how frameworks work.

    For those looking for PHP RESTful frameworks I have put together a quick list with rather modest descriptions (will try to improve and add an objective view as I get into details for each of them). Also, there is a poll so feel free to vote.

    http://davss.com/tech/php-rest-api-frameworks/

    I hope it helps anyone with making decision.

  54. Jan June 8, 2013 at 8:35 am #

    super bad, typical XSS-hole pattern:
    echo ‘{“error”:{“text”:’. $e->getMessage() .’}}’;

    secure:
    $data = array(‘error’=> array(‘text’=>$e->getMessage()));
    echo json_encode($data);

    bad:
    echo ‘{“wine”: ‘ . json_encode($wines) . ‘}’;

    better:
    $data = array(‘wine’ => $wines);
    echo json_encode($data);

    • myself June 28, 2013 at 3:29 pm #

      Are you really, REALLY sure that the code fragments you quoted constitute XXS-holes?

      • myself June 28, 2013 at 3:30 pm #

        of course, I meant “XSS” :)

  55. darkhorn June 11, 2013 at 9:19 am #

    Why everything is in one single file? How we can separate them?

  56. Ayaz June 17, 2013 at 11:29 am #

    Excellent, All doubts are cleared about (express, mongodb) with nodejs.

    Thanks :-)

  57. Pablo Neutrino June 17, 2013 at 9:08 pm #

    very helpful! thanks dude!!!!

  58. Carles July 4, 2013 at 4:51 am #

    Greatttt!!!!!!! very useful!!! maravilloso amigo…
    Justo lo que necesitaba…
    Best regards, un abrazo from Barcelona

  59. Nbaleli July 14, 2013 at 8:15 am #

    Great article, Well written and understandable even for a complete newbie, like me!
    Thank you.

  60. Billy July 25, 2013 at 7:55 pm #

    So, I’m still having problem. I put all the files on my localhost, and I made all the path changes and made the DB config changes.

    The errors that are being thrown have to do with the directory structure, i.e., when I try to search, I get a 404 because “localhost/search/query” doesn’t exist.

    Can someone explain the htaccess/write rules I need to implement?

    Thanks.

  61. Batuhan Küçükali August 4, 2013 at 8:33 am #

    Thank you. Great article. I am looking article.

  62. Kapil August 10, 2013 at 2:23 am #

    Thanks, for the good article.

    I am able to see all get services working for this example. However when I am tring for “POST” or “PUT” it gives me 500 error. Can please someone help me for a solution.

    Thank in advance.

    Regards,
    Kapil

  63. luffy September 4, 2013 at 2:06 am #

    hi,
    Thanks for this article..Complete Noob question… i m using sencha touch which uses a similar ajax request like in jquery.. so thats fine but if i send parameters seperately as parameters using post method and suppose in php( call them $_post[params]) instead of sending them in a the URL is that not restful??..if it is not then what is that method called….thanks a lot

    regards

  64. David September 29, 2013 at 2:08 pm #

    Thanks, this was very clear and usefull

  65. John Kuiper October 8, 2013 at 11:51 am #

    The tutorial is great and simple.
    But I can’t get it working.
    Firebug give me this error: [17:46:32.693] GET http://localhost/cellar/api/wines [HTTP/1.1 404 Not Found 8ms]

    I’ve changed the main.js (var rootURL = “http://localhost/cellar/api/wines”;)

    Also curl gives an 404.

    do I have to change something in the .htaccess?

  66. John Kuiper October 10, 2013 at 8:51 am #

    My modwrite was not working.
    After reinstall apache and php, te problem is solved.

    With curl I get the requested data.
    But my browser is not show data.
    The main.js is extended by this function:

    function findAll() {
    console.log(‘findAll’);
    $.ajax({
    type: ‘GET’,
    url: rootURL,
    dataType: “json”, // data type of response
    success: renderList,
    error : alert(‘data error’)
    });
    }

    An error occured when retrieving data back the index.php script.

    Something is wrong in the js script but I can’t find it.

    • John Kuiper October 11, 2013 at 10:24 am #

      Finally, it works.

      I’ve had n DNS type error in main.js, therefore the client couldn’t get any information.

  67. me October 18, 2013 at 4:18 am #

    GET and DELETE is working, but when I try POST using cURL it send ‘could not resolve host:application”could not resolve host:new wine’ ‘could not resolve host:year’

    PUT also not working.

  68. Laurence November 4, 2013 at 4:22 pm #

    Spanish:
    Que genial que pongas todo bien explicado y con la opción de descargar el proyecto.
    Recién estoy investigando sobre Slim, y hasta ahora no había encontrado un tutorial tan explicito… y sobre todo que tenga código funcionando, he descargado y funciona muy bien, excepto por lo de agregar (he visto los comentarios de otras personas que tienen el mismo error) pero muy explícito y muy detallado.

    You are awesome ;)

  69. Christopher Stevens November 16, 2013 at 10:57 am #

    Hey, thanks for the great example! Slim-ing my upcoming employee business card database project (looking much like your wine project) will be a good improvement over my habitual methods. I’m also a fan of your getConnection() PHP function and formToJSON() JavaScript function!

  70. Gabriele December 17, 2013 at 4:48 am #

    Good article, is usefull, now I’m trying to figure out a little variation of the case. First in place of wine I have put something else. Second in place of jQuery I will put angular.js or Backbone.js

    Any way thank you!

  71. Hamdan December 25, 2013 at 12:14 am #

    Hey, thanks for this article. but i have a problem. i can’t add the wine to database.
    when i add, always show error message.
    thank’s before.

  72. Khoi December 30, 2013 at 10:57 pm #

    Very thanks about your suggestion

  73. Alex January 18, 2014 at 4:05 pm #

    For those of u who have problems with add and put, try to write \Slim before Slim::getInstance()->request();
    like
    \Slim\Slim::getInstance()->request();

    and change line 5 to:
    $app = new \Slim\Slim();

    best regards
    alex

    • Ciaran October 22, 2014 at 12:03 pm #

      This is an Awesome Simple comment thank you for your help. Saved my Day and added value to an all ready invaluable tutorial.

  74. blader January 30, 2014 at 2:37 pm #

    plase!!!! help me!!! please.

    I can’t use the POST whit ajax,
    I can only do gets..

    • Jonathan G February 6, 2014 at 8:06 pm #

      simply remove the following line from the addWine() function:

      “error_log(‘addWine\n’, 3, ‘/var/tmp/php.log’);”

      • Robert June 19, 2014 at 6:15 pm #

        event after removing – “error_log(‘addWine\n’, 3, ‘/var/tmp/php.log’);”

        I am not able to achieve the results.
        Can you share CURL Request format as well

  75. Jonathan G February 6, 2014 at 8:05 pm #

    To fix the Add Wine problem… simply remove the following line from the addWine() function:

    “error_log(‘addWine\n’, 3, ‘/var/tmp/php.log’);”

    Then everything works brilliantly

    Great tutorial!

  76. Felix February 11, 2014 at 3:08 pm #

    can’t seem to get the PUT working

    Here is my info

    // curl -i -X PUT -H ‘Content-Type: application/json’ -d ‘{“id”:”2″, username”: “winey”, “first_name”: “mr”, “last_name”: “wine”, “address”: “la”}’ http://localhost/api/users/2

    function updateUser($id) {
    $request = \Slim\Slim::getInstance()->request();
    // $body = $request->getBody();
    // $user = json_decode($body);
    $user = json_decode($request->getBody());
    $sql = “UPDATE users SET username=:username, first_name=:first_name, last_name=:last_name, address=:address WHERE id=:id”;
    try {
    $db = getConnection();
    $stmt = $db->prepare($sql);
    $stmt->bindParam(“id”, $id);
    $stmt->bindParam(“username”, $user->username);
    $stmt->bindParam(“first_name”, $user->first_name);
    $stmt->bindParam(“last_name”, $user->last_name);
    $stmt->bindParam(“address”, $user->address);
    $stmt->execute();
    $db = null;
    echo json_encode($user);
    } catch(PDOException $e) {
    echo ‘{“error”:{“text”:’. $e->getMessage() .’}}’;
    }
    }

  77. sachin tyagi February 19, 2014 at 12:49 pm #

    if your app is not responding.

    Add the var data = JSON.parse(data);

    into renderList(data) function into main.js file as first line.

  78. Manoj Madhavan March 26, 2014 at 6:07 am #

    Hi, Great Tutorial for Restful api.

  79. Pico April 1, 2014 at 5:25 am #

    Merci beaucoup pour votre application, elle fonctionne directement bien !

    Attention pour les francophones, il faut que votre serveur web (apache) ait le fichier .htaccess activé dans le répertoire /www/cellar/api/ ainsi que le module de récriture des url activé. Vous trouverez les commandes et instructions nécessaires sur le site ubuntu-fr.org pour apache et la création de la base “cellar” dans mysql. Bonne recherche ;)

    Encore merci à Christophe Coenraets et à chacun pour ses commmentaires.

  80. David April 17, 2014 at 8:51 am #

    Great tutorial who helped me to understand how Slim works with real informations.
    One thing is “missing”, an example who use an oauth authentification to secure the API.
    If you have any example…
    Thank you.

  81. I know this web site offers quality based articles or reviews and other stuff, is there any other
    site which presents such stuff in quality?

  82. Cedric D. Anidie May 6, 2014 at 6:32 pm #

    This is a very simple but great article.
    I’ve learn alot.

    Thank you.

  83. Claytonzesvlh.pen.io May 19, 2014 at 2:40 pm #

    Today we’re equally experienced in online marketing, including development
    of websites, content marketing, SEO, local search, you know be page 1 ranking of Google,
    pay per click. 10 Professional direct marketers need to keep in mind that your envelope has only
    one important job – to get opened.

  84. Adha May 20, 2014 at 3:13 am #

    sir
    i got this error
    Slim Application Errorbody{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{display:inline-block;width:65px;}Slim Application ErrorThe application could not run because of the following error:Details:Message: error_log(/var/tmp/php.log): failed to open stream: No such file or directoryFile: C:\xampp\htdocs\cellar\api\index.phpLine: 45Stack Trace:#0 [internal function]: Slim::handleErrors(2, ‘error_log(/var/…’, ‘C:\xampp\htdocs…’, 45, Array)
    #1 C:\xampp\htdocs\cellar\api\index.php(45): error_log(‘addWine\n’, 3, ‘/var/tmp/php.lo…’)
    #2 [internal function]: addWine()
    #3 C:\xampp\htdocs\cellar\api\Slim\Route.php(392): call_user_func_array(‘addWine’, Array)
    #4 C:\xampp\htdocs\cellar\api\Slim\Slim.php(1052): Slim_Route->dispatch()
    #5 C:\xampp\htdocs\cellar\api\index.php(14): Slim->run()
    #6 {main}

    please help me

    if i using method GET there is no problem

  85. Gideon Maina June 1, 2014 at 10:02 am #

    Good job thanks and maybe you could be posting tips and tweaks too …!!!! Great!

  86. Luis June 2, 2014 at 7:31 pm #

    Your tutorial was very helpful to build my web application, if I not read this article, today I’m not able to do what I did in my project.

    Thanks, and sorry for my bad English

  87. Scott Warnick June 10, 2014 at 5:35 pm #

    I am struggling with URL rewriting on WAMP. With the .htaccess file as distributed I get a 200 error. If remove the .htaccess file I get a 404 error as I should. Can anyone supply details on how to make this work? My apologies if it has been answered already.

  88. Robert June 19, 2014 at 6:11 pm #

    Any one have any idea – why POST is not working? Why its taking values from request??

    here is output
    C:\curl>curl -i -X POST -H ‘Content-Type: application/json’ -d ‘{“name”: “New Wine”, “year”: “2009″}’ http://localhost:88/cellar/api/wines
    curl: (6) Could not resolve host: application
    curl: (6) Could not resolve host: New Wine,
    curl: (6) Could not resolve host: year
    curl: (3) [globbing] unmatched close brace/bracket in column 5
    HTTP/1.1 200 OK
    Date: Thu, 19 Jun 2014 22:10:29 GMT
    Server: Apache/2.4.4 (Win64) OpenSSL/1.0.1d PHP/5.4.12
    X-Powered-By: PHP/5.4.12
    Set-Cookie: PHPSESSID=1394b9b8e54757bde9e7627b1f48a6d2; path=/
    Content-Length: 97
    Set-Cookie: 1394b9b8e54757bde9e7627b1f48a6d2=DEFAULT%7C0%7C2M3TMlgUx3gTlaarYzHIdD28l8q9FTcNubt55%2BUGpAo%3D%7C7456bf61db3500c8bb7b3bc38082a470ce4a2ad3; path=/
    Content-Type: text/html

    {“name”:null,”grapes”:null,”country”:null,”region”:null,”year”:null,”description”:null,”id”:”10″}
    C:\curl>

  89. John July 3, 2014 at 10:24 am #

    This is still one of the best tuts out there. I have used this as my starting template on many projects.
    So Easy.
    Thanks Again!

  90. Hire ROR Developer July 4, 2014 at 9:15 am #

    Thanks for this value able post. I have read all the things very carefully it’s really a helpful and effective post.

  91. john invictus July 15, 2014 at 9:58 am #

    thank,,thanks for creating a simple understandable tutorial

  92. Patrick July 17, 2014 at 11:58 am #

    After configuration I run the app and none of the data appears. The HTML is rendered but I am left with an empty shell of an applicaion. I noticed that the hosted example of this app also exhibits the same issue? Has anyone else experienced this and figured out how to fix it? Thanks guys! Thinking this is something simple.

  93. Sean Loper August 21, 2014 at 9:39 pm #

    I was able to fix it and update it to newest jquery, if you need help, email me : Grimmdev@gmail.com and I’ll help explain

    • Gary September 1, 2014 at 5:14 am #

      I tried to insert record or POST I encountered error, but it will insert blank information. see error below

      C:\Users\Jun-Jin>curl -i -X POST -H ‘Content-Type: application/json’ -d ‘{“name”
      : “Red Horse”, “year”: “2014″}’ http://localhost/cellar/api/wines
      curl: (6) Could not resolve host: application
      curl: (6) Could not resolve host: Red Horse,
      curl: (6) Could not resolve host: year
      curl: (3) [globbing] unmatched close brace/bracket in column 5
      HTTP/1.1 200 OK
      Date: Mon, 01 Sep 2014 09:08:53 GMT
      Server: Apache/2.4.7 (Win32) OpenSSL/1.0.1e PHP/5.5.9
      X-Powered-By: PHP/5.5.9
      Set-Cookie: PHPSESSID=b3016b573e73eaae40108f60b48374ca; path=/
      Content-Length: 97
      Set-Cookie: b3016b573e73eaae40108f60b48374ca=DEFAULT%7C0%7C2M3TMlgUx3gTlaarYzHId
      D28l8q9FTcNubt55%2BUGpAo%3D%7C7456bf61db3500c8bb7b3bc38082a470ce4a2ad3; path=/
      Content-Type: text/html

      {“name”:null,”grapes”:null,”country”:null,”region”:null,”year”:null,”description
      “:null,”id”:”45″}

      I someone can help me on this. Thanks for big help.

      regards,

      • Angom September 10, 2014 at 5:26 am #

        Hii have you solved that issue????, if you solved please share

        This is working api for POST, i remake it but its not sending in json format request

        $app->post(‘/postwine/:id’, function() use ($app) {
        // $request = \Slim\Slim::getInstance()->request();
        //$wine = json_decode($request->getBody());

        $name = $app->request->post(‘name’);
        $grapes = $app->request->post(‘grapes’);

        $data = array($name, $grapes, …);

        $db = getConnection();
        $stmt = $db->prepare(“INSERT INTO wines(name, grapes, country, region, … ) VALUES( ?, ?, ?, …)”);
        $stmt->execute($data);
        });

  94. Gary September 1, 2014 at 3:15 am #

    Hi, newbie here in Web Services and Slim Framework. What I did today after downloading the sample in github, I successfully installed example system.

    I already tested these methods below based on the example like :
    – GET
    – PUT and
    – DELETE

    all of them are running and successfully tested but I don’t know how to run and test the POST?

    Any idea how I can test in adding records using PHP Slim Framework?

    Thanks in advance.

    • Gary September 1, 2014 at 5:16 am #

      C:\Users\Jun-Jin>curl -i -X POST -H ‘Content-Type: application/json’ -d ‘{“name”
      : “Red Horse”, “year”: “2014″}’ http://localhost/cellar/api/wines
      curl: (6) Could not resolve host: application
      curl: (6) Could not resolve host: Red Horse,
      curl: (6) Could not resolve host: year
      curl: (3) [globbing] unmatched close brace/bracket in column 5
      HTTP/1.1 200 OK
      Date: Mon, 01 Sep 2014 09:08:53 GMT
      Server: Apache/2.4.7 (Win32) OpenSSL/1.0.1e PHP/5.5.9
      X-Powered-By: PHP/5.5.9
      Set-Cookie: PHPSESSID=b3016b573e73eaae40108f60b48374ca; path=/
      Content-Length: 97
      Set-Cookie: b3016b573e73eaae40108f60b48374ca=DEFAULT%7C0%7C2M3TMlgUx3gTlaarYzHId
      D28l8q9FTcNubt55%2BUGpAo%3D%7C7456bf61db3500c8bb7b3bc38082a470ce4a2ad3; path=/
      Content-Type: text/html

      {“name”:null,”grapes”:null,”country”:null,”region”:null,”year”:null,”description
      “:null,”id”:”45″}

  95. Amit September 7, 2014 at 10:34 am #

    I can’t get this code running. There is just blank HTML when I run in xampp. Please Help.Thanks

  96. Sean Loper September 13, 2014 at 1:54 pm #

    https://drive.google.com/file/d/0B7h4Bm_Zn_MeNFNaX0NYTUNkblk/edit?usp=sharing
    This is a complete working package of the one from Github, with updated Jquery and fixes. Prepackaged just like the github svn so just follow the same setup.

  97. Powell September 14, 2014 at 1:42 pm #

    Thank You, now I first understood how Rest Slim works.

  98. Venance Edson October 1, 2014 at 10:26 am #

    The very first RESTful code to work with no problem,”ahsante sana”

Trackbacks/Pingbacks

  1. RESTful services with jQuery and Java using JAX-RS and Jersey - December 1, 2011

    [...] NOTE: This is the Java version of this article and its companion app. A PHP version is available here. [...]

  2. http://links.soudev.com.br - December 1, 2011

    RESTful services with jQuery, PHP and the Slim Framework…

    Post interessante que mostra o Slim Framework para PHP, uma solução leve para implementar facilmente um RESTFul em PHP e como consumir via AJAX com JQuery…

  3. Backbone.js Wine Cellar Tutorial — Part 1: Getting Started - December 6, 2011

    [...] I also blogged a non-Backbone version of the application here (Java back-end) and here (PHP back-end), which you can look at for [...]

  4. RESTful services with jQuery, PHP and the Slim Framework « lolososo - December 15, 2011

    [...] RESTful services with jQuery, PHP and the Slim Framework. Share this:TwitterFacebookLike this:LikeBe the first to like this post. [...]

  5. Confluence: Mobile Devices Development - January 15, 2012

    PHP…

    Yii framework…

  6. Backbone.js酒窖教程 – 第2部分:CRUD操作 | Adobe CS6 - May 24, 2012

    [...] the non-Backbone Java back-endor the PHP back-end. 作者 Christophe [...]

  7. Creating a REST API using Node.js, Express, and MongoDB - October 2, 2012

    [...] MongoDB to rewrite a RESTful API I had previously written in Java and PHP with MySQL (Java version, PHP version), and I thought I’d share the [...]

  8. RESTful services with jQuery, PHP and the Slim Framework | Christophe Coenraets | Andreas V. Bourakis - August 28, 2014

    […] RESTful services with jQuery, PHP and the Slim Framework | Christophe Coenraets. […]

  9. Creating Restful Services/API using the Slim Framework for PHP || Calling API using Jquery | Website and Mobile Apps - Articles and Tips - October 22, 2014

    […] This below link shows how to create RESTful API using Slim framework and also how to call that api using Jquery. Click Here […]

Leave a Reply

css.php