【问题标题】:PHP `use` import namespace causes page to crashPHP`use`导入命名空间导致页面崩溃
【发布时间】:2019-07-27 11:10:37
【问题描述】:

PHPMailer 在它自己的基本框架上的测试脚本中运行良好。但是,它正在崩溃并且没有在另一个页面上报告任何错误。我已将问题隔离到以下代码行:

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

当我忽略这些行时,我得到了 PHP 错误:

致命错误:未捕获的错误:在 /path/to/file.php:166 中找不到类 'PHPMailer' 堆栈跟踪:在第 166 行的 /path/to/file.php 中抛出 #0 {main}

当我包含这些行时(我相信我需要这样做才能使用导入类的命名空间),我只会得到一个空白的白色屏幕。页面顶部开启报错如下:

error_reporting(E_ALL);
ini_set('display_errors', 1);

但是,页面上没有错误报告。

其余的类文件如下导入,路径正确,除非我更改路径,否则它们不会报告错误。

require '../../../wp-content/plugins/PHPMailer/Exception.php';
require '../../../wp-content/plugins/PHPMailer/PHPMailer.php';
require '../../../wp-content/plugins/PHPMailer/SMTP.php';

我在 PHP 网站上查找了有关 use 的信息,但是当我搜索 (http://ca3.php.net/manual-lookup.php?pattern=use&scope=quickref) 时没有列出任何内容。

这是 file.php 中的完整代码。我知道还有其他问题,例如数据输入清理等,但我正在重构别人的代码:

<?php

error_reporting(E_ALL);
ini_set('display_errors', 1);
var_dump($_POST);

// PayPal Config Constants
require "../../../mail-config.php";
require "../../../keys-config.php";

/** Send HTTP POST Request for PayPal Payment */
function PPHttpPost($methodName_, $nvpStr_) {

    // Get the environment set in the keys-config.php file
    $environment = PAYPAL_ENVIRONMENT;
    // Use the keys and endpoint for the environment
    if("sandbox" === $environment || "beta-sandbox" === $environment) {
        // Set the API URL
        $API_Endpoint = PAYPAL_API_ENDPOINT_SANDBOX;
        // Set up your API credentials, PayPal end point, and API version.
        $API_UserName = urlencode(PAYPAL_API_USERNAME_SANDBOX);
        $API_Password = urlencode(PAYPAL_API_PASSWORD_SANDBOX);
        $API_Signature = urlencode(PAYPAL_API_SIGNATURE_SANDBOX);
    } else {
        // Set the API URL
        $API_Endpoint = PAYPAL_API_ENDPOINT;
        // Set up your API credentials, PayPal end point, and API version.
        $API_UserName = urlencode(PAYPAL_API_USERNAME);
        $API_Password = urlencode(PAYPAL_API_PASSWORD);
        $API_Signature = urlencode(PAYPAL_API_SIGNATURE);
    }

    // Set the version
    $version = urlencode('51.0');
    // Set the curl parameters.
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    // Turn off the server and peer verification (TrustManager Concept).
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    // Set the API operation, version, and API signature in the request.
    $nvpreq = "METHOD=$methodName_&VERSION=$version&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$nvpStr_";
    // Set the request as a POST FIELD for curl.
    curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
    // Get response from the server.
    $httpResponse = curl_exec($ch);

    // If the method failed
    if(!$httpResponse) {
        exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
    }

    // Extract the response details.
    $httpResponseAr = explode("&", $httpResponse);
    $httpParsedResponseAr = array();
    foreach ($httpResponseAr as $i => $value) {
        $tmpAr = explode("=", $value);
        if(sizeof($tmpAr) > 1) {
            $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
        }
    }

    // If data in response is invalid
    if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
        exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
    }

    // Return the http response
    return $httpParsedResponseAr;
}

// Prepare PayPal Payment Request
// Set request-specific fields.
// 'Authorization' or 'Sale'
$paymentType = urlencode('Sale');
// Name Details
$firstName = urlencode($_POST['firstname']);
$lastName = urlencode($_POST['lastname']);
// Credit Card details
$creditCardType = urlencode($_POST['customer_credit_card_type']);
$creditCardNumber = urlencode($_POST['cardnum']);
$expDateMonth = $_POST['cc_expiration_month'];
// Month must be padded with leading zero
$padDateMonth = urlencode(str_pad($expDateMonth, 2, '0', STR_PAD_LEFT));
$expDateYear = urlencode($_POST['cc_expiration_year']);
$cv = urlencode($_POST['cv']);
// Address Details
$address1 = urlencode($_POST['streetaddy']);
$city = urlencode($_POST['city']);
$state = urlencode($_POST['province']);
$postal_code = urlencode($_POST['postalcode']);
// US or other valid country code
$country = urlencode($_POST['country']);
$price = urlencode($_POST['price']);
// or other currency ('GBP', 'EUR', 'JPY', 'CAD', 'AUD')
$currencyID = urlencode('CAD');

// Add request-specific fields to the request string.
$nvpStr =   "&PAYMENTACTION=$paymentType&AMT=$price&CREDITCARDTYPE=$creditCardType&ACCT=$creditCardNumber".
            "&EXPDATE=$padDateMonth$expDateYear&CVV2=$cv&FIRSTNAME=$firstName&LASTNAME=$lastName".
            "&STREET=$address1&CITY=$city&STATE=$state&ZIP=$postal_code&COUNTRYCODE=$country&CURRENCYCODE=$currencyID";

// Execute the API operation; see the PPHttpPost function above.
$httpParsedResponseAr = PPHttpPost('DoDirectPayment', $nvpStr);

if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) {

    //Below line is response code from original
    //exit('Direct Payment Completed Successfully: '.print_r($httpParsedResponseAr, true));

    // Require the PHPMailer classes
    use PHPMailer\PHPMailer\PHPMailer;
    use PHPMailer\PHPMailer\Exception;
    require '../../../wp-content/plugins/PHPMailer/Exception.php';
    require '../../../wp-content/plugins/PHPMailer/PHPMailer.php';
    require '../../../wp-content/plugins/PHPMailer/SMTP.php';

  //FIELDS
  $first_name = $_POST['firstname'];
  $last_name = $_POST['lastname'];
  $email_from = $_POST['email'];
  $phone = $_POST['phone'];
  $ad = $_POST['ad'];
  $price = $_POST['price'];
  $edition = $_POST['edition'];
  $issues = $_POST['issues'];
  $category = $_POST['category'];
  $order_id = $_POST['order_id'];
  $email_message = "A Classified Ad has been purchased from the Speaker website. Details of the ad are below.\n\n";

  // Filter the string
  function clean_string($string) {
    $bad = array("content-type","bcc:","to:","cc:","href");
    return str_replace($bad,"",$string);
    $string = filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
  }

  // Build the Email message body contents
  $email_message .= "<b>Order ID:</b> ".clean_string($order_id)."<br>";
  $email_message .= "<b>First Name:</b> ".clean_string($first_name)."<br>";
  $email_message .= "<b>Last Name:</b> ".clean_string($last_name)."<br>";
  $email_message .= "<b>Email:</b> ".clean_string($email_from)."<br>";
  $email_message .= "<b>Telephone:</b> ".clean_string($phone)."<br>";
  $email_message .= "<b>Category:</b> ".clean_string($category)."<br>";
  $email_message .= "<b>Ad Text:</b> ".clean_string($ad)."<br>";
  $email_message .= "<b>Edition:</b> ".clean_string($edition)."<br>";
  $email_message .= "<b>Number of Issues:</b> ".clean_string($issues)."<br>";
  $email_message .= "<b>Price:</b> ".clean_string($price)."<br>";

  // Set up the email to be sent
  $mail = new PHPMailer(); // create a new object
  $mail->IsSMTP(); // enable SMTP
  $mail->SMTPDebug = 0;
  $mail->SMTPAuth = true; // authentication enabled
  $mail->SMTPSecure = 'ssl'; // secure transfer enabled REQUIRED for Gmail
  $mail->Host = "smtp.gmail.com";
  $mail->Port = 465; // or 587
  $mail->IsHTML(true);
  $mail->Username = SITE_EMAIL_SMTP_USERNAME;
  $mail->Password = SITE_EMAIL_SMTP_PASSWORD;
  $mail->SetFrom(SITE_EMAIL_FROM_ADRESS_LIST);
  $mail->Subject = "Classified Ad Submission From The ".NEWSPAPER_NAME." Website";
  $mail->Body = $email_message;
  // Add all the company email addresses to the send list
  foreach(PAYWALL_NOTIFICATION_EMAIL_ADDRESSES_ARRAY as $email_address){
    $mail->AddAddress($email_address);
  }
    // Add the purchaser's email address to the send list
    $mail->AddAddress($email_from);

  // If mail fails to send
  if(!$mail->Send()) {
    //REDIRECT TO FAILED PAGE
     header( 'Location: /order-not-completed' );
  } else {
   //REDIRECT TO SUCCESS PAGE
   header( 'Location: /success' );
  }

} else  {
    //Below line is response code for testing
    exit('DoDirectPayment failed: ' . print_r($httpParsedResponseAr, true));

    //REDIRECT TO FAILED PAGE
  header( 'Location: /order-not-completed' );
}

?>

【问题讨论】:

  • 你的 PHP 版本是多少?
  • 你能显示path/to/file.php的完整内容吗?

标签: php namespaces phpmailer error-reporting


【解决方案1】:

这意味着你的 PHP 版本太旧了。 Namespacesuse 语法是在 PHP 5.3 中引入的,并且已经过时多年了。

PHPMailer 6.0.x 至少需要 PHP 5.5,因此请更新您的 PHP,最好是最新版本(当前为 7.3)。

【讨论】:

  • 我也是这么想的,但这很奇怪,因为看起来如果 PHP 版本
  • 在这种情况下我使用的是 PHP 7.1。该网站最初使用 PHP 5.6,但我正在迁移和更新它。
  • 可能与路径的位置有关吗?当一切(PHPMailer 文件和脚本)都在 web 根目录的同一个文件夹中时,效果很好。一个 PHPMailer 位于 wp-content/plugins/PHPMailer/ 的文件夹中,脚本 php 文件位于 wp-content/themes/themename/process-payment.php 文件夹中。在包含这两个“使用”行中的任何一个之前,所有内容都会加载并报告错误。
  • 我也在通过 MAMP 运行 webstack。
  • 如果出现白屏,所涉及的错误将在您的网络服务器的错误日志中。
【解决方案2】:

这里是描述使用 PHP 的 use 函数导入命名空间的页面:http://php.net/manual/en/language.namespaces.importing.php

导入的范围规则

use 关键字必须在文件的最外层范围内声明( 全局范围)或内部命名空间声明。这是因为 导入是在编译时而不是运行时完成的,所以它不能 块作用域。以下示例将显示非法使用 使用关键字: 命名空间语言;

函数 toGreenlandic() {

use Languages\Danish;

// ... }

虽然上述代码没有在函数侧使用use 语句,但它不在文件顶部,并且在use 语句之前声明了其他函数。在将use 语句移动到文件顶部后,我测试了上面的代码

简而言之:始终将 use 语句放在 PHP 文件的顶部以及函数或类之外。

【讨论】:

    猜你喜欢
    • 2011-01-24
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    • 2020-10-27
    • 1970-01-01
    • 2014-05-09
    • 2019-03-11
    • 1970-01-01
    相关资源
    最近更新 更多