PHP 'use' import 命名空间导致页面崩溃

PHP `use` import namespace causes page to crash

提问人:raw-bin hood 提问时间:3/6/2019 最后编辑:Communityraw-bin hood 更新时间:3/7/2019 访问量:738

问:

PHPMailer 在测试脚本中工作正常。但是,它崩溃了,并且没有在另一个页面上报告任何错误。我已将问题隔离到以下代码行:

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

当我省略这些行时,我收到PHP错误:

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

当我包含这些行时(我认为我需要这样做才能使用导入类的命名空间),我只是得到一个空白的白屏。错误报告在页面顶部处于打开状态,如下所示:

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网站上查找了有关的信息,但是当我搜索(https://www.php.net/manual-lookup.php?pattern=use&scope=quickref)时没有列出任何内容。use

这是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 命名空间 phpmailer 错误报告

评论

0赞 Don't Panic 3/6/2019
你的PHP版本是什么?
0赞 rob006 3/6/2019
你能展示完整的内容吗?path/to/file.php

答:

0赞 Synchro 3/6/2019 #1

这意味着您的PHP版本太旧了。命名空间和语法是在 PHP 5.3 中引入的,这已经过时了很多年。use

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

评论

0赞 Don't Panic 3/6/2019
这也是我在想的,但这很奇怪,因为似乎如果 PHP 版本是 < 5.3,那么所需的文件也会包含解析错误,并且 OP 说它可以正常工作。
0赞 raw-bin hood 3/6/2019
在这种情况下,我使用的是PHP 7.1。该网站最初是 PHP 5.6,但我正在迁移和更新它。
0赞 raw-bin hood 3/6/2019
这可能与路径的位置有关吗?当所有内容(PHPMailer 文件和脚本)都在 Web 根目录的同一文件夹中时,效果很好。一个 PHPMailer 位于 wp-content/plugins/PHPMailer/ 的文件夹中,脚本 php 文件位于 wp-content/themes/themename/process-payment.php 文件夹中。所有内容都会加载并报告错误,直到包含这两个“use”行中的任何一个。
0赞 raw-bin hood 3/6/2019
此外,我正在通过MAMP运行Webstack。
0赞 Synchro 3/7/2019
如果您看到白屏,则所涉及的错误将出现在 Web 服务器的错误日志中。
0赞 raw-bin hood 3/7/2019 #2

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

用于导入的范围规则

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

函数 toGreenlandic() {

use Languages\Danish;

// ... }

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

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