Swift - PHP : Textfield value sent over to PHP is received as null - php

I hope you all are doing well and staying safe! :)
I am new to iOS programming. I am trying to post values from a textfield to a MYSQL Database. As a first step, I tried to just print the values received on the PHP end.
The values are printed on the Swift end but on the PHP end, an empty string(null) is received. Could you please help and let me know why the string received on PHP end is null? Please help! I am stuck and unsure of what to do next.
I have tried retrieving values from the database and that code works perfectly fine.
Thanks in advance!
EDITED:
This has been now fixed. The correct code is below -
Swift Code:
struct DatatoPost : Codable{
var name : String
init() {
name = "Empty String"
}
}
var myDatatoPost = DatatoPost()
//Protocol created for this structure so that it can be applied to multiple class (View Controllers) that create a delegate for it(ManageDataDelegate)
protocol ManageDataDelegate {
func updateViewController(_ myManager : ManageData, saveOutputData: OutputData)
func didFailError(error : Error)
}
/* what action is expected to be taken on data reached through PHP file*/
struct ManageData {
var delegate : ManageDataDelegate?
var data : Data
init() {
data = Data()
}
//create POST URL based on function - this is the URL to post data to the backend.
mutating func postPHPData(){
let urlPostString = myConstant.baseURL + myConstant.postPHPValue
print(urlPostString)
performPostOperation(urlPostString)
}
//Steps to create URL and other related objects - prepare data for parsing.
mutating func performPostOperation(_ urlPostString : String) {
//1. Create URL
if let url = URL(string: urlPostString){
//Create request variable
var request : URLRequest = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
do{
let params : [String : Encodable] = ["name": myDatatoPost.name]
data = try JSONSerialization.data(withJSONObject: params, options: .init())
let body = Data(data).base64EncodedData()
print("Data is: ")
let dataString = String(data: data, encoding: .utf8)
print(dataString)
request.httpBody = body
let requestString = String(data: request.httpBody!, encoding: .utf8)
print("Request String is:")
print(requestString)
//2. Create URLSession
let session = URLSession(configuration: .default)
//3. Give the session a task
let task = session.dataTask(with: request as URLRequest, completionHandler: handlePOST(data:response:error:))
//4. Start the session
task.resume()
}catch{
print(error)
}
}
}
//Function that lists the activities that need to be completed in the URL session - GET Data.
func handlePOST(data : Data?, response : URLResponse?, error: Error?){
if error != nil {
delegate?.didFailError(error: error!)
print("error is")
print(error!)
return
}
if let safeData = data{
let dataString = String(data: safeData, encoding: .utf8)
print(dataString)
}
print(response)
}
}
PHP Code:
<?php
echo "we are here";
// Create connection
$con = mysqli_connect("localhost","username","password","dbname");
echo "we are here again";
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: ";
}
$postdata = json_decode(file_get_contents("php://input"),TRUE);
$decoded = base64_decode($postdata);
echo "decoded!";
print_r($decoded,true);
//this value is not printed
echo "postdata";
echo $postdata->name;
//this value is not printed
$name= $postdata["name"];
echo "Name";
echo $postdata["name"];
//this value is not printed
echo "Base 64";
echo base64_decode($postdata["name"]);
echo base64_decode($postdata->name);
//This value is not printed
if (empty($postdata["name"])){
echo "String is empty";
//this is printed
}
if (empty($postdata->name)){
echo "String is empty";
//This is printed
}
echo "Its done";
// Close connections
mysqli_close($con);
?>

You have specified your request’s Content-Type to be application/json. So it should be JSON, free of base64 encoding. The only time you should use base64-encoding is if you are trying to send binary data in JSON. (And even then, in that case, we would reach for application/x-www-form-urlencoded request, not application/json request.)
Anyway, to send JSON request and parse JSON response:
protocol ManageDataDelegate: class {
func didFailError(error: Error)
func didReceiveResponse(object: Any)
}
/* what action is expected to be taken on data reached through PHP file*/
struct ManageData {
weak var delegate: ManageDataDelegate? // delegates should always be weak to avoid strong reference cycle; obviously `ManageDataDelegate` must be class protocol
//create POST URL based on function - this is the URL to post data to the backend.
func postPHPData(name: String) {
let urlPostString = URL(string: MyConstant.baseURL)!.appendingPathComponent(MyConstant.postPHPValue)
print(urlPostString)
performPostOperation(urlPostString, name: name)
}
//Steps to create URL and other related objects - prepare data for parsing.
func performPostOperation(_ url: URL, name: String) {
//Create request variable
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
do {
let params = ["name": name]
let body = try JSONSerialization.data(withJSONObject: params)
// 1. for diagnostic purposes, let's look at the JSON
if let json = String(data: body, encoding: .utf8) {
print("JSON is:", json)
}
request.httpBody = body
//2. Create URLSession
let session = URLSession(configuration: .default)
//3. Give the session a task
let task = session.dataTask(with: request, completionHandler: handlePOST(data:response:error:))
//4. Start the session
task.resume()
//5. If creating a URLSession locally, make sure to invalidate it when the request is done or else you will leak memory; better, create one `URLSession` and reuse it for all of your requests (and then you don't need/want to invalidate it)
session.finishTasksAndInvalidate()
} catch {
print(error)
}
}
enum ManageDataError: Error {
case unknownError(Data?, URLResponse?, Error?)
case notJsonResponse(String)
}
//Function that lists the activities that need to be completed in the URL session - GET Data.
func handlePOST(data: Data?, response: URLResponse?, error: Error?) {
guard let responseData = data, error == nil else {
let error = error ?? ManageDataError.unknownError(data, response, error)
delegate?.didFailError(error: error)
print("error is")
print(error)
return
}
if let object = try? JSONSerialization.jsonObject(with: responseData) {
delegate?.didReceiveResponse(object: object)
} else if let string = String(data: responseData, encoding: .utf8) {
delegate?.didFailError(error: ManageDataError.notJsonResponse(string))
} else {
delegate?.didFailError(error: ManageDataError.unknownError(data, response, error))
}
print(response ?? "No response")
}
}
There are a variety of refinements buried in the above (if creating a session, you must invalidate it when finished; passing responses to the delegate; making sure delegate reference is weak to avoid strong reference cycles; etc.), but hopefully this illustrates the idea: No base64-encoding is needed or desired with JSON requests.
Note, you have specified the request’s Accept to also be application/json so I would make sure it did precisely that:
<?php
header("Content-Type: application/json");
// Create connection
$con = mysqli_connect("localhost","username","password","dbname");
// Check connection
if (mysqli_connect_errno())
{
$result = [
"success" => false,
"message" => "Failed to connect to MySQL: " . mysqli_connect_error()
];
echo json_encode($result, JSON_PRETTY_PRINT);
exit();
}
$postdata = json_decode(file_get_contents("php://input"), true);
if (isset($postdata["name"]))
{
$result = [
"success" => true,
"name" => $postdata["name"]
];
}
else
{
$result = [
"success" => false,
"message" => "'name' not found",
"postdata" => $postdata
];
}
echo json_encode($result, JSON_PRETTY_PRINT);
// Close connections
mysqli_close($con);
?>
So, this parses the JSON and checks for name, but returning a JSON response, which is what the client was looking for.
There are other refinements I would suggest (e.g. I would use JSONEncoder and JSONDecoder rather than JSONSerialization; not create new URLSession for every request; usually a “network controller” like this would be a reference type so that you can use the same one wherever needed; I would use a framework such as Laravel in the server code, etc.), but I did not want to stray too far from the question at hand.

Related

Confused on how to upload variables from swift to php files for mysql use

I have an app in xcode where I will be taking notes and uploading them to a server on the web. I have the following code in xcode to POST. I'm getting an error
The data couldn’t be read because it isn’t in the correct format.
Here are my parameters to upload to php
let parameters: [String: Any] = ["title": title, "post": post]
Here is my create Post code
func createPost(parameters: [String: Any]) {
guard let url = URL(string: "\(prefixUrl)/post.php") else {
print("Did not find url")
return
}
let data = try! JSONSerialization.data(withJSONObject: parameters)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = data
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request ) { (data, res, error) in
if error != nil {
print("error", error?.localizedDescription ?? "")
return
}
do {
if let data = data {
let result = try JSONDecoder().decode([postDataBase].self, from: data)
DispatchQueue.main.sync {
print(result)
}
}else {
print("No Data")
}
} catch let JsonError {
print("fetch json error:", JsonError.localizedDescription)
}
}.resume()
}
The create post is wrapped in a class ViewDataBase with other CRUD commands...
I have a struct postDataBase where i know the error The data couldn’t be read because it isn’t in the correct format. could be happening as well. I've changed these to various data types with no success
struct postDataBase: Decodable {
var ID: String
var title: String
var post: String
}
My php code is here. I use bluehost to support my database so i can have a public domain. If you need my username and password let me know i can change it later.
<?php
$connection=mysqli_connect("localhost","****","****");
$ID = $_POST['ID'];
$title = $_POST['title'];
$post = $_POST['post'];
if(!$connection)
{
die('Connection Failed');
}
else
{
$dbconnect = #mysqli_select_db('mlbroadv_PlantAssistDB', $connection);
if(!$dbconnect)
{
die('Could not connect to Database');
}
else
{
$query = "INSERT INTO Notes (title, post) VALUES ( '$title', '$post');";
mysqli_query($query, $connection) or die(mysqli_error());
echo 'Successfully added.';
echo $query;
}
}
?>
My goal is getting my swift data uploaded to php and into mySQL database. There seems to be a disconnect somewhere...
I think the error lies in the following code where the php files is read in to connect with mySQL and to upload my variables...
EDIT:
let data = try! JSONSerialization.data(withJSONObject: parameters)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = data
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request ) { (data, res, error) in
EDIT 2: Still Trying to get it
For this line...
let parameters: [String: Any] = ["title": "Fgh", "post": "Fgg"
I get...
Param raw data is coded as: ["post": "Fgg", "title": "Fgh"]
For this line...
let dataParam = try! JSONSerialization.data(withJSONObject: parameters)
I Get...
json serialization request is coded as: 28 bytes
For this line...
URLSession.shared.dataTask(with: request as URLRequest ) { (data, res, error) in
if error != nil {
print("urlsession error is coded as: ", error?.localizedDescription ?? "")
return
}
I Get for the data varaible...
urlsession data is coded as: 235 bytes
and for the res variable, I get the following repsonse...
urlsession results is coded as: <NSHTTPURLResponse: 0x282ea64c0> { URL: https://mlbroadvisions.com/post.php } { Status Code: 200, Headers {
"Content-Encoding" = (
gzip
);
"Content-Type" = (
"text/html; charset=UTF-8"
);
Date = (
"Fri, 22 Jul 2022 16:07:03 GMT"
);
Server = (
cloudflare
);
Vary = (
"Accept-Encoding"
);
"cf-cache-status" = (
DYNAMIC
);
"cf-ray" = (
"72ed6d53f9072be1-ORD"
);
"expect-ct" = (
"max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\""
);
"host-header" = (
"c2hhcmVkLmJsdWVob3N0LmNvbQ=="
);
} }
during the ...
catch let error as NSError {
print(error.localizedDescription)
It gives me the error...
The data couldn’t be read because it isn’t in the correct format.
json data is coded as: 235 bytes
What part of my code do i need to change to get it into the correct format i've tried a lot of things none of which worked.

PHP not receiving POST data from Swift

I'm trying to write to a database and not able to get POST data from Swift into PHP. I've checked everything along the way and the data is present in request.httpBody before sending the request, but I get this error
"SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'order_id' cannot be null"
Also PHP prints an empty array of $request
Any help is appreciated. Racking my brain on this one!
Here's the code
SWIFT:
func saveNewProduct(product: ProductClass) {
//declare parameter as a dictionary which contains string as key and value combination.
let productDict: [String:Any] = ["order_id": product.order_id!,
"product_sku": product.product_sku!,
"product_description": product.product_description!,
"product_base_price": product.product_base_price!,
"product_price": product.product_price!,
"product_min_qty": product.product_min_qty!,
"product_qty": product.product_qty!,
"product_subtotal": product.product_subtotal!,
"product_imageURL": product.product_imageURL!]
let urlString: String = "https://www.mywebsite.com/dbinsertproduct.php"
guard let url = URL(string: urlString) else {
print("Error: cannot create URL")
return
}
//create the session object
let session = URLSession.shared
//create the URLRequest object using the url object
var request = URLRequest(url: url)
//set http method as POST
request.httpMethod = "POST"
do {
request.httpBody = try? JSONSerialization.data(withJSONObject: productDict, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: request, completionHandler: {
data,response,error in
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print(json)
// handle json...
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
}
PHP:
<?php include("dbclass.php"); ?>
<?php
$postdata = file_get_contents("php://input");
$request = json_decode($postdata, true);
$newProduct = new DBConnector('mysql.mysite.com', 'username', 'password', 'mysiteorders');
$p = $newProduct->dbInsertProduct($request);
error_log($p);
echo ($p);
?>
More PHP:
public function dbInsertProduct($request)
{
try {
$stmt = $this->prepare("INSERT INTO `products` (`order_id`,`product_sku`,`product_description`,`product_base_price`,`product_price`,`product_notes`,`product_min_qty`,`product_qty`,`product_subtotal`,`product_imageURL`) VALUES (:order_id,:product_sku,:product_description,:product_base_price,:product_price,:product_notes,:product_min_qty,:product_qty,:product_subtotal,:product_imageURL);");
$stmt->bindParam(':order_id', $request['order_id']);
$stmt->bindParam(':product_sku', $request['product_sku']);
$stmt->bindParam(':product_description', $request['product_description']);
$stmt->bindParam(':product_base_price', $request['product_base_price']);
$stmt->bindParam(':product_price', $request['product_price']);
$stmt->bindParam(':product_notes', $request['product_notes']);
$stmt->bindParam(':product_min_qty', $request['product_min_qty']);
$stmt->bindParam(':product_qty', $request['product_qty']);
$stmt->bindParam(':product_subtotal', $request['product_subtotal']);
$stmt->bindParam(':product_imageURL', $request['product_imageURL']);
error_log( print_r($request, TRUE) );
$stmt->execute();
} catch(PDOException $e) {
error_log($e->getMessage());
echo json_encode($e->getMessage());
}
}
UPDATE:
The request shows up as GET, not POST (verified with Charles proxy).
As you can see in the code, I'm setting request.httpMethod = "POST". Am I missing something else??
I found that the POST was being changed to GET upon redirect from www.mysite.com to mysite.com. Removing the 'www' did the trick.

POST data from iOS to php server always NULL - iOS 10, Swift 3, php

i am implementing a FCM app server and wanted to store the device registration token id into my own database (Server written in PHP).
I realise the data in device id token is always null, Can someone point the right way to store the token accordingly into database?
Really appreciated perhaps someone could guide me on this issue, thanks!
Kindly refer the code/screenshots below:-
AppDelegate.swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var token = ""
for i in 0..<deviceToken.count {
token += String(format: "%02.2hhx", arguments: [deviceToken[i]])
}
print("Registration succeeded!")
print("Token: ", token)
Callquery(token)
}
AppDelegate.swift (Callquery method which send a POST request to server side script)
func Callquery(_ token: String)
{
// append parameter to oneDictionary
let tokenString = ["token": token] as [String: Any]
// create the request
var request = URLRequest(url: URL(string:"https://YourURL.com/admin/registerToken.php")!)
// set the method as POST
request.httpMethod = "POST"
// append the paramter to body
request.httpBody = try! JSONSerialization.data(withJSONObject: tokenString, options: [])
// create the session
URLSession.shared.dataTask(with:request, completionHandler: {(data, response, error) in
if error != nil {
print("There was error during datatask session")
print(error)
} else {
do {
guard let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] else { return }
guard let errors = json?["errors"] as? [[String: Any]] else { return }
if errors.count > 0 {
// show error
print("There is an error during parse JSON datatask")
return
} else {
// show confirmation
print("datatask with JSON format performed successfully")
}
}
}
print(request)
}).resume()
}
Service Side Script(registerToken.php):
<?php
include 'config.php';
$token = $_POST['token'];
$sql = "INSERT INTO users (email,device_id) VALUES ('email','$token')";
mysqli_query($conn, $sql);
mysqli_close($conn);
?>
Running App with real devices log as below:-
Database users table (device id always has nothing):-
users table structure:-
tokenString :-
I had solved this issue by using GET method instead of POST method as below:-
Appdelegate.swift :
var request = URLRequest(url: URL(string:"https://YourURL.com/admin/registerToken.php?token=\(token)")!)
Server side script :
$token = $_GET['token'];

POST with swift and API

I've a problem when I try to send a POST request to my API on my server, I've followed many many different tutorials but it still doesn't work.
I know than my problem is with the POST request but I can't solve it !
So this is my code in Swift and my API in php : (and yes I've replaced the xxxx by the real IDs in my code)
To sum up server receive the request and for example if I manually enter a pseudo it works, It's really the POST method who doesn't work.. The server doesn't receive the POST parameter
Swift code :
var request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/academy/test.php")!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var params = ["pseudo":"test"] as Dictionary<String, String>
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()*/
PHP Code :
$BDD_hote = 'xxxxx';
$BDD_bd = 'xxxxx';
$BDD_utilisateur = 'xxxxx';
$BDD_mot_passe = 'xxxxx';
try{
$bdd = new PDO('mysql:host='.$BDD_hote.';dbname='.$BDD_bd, $BDD_utilisateur, $BDD_mot_passe);
$bdd->exec("SET CHARACTER SET utf8");
$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch(PDOException $e){
echo 'Erreur : '.$e->getMessage();
echo 'N° : '.$e->getCode();
}
$pseudo = addslashes($_POST["pseudo"]);
$req = $bdd->query("SELECT * from users WHERE pseudo='$pseudo'");
$resultArray = array();
$donnees = $req->fetch();
echo json_encode($donnees);
Thanks by advance :)
As others have pointed out, the encoding of the request is not quite right. Your server code is not expecting JSON request, but rather is using $_POST variables (which means that the request should have Content-Type of application/x-www-form-urlencoded). So that's what you should create. For example in Swift 3 and later:
var request = URLRequest(url: url)
request.httpMethod = "POST"
let parameters = ["somekey" : "valueforkey"]
request.setContent(with: parameters)
let task = session.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error ?? "Unknown error")
return
}
// your response parsing code here
}
task.resume()
The setContent method would take a dictionary of the form ["key1": "foo", "key2" : "bar"] and populate the httpBody with something that looks like key1=foo&key2=bar. If you do that, the server will be able to parse the $_POST from the request.
extension URLRequest {
/// Set body and header for x-www-form-urlencoded request
///
/// - Parameter parameters: Simple string dictionary of parameters to be encoded in body of request
mutating func setContent(with parameters: [String: String]) {
setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let array = parameters.map { entry -> String in
let key = entry.key.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)!
let value = entry.value.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)!
return key + "=" + value
}
httpBody = array.joined(separator: "&").data(using: .utf8)!
}
}
Note, this also percent-encodes the values (and, just in case, the keys, too), which is critical. While others have advised using addingPercentEncoding with .urlQueryAllowed, sadly that will not do the job, as it will let certain reserved characters (notably +) pass unescaped. Most web services will interpret the + as a space, in conformance with the x-www-form-urlencoded spec. So, adapting an approach adopted by Alamofire, I define a character set which will encode values with the various delimiters:
extension CharacterSet {
/// Returns the character set for characters allowed in the individual parameters within a query URL component.
///
/// The query component of a URL is the component immediately following a question mark (?).
/// For example, in the URL `http://www.example.com/index.php?key1=value1#jumpLink`, the query
/// component is `key1=value1`. The individual parameters of that query would be the key `key1`
/// and its associated value `value1`.
///
/// According to RFC 3986, the set of unreserved characters includes
///
/// `ALPHA / DIGIT / "-" / "." / "_" / "~"`
///
/// In section 3.4 of the RFC, it further recommends adding `/` and `?` to the list of unescaped characters
/// for the sake of compatibility with some erroneous implementations, so this routine also allows those
/// to pass unescaped.
static var urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]#" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode)
return allowed
}()
}
For Swift 2 rendition, see previous revision of this answer.
Try this:
let myURL = NSURL(string: "http://localhost:8888/academy/test.php")!
let request = NSMutableURLRequest(URL: myURL)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
let bodyStr:String = "pseudo=test"
request.HTTPBody = bodyStr.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
// Your completion handler code here
}
task.resume()
You have to encode your data using UTF8 string encoding. If you need to set more than one field&value pairs for request body, you can change the body string, for example, "pseudo=test&language=swift". In fact, I usually create an extension for NSMutableURLRequest and add a method which takes a dictionary as parameter and sets the content of this map(dictionary) as HTTPBody using correct encoding. This may work for you:
extension NSMutableURLRequest {
func setBodyContent(contentMap: Dictionary<String, String>) {
var firstOneAdded = false
let contentKeys:Array<String> = Array(contentMap.keys)
for contentKey in contentKeys {
if(!firstOneAdded) {
contentBodyAsString += contentKey + "=" + contentMap[contentKey]!
firstOneAdded = true
}
else {
contentBodyAsString += "&" + contentKey + "=" + contentMap[contentKey]!
}
}
contentBodyAsString = contentBodyAsString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
self.HTTPBody = contentBodyAsString.dataUsingEncoding(NSUTF8StringEncoding)
}
}
And you can use this as:
request.setBodyContent(params)
I hope this helps you!
the following php code is for receiving application/url+encode encoded post message. please refer https://en.wikipedia.org/wiki/Percent-encoding
$_POST["pseudo"]
and your swift code was sending a JSON encoded string data. They are incompatible.
If you don't want to change the php code, in Swift you should send url-encode format message, li:
// UPDATED with corrections from #Rob
var params = ["param1":"value1", "papam2": "value 2"]
var body = ""
for (key, value) in params {
body = body.stringByAppendingString(key)
body = body.stringByAppendingString("=")
body = body.stringByAppendingString(value.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)
body = body.stringByAppendingString("&")
}
body = body.substringToIndex(advance(body.startIndex, countElements(body)-1)) // remove the last "&"
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)

How can I get a PHP variable over to swift [duplicate]

This question already has answers here:
How to make HTTP request in Swift?
(21 answers)
Closed 8 years ago.
I want a variable in php to get over in swift (or get the value for the variable). How can I do that?
$name = "William";
How can I get this string "William" to my Swift script? Can anyone help me?
I know it's something with JSON and POST or something but otherwise I am complete lost.
When you want to get data from PHP to an iOS device, I would recommend having the PHP code send it as JSON. JSON is easier for the the client app to parse (especially as your web service responses get more complicated) and it makes it easier to differentiate between a valid response and some generic server error).
To send JSON from PHP, I generally create an "associative array" (e.g., the $results variable below), and then call json_encode:
<?php
$name = "William";
$results = Array("name" => $name);
header("Content-Type: application/json");
echo json_encode($results);
?>
This (a) specifies a Content-Type header that specifies that the response is going to be application/json; and (b) then encodes $results.
The JSON delivered to the device will look like:
{"name":"William"}
Then you can write Swift code to call NSJSONSerialization to parse that response. For example, in Swift 3:
let url = URL(string: "http://example.com/test.php")!
let request = URLRequest(url: url)
// modify the request as necessary, if necessary
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print("request failed \(error)")
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String], let name = json["name"] {
print("name = \(name)") // if everything is good, you'll see "William"
}
} catch let parseError {
print("parsing error: \(parseError)")
let responseString = String(data: data, encoding: .utf8)
print("raw response: \(responseString)")
}
}
task.resume()
Or in Swift 2:
let url = NSURL(string: "http://example.com/test.php")!
let request = NSMutableURLRequest(URL: url)
// modify the request as necessary, if necessary
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard let data = data else {
print("request failed \(error)")
return
}
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: String], let name = json["name"] {
print("name = \(name)") // if everything is good, you'll see "William"
}
} catch let parseError {
print("parsing error: \(parseError)")
let responseString = String(data: data, encoding: NSUTF8StringEncoding)
print("raw response: \(responseString)")
}
}
task.resume()
I'm answering this as an iOS/PHP dev rather than a Swift programmer.
You need to send an HTTP request to the webserver hosting the PHP script, which will return the contents of the web page given any specified parameters.
For example, if you sent an GET HTTP request to the following PHP script, the response would be "William" in the form of NSData or NSString depending on the method you use.
<?php
$name = "William";
echo $name;
?>
With a parameter GET http://myserver.com/some_script.php?name=William:
<?php
$name = $_GET['name']; // takes the ?name=William parameter from the URL
echo $name; // William
?>
As to the Swift side of things, there is a perfectly valid answer here which denotes one of the myriad methods of sending a request: https://stackoverflow.com/a/24016254/556479.

Categories