0

I have an iOS app using Swift 3 using a PHP file to receive objects but now working to update objects into the database.

I'm new to PHP so my question is, is the php code below correct? It's supposed to insert a variable from my app which is +1 points from a button to go through php and UPDATE my 'tests' table in mysql database. I already have a column in the database called testPop and the variable is also called testPop which is received in a json object array but I'm just trying to update the table.

So if row1 = id:1 testName:test1 testPop:0

I want testPop to update its value every time someones adds a point +1

Current PHP Code:

<?php

$host = "host";
$db = "db";
$user = "user";
$pass = "pass";

$connection = mysql_connect($host,$user,$pass);

// Guessing: Posting into MySQL Object
$id = $_POST["id"];

// Checking if connection can be established
if(!$connection){
    die("Connection Failed");
}
else
{
    // Selecting Database
    $dbconnect = mysql_select_db($db, $connection);

    // Check if it can connect to Database
    if(!$dbconnect){
        die("Unable to connect to Database");
    }
    else
    {
        $query = sprintf("UPDATE tests SET testPop=testPop+1 WHERE id = %d", $id);

        $resultset = mysql_query($query, $connection);

        echo "Successfully added";
        echo $query;
    }
}

?>

Swift 3 Code: Sending Data to database:

func sendData() {

    let postDataURL = "http://exampleip.com/Send.php"
    let url: NSURL = NSURL(string: postDataURL)!
    let request: NSMutableURLRequest = NSMutableURLRequest(url:url as URL)

    let bodyData = String(1)

    request.httpMethod = "POST"
    request.httpBody = bodyData.data(using: String.Encoding.utf8)
    NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: OperationQueue.main)
    {
        (response, data, error) in
        print(response!)

        if let httpResponse = response as? HTTPURLResponse {
            let statusCode = httpResponse.statusCode

            if statusCode==200 {
                print("Connection Successful")

            } else {
                print("Connection Failed (!200)")
            }
        }
    }
}

----- Added Additional Code for better understanding -----

New: MySQL Code

CREATE TABLE IF NOT EXISTS `tests` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`testName` varchar(255) DEFAULT NULL,
`testPop` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=13 ;

INSERT INTO `tests` (`id`, `testName`, `testPop`) VALUES
(1, 'Test 1', '0'),
(2, 'Test 2', '0'),
(3, 'Test 3', '0'),
(4, 'Test 4', '0'),
(5, 'Test 5', '0'),
(6, 'Test 6', '0'),
(7, 'Test 7', '0'),
(8, 'Test 8', '0'),
(9, 'Test 9', '0'),
(10, 'Test 10', '0'),
(11, 'Test 11', '0'),
(12, 'Test 12', '0');

Example: On how I receive from the database, using json. Don't know if this helps. Swift 3

func retrieveData() {

let getDataURL = "http://exampleip.org/tests.php"
let url: NSURL = NSURL(string: getDataURL)!

do {

    let data: Data = try Data(contentsOf: url as URL)
    jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray

    // Looping through jsonArray
    for i in 0..<jsonArray.count {

        // Create Test Object
        let tID: String = (jsonArray[i] as AnyObject).object(forKey: "id") as! String
        let tName: String = (jsonArray[i] as AnyObject).object(forKey: "testName") as! String
        let tPop: String = (jsonArray[i] as AnyObject).object(forKey: "testPop") as! String

        // Add Test Objects to Test Array
        testArray.append(Test(testName: tName, andTestPop: tPop, andTestID: tID))

    }
}
catch {
    print("Error: (Retrieving Data)")
}

myTableView.reloadData()
}
WokerHead
  • 947
  • 2
  • 15
  • 46
  • what is `$_POST["a"]` supposed to be equal to? – robere2 Dec 05 '16 at 22:48
  • 3
    If you're writing new code, **_please_ don't use the `mysql_*` functions**. They are old and broken, were deprecated in PHP 5.5 (which is so old it no longer even receives security updates), and completely removed in PHP 7. Additionally, your code is wide open to [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) attacks. Use [`PDO`](https://secure.php.net/manual/en/book.pdo.php) or [`mysqli_*`](https://secure.php.net/manual/en/book.mysqli.php) with _prepared statements_ and _parameter binding_ instead. See http://stackoverflow.com/q/12859942/354577 for details. – ChrisGPT was on strike Dec 05 '16 at 22:49
  • @bugfroggy thats for when I was using INSERT INTO VALUES not UPDATE – WokerHead Dec 05 '16 at 22:51
  • @Chris Thanks! Was that the only errors in the code? Changing the mysql_* functions to mysqli? – WokerHead Dec 05 '16 at 22:56
  • Your code is incorrect then because you're using it in your `UPDATE` query: `$testPop = $_POST["a"]; $query = "UPDATE tests SET testPop='$testPop' WHERE $testPop";` – robere2 Dec 05 '16 at 22:56
  • @BroSimple You should change your queries to be prepared statements as well rather than just literally appending an `i` to all of your `mysql_*` functions. While it would work, it's not recommended. – robere2 Dec 05 '16 at 22:58
  • Whats the correct way of going by this? – WokerHead Dec 05 '16 at 22:58
  • @BroSimple Going about what, exactly? I'm not sure what you want to update and in what scenario. Do you want when a page is loaded for something to be updated in a database? Which value in which row do you want to be updated? – robere2 Dec 05 '16 at 23:00
  • FYI - nothing about this question is specific to iOS or Swift. It applies to any client. – rmaddy Dec 05 '16 at 23:02
  • @bugfroggy I have another question open explaining the iOS part but I made this one because I thought I had to fix the php code first then move to something else. http://stackoverflow.com/questions/40956595/php-swift-receiving-object-add-1-send-it-back-to-database?noredirect=1#comment69122748_40956595 – WokerHead Dec 05 '16 at 23:07
  • @rmaddy I thought I had to go through to the php first but I have another question with the swift side code. http://stackoverflow.com/questions/40956595/php-swift-receiving-object-add-1-send-it-back-to-database?noredirect=1#comment69122748_40956595 – WokerHead Dec 05 '16 at 23:08
  • @BroSimple but when this script is run, you want it to update something in a database. Is that correct? – robere2 Dec 05 '16 at 23:09
  • Yes thats correct – WokerHead Dec 05 '16 at 23:10
  • that `$testPop` is that a string? and where's the form for this? – Funk Forty Niner Dec 05 '16 at 23:11
  • and this `WHERE $testPop` how is that supposed to end as? seems unfinished to me. anyhow, somebody "popped" an answer below, ask them. – Funk Forty Niner Dec 05 '16 at 23:12
  • Yes in my ios app, its received as a string, what do you mean with form, the mysql code? – WokerHead Dec 05 '16 at 23:12
  • @BroSimple Okay. And you want which value(s) to be updated? What conditions must they meet in your `WHERE` statement? – robere2 Dec 05 '16 at 23:13
  • The testPop should be updated with an increment of +1 – WokerHead Dec 05 '16 at 23:14
  • But do you only have one row? Which row(s) do you want it updated on? All of them? – robere2 Dec 05 '16 at 23:18
  • @bugfroggy i have several rows like 50+ objects, in my swift app the user clicks the button on which row they want to add +1 – WokerHead Dec 05 '16 at 23:21
  • In that case you need your app to send a parameter to your PHP script with the row ID you want to be updated. Your MySQL query will look something like `UPDATE \`tests\` SET \`testPop\`='$testPop' WHERE \`id\`='$rowID'`. You should also convert this and the rest of your script to use the latest MySQLi techniques: [Prepared Statements](http://php.net/manual/en/mysqli.quickstart.prepared-statements.php) and [MySQLi Overview](http://php.net/manual/en/book.mysqli.php). Other than that your script looks fine to me. – robere2 Dec 05 '16 at 23:30
  • @bugfroggy thank you I will try this. Also normally in my app I use indexPath.row to get the specific row? Does that change anything? – WokerHead Dec 05 '16 at 23:35
  • I don't know how to code in iOS or what the goal of your application is so this question would be better for someone who does know. Sorry. – robere2 Dec 05 '16 at 23:37

1 Answers1

2
$id = $_POST["id"];
$query = sprintf("UPDATE tests SET testPop=testPop+1 WHERE id = %d", $id);
  • First, if you're incrementing a value, let the database do it for you. This will prevent a race condition: if/when 2 queries happen simultaneously, only one will be saved properly.

  • Second, don't add user-generated input directly into a query without escaping. Using sprintf with %d forces the id variable to an integer.

ClickLabs
  • 547
  • 3
  • 5
  • How is this code? $query = sprintf("UPDATE tests SET testPop=$testPop+1 WHERE id = $id"); - Its the same except I changed it to $testPop or do I do it your way? – WokerHead Dec 06 '16 at 21:23
  • @BroSimple Since I don't know your application, I cannot tell you exactly what to do. But, your example still uses un-escaped user input. If you don't care about a race-condition and we assume testPop is an integer, you can do `$query = sprintf("UPDATE tests SET testPop=%d+1 WHERE id = %d", $testPop, $id);` – ClickLabs Dec 06 '16 at 22:52
  • With the code I have, the database is not being updated. - I added additional code to the question, maybe you'll get a better understanding. Also updated the php code and sendData code. – WokerHead Dec 06 '16 at 23:26
  • 1
    Since you're +1'ing a test, my original answer seems to be the best. `$query = sprintf("UPDATE tests SET testPop=testPop+1 WHERE id = %d", $id);` That way, if testPop was 4, it is now 5. – ClickLabs Dec 07 '16 at 00:29
  • Okay thanks trying this code but is the swift code for sending data to database, is it correct? How would I know the php code worked? – WokerHead Dec 07 '16 at 02:19