html form to XML response and reply - php

I have a form that looks like this. Now a client has asked to convert this to a format that queries and sends response in XML. Can someone pint me to appropriate tutorial or example in PHP. There seems to be many ways of doing this
<form action="" method='post'>
<table>
<tr><td>User Number </td><td><input type='text' name='task_user_no' value='<?=$task_user_no?>'></td></tr>
<tr><td>Date </td><td><input type='text' name='task_date' value='<?=$task_date?>'> (YYYYMMDD)</td></tr>
<tr><td>From Time </td><td><input type='text' name='task_from_time' value='<?=$task_from_time?>'>(HHMM)</td></tr>
<tr><td>To Time </td><td><input type='text' name='task_to_time' value='<?=$task_to_time?>'>(HHMM)</td></tr>
<tr><td>Message </td><td><input type='text' name='task_message' value='<?=$task_message?>'></td></tr>
<tr><td> </td><td><input type='submit' value='submit' name='submit' ></td></tr>
</form>

Well since you havent provided details ill lay down the basics:
A cron job, user interaction, or some other trigger invokes the request on the Remote Server (RS)
The php script on the RS builds a query to send to the Application Server (AS) that hosts your site/application
The AS parses the request variables and builds a query for the data store.
The AS makes the query on data store, and transforms the results to an XML format
The AS sends the response as XML to the RS
The RS parses the XML and does whatever it needs to do with the data it contains
So given these steps some example scripts:
RS Server Script
// set up params for query:
$params = array(
'task_no' => '0000000'
'task_date' => 'YYYYMMDD',
'task_from_time' => 'HHMM',
'task_to_time' => 'HHMM',
'taks_message' => 'The Message'
);
$client = curl_init('http://remote-server.com/task.php');
// return the response instead of outputting it
curl_setopt($client, CURLOPT_RETURNTRANSFER, true);
// make it a POST request, use CURLOPT_GET for Get requests
curl_setopt($client, CURLOPT_POST, true);
// set the data to send.. if using get then intstead use http_build_query($params) and append the resuult to the URL used in curl_init
curl_setopt($client, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($client);
// load the response as xml
try
{
$responseXml = new SimpleXmlElement($response);
// do stuff here with the result see SimpleXml documentation for working with the xml nodes
exit;
}
catch(Exception $e)
{
// log message from exception
// exit with a non-zero status code may be important for cron or a shell invocation
exit($e->getCode());
}
task.php script on the AS
// Im going to use PDO for simplicity sake
$db = new PDO($dsn, $user, $pass);
$query = 'SELECT * from table_name'
.'WHERE task_user_no = :task_user_no'
.'AND task_date = :task_date'
.'AND task_from_time = :task_from_time'
.'AND task_to_time = :task_to_time';
$stmt = $db->prepare($query);
$params = $_POST; // make a copy for binding
$xml = new DOMDocument('1.0', 'UTF-8');
// create some basic elements
$response = $xml->createElement('response');
$info = $xml->createElement('info');
$results = $xml->createElement('results');
// set up an array we can append later if there are errors
$errors = array();
foreach($params as $field => $value)
{
$paramName = ':' . $field;
switch($field)
{
case 'task_user_no':
$paramType = PDO::PARAM_INT; // assuming an int pk/fk
break;
default:
$paramType = PDO::PARAM_STR; // assuming string for all others
break;
}
if(!$stmt->bindParam($paramName, $param[$field], $paramType))
{
$errors[] = $xml->createElement('error', sprintf(
'Value for (%s) does not exist or is not of the proper type (%s).'
$field,
$paramType
));
}
}
if(!$stmt->execute() && ($pdoError = $stmt->errorCode()))
{
$errors[] = sprintf(
'There was an error retrieving your data, Error (%s)',
$pdoError
);
}
while(false !== ($record = $stmt->fetch(PDO::FETCH_ASSOC)))
{
$task = $xml->createElement('task');
foreach($record as $col => $val)
{
$task->appendChild($xml->createElement($col, $val));
$results->appendChild($task);
}
}
if(!empty($errors))
{
$errorsElement = $xml->createElement('errors');
foreach($errors as $error)
{
$errorsElement->appendChild($xml->createElement('error', $error));
}
$info->appendChild($errorsElement);
}
$response->appendChild($info);
$response->appendChild($results);
$xml->appendChild($response);
$responseStr = $xml->saveXml();
header('Content-type: text/xml');
header('Content-length: '. strlen($responseStr));
header('HTTP/1.1 200 Ok');
print $responseStr;
exit;
Of course you can use existing libraries to further simplicty things... For example instead of using curl you could use Zend_Http_Client (which i would definitely recommend since it not only allows you to use curl but also fopen and direct sockets). OR for the xml response parsing on the AS you could use Zend_Dom_Query which basically allows you to work with the xml response in a way similar to jQuery (css selectors and what not instead of xPath).

Take a look at Jquery Ajax Function
Doc

Related

PHP script receives GET instead of POST REQUEST

I am using PHP with XAMPP and Dialogflow to create a chat interface. In a simple intent(question) in Dialogflow, I have created a webhook to XAMPP regarding the question 'Who is X' (e.g. Paul, George). Therefore , I place a POST REQUEST in order to have access to the json form of this question in DIalogflow so that I can answer it as I want to. Specifically, the ultimate goal of this is to retrieve some data from a MySQL database in phpMyAdmin about this question and respond for example that 'X is a developer' or 'X is a financial analyst'. This is why wrote a php script which is the following:
<?php
$method = $_SERVER['REQUEST_METHOD'];
// Process when it is POST method
if ($method == 'POST') {
$requestBody = file_get_contents('php://input');
$json = json_decode($requestBody);
$text = $json->result->parameters;
switch($text) {
case 'given-name':
$name = $text->given-name;
$speech = $name . 'is a developer';
break;
default:
$speech = 'Sorry I did not get this. Can you repeat please?';
}
$response = new \stdClass();
$response->speech = "";
$response->displayText = "";
$respone->source = "webhook";
echo json_encode($response);
}
else
{
echo "Method not allowed";
}
?>
However, the output of this program is: Method not allowed.
Paradoxically enough $method has the value 'GET' so it identifies a GET REQUEST while Dialogflow explicitly states at the webhook page that
Your web service will receive a POST request from Dialogflow in the
form of the response to a user query matched by intents with webhook
enabled.
Hence I am wondering: why my php script cannot see and process the POST REQUEST from Dialogflow?
P.S. Questions close to mine are the following: Form sends GET instead of POST, Why is $_SERVER['REQUEST_METHOD'] always GET?.
It doesn't work because $_SERVER['REQUEST_METHOD'] == "GET" by default.
So you program execute the 'else' condition.
You need to submit a request with the POST method to change this value.
You can use
<form method="POST">
[...]
</form>
in your HTML, or
$.ajax({
url : "ajax_url.php",
type : 'POST',
data : 'data='+data,
[...]
});
in your AJAX JS code for example
Here i am doing same like you from below code your Query will be resolved,
index.php
<?php
require 'get_enews.php';
function processMessage($input) {
$action = $input["result"]["action"];
switch($action){
case 'getNews':
$param = $input["result"]["parameters"]["number"];
getNews($param);
break;
default :
sendMessage(array(
"source" => "RMC",
"speech" => "I am not able to understand. what do you want ?",
"displayText" => "I am not able to understand. what do you want ?",
"contextOut" => array()
));
}
}
function sendMessage($parameters) {
header('Content-Type: application/json');
$data = str_replace('\/','/',json_encode($parameters));
echo $data;
}
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input["result"]["action"])) {
processMessage($input);
}
?>
get_enews.php
<?php
function getNews($param){
require 'config.php';
$getNews="";
$Query="SELECT link FROM public.news WHERE year='$param'";
$Result=pg_query($con,$Query);
if(isset($Result) && !empty($Result) && pg_num_rows($Result) > 0){
$row=pg_fetch_assoc($Result);
$getNews= "Here is details that you require - Link: " . $row["link"];
$arr=array(
"source" => "RMC",
"speech" => $getNews,
"displayText" => $getNews,
);
sendMessage($arr);
}else{
$arr=array(
"source" => "RMC",
"speech" => "No year matched in database.",
"displayText" => "No year matched in database.",
);
sendMessage($arr);
}
}
?>
php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input

Passing Array via SOAP for SAP Webservice

I am trying to pass a 2D Array via SOAP for SAP Webservice.
But I am unable to pass the same.
I am able to pass a value, also I am able to accept a table output from SAP.
Please guide.
I tried to typecast array as an object.
My Code:
<?php
include("include/config.php");
$sql = "SELECT tid,OrderNumber FROM transhistory ORDER by timestamp ASC limit 2";
$result= mysqli_query($db,$sql);
$i=0;
while($row = mysqli_fetch_array($result,MYSQLI_ASSOC)) {
//Array based on output table
$pmt[$i][0] = ""; //Mandt
$pmt[$i][1] = $row["tid"]; //Refnum
$pmt[$i][2] = $row["OrderNumber"]; //Orderno
$i++;
}
/*Two methods I tried */
$object = (object) $pmt;
$object = json_decode(json_encode($pmt), FALSE);
#Define Authentication
$SOAP_AUTH = array( 'login' => 'abc',
'password' => 'abc');
#Specify WSDL
$WSDL = "working URL here";
#Create Client Object, download and parse WSDL
$client = new SoapClient($WSDL,$SOAP_AUTH);
#Setup input parameters (SAP Likes to Capitalise the parameter names)
$params = array(
'Zpmt' => $object
);
#Call Operation (Function). Catch and display any errors
try {
$result = $client->ZphpOT($params);
} catch (SoapFault $exception) {
echo 'Error!Server Connectivity issue. Please try again later.';
die();
}
?>
I don't know if the answer may be useful for somebody but usually you send parameters like this
$result = $client->ZphpOT("VARIABLE_NAME"=>$params);

Calling REST API to retrieve data from a website using URL and parameters

Hi I have to get an information from a website using url and login parameters and some XML parameters as input Using a PHP. I am new to any API calls so please explain me how can I use these parameters in my PHP code and make a request to a server to get the information
When I use these in SOAP UI I can get the demo result, I need to build the same in PHP.
https://transact-prelive.litle.com/vap/communicator/online
Username: u82917418420715660
Password: dENteSXnXwfqKHF
Merchant Id: 01183990
<litleOnlineRequest version="9.4" xmlns="http://www.litle.com/schema" merchantId="01183990">
<authentication>
<user>u82917418420715660</user>
<password>dENteSXnXwfqKHF</password>
</authentication>
<authorization id="834262" reportGroup="ABC Division" customerId="038945">
<orderId>65347567</orderId>
<amount>40000</amount>
<orderSource>3dsAuthenticated</orderSource>
<billToAddress>
<name>John Smith</name>
<addressLine1>100 Main St</addressLine1>
<city>Boston</city>
<state>MA</state>
<zip>12345</zip>
<email>jsmith#someaddress.com</email>
<phone>555-123-4567</phone>
</billToAddress>
<card>
<type>VI</type>
<number>4000000000000001</number>
<expDate>1209</expDate>
<cardValidationNum>555</cardValidationNum>
</card>
<cardholderAuthentication>
<authenticationValue></authenticationValue>
<authenticationTransactionId></authenticationTransactionId>
</cardholderAuthentication>
</authorization>
</litleOnlineRequest>
You can use nusoap library to use SOAP with PHP. Here is an example how you can use it. It is just similar to your query.
$this->load->library("lib_nusoap");
$wsdl = "https://transact-prelive.litle.com/vap/communicator/online";
$client = new nusoap_client($wsdl, 'wsdl');
//$client->setCredentials($api_username,$api_password);
$error = $client->getError();
if ($error)
{
echo "\nSOAP Error\n".$error."\n";
return false;
}
else
{
$params = array ('user' => "u82917418420715660 ", 'Password' => "dENteSXnXwfqKHF ");
$result = $client->call('retrive', $params);
if ($client->fault)
{
print_r($result);
print $client->fault;
}
else
{
$result_arr = json_decode($result, true);
}
}
print_r($result_arr);
Nusoap library will handle CURL API call.

php soapclient returns null but getPreviousResults has proper results

I've ran into trouble with SOAP, I've never had this issue before and can't find any information on line that helps me solve it.
The following code
$wsdl = "path/to/my/wsdl";
$client = new SoapClient($wsdl, array('trace' => true));
//$$textinput is passed in and is a very large string with rows in <item></item> tags
$soapInput = new SoapVar($textinput, XSD_ANYXML);
$res = $client->dataprofilingservice(array("contents" => $soapInput));
$response = $client->__getLastResponse();
var_dump($res);//outputs null
var_dump($response);//provides the proper response as I would expect.
I've tried passing params into the SoapClient constructor to define soap version but that didnt' help. I've also tried it with the trace param set to false and not present which as expected made $response null but $res was still null. I've tried the code on both a linux and windows install running Apache.
The function definition in the WSDL is (xxxx is for security reasons)
<portType name="xxxxServiceSoap">
<operation name="dataprofilingservice">
<input message="tns:dataprofilingserviceSoapIn"/>
<output message="tns:dataprofilingserviceSoapOut"/>
</operation>
</portType>
I have it working using the __getLastResponse() but its annoying me it will not work properly.
I've put together a small testing script, does anyone see any issues here. Do I need a structure for the return type?
//very simplifed dataset that would normally be
//read in from a CSV file of about 1mb
$soapInput = getSoapInput("asdf,qwer\r\nzzxvc,ewrwe\r\n23424,2113");
$wsdl = "path to wsdl";
try {
$client = new SoapClient($wsdl,array('trace' => true,'exceptions' => true));
} catch (SoapFault $fault) {
$error = 1;
var_dump($fault);
}
try {
$res = $client->dataprofilingservice(array("contents" => $soapInput));
$response = $client->__getLastResponse();
echo htmlentities($client->__getLastRequest());//proper request echoed
echo '<hr>';
var_dump($res);//null
echo "<hr>";
echo(htmlentities($response));//proper response echoed
} catch (SoapFault $fault) {
$error = 1;
var_dump($fault);
}
function getSoapInput($input){
$rows = array();
$userInputs = explode("\r\n", $input);
$userInputs = array_filter($userInputs);
//
$inputTemplate = " <contents>%s</contents>";
$rowTemplate = "<Item>%s</Item>";
//
$soapString = "";
foreach ($userInputs as $row) {
// sanitize
$row = htmlspecialchars(addslashes($row));
$xmlStr = sprintf($rowTemplate, $row);
$rows[] = $xmlStr;
}
$textinput = sprintf($inputTemplate, implode(PHP_EOL, $rows));
$soapInput = new SoapVar($textinput, XSD_ANYXML);
return $soapInput;
}
Ok after much digging it is related to relative namespaces, it appears that PHP doesn't handle them well within the WSDL or the SOAP Envelope. So since I don't have control of the SOAP Server I will continue to get the response via __getLastResponse();.
Hopefully this will save some people some time it was hard to find.
You are mixing things here. __getLastResponse() returns the bare XML string response from the server if you make use of the 'trace' => true option. That is for debugging only.
So regardless whether 'trace' => true or not, the method which you would like to call originally returns the same and that is totally normal. Setting tracing to on won't change the behaviour, it just offers an additional feature, the return value for __getLastResponse().
As the SoapClient does not throw any exception I'd say that your call is going okay and NULL is a valid return value.
You might want to provide the actual XML string and/or the WSDL defintion so that one could inspect if that's the case or not.

get a PUT request with Codeigniter

I have a problem right now with CodeIgniter : I use the REST Controller library (which is really awesome) to create an API but I can not get PUT requests...
This is my code :
function user_put() {
$user_id = $this->get("id");
echo $user_id;
$username = $this->put("username");
echo $username;
}
I use curl to make the request :
curl -i -X PUT -d "username=test" http://[...]/user/id/1
The user_id is full but the username variable is empty. Yet it works with the verbs POST and GET.
Have you any idea please?
Thank you !
According to: http://net.tutsplus.com/tutorials/php/working-with-restful-services-in-codeigniter-2/ we should consult https://github.com/philsturgeon/codeigniter-restserver/blob/master/application/libraries/REST_Controller.php#L544 to see that this method:
/**
* Detect method
*
* Detect which method (POST, PUT, GET, DELETE) is being used
*
* #return string
*/
protected function _detect_method() {
$method = strtolower($this->input->server('REQUEST_METHOD'));
if ($this->config->item('enable_emulate_request')) {
if ($this->input->post('_method')) {
$method = strtolower($this->input->post('_method'));
} else if ($this->input->server('HTTP_X_HTTP_METHOD_OVERRIDE')) {
$method = strtolower($this->input->server('HTTP_X_HTTP_METHOD_OVERRIDE'));
}
}
if (in_array($method, array('get', 'delete', 'post', 'put'))) {
return $method;
}
return 'get';
}
looks to see if we've defined the HTTP header HTTP_X_HTTP_METHOD_OVERRIDE and it uses that in favor of the actual verb we've implemented on the web. To use this in a request you would specify the header X-HTTP-Method-Override: method (so X-HTTP-Method-Override: put) to generate a custom method override. Sometimes the framework expects X-HTTP-Method instead of X-HTTP-Method-Override so this varies by framework.
If you were doing such a request via jQuery, you would integrate this chunk into your ajax request:
beforeSend: function (XMLHttpRequest) {
//Specify the HTTP method DELETE to perform a delete operation.
XMLHttpRequest.setRequestHeader("X-HTTP-Method-Override", "DELETE");
}
You can try to detect the method type first and seperate the different cases. If your controller only handles REST functions it could be helpful to put get the required information in the constructor.
switch($_SERVER['REQUEST_METHOD']){
case 'GET':
$var_array=$this->input->get();
...
break;
case 'POST':
$var_array=$this->input->post();
...
break;
case 'PUT':
case 'DELETE':
parse_str(file_get_contents("php://input"),$var_array);
...
break;
default:
echo "I don't know how to handle this request.";
}
In CodeIgniter 4 use getRawInput which will retrieve data and convert it to an array.
$data = $request->getRawInput();
look this issue in github
PUT parameters only work in JSON format
https://github.com/chriskacerguis/codeigniter-restserver/issues/362
Checkout this link in the official Code Igniter Docs Using the Input Stream for Custom Request Methods
This is the Code Igniter way to do it.
Just call the below if the body of the request is form-urlencoded
$var1 = $this->input->input_stream('var_key')
// Or
$var1 = $this->security->xss_clean($this->input->input_stream('var_key'));
Codeigniter put_stream has provided no help, instead I had to use php input stream as following method can be added to helpers, from there you can parse put request in any of the controllers:
function parsePutRequest()
{
// Fetch content and determine boundary
$raw_data = file_get_contents('php://input');
$boundary = substr($raw_data, 0, strpos($raw_data, "\r\n"));
// Fetch each part
$parts = array_slice(explode($boundary, $raw_data), 1);
$data = array();
foreach ($parts as $part) {
// If this is the last part, break
if ($part == "--\r\n") break;
// Separate content from headers
$part = ltrim($part, "\r\n");
list($raw_headers, $body) = explode("\r\n\r\n", $part, 2);
// Parse the headers list
$raw_headers = explode("\r\n", $raw_headers);
$headers = array();
foreach ($raw_headers as $header) {
list($name, $value) = explode(':', $header);
$headers[strtolower($name)] = ltrim($value, ' ');
}
// Parse the Content-Disposition to get the field name, etc.
if (isset($headers['content-disposition'])) {
$filename = null;
preg_match(
'/^(.+); *name="([^"]+)"(; *filename="([^"]+)")?/',
$headers['content-disposition'],
$matches
);
list(, $type, $name) = $matches;
isset($matches[4]) and $filename = $matches[4];
// handle your fields here
switch ($name) {
// this is a file upload
case 'userfile':
file_put_contents($filename, $body);
break;
// default for all other files is to populate $data
default:
$data[$name] = substr($body, 0, strlen($body) - 2);
break;
}
}
}
return $data;
}
CodeIgniter doesn't support reading incoming PUT requests and if it's not essential I would stick to GET/POST for your API as its probably not necessary.
If you do need to read PUT requests take a look at Accessing Incoming PUT Data from PHP.

Categories