0

I a working on an iOS app that needs to get data from a remote server.

This is the Swift code that is getting the JSON array from the PHP script:

func doSearch(_ searchWord: String)
    {
        // Dismiss the keyboard


        // Create URL
        let myUrl = URL(string: "...getAsesores.php")

        // Create HTTP Request
        let request = NSMutableURLRequest(url:myUrl!);
        request.httpMethod = "POST";

        if let x = UserDefaults.standard.object(forKey:"miCodigoAgencia") as? String
        {
            print (x)
        }


        let postString = "searchWord=\(UserDefaults.standard.object(forKey:"miCodigoAgencia"))";
        print (postString)
        request.httpBody = postString.data(using: String.Encoding.utf8);

        // Execute HTTP Request
        URLSession.shared.dataTask(with: request as URLRequest,
                                   completionHandler: { (data, response,error) -> Void in

            // Run new async task to be able to interact with UI
            DispatchQueue.main.async {

                // Check if error took place
                if error != nil
                {
                    // display an alert message
                    self.displayAlertMessage(error!.localizedDescription)
                    return
                }


                do {

                    // Convert data returned from server to NSDictionary
                    let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary



                    // Cleare old search data and reload table
                    self.searchResults.removeAll(keepingCapacity: false)


                    // If friends array is not empty, populate searchResults array
                    if let parseJSON = json {

                        if let friends  = parseJSON["friends"] as? [AnyObject]
                        {
                            let primerName = ["Nombre": "Selecciona un asesor" ,"Apellidos": " ", "Id": " ", "Tel": " ", "Email": " " ]
                             self.searchResults.append(primerName)

                            for friendObj in friends
                            {
                                let fullName = ["Nombre": friendObj["nombre"] as! String, "Apellidos": friendObj["apellidos"] as! String, "Id": friendObj["id"] as! String, "Tel": friendObj["tel"] as! String, "Email": friendObj["email"] as! String]

                                self.searchResults.append(fullName)

                            }


                            self.pickerAsesores.reloadAllComponents()

                        } else if(parseJSON["message"] != nil)
                        {
                            // if no friends returned, display message returned from server side
                            let errorMessage = parseJSON["message"] as? String

                            if(errorMessage != nil)
                            {
                                // display an alert message
                                self.displayAlertMessage(errorMessage!)
                            }
                        }
                    }

                } catch {
                    print(error);
                }

            } // End of dispatch_async


        }) // End of data task


        .resume()

    } // end of doSearch() function

Then there is the PHP part on two files:

FILE 1 getAsesores.php:

<?php
require("../db/MySQLDAO.php");


$config = parse_ini_file('../../../SwiftPhp.ini');
$dbhost = trim($config["dbhost"]);
$dbuser = trim($config["dbuser"]);
$dbpassword = trim($config["dbpassword"]);
$dbname = trim($config["dbname"]);


$dao = new MySQLDAO($dbhost, $dbuser, $dbpassword, $dbname);
$dao->openConnection();

$searchWord = null;

if(!empty($_REQUEST["searchWord"]))
{
   $searchWord = htmlentities($_REQUEST["searchWord"]);
}

$friends = $dao->buscarAsesores($searchWord);


if(!empty($friends))
{
    $returnValue["friends"] = $friends;
} else {
    $returnValue["message"] = "Could not find records";
}

$dao->closeConnection();

echo json_encode($returnValue);

?>

And file 2: MySQLDAO.php:

public function buscarAsesores($searchWord)
{
    $returnValue = array();

    $sql = "select * from members LEFT JOIN tb_agencias ON members.agencia_usuario = tb_agencias.id_agencia where 1";

    if(!empty($searchWord))
    {
        $sql .= " and ( codigo_agencia like ?  )";
          $sql .= " ORDER BY nombre";

    }

    $statement = $this->conn->prepare($sql);

    if (!$statement)
        throw new Exception($statement->error);

    if(!empty($searchWord))
    {
      $searchWord = '%' ;
      $statement->bind_param("s",  $searchWord );
    }

    $statement->execute();

    $result = $statement->get_result();

     while ($myrow = $result->fetch_assoc()) 
     {
       $returnValue[] = $myrow;
     }

    return $returnValue;
} 

If I call the PHP directly from the browser, the result is not correct, the query is not filtering the records as I want, and the iOS app shows all records.

If I remove the line:

  $searchWord = '%' ;

as commented in my previous question here at SO Weird filter result in PHP function

at MySQLDAO.php, then the query filters the records as I want, but the app shows the message: Could not find records

Any help is welcome.

EDITED CODE UPDATED TO SWIFT 3 FROM THE CORRECT ANSWER BY @Chris:

 if let x = UserDefaults.standard.object(forKey:"miCodigoAgencia") as? String {
            print (x)
            var postString = "searchWord=\(x)".addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed);
            print (postString)
            request.httpBody = postString?.data(using: String.Encoding.utf8)
            request.setValue("\(request.httpBody?.count)", forHTTPHeaderField:"Content-Length")
        }

1 Answer 1

1

I see a few of things.

  1. You are overwriting the value of $searchWord to always be '%'.
  2. In the iOS app, you may need to set the Content-Type header to a Form-savvy value in your request. You may also need to set Content-Length. EDIT: Default value is application/x-www-form-urlencoded, you need to actually url-encode your value ;-)
  3. You probably want to surround your search term with %'s in your sql

For number 1, this code:

if(!empty($searchWord))
    {
      $searchWord = '%' ;
      $statement->bind_param("s",  $searchWord );
    }

Should be like this

if(!empty($searchWord)) {
  $statement->bind_param("s",  $searchWord );
}

For number 2 in the iOS app, add code like this (note that I removed redundant call to UserDefaults):

let request = NSMutableURLRequest(url:myUrl!);
request.httpMethod = "POST";

if let x = UserDefaults.standard.object(forKey:"miCodigoAgencia") as? String {
  print (x)
  var postString = "searchWord=\(x))".addingPercentEncoding(withAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet());
  print (postString)
  request.httpBody = postString.data(using: String.Encoding.utf8)
  request.setValue("\(request.httpBody.length)", forHTTPHeaderField:"Content-Length")
}

For number 3, change " and ( codigo_agencia like ? )" to " and ( codigo_agencia like %?% )" (or use only the latter one to make your search require matching the start of the data).

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you @Chris, as stated in my question, point number 1 solves the filtering issue. But I need your help solving point 2
@mvasco updated with example and update to #2, I think you needed to actually URL-encode the body.
Thank you @Chris, I get an error at line: var postString = "searchWord=(x))".stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()); Static member init(String interpolation segment cannot be used on instance of type String
Looks like that method changed in Swift 3. Updated. If it still gives you trouble, break out the assignment of postString into two lines. One for the simple interpolation, another for the URLEncoding. That should help you debug it easier.
I will add to my question the updated code to Swift 3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.