How to do php REST API POST call in xcode swift 4? [on hold]

How do I write this PHP code in swift to get the API json data? 🙂 Hope you can help me, thanks!

Im not sure what goes wrong. Could it be that my API php side needs to be able to get json data requests?

Sorry I am not really skilled, but really want to learn this!


<?php $post = [ 'email' => 'admin@admin.com', 'pwd' => '123', 'table' => 'users', 'conditions' => array('id' => 1) ]; $url = 'www.***.com/api/rest/GetRow'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post)); $response = curl_exec($ch); var_export($response); ?>


This is what I tried with swift:


struct Post: Codable { let email: String let pwd: String let table: String let conditions: Dictionary<String, Int> } func submitPost(post: Post, completion:((Error?) -> Void)?) { var urlComponents = URLComponents() urlComponents.scheme = "https" urlComponents.host = "***.com" urlComponents.path = "/api/rest/GetRow" guard let url = urlComponents.url else { fatalError("Could not create URL from components") } / var request = URLRequest(url: url) request.httpMethod = "POST" / / var headers = request.allHTTPHeaderFields ?? [:] headers["Content-Type"] = "application/json" request.allHTTPHeaderFields = headers / let encoder = JSONEncoder() do { let jsonData = try encoder.encode(post) / request.httpBody = jsonData print("jsonData: ", String(data: request.httpBody!, encoding: .utf8) ?? "no body data") } catch { completion?(error) } / let config = URLSessionConfiguration.default let session = URLSession(configuration: config) let task = session.dataTask(with: request) { (responseData, response, responseError) in guard responseError == nil else { completion?(responseError!) return } / if let data = responseData, let utf8Representation = String(data: data, encoding: .utf8) { print("response: ", utf8Representation) } else { print("no readable data received in response") } } task.resume() } func buttonTapped() { let myPost = Post(email:"admin@admin", pwd:"123", table: "users" , conditions: ["id":1]) submitPost(post: myPost) { (error) in if let error = error { fatalError(error.localizedDescription) } } } buttonTapped()



and this is the API I used:


<?php require_once("Rest.inc.php"); class API extends REST { public $data = ""; const DB_SERVER = "***.com.mysql"; const DB_USER = "***"; const DB_PASSWORD = "***"; const DB = "***"; private $db = NULL; public function __construct(){ parent::__construct(); / $this->dbConnect(); / } / * Database connection */ private function dbConnect(){ $this->db = mysqli_connect(self::DB_SERVER,self::DB_USER,self::DB_PASSWORD, self::DB); } / * Public method for access api. * This method dynmically call the method based on the query string * */ public function processApi(){ $func = strtolower(trim(str_replace("/","",$_REQUEST['rquest']))); if((int)method_exists($this,$func) > 0) $this->$func(); else $this->response('',404); / } / * Simple login API * Login must be POST method * email : <USER EMAIL> * pwd : <USER PASSWORD> */ private function login(){ / if($this->get_request_method() != "POST"){ $this->response('',406); } $email = $this->_request['email']; $password = $this->_request['pwd']; $return = null; if(!empty($email) and !empty($password)){ if(filter_var($email, FILTER_VALIDATE_EMAIL)){ $sql = mysqli_query($this->db, "SELECT id FROM `users` WHERE email = '".$email."' AND password = '".md5($password)."' LIMIT 1"); if(mysqli_num_rows($sql) > 0){ $result = mysqli_fetch_array($sql,MYSQLI_NUM); $return = $result[0]; } } } return $return ; } function GetRow(){ if($this->login() > 0){ $table_name = $this->_request['table']; $conditions = $this->_request['conditions']; if(isset($this->_request['order_by'])) $order_by = $this->_request['order_by']; else $order_by = null; $sql0 = "SELECT * FROM ".$table_name." WHERE 1=1"; if($conditions != null) { foreach($conditions as $key=>$value){ $sql0 .= " AND {$key} = '${value}'"; } } if($order_by != null) { $sql0 .=" ORDER BY "; foreach($order_by as $key=>$value){ $sql0 .= " {$key} ${value}"; } } / $sql0 .= " LIMIT 1"; $sql = mysqli_query($this->db, $sql0); if(mysqli_num_rows($sql) > 0){ if($row = mysqli_fetch_array($sql, MYSQLI_ASSOC)) $this->response($this->json($row), 200); else $this->response(array('status' => "Failed", "msg" => "Sorry It's Not Working"), 400); } $this->response('', 204); / } $error = array('status' => "Failed", "msg" => "Sorry It's Not Working"); $this->response($this->json($error), 400); } public function db_escape($value = "", $nullify = false){ $value = @html_entity_decode($value); $value = @htmlspecialchars($value); / $nullify = ($nullify === null) ? (false) : ($nullify); / if ((!isset($value)) || (is_null($value)) || ($value === "")) { $value = ($nullify) ? ("NULL") : ("''"); } else { if (is_string($value)) { / if (function_exists('mysqli_real_escape_string')) { $value = "'" . mysqli_real_escape_string($this->db, $value) . "'"; } else { $value = "'" . mysqli_escape_string($this->db, $value) . "'"; } } else if (!is_numeric($value)) { / display_error("ERROR: incorrect data type send to sql query"); echo '<br><br>'; exit(); } } return $value; } / * Encode array into JSON */ private function json($data){ if(is_array($data)){ return json_encode($data); } } } / $api = new API; $api->processApi(); ?>



Seems like i can´t post the code formattet the right way here. But you can see the code at my same question at stackoverflow: https://stackoverflow.com/questions/48782851/how-to-do-php-rest-api-post-call-in-xcode-swift-4?noredirect=1#comment84580658_48782851

Replies

I can’t really help you with the PHP side of things; that’s one language I’ve never had an excuse to get to grips with. I do, however, have a concrete suggestion: you should approach this problem by first deciding what the JSON for a request is supposed to look like. You can then debug each side of the problem separately.

Based on your PHP code I imagine the JSON you’re expecting might look like this:

{
  "email" : "admin@admin.com",
  "pwd" : "123",
  "table" : "users"
}

Note This doesn’t include the

conditions
property because I’m not sure what you’re doing with the PHP there.

You can then write Swift code to generate that JSON. For example:

struct User : Codable {
    var email: String
    var pwd: String
    var table: String
}
let u = User(email: "admin@admin.com", pwd: "123", table: "users")
let jsonData = try! JSONEncoder().encode(u)
print(String(bytes: jsonData, encoding: .utf8)!)

This prints:

{"email":"admin@admin.com","pwd":"123","table":"users"}

which is a good match for your expectations.

At this point you need to run through a similar process on the PHP side to make sure it’s decoding that JSON correctly.

Once you have that working you can join things up via your networking requests. That might Just Work™, but if it doesn’t you can use a debugging proxy to see the request being sent on the ‘wire’ is formatted correctly. If it isn’t, you can look at the sender to see what’s going wrong. If it is, you have to look at the receiving side of things.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"