In reply to Andy's comment, I think you can get CURLOPT_PUT to work if you provide the data using INFILE instead of POSTFIELDS. For example:
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_INFILE, $putData);
curl_setopt($ch, CURLOPT_INFILESIZE, strlen($putString));
I would guess the reason is that POST can be used with either form data or a payload, but using PUT with form data doesn't make sense.