Last Updated: February 25, 2016
·
1.131K
· geetotes

POSTing to Rails apps with PHP and duct tape

Say you've got a RESTful rails app that you need to make a post request back to from a PHP script. It's not my place to ask why you would have such a mutant creation, but here's how you would do it:

First, disable CSRF protection in your Rails app (you know you're in trouble when the first thing you need to do is disable CSRF protection):

#/app/controller/application_controller.rb

protect_from_forgery :except => [:create, :update]

Now, for the sake of argument, let's say your PHP script is grabbing a model exposed as JSON, changing an attribute, then updating it back to the server.

First, we'll grab the JSON and set the variable

$json = file_get_contents("http://0.0.0.0:3000/my_modesl/13.json")
$model = json_decode($json)
$model->my_attribute = "foo"

Since this model will eventually be re-serialized and PUT back to the server, we need to get rid of the created_at and updated_at attributes, since they aren't attribute_accessible

unset($model->created_at, $model->updated_at)

Now we'll prep the most basic of HTTP requests
$url = 'http://0.0.0.0:3000/my_models/13.json';
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'PUT',
'content' => httpbuildquery(array('my_model' => $model)),
),
);

Note how the $model object has to be wrapped in an array. This is how Rails likes it. To finish up, we'll send the request.

$context  = stream_context_create($options);
$result = @file_get_contents($url, false, $context);

Heh, notice the @ in front of file_get_contents? This is to suppress any errors or warnings that may arise and is entirely optional.

Congratulations, you've created a monster!