How to write a secure SELECT query which has a variable number of user-supplied values with mysqli?

后端 未结 2 1724
故里飘歌
故里飘歌 2020-12-02 03:02

I would like some help to execute a foreach into my code.

I post multiple value into username : as username[0] = user1 , user2

but my foreach gi

相关标签:
2条回答
  • 2020-12-02 03:25

    Remove the '$value = $username_grab;' inside the foreach

    i.e.

    foreach ($username_grab as $value){
        // $value = $username_grab;   This does not belong
    

    If that doesn't help, can you show the code this POSTs from and do a

    print_r($username_grab)
    

    just after you set it

    Edit

    <?php
    $companyname = $_POST['companyname'];
    $username_grab = $_POST['username'];                            // This (based on your example) is a weird single index array - Array ( [0] => user1,user2 )
    // $username = implode(",", $username_grab);                    // implode turns an array into a string using a delimiter
    $usernames = explode(",", $username_grab[0]);                   // explode turns a string into an array by delimiter. The [0] index is for the post coming through as such
    // $usernames should now look something like this. This is the array you will be working with
    // Array ( [0] => user1, [1] => user2 )
    
    foreach($usernames AS $value)
    {
        $sql = "select * from linked_user where username = '" . mysqli_escape_string($value) . "' and company_name = '" . mysqli_escape_string($companyname) . "'"; // SQL injection is a threat. Seperate issue to look into   
        $res = mysqli_query($conn,$value);
        $cnt = 0;                                                   // Looking for multiple results. Counter for array
        while($row = mysqli_fetch_array($res))
        {
            $returnValue[$cnt]['username'] = $row['username'];      // Create a two dimensional array (multiple users. Each has their own index then
            $returnValue[$cnt]['user_scid'] = $row['user_scid'];    // Can replace the $cnt field with $row['userid'] (or whatever) if you have a primary key on the table i.e. $returnValue[$row['userid']]['username'] = $row['username'];
        }
        $cnt++;                                                     // Increase the counter for the next user
    }
    
    // $returnValue should now look something like this
    // Array ( 
    // [0] => Array (
    //          ['username'] => 'user1', 
    //          ['user_scid'] => 'whateverthedbsaysforuser1'),
    // [1] => Array (
    //          ['username'] => 'user2', 
    //          ['user_scid'] => 'whateverthedbsaysforuser2'),
    // )
    echo json_encode($returnValue);
    ?>
    
    0 讨论(0)
  • 2020-12-02 03:45

    The task you are to perform is a prepared statement with a variable number of placeholders. This is simpler in PDO, but I'll show you the mysqli object-oriented style approach. No matter what, always print a json encoded array so that your receiving script knows what kind of data type to expect.

    I had a snippet laying around that includes a full battery of diagnostics and error checking. I have not tested this script, but it has quite the resemblance to this post of mine.

    if (empty($_POST['companyname']) || empty($_POST['username'])) {  // perform any validations here before doing any other processing
        exit(json_encode([]));
    }
    
    $config = ['localhost', 'root', '', 'dbname'];  // your connection credentials or use an include file
    $values = array_merge([$_POST['companyname']], explode(',', $_POST['username']));  // create 1-dim array of dynamic length
    $count = sizeof($values);
    $placeholders = implode(',', array_fill(0, $count - 1, '?'));  // -1 because companyname placeholder is manually written into query
    $param_types = str_repeat('s', $count);
    if (!$conn = new mysqli(...$config)) {
        exit(json_encode("MySQL Connection Error: <b>Check config values</b>"));  // $conn->connect_error
    }
    if (!$stmt = $conn->prepare("SELECT user_scid, user_scid FROM linked_user WHERE company_name = ? AND username IN ({$placeholders})")) {
        exit(json_encode("MySQL Query Syntax Error: <b>Failed to prepare query</b>"));  // $conn->error
    }
    if (!$stmt->bind_param($param_types, ...$values)) {
        exit(json_encode("MySQL Query Syntax Error: <b>Failed to bind placeholders and data</b>"));  // $stmt->error;
    }
    if (!$stmt->execute()) {
        exit(json_encode("MySQL Query Syntax Error: <b>Execution of prepared statement failed.</b>"));  // $stmt->error;
    }
    if (!$result = $stmt->get_result()) {
        exit(json_encode("MySQL Query Syntax Error: <b>Get Result failed.</b>")); // $stmt->error;
    }
    exit(json_encode($result->fetch_all(MYSQLI_ASSOC)));
    

    If you don't want the bloat of all of those diagnostic conditions and comments, here is the bare bones equivalent which should perform identically:

    if (empty($_POST['companyname']) || empty($_POST['username'])) {
        exit(json_encode([]));
    }
    
    $values = explode(',', $_POST['username']);
    $values[] = $_POST['companyname'];
    $count = count($values);
    $placeholders = implode(',', array_fill(0, $count - 1, '?'));
    $param_types = str_repeat('s', $count);
    
    $conn = new mysqli('localhost', 'root', '', 'dbname');
    $stmt = $conn->prepare("SELECT user_scid, user_scid FROM linked_user WHERE username IN ({$placeholders}) AND company_name = ?");
    $stmt->bind_param($param_types, ...$values);
    $stmt->execute();
    $result = $stmt->get_result();
    exit(json_encode($result->fetch_all(MYSQLI_ASSOC)));
    
    0 讨论(0)
提交回复
热议问题