Xử lý gợi ý kiểu trung tính trong Magento


15

Chỉ tự hỏi liệu có ai có chiến lược tốt hơn tôi nghĩ về việc kiểm tra loại để cùng tồn tại với trình xử lý lỗi tùy chỉnh của Magento không. Cụ thể, tôi đang tự hỏi về một "Lỗi nghiêm trọng có thể bắt được" như bị ném trong trường hợp tham số không khớp kiểu. Đây là một ví dụ từ Magelớp:

/**
 * Write exception to log
 *
 * @param Exception $e
 */
public static function logException(Exception $e)
{
    if (!self::getConfig()) {
        return;
    }
    $file = self::getStoreConfig('dev/log/exception_file');
    self::log("\n" . $e->__toString(), Zend_Log::ERR, $file);
}

Do trình xử lý lỗi, mọi thứ đều có thể được truyền cho phương thức, bao gồm một Zend_Date(sẽ hoạt động tốt, nhưng trông cực kỳ khó hiểu trong nhật ký ngoại lệ của bạn) hoặc a Mage_Core_Model_App, thực sự sẽ có lỗi nghiêm trọng.

Có thể thực hiện lại việc kiểm tra kiểu ở đầu một phương thức: $e instanceof Exceptionnhưng các chiến thuật như vậy đánh bại mục đích của một kiểu chữ.

Bất kỳ gợi ý gợi ý?

Câu trả lời:


5

Câu hỏi hay +1

Đã thực hiện một số nghiên cứu và kiểm tra sau một điểm tốt theo hướng sau cuộc thảo luận của tôi với @mpw về câu trả lời đầu tiên của tôi. Tôi đã hiểu nhầm nó lần đầu tiên.

Sẽ thêm một số mã để làm rõ để những người khác hiểu vấn đề tốt hơn.

Một lưu ý trước khi cất cánh

Tôi chưa bao giờ có vấn đề như vậy cho đến khi điều này xuất hiện. Phát triển trong Magento với chế độ nhà phát triển cho phép tôi thậm chí không nghĩ một giây nào về việc này. Vì vậy, mỗi khi tôi xì hơi , nó sẽ xuất hiện và sẽ được sửa cho phù hợp.

Vấn đề với một mẫu giải thích

Câu nói nghiêm trọng của bạn sẽ được ghi lại (nếu được bật) và mã sẽ tiếp tục như bình thường vì không có lỗi nào được đưa ra mageCoreErrorHandlerhoặc chương trình sẽ xảy ra exit.

Trình xử lý lỗi lõi đầu tiên của Magento cho các lỗi không thể so sánh được app/code/core/Mage/Core/functions.php

/**
 * Custom error handler
 *
 * @param integer $errno
 * @param string $errstr
 * @param string $errfile
 * @param integer $errline
 */
function mageCoreErrorHandler($errno, $errstr, $errfile, $errline){
    /**
     * Some internal logic here for building the error message
     */

    $errorMessage .= ": {$errstr}  in {$errfile} on line {$errline}";
    if (Mage::getIsDeveloperMode()) {
        throw new Exception($errorMessage);
    } else {
        Mage::log($errorMessage, Zend_Log::ERR);
    }
}

Như bạn có thể thấy, trong chế độ nhà phát triển, nó sẽ báo một cái gì đó hữu ích, nó sẽ báo lỗi. Khi tắt nó sẽ đăng nhập (nếu được bật) và tiếp tục.

Bằng chứng

Của tôi testfile.php

require 'app/Mage.php';
Mage::app('admin')->setUseSessionInUrl(false);

// Test function which expect Customer_Model_Customer
function test(Customer_Model_Customer $customer)
{
    var_dump('Do not show me because ' . get_class($customer) . ' is not a customer.');
}

// Enabled developer mode
Mage::setIsDeveloperMode(true);

// Put a var in here
$noGood = Mage::app();

// Make some context
var_dump('hello');
try {
    // Call test function with a not accepted var
    test($noGood);

    // Tell if we get here
    var_dump('And we are here!');

} catch (Exception $e) {
    var_dump('You should die, because I am doing something which I should not do');
}

Kết quả

Developermode được kích hoạt. Kết quả đúng

string(5) "hello"
string(66) "You should die, because I am doing something which I should not do"

Developermode bị vô hiệu hóa, kết quả không chính xác

string(5) "hello"
string(61) "Do not show me because Mage_Core_Model_App is not a customer."
string(16) "And we are here!"

Vì vậy, cuối cùng nó sẽ bỏ qua lỗi và tiếp tục dòng mã tiếp theo. Có thể với kết quả thậm chí kỳ lạ hơn. (như @mpw chỉ ra)

Phần kết luận

có thể xảy ra rằng ai đó đang phát triển theo cách mà các lỗi sẽ không được chú ý và cuối cùng nó sẽ cho kết quả bất ngờ.

Tất nhiên khi phát triển một cách chuyên nghiệp. Lỗi sẽ được chú ý và được chú ý . Cách để ngăn chặn điều này trong Magento là luôn cho phép Developermode trong môi trường phát triển / thử nghiệm.

IMHO không bao giờ nên đi đến điểm thảo luận này, trong đó kiểm tra một biến số lần thứ hai (ít nhất đó là cách tôi sẽ mô tả nó) là cách để đi. Mã phải được kiểm tra trước khi phát hành trên môi trường sản xuất. Nó không cần thiết

Suy nghĩ thứ hai

Có lẽ Magento nên dừng lại sau một lỗi nghiêm trọng. Hoặc tạo một báo cáo và hiển thị nó cho khách truy cập. Bằng cách này, các dòng mã tiếp theo sẽ không bao giờ được thực thi và mọi thứ sẽ được chú ý.


> Của thô khi phát triển một cách chuyên nghiệp. Lỗi sẽ được chú ý và được chú ý. Cách để ngăn chặn điều này trong Magento là luôn cho phép Developermode trong môi trường phát triển / thử nghiệm. ¶ Tôi đồng ý với điều đó. Mục tiêu của tôi là để Magento tôn trọng các quy tắc ngôn ngữ trong chế độ sản xuất. Có vẻ như nó sẽ yêu cầu một mô-đun tùy chỉnh có lẽ. Cảm ơn sự sáng suốt của bạn!
mpw

Có lẽ Magento nên ném một ngoại lệ trong cả hai trường hợp. Người dùng sẽ được cung cấp trang lỗi Magento và trong var / ngoại lệ sẽ có logfile phù hợp, giống như các trường hợp ngoại lệ thông thường. Điều tuyệt vời ở đây là mã sẽ không được thực thi mà không cần thông báo trước. Bạn có thể sao chép tệp chức năng vào ứng dụng / mã / cục bộ và luôn ném ngoại lệ
Jeroen

1
Tôi đã quyết định đánh dấu đây là câu trả lời. Mặc dù tôi vẫn nghĩ rằng những lỗi bị bóp nghẹt như thế là nguy hiểm, nhưng dường như không có cách nào để đảm bảo Magento tôn trọng các kiểu chữ mà không mở ra các vấn đề khác. Lời nhắc để duy trì chế độ dev được bật là một điều tốt cho độc giả trong tương lai và đó là điều quan trọng nhất
mpw

2

Câu hỏi hay. Tôi nghĩ rằng đây là một vấn đề chung với E_RECOVERABLE_ERRORPHP.

Những gì bạn có trong câu hỏi của bạn là xử lý ngoại lệ, không phải xử lý lỗi. Trình xử lý lỗi đang gây ra sự cố thực tế mà bạn thảo luận ở đây với các lỗi nghiêm trọng có thể bắt được ( E_RECOVERABLE_ERROR) .

PHP 7 và HHVM đã giải quyết vấn đề này.

Tệ hơn với Magento vì trình xử lý lỗi không xử lý được điều này vì lớp lỗi 5.2.

Một loại xử lý lỗi hữu ích hơn sẽ xử lý lớp lỗi này và biến các lỗi này thành ErrorException s. Ví dụ (không phải bởi tôi, từ đây ):

set_error_handler(function($errno, $errstr, $errfile, $errline) {
    if ($errno === E_RECOVERABLE_ERROR) {
        throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
    }
    return false;
});

Vì vậy, trong ánh sáng của Magento, trình xử lý lỗi mặc định là hàm toàn cục mageCoreErrorHandlertrong app/code/core/Mage/Core/functions.php. Nó lấy của đăng ký thông qua Mage::app()bởi các init()phương pháp của Mage_Core_Model_App ( app/code/core/Mage/Core/Model/App.php) (thông qua bảo vệ _initEnvironment()phương pháp).

Một trình quan sátcontroller_front_init_before đăng ký trình xử lý lỗi PHP của riêng bạn lên trên sẽ đủ sau đó (các trình xử lý lỗi trong PHP có thể xếp chồng lên nhau):

$previous = set_error_handler(function($errno, $errstr, $errfile, $errline) use (&$previous) {
    if ($errno === E_RECOVERABLE_ERROR) {
        throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
    }
    if ($previous) {
        return call_user_func($previous, $errno, $errstr, $errfile, $errline);
    }
    return false;
});

Các lỗi nghiêm trọng có thể bắt được sau đó được chuyển thành ngoại lệ và bạn có thể xử lý chúng trong mã mở rộng của riêng bạn hoặc chúng không bị phát hiện và sẽ được nhìn thấy trong nhật ký ngoại lệ (thay vì cửa hàng của bạn chạy gaga trên các loại sai như hành vi hiện tại là các chương trình chết đừng nói dối ). Trong PHP 7, ngoại lệ để tìm kiếm không phải là ErrorException mà là TypeException (là BaseException ) cho các lỗi nghiêm trọng hiện có thể bắt được .

Tất cả các lỗi khác được chuyển cho bộ xử lý lỗi của Magento.

Lưu ý: Tôi chưa thử điều này, đây là một bài viết nhưng tôi biết vấn đề bạn đang hỏi và phân tích xử lý lỗi đã được thực hiện đối với 1.5.1.0 và được xác minh theo 1.9.1.0 thông qua phân tích mã. Các xử lý lỗi xếp chồng nên làm việc. Tôi nối thêm một mã ví dụ mở rộng cho thấy hầu hết các phần làm việc.

Tôi chưa đóng gói cái này như một phần mở rộng magento nhưng nó nên được chuyển thẳng với modman. Tôi sẽ đặt nó trên github.

Phụ lục: Trình xử lý lỗi

Ví dụ mã sau đây ( bản demo trực tuyến ) cho thấy việc sắp xếp các trình xử lý lỗi và ngoại lệ ném vào lỗi nghiêm trọng có thể bắt được :

<?php
/**
 * error handler demonstration
 *
 * stackable error handle with previous call and catchable error exceptions
 *
 * @author hakre <http://hakre.wordpress.com>
 * @link /magento//a/64972/4115
 */

set_error_handler(function() {
    $args = func_get_args();
    var_dump("me is the previous error handler", $args);
});

$previous = set_error_handler(function($errno, $errstr, $errfile, $errline) use (&$previous) {
    if ($errno === E_RECOVERABLE_ERROR) {
        throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
    }
    if ($previous) {
        return call_user_func($previous, $errno, $errstr, $errfile, $errline);
    }
    return false;
});

$test = function(callable $test) {};

$a = $undefined; // provoke little warning

$test(new stdClass); // provoke catchable fatal error

Chương trình đầu ra

string(32) "me is the previous error handler"
array(4) {
  [0]=>
  int(8)
  [1]=>
  string(29) "Undefined variable: undefined"
  [2]=>
  string(45) "/tmp/execpad-0eca072b619d/source-0eca072b619d"
  [3]=>
  int(28)
}

Fatal error: Uncaught exception 'ErrorException' with message 'Argument 1 passed to {closure}() must be callable, object given, called in /tmp/execpad-0eca072b619d/source-0eca072b619d on line 30 and defined' in /tmp/execpad-0eca072b619d/source-0eca072b619d:26
Stack trace:
#0 /tmp/execpad-0eca072b619d/source-0eca072b619d(26): {closure}(4096, 'Argument 1 pass...', '/tmp/execpad-0e...', 26, Array)
#1 /tmp/execpad-0eca072b619d/source-0eca072b619d(30): {closure}(Object(stdClass))
#2 {main}
  thrown in /tmp/execpad-0eca072b619d/source-0eca072b619d on line 26

Tuyệt vời viết lên. Trong quá trình thử nghiệm của bạn, có sự suy giảm hiệu suất có thể đo lường được từ việc thiết lập lại trình xử lý lỗi không?
mpw

Tôi đã không cho đến nay. Ngoài ra còn có một khu vực liên quan trong lõi, trong đó trên chế độ phát triển, tất cả các cảnh báo / lỗi được chuyển đổi thành Ngoại lệ (và không phải ErrorExceptuion - thậm chí không được ghi lại). Điều này có lẽ đòi hỏi một bản vá để sửa lỗi này một cách lành mạnh. Đối với trình xử lý lỗi, không có phương thức điều phối tốt nào có sẵn, ở đây tôi bằng cách nào đó có xu hướng vá lõi thậm chí để mang một trình xử lý lỗi mặc định cố định vào.
hakre

1

Nó đã được xử lý bởi PHP mặc định bằng cách thêm (Exception $e)vào định nghĩa tham số hàm.

Bạn không thể chuyển bất cứ thứ gì khác cho chức năng này ngoài Ngoại lệ hoặc mở rộng Ngoại lệ.


Hãy xem mageCoreErrorHandlerchức năng. Một lỗi được kích hoạt bởi các thông số không chính xác sẽ được xử lý và loại bỏ trong chế độ không dành cho nhà phát triển và ném Exceptionvào chế độ nhà phát triển.
mpw

Một cái gì đó là sai nghiêm trọng khi như vậy xảy ra ở nơi đầu tiên. Magento mageCoreErrorHandlerphải chắc chắn rằng khách truy cập sẽ không gặp phải lỗi nào. Bạn có thể tự xây dựng một cái try{}catch(){}để lấy chúng và nếu bạn không thể vượt qua chúng.
Jeroen

Xem xét không có trường hợp ngoại lệ nào được đưa ra trong trường hợp lỗi nghiêm trọng có thể bị loại bỏ, việc thử / bắt sẽ giúp tôi điều gì?
mpw

1
Cuối cùng tôi cũng nhận được nó, sau một bài kiểm tra cục bộ ... Bạn rất đúng, lỗi đã được loại bỏ và mã sẽ tiếp tục. Tôi sẽ cập nhật câu trả lời của mình và thêm một số suy nghĩ thêm
Jeroen

Tôi sẽ đăng một câu trả lời mới nếu không cuộc trò chuyện của chúng tôi không có ý nghĩa gì cả
Jeroen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.