PDA

View Full Version : POST using CURL


mamamia
08-30-2007, 10:30 PM
There seems to be a major deficiency with the CURL option, unless I'm doing something wrong. Please help.

My goal is to have user populate a form and then POST that form to an ecommerce website. However, it appears that the names of the elements being passed in the form are the Fabrik generated names and not the labels. For example, if the ecommerce site requires an element called 'last_name' and I create this in my Fabrik form, then post it via CURL, the posted element name comes out as 'jos_fabrik_data_1___last_name'. This is not good.

This is what I have for my CURL code:

$ch = curl_init("http://www.mywebsite.com/content/view/44/69/");
curl_setopt($ch, CURLOPT_POST, true);
$str = "";
foreach($_REQUEST as $key => $val ){
$str .= "&$key=$val";
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $str);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);

And this is some test PHP code I wrote to see if I can retrieve the values from the POST (similar to what the ecommerce site would be doing):
$lastname_label = $_POST['last_name'];
$lastname_generated = $_POST['jos_fabrik_data_1___last_name'];
echo "lastname using label: " . $lastname . " <br/>"; //nothing outputted
echo "lastname using generated name: " . $lastname_generated . " <br/>"; //value comes through

thanks in advance
mamamia

cheesegrits
08-30-2007, 11:32 PM
You should have a "Session name format" option on your form (under the jump page options), allowing you to choose between 'Short' or 'Full'. 'Full' uses the 'table_name__element_name' format. 'Short' uses just 'element_name'.

-- hugh

mamamia
08-30-2007, 11:40 PM
It appears regardless of whether I select "short" or "full", I can only retrieve the full named element via PHP.

cheesegrits
08-30-2007, 11:49 PM
Oh yeah, the code that does that is in the actual buildJumpPage() logic. Doh! My bad.

In which case, just split the key up yourself:

$key = array_pop( explode( '__', $key ) );

If you want, you could global in $this->_joinTableElementStep (or whatever data structure currently in scope defines that variable), and use that instead of hard coding '__'.

-- hugh

cheesegrits
08-31-2007, 12:05 AM
PS ... this isn't really a 'major deficiency' in the CURL handling. I'd say it's more of a 'minor quirk'.

If you let Fabrik handle the POST'ing of the data, it'll do the right thing depending on the session name format you select.

It's only if you wish to run your own PHP that you get the full key names, regardless. Which is to be expected, as Fabrik has to use the 'full' format on the actual form itself, to avoid label conflicts with other elements (i.e. joined from other tables, with the same element name). And of course if you use your own PHP, you can just split the element part out of the full key, if that's what you want.

BTW, I think you'll find you don't need to do the curl_init(). Fabrik already does this, right before it evals your code:

$ch = curl_init( $this->form_submit_jumppage );
/* URL of gateway for cURL to post to*/
eval($this->curl_code);
/* this presumes that the CURL script will deal with the redirect*/


So you just need to "global $ch;".

-- hugh

mamamia
08-31-2007, 12:38 AM
Thanks for putting the time on this Hugh.

So following your suggestion of parsing, is the following correct (I am not a PHP expert)? Cuz it is not working :)

curl_setopt($ch, CURLOPT_POST, true);
$str = "";
foreach($_REQUEST as $key => $val ){
$key = array_pop( explode( '__', $key ) );
$str .= "&$key=$val";
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $str);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);

When I try to retrieve the key/value pairs as short or full format i get empty for both. Maybe I should traverse the list of all key/value pairs in the posted form and display them to see the problem. But I'm not sure how to do this in PHP.

thanks in advance.
mamamia

cheesegrits
08-31-2007, 01:20 AM
You'll need to "global" the $ch from Fabrik. Meaning the first line of your script needs to be:

global $ch;

The 'global' mechanism in PHP is there to prevent you from accidentally stomping on variables of the same name in the rest of the code. Without the "global $ch", you are working on a purely local variable which has no connection with the one Fabrik set up. Only if you "global $ch" will PHP then know that your really do want to be using the instance of $ch from Fabrik.

That may not be the only problem, but needs to be there anyway.

-- hugh

mamamia
08-31-2007, 04:43 PM
That made things much worse. Adding "global $ch;" as the first line of my CURL script now generates the following error upon form submit:

Warning: curl_setopt(): supplied argument is not a valid cURL handle resource in /home/mywebsite/www/www/components/com_fabrik/fabrik.class.php(1315) : eval()'d code on line 2

Warning: curl_setopt(): supplied argument is not a valid cURL handle resource in /home/mywebsite/www/www/components/com_fabrik/fabrik.class.php(1315) : eval()'d code on line 9

Warning: curl_setopt(): supplied argument is not a valid cURL handle resource in /home/mywebsite/www/www/components/com_fabrik/fabrik.class.php(1315) : eval()'d code on line 11

Warning: curl_exec(): supplied argument is not a valid cURL handle resource in /home/mywebsite/www/www/components/com_fabrik/fabrik.class.php(1315) : eval()'d code on line 13

Warning: curl_close(): supplied argument is not a valid cURL handle resource in /home/mywebsite/www/www/components/com_fabrik/fabrik.class.php(1315) : eval()'d code on line 14

All was working just fine withouth the "global $ch;" My problem was how to parse the key from the generated full name to make it in the short format.

cheesegrits
08-31-2007, 10:02 PM
My apologies, that should just be:

global $ch;

... without using the ()'s. I'd been programming in perl all day yesterday, and the equivalent functions in perl use ()'s, where PHP doesn't.

If you want to see the values, add a var_dump() in there to see the content of the variables.

Also note it should be ___ (three underscores), not __ (two underscores) as I typed last night.

So try something like this:

global $ch;
curl_setopt($ch, CURLOPT_POST, true);
$str = "";
foreach($_REQUEST as $key => $val ){
$key = array_pop( explode( '___', $key ) );
var_dump($key, $val); echo "<br />";
$str .= "&$key=$val";
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $str);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);


... which on my test box prints out stuff like this:

string 'option' (length=6)
string 'com_fabrik' (length=10)

string 'fabrik_internal_id' (length=18)
int 12

string 'common_name' (length=11)
string 'Tomato' (length=6)

string 'time_date' (length=9)
string '2007-08-31' (length=10)

string 'botanical_name' (length=14)
string 'Fruitus Horriblus' (length=17)


etc etc.

BTW, I assume you don't want to append ALL the CGI args to the detsination URL, so you should probably insert some code to pick the ones you want and only append those. So for instance if you just wanted the keys/vals for 'first_name', 'last_name' and 'email', you could do something like this:

global $ch;
curl_setopt($ch, CURLOPT_POST, true);
$str = "";
$my_keys = array('first_name','last_name','email');
foreach($_REQUEST as $key => $val ){
$key = array_pop( explode( '___', $key ) );
if (in_array( $key, $my_keys )) {
$str .= "&$key=$val";
}
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $str);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);


-- hugh

cheesegrits
08-31-2007, 10:17 PM
PS, on my test server the above example doesn't actually seem to hit the jump page after the curl_exec(), but that might be my server. It's a Windows box, and I've never used CURL on it. Took me a while to get CURL going in PHP5 on Apache2 on Windows XP.

If anyone stumbles across this thread trying to make PHP5 curl load in Apache on XP, the trick seems to be you have to copy leay32.dll and ssleay.dll from your \php directory to somewhere the web server can find them, like \windows\system32. Also make sure you uncomment the php_curl.dll extension line, and set a session.save_path, in php.ini. If you wanna use SSL, you'll also have to install OpenSSL.

My phpinfo() now shows curl is loaded, and curl_init() exists. I just haven't quite worked out why it doesn't seem to be hitting the jump page yet tho!

But at least the code in the previous post is picking up and splitting out the right CGI args.

-- hugh

mamamia
08-31-2007, 11:38 PM
Hugh, you have been most helpful. I finally got it to work based on your input. Although I did have to get rid of the first line "global $ch;" as it was still causing the errors as I had mentioned earlier...maybe Fabrik has that code built in already...I don't know, but regardless it worked without it.

Now, on to my next Fabrik CURL issue in another thread...maybe you can help with that as well :)

mamamia

cheesegrits
09-01-2007, 12:00 AM
Hugh, you have been most helpful.


Glad I could help. I'd never actually used the curl stuff yet, and I was looking for an excuse to try it out, as I will be needing it soon.

I finally got it to work based on your input. Although I did have to get rid of the first line "global $ch;" as it was still causing the errors as I had mentioned earlier...maybe Fabrik has that code built in already...I don't know, but regardless it worked without it.


Well, I realized a little while ago that I made the assumption that your "jump page" URL would be the same as the one you wanted to curl to. Which is what Fabrik assumes, by provding the $ch already set up for that URL. See the tooltip on the 'curl script' box. If that isn't the case, then you will need to set up your own with a curl_init() to the URL you want.

NOTE - if you also want to actually go to a specific jump page after posting and processing the curl data, you'll need to do the redirect yourself. In other words, if you supply a 'curl script' (and set the 'process curl script' option), it won't do the redirect to the jump page automagically. I'm working on that now, I'll update this post when I figure that one out. It's only one line of code in the curl_script, but I can never remember the darn thing.

I'll check for your other post.

-- hugh

andrelewis
09-01-2007, 02:38 PM
For completeness it's:

header('Location: ' . 'http://myurl.com/');

:)

Andre