簡體   English   中英

PHP-如何檢查表或表行是否為空?

[英]php - how to check if table or table row is empty?

我定義了以下函數來檢查表行是否為空

function check_table($table) {
    global $con;
    $result = mysqli_query($con, "SELECT * FROM $table");
    return (mysqli_num_rows($result) > 0) ? true : false;
}

然后調用它來填寫表格

// check if payment table is empty, then insert into in, else update it
if(check_table('payment_details') == false) {
    insert_into_table('payment_details',$payment_detail);
} else {
    update_table($session_user_id,'payment_details',$payment_detail);
}

insert_into_table()定義

function insert_into_table($table,$register_data) {
    global $con;
    array_walk($register_data, 'array_sanitize');

    $fields = '`' . implode('`, `', array_keys($register_data)) . '`';
    $data = '\'' . implode('\', \'', $register_data) . '\'';
    mysqli_query($con , "INSERT INTO $table ($fields) VALUES ($data)");
}

但它沒有返回所需的值,並且執行該表后該表仍然為空。 它不起作用。

所以我哪里錯了?

任何幫助將不勝感激。

謝謝

新更新

這就是我的所有代碼,只是確保我做對了嗎? 如果沒有,請給我一些改進的建議。

init.php

$session_user_id = $_SESSION['userid'];
//users table
$user_data = user_data($session_user_id,'users', 'id','username','password','first_name','last_name','email','allow_email',
'password_recover','active','city','state','country','phone','custom','date','plan','duration','domain','amount',
'pp_txn_id', 'pp_item_no','pp_payment_status','pp_payer_email','pp_payment_date','pz_reference_no', 'pz_item_no',
'pz_payment_status','pz_payer_email','pz_payment_date','expiry','status','cpanel');

// for paypal payments
$pp_data = user_data($session_user_id,'pp_details','pp_txn_id','pp_item_no','pp_payment_status','pp_payer_email','pp_payment_date');
// for payza payments
$pz_data = user_data($session_user_id,'pz_details','pz_reference_no','pz_item_no','pz_payment_status','pz_payer_email','pz_payment_date');

member.php

require_once(get_template_directory().'/member/core/init.php');

$customField = $user_data['custom'];
//check if transaction is done
if ( $customField == $user_data['id'] && ($user_data['pz_payment_status'] == 'Success') || ($user_data['pp_payment_status'] == 'Completed') ) {
    //info for pp_details table
        $pp_detail = array(
            'id'                => $user_data['id'],
            'pp_txn_id'         => $user_data['pp_txn_id'],
            'pp_item_no'        => $user_data['pp_item_no'],
            'pp_payment_status' => $user_data['pp_payment_status'],
            'pp_payer_email'    => $user_data['pp_payer_email'],
            'pp_payment_date'   => $user_data['pp_payment_date'],
        );
        //info for pz_details table
        $pz_detail = array(
            'id'                => $user_data['id'],
            'pz_reference_no'   => $user_data['pz_reference_no'],
            'pz_item_no'        => $user_data['pz_item_no'],
            'pz_payment_status' => $user_data['pz_payment_status'],
            'pz_payer_email'    => $user_data['pz_payer_email'],
            'pz_payment_date'   => $user_data['pz_payment_date'],
        );
        //reset the users table if transaction is success
        $update_data = array(
            'status' => 'Active',
            'pp_txn_id' => NULL,
            'pp_item_no' => NULL,
            'pp_payment_status' => NULL,
            'pp_payer_email' => NULL,
            'pp_payment_date' => NULL,
            'pz_reference_no' => NULL,
            'pz_item_no' => NULL,
            'pz_payment_status' => NULL,
            'pz_payer_email' => NULL,
            'pz_payment_date' => NULL,
        );
    // check if payment table is empty, then insert into in
    if(check_table($session_user_id,'pp_details') == false) {
        if ($user_data['pp_payment_status'] == 'Completed') {
            insert_into_table('pp_details',$pp_detail);
            update_user($session_user_id, $update_data);
        }
    } elseif (check_table($session_user_id,'pz_details') == false) {
        if ($user_data['pz_payment_status'] == 'Success') {
            insert_into_table('pz_details',$pz_detail);
            update_user($session_user_id, $update_data);
        }
    }
    // make sure if user_data transaction id's not match with payment_data details, then activate the package
    if ( ($user_data['pp_txn_id']) != ($pp_data['pp_txn_id']) ) {
        // update the pp_details table
        update_table($session_user_id,'pp_details',$pp_detail);
        // reset the users table and activate package
        update_user($session_user_id, $update_data);

    } elseif ( ($user_data['pz_reference_no']) != ($pz_data['pz_reference_no']) ) {
        // update the pz_details table
        update_table($session_user_id,'pz_details',$pz_detail);
        // reset the users table and activate package
        update_user($session_user_id, $update_data);
    }
    // email credentials 
    if ( $user_data['pp_payment_status'] == 'Completed' ) {
        $transactionID  = $pp_data['pp_txn_id'];
        $itemNo         = $pp_data['pp_item_no'];
        $paymentStatus  = $pp_data['pp_payment_status'];
        $paymentDate    = $pp_data['pp_payment_date'];
        if ($pp_data['pp_payer_email'] !== $user_data['email']) {
            $customer_Email = array($pp_data['pp_payer_email'],$user_data['email']);
        } else {
            $customer_Email = array($user_data['email']);
        }
    } elseif ( $user_data['pz_payment_status'] == 'Success' ) {
        $transactionID  = $pz_data['pz_reference_no'];
        $itemNo         = $pz_data['pz_item_no'];
        $paymentStatus  = $pz_data['pz_payment_status'];
        $paymentDate    = $pz_data['pz_payment_date'];
        if ($pz_data['pz_payer_email'] !== $user_data['email']) {
            $customer_Email = array($pz_data['pz_payer_email'],$user_data['email']);
        } else {
            $customer_Email = array($user_data['email']);
        }
    }

    $message = "Thank You <b>".$user_data['first_name']."</b> for using our service.<br> Your Transaction details are below:<br><br>
            Transaction ID/Reference: $transactionID<br>
            Item No: $itemNo <br>
            Payment Status: $paymentStatus <br>
            Payment Date: $paymentDate <br><br>
            Kind Regards <br>
            - HostPLUS1 &copy; ".date('Y')."
    ";
    if ( isset($_GET['success']) && empty($_GET['success']) ) {
        //if sucess then refresh the page to remove the $_GET val
        refresh('3',$_SERVER['SCRIPT_URI']);
        if ($user_data['status'] == 'Active') {
            email($customer_Email,'Thank you, your payment has been completed',$message);

        }
    }
};

我已經在名為user_functions.php的單獨文件中定義了所有函數

HSN,您在哪里指定檢查表格的條件? 您說的是"SELECT * FROM $table" ,但沒有指定條件(或Yegor指出的限制)。 這意味着,即使您的payment_details表中只有 (1)個交易,也不會處理任何新交易。 您應該使用條件過濾結果。

我相信您是為PayPal IPN編寫的,因此我將這樣格式化我的答案。 在所有重寫下面,您將看到有關為什么我建議我做什么的信息。

這是我建議重寫它的方式:

/* Escape the variables right away */
// global $con; // uncomment this if you need to. I don't know where in your code it's defined
$clean_ppTxnId = ""; // we'll use this in check table.
foreach($payment_detail as $key => $value){
   $escapedKey = $con->escape_string($key);
   $escapedValue = $con->escape_string($value);
   if($key == 'pp_txn_id'){  $clean_ppTxnId = $escapedValue;  }
   unset($payment_detail[$key]);
   $payment_detail[$escapedKey] = $escapedValue;
}
// the payment details have now been looped, sanitized and replaced.

// check if payment table is empty, then insert into in, else update it
if(check_table('payment_details') == false) {
    /* new payment that we've never seen before */
    insert_into_table('payment_details',$payment_detail);
} else {
    /* if we go into the else statement, this exact payment has already
     * been processed once. */

    /* update_table($session_user_id,'payment_details',$payment_detail); */

    /*******
     * The line above is going to force you to either double process or
     * you'll overwrite PayPal transaction records.
     * Instead, this should be regarded as PayPal sending the transaction
     * to your IPN a second time (which does happen).
     ******/
}
/* If you're done with all database transactions at this point, you should call $con->close(); */

現在使用check_table函數

function check_table($table, $clean_ppTxnId) {
    global $con;
    $result = $con->("SELECT * FROM `$table` WHERE (`pp_txn_id` = '$clean_ppTxnId') LIMIT 1");
    // I've added a where conditional to filter results and a LIMIT statement as Yegor suggested.
    $returnVal = ($result->num_rows > 0) ? true : false;
    $result->close();
    return returnVal;
}

最后是insert_into函數:

function insert_into_table($table,$register_data) {
    global $con;
    /* removed array_walk because my solution filters the data in before
     * calls this function.
     */

    $fields = '`' . implode('`, `', array_keys($register_data)) . '`';
    $data = '\'' . implode('\', \'', $register_data) . '\'';
    $result = $con->query("INSERT INTO `$table` ($fields) VALUES ($data);");
    // you can check the result for something if you want, but you shouldn't need to.
    $result->close();
}

編輯摘要:

  • 我添加了條件檢查,以便您的IPN可以處理1筆以上的總付款。
  • 我增加了防止雙重處理付款的保護。
  • 我實現了MySQLi的real_escape_string (也稱為escape_string )函數。 此函數使用MySQL數據庫的設置來清理/轉義輸入。 也許您的array_sanitize()函數已經在執行此操作,但是我決定添加它,因為您沒有發布該函數。
  • 我已經將所有MySQLi命令/查詢切換為OOP樣式。 這在某種程度上是不受歡迎的,但我也發現它們一目了然,編寫起來也更快。
  • 最后,我添加了命令以關閉查詢結果。 這樣可以釋放數據庫資源和服務器內存。 當腳本完成運行/退出時,它們將自動關閉,但是如果您提前關閉它們,則服務器和數據庫都會更快地收回資源。

由於並非您的所有代碼都已發布,因此您必須決定是否應將這些編輯中的任何一個添加到您的代碼中。 但是,如果這是針對我認為的PayPal IPN,那么這些編輯可能會很有用。 無論如何,您都必須做出決定。


更新:好的,更新之后,我對您的代碼及其邏輯有一些疑問。

這是您的代碼:

// make sure if user_data transaction id's not match with payment_data details, then activate the package
if (!empty($payment_data['pp_txn_id']) === !empty($user_data['pp_txn_id']) || !empty($payment_data['pz_reference_no']) === !empty($user_data['pz_reference_no'])) {
    $update_data = array(
        'status' => 'Active',
    );
    update_user($session_user_id, $update_data);
}

注釋說,請make sure if user_data transaction id's not match with payment_data details, then activate the package ,但是if語句不執行此操作。 實際上,此if語句可能會執行您不希望執行的操作。

第一部分說if(!empty($array['index']) === !empty($another_array['index']))讓我們來分解一下。

  • empty()返回一個布爾值,該布爾值指示變量是否不包含內容(如果字符串為''""則在字符串上調用empty為true)。 因此,讓$array['index'] = "foo"; ,則empty($array['index'])變為empty("foo") 而且我們知道它將返回false,因為該字符串不為空。
  • 接下來,您要說!empty(...) 因此,以擴展形式, $boolean_returned_by_not_empty = (empty(...) ? false : true); 您將布爾值切換為相反的值。 這很好並且可以理解。
  • 那就是說!empty(...) === !empty($another_array['index'])

這是第一部分的邏輯失敗的地方。 您在評論中說,您想比較它們是否匹配,但是您要比較的是它們是否均為空或都包含內容。 這意味着如果您分配$payment_details['pp_txn_id'] = "foo"; $user_data['pp_txn_id'] = "bar"; if語句將運行,因為盡管它們不匹配,但沒有一個為空。 同樣,如果它們確實匹配( $payment_details['pp_txn_id'] = "foobar";$user_data['pp_txn_id'] = "foobar"; ),則您的代碼將運行if語句來更新表。

在if語句的第二部分中,您正在做同樣的事情,然后只說if either pair contains two strings with some data (this data doesn't even have to match), then go ahead and update the table.

我認為,當您想知道它們是否不匹配時,這沒有邏輯意義。 我相信對此更好的檢查是:

if( ($payment_details['pp_txn_id'] !== $user_data['pp_txn_id']) ||
    ($payment_data['pz_reference_no'] !== !$user_data['pz_reference_no']) ){

    $update_data = array(
        'status' => 'Active',
    );
    update_user($session_user_id, $update_data);

}

另外,在看到您添加的代碼后,我現在建議您執行array_walk($payment_detail, 'array_sanitize'); 我把foreach循環放在哪里。 然后只需在array_walk之后分配$clean_ppTxnId 現在,我可以看到您的array_sanitize是安全的。


綜上所述,由於該腳本缺少細節和內容,因此仍然存在一些問題。 基本思想應該是:

  1. 用戶付費
  2. PayPal與您的IPN聯系
  3. 您檢入數據庫以查看是否已經處理了該事務ID。 如果有,請忽略它。
  4. 如果尚未處理,請檢查商品的成本( settle_amount ;惡意購買者有可能更改HTML amount屬性),並檢查所有其他必要變量是否符合預期條件。 如果不是,則說明結帳已被篡改,不應進行處理。
  5. 如果結帳沒有被篡改,並且一切似乎都很好,則應繼續進行。 繼續並清理變量。
  6. 現在,將事務詳細信息記錄到數據庫的事務表中。
  7. 如果用戶在購買前進行注冊,則應嘗試從用戶表中獲取與該用戶相關的行,然后繼續執行步驟#8。 如果他們在購買時已注冊,則通過執行INSERT INTO <Table name for the user table goes here> (<column name 1>, <column name 2>, ...) VALUES (<value 1>, <value 2>, ...);添加一行INSERT INTO <Table name for the user table goes here> (<column name 1>, <column name 2>, ...) VALUES (<value 1>, <value 2>, ...); 如果您剛剛注冊了執行此操作的用戶,請轉到步驟9。
  8. 如果您使用的是#8,那么您是在更新用戶而不是創建新用戶。 在這一步,您應該檢查從數據庫獲取用戶的查詢是否成功。 如果確實成功並且用戶存在於系統上,則繼續更新用戶行,並將status設置為Active 否則,將錯誤記錄在數據庫的警告表中,以便以后可以查看它,以查看是否需要退款或更正代碼。
  9. 可選 )如果您選擇這樣做,則可以向payer_email發送一封電子郵件(我不會詳細介紹,但是您可以使用PHP的mail()函數),以通知用戶交易已被處理。

好吧,我發現了我的錯誤並解決了

我的數組'pz_payment_data' => $user_data['pz_payment_data'],有拼寫錯誤'pz_payment_data' => $user_data['pz_payment_data'],

$payment_detail = array(
    'id' => $user_data['id'],
    'pp_txn_id' => $user_data['pp_txn_id'],
    'pp_payment_date' => $user_data['pp_payment_date'],
    'pz_reference_no' => $user_data['pz_reference_no'],
    'pz_payment_date' => $user_data['pz_payment_date'],
);

我修復了它,現在可以工作了:)

您的功能不好:

function check_table($table) {
    global $con;
    $result = mysqli_query($con, "SELECT * FROM $table");
    return (mysqli_num_rows($result) > 0) ? true : false;
}

因為它只選擇所有行以獲取布爾結果,所以我認為您可以改進它:

function check_table($table) {
    global $con;
    $result = mysqli_query($con, "SELECT * FROM $table LIMIT 1");
    return (mysqli_num_rows($result) > 0) ? true : false;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM