【问题标题】:Check duplication record from one table and duplication record insert to another table using php script使用php脚本检查一个表中的重复记录并重复记录插入到另一个表中
【发布时间】:2020-12-05 14:04:49
【问题描述】:

我有两个下表

1)候选人详情

EmployeeId  FirstName       LastName    Mobile          Email     BatchId
1           fn1             ln1         123456789       Email1      75
2           fn2             ln2         123456790       Email2      75
3           fn3             ln3         123456791       Email3      75
4           fn4             ln4         123456792       Email4      75
                

2)重复候选

EmployeeId  FirstName       LastName    Mobile          Email     BatchId

我的要求是,如果 CandidateDetails 表中已经有 EmployeeId,则复制记录以插入 DuplicateCandidate

以下是仅用于将数组插入 CandidateDetails 表的 PHP 脚本,但我无法检查员工 ID 是否重复的条件,然后将该记录插入另一个 DuplicateCandidate强>表。

<?php
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Credentials: true ");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header("Access-Control-Allow-Headers: X-Custom-Header, Origin, Content-Type , Authorisation , X-Requested-With");
header("Content-Type: application/json; charset=UTF-8 ");

$json = file_get_contents('php://input');
$decoded = json_decode($json, true);

print_r($decoded);
 $id=$_GET['id'];

function conn() {
  $dbhost = "xxxx";
  $user = "xxx";
  $pass = "xxx";
  $db = "xxxx";
  $conn = new PDO('mysql:host=xxx;dbname=xxx', $user, $pass);
  return $conn;
}
$db = conn();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);                  
$p = $db->prepare("INSERT INTO CandidateDetails(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)VALUES(:EmployeeId,:FirstName,:LastName,:Mobile,:Email,'$id')");
                   
foreach ($decoded as $item) {
  $p->execute($item);
}

echo json_encode(true);

?>

【问题讨论】:

    标签: php mysql apache htdocs


    【解决方案1】:
    <?php
    header("Access-Control-Allow-Origin: http://localhost:4200");
    header("Access-Control-Allow-Credentials: true ");
    header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
    header("Access-Control-Allow-Headers: X-Custom-Header, Origin, Content-Type , Authorisation , X-Requested-With");
    header("Content-Type: application/json; charset=UTF-8 ");
    
    $json = file_get_contents('php://input');
    $decoded = json_decode($json, true);
    
    print_r($decoded);
    $id = $_GET['id'];
    
    function conn()
    {
        $dbhost = "x.x.x.x";
        $user = "x";
        $pass = "x";
        $db = "x";
        $conn = new PDO('mysql:host=x;dbname=x', $user, $pass);
        return $conn;
    }
    $db = conn();
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    foreach ($decoded as $item)
    {
        echo $item['EmployeeId'];
    
        $sql = "SELECT * FROM CandidateDetails WHERE EmployeeId = " . $item['EmployeeId'];
        //$result = $conn-                         >query($sql);
        echo $item['EmployeeId'];
        echo $sql;
        $result = $db->query($sql);
        //echo $result;
        //echo $result->num_rows;
        $count = $result->rowCount();
        echo $count;
        if ($count > 0)
        {
            //DuplicateCandidate
            echo "duplicte results";
            //$p = $db->prepare("INSERT INTO CandidateDetailsLog(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)VALUES(:EmployeeId,:FirstName,:LastName,:Mobile,:Email,'$id')");
            $p = $db->prepare("INSERT INTO CandidateDetailsLog(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)
                                          VALUES ('" . $item['EmployeeId'] . "', '" . $item['FirstName'] . "',
                                                          '" . $item['LastName'] . "', '" . $item['Mobile'] . "', '" . $item['Email'] . "',
                                                           '" . $id . "')");
    
            $p->execute();
        }
        else
        {
            echo "0 results";
            //$p = $db->prepare("INSERT INTO CandidateDetails(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)VALUES(:EmployeeId,:FirstName,:LastName,:Mobile,:Email,'$id')");
            $p = $db->prepare("INSERT INTO CandidateDetails(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)
                                          VALUES ('" . $item['EmployeeId'] . "', '" . $item['FirstName'] . "',
                                                          '" . $item['LastName'] . "', '" . $item['Mobile'] . "', '" . $item['Email'] . "',
                                                           '" . $id . "')");
    
            $p->execute();
        }
    
    }
    
    $o = $db->prepare("UPDATE BatchDetailsInfo SET BatchStatus='B2' WHERE BatchId='$id'");
    $o->execute();
    
    echo json_encode(true);
    
    ?>
    

    【讨论】:

    【解决方案2】:

    虽然接受的答案可能会起作用,但它有几个SQL injection 漏洞,包括$_GET['id'](不应该被信任 - 恶意行为者可以在此处放置任何内容,包括用于清除数据库的 SQL 命令),以及从php://input 获取的 JSON(同样 - 即使它是有效的 JSON,您也可以在此处隐藏删除数据的命令)。参数转义(作为您的原始示例)是要走的路。

    <?php
    
    /* Your headers etc here*/
    
    ///Build a database connection
    function db_conn() {
        /* Your Mysql setup with user/pass/db etc in a PDO object here*/
        $db=new PDO('mysql:host=x;dbname=x', $user, $pass);
        //You might want to set this here (for all connections:)
        //$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $db;
    }
    
    ///Search the candidate table for an entry for the given ID
    function db_employeeCandidateExists($db,$dangerEmployeeId) {
        $stmt=$db->prepare('SELECT EmployeeId FROM CandidateDetails WHERE EmployeeId=?');
        $stmt->execute([$dangerEmployeeId]);
        $result=$stmt->fetchAll();//We're expecting 0 rows (not found) or 1 row with the ID if it's a dup
        return count($result)>0;
    }
    
    ///Add a row to the DuplicateCandidate table
    function db_addDuplicate($db,$dangerRow,$dangerBatchId) {
        //All columns you want to fill out - layed out to be visually obvious how many there are
        $cols=['EmployeeId',
            'FirstName',
            'LastName',
            'Mobile',
            'Email',
            'BatchId'];
        //Values for the above columns - layed out to be visually equal to above
        // don't forget
        $vals=[$dangerRow['EmployeeId'],
            $dangerRow['FirstName'],
            $dangerRow['LastName'],
            $dangerRow['Mobile'],
            $dangerRow['Email'],
            $dangerBatchId];
        //The parameters can use a count of the cols (above)
        $params=substr(str_repeat('?,',count($cols)),0,-1);
    
        $stmt=$db->prepare('INSERT INTO DuplicateCandidate ('.
            implode(',',$cols).
            ') VALUES ('.
            $params.
            ')');
    
        $stmt->execute($vals);
        //todo: You might want to check there are no SQL errors reported here
    }
    
    ///Add a row to the CandidateDetails table
    function db_addCandiate($db,$dangerRow,$dangerBatchId) {
        //All columns you want to fill out - layed out to be visually obvious how many there are
        $cols=['EmployeeId',
            'FirstName',
            'LastName',
            'Mobile',
            'Email',
            'BatchId'];
        //Values for the above columns - layed out to be visually equal to above
        // don't forget
        $vals=[$dangerRow['EmployeeId'],
            $dangerRow['FirstName'],
            $dangerRow['LastName'],
            $dangerRow['Mobile'],
            $dangerRow['Email'],
            $dangerBatchId];
        //The parameters can use a count of the cols (above)
        $params=substr(str_repeat('?,',count($cols)),0,-1);
    
        $stmt=$db->prepare('INSERT INTO CandidateDetails ('.
            implode(',',$cols).
            ') VALUES ('.
            $params.
            ')');
    
        $stmt->execute($vals);
        //todo: You might want to check there are no SQL errors reported here
    }
    
    ///Get JSON from input and decode it into an associative array
    function getJson() {
        $json = file_get_contents('php://input');
        return json_decode($json, true);
    }
    
    $db = db_conn();
    //You might want to set this inside the `conn()` method for all usage?
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    // *** *** Dangerous CONTENT *** ***
    // Both $id (presuambly an integer) and $json (an associative array of data)
    // are user-provided and therefore the cannot be trusted - you NEED to escape these
    // values before using them in SQL
    $dangerBatchId = $_GET['id'];
    $dangerJson = getJson();
    
    foreach($dangerJson as $dangerItem)
    {
        if (db_employeeCandidateExists($db,$dangerItem['EmployeeId'])) {
            //Duplicate
            db_addDuplicate($db,$dangerItem,$dangerBatchId);
            echo 'Applicant '.$dangerItem['EmployeeId']." was a duplicate\n";
        } else {
            db_addCandiate($db,$item,$dangerBatchId);
            echo 'Applicant '.$dangerItem['EmployeeId']." added\n";
        }
    }
    // Further processing
    

    我使用了位置参数转义 (?),它也应该适用于 MySQL。命名位置转义 (:id) 可能更好,但不允许我快速生成所有参数(构建 $params 字符串),并且我测试的数据库不支持它们。

    在将组件分离为函数之后(就像我所做的那样),您会注意到我们有一些以db_ 开头的函数...您可以改为配置将它们捆绑到一个类中。那时您可以避免将$db 作为第一个参数传递,因为您可以在课程内部共享它。 但是这是一个完全不同的主题,超出了您最初问题的范围。

    【讨论】:

      猜你喜欢
      • 2012-03-23
      • 2020-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-03
      相关资源
      最近更新 更多