Không thể sử dụng giá trị trả về của phương thức trong ngữ cảnh ghi


465

Tôi nghĩ rằng đoạn mã sau sẽ hoạt động, nhưng nó không (Đã chỉnh sửa: Bây giờ hoạt động trong PHP 5.5+) :

if (!empty($r->getError()))

getError()Đơn giản là ở đâu :

public function getError()
{
    return $this->error;
}

Nhưng tôi đã kết thúc với lỗi này:

không thể sử dụng giá trị trả về của phương thức trong ngữ cảnh ghi

Điều đó có nghĩa là gì? Đây không phải chỉ là một đọc?


2
Có thể trong PHP 5.5, bạn sẽ được phép chuyển các biểu thức tới empty: wiki.php.net/rfc/empty_isset_exprs
Carlos Campderrós


Ok tôi thấy Câu trả lời của porneL cũng đúng với mã này của tôi if ( !$e->find('div') ) để kiểm tra xem phần tử HTML DOM hiện tại có trống hay không. Tôi sử dụng nó bên trong vòng lặp để in ra chỉ một Div mà không có Div bên trong nó.
Salem

Câu trả lời:


769

empty() cần truy cập giá trị theo tham chiếu (để kiểm tra xem tham chiếu đó có trỏ đến thứ gì đó tồn tại không) và PHP trước 5.5 không hỗ trợ tham chiếu đến các giá trị tạm thời được trả về từ các hàm.

Tuy nhiên, vấn đề thực sự bạn gặp phải là bạn hoàn toàn sử dụng empty(), tin tưởng nhầm rằng giá trị "trống" khác với "sai".

Trống chỉ là một bí danh cho !isset($thing) || !$thing. Khi thứ bạn đang kiểm tra luôn tồn tại (trong kết quả PHP của các lệnh gọi hàm luôn tồn tại), empty()hàm khônggì ngoài toán tử phủ định .

PHP không có khái niệm về sự trống rỗng . Các giá trị đánh giá thành sai là trống, các giá trị đánh giá thành đúng là không trống. Đó là một thứ tương tự. Mã này:

$x = something();
if (empty($x)) 

và điều này:

$x = something();
if (!$x) 

luôn luôncùng một kết quả, trong mọi trường hợp, cho tất cả các kiểu dữ liệu (vì $xđược định nghĩa empty()là dự phòng).

Giá trị trả về từ phương thức luôn tồn tại (ngay cả khi bạn không có returncâu lệnh, giá trị trả về tồn tại và chứa null). Vì thế:

if (!empty($r->getError()))

là tương đương logic với:

if ($r->getError())

29
Đây là một câu trả lời tốt hơn nhiều so với câu trả lời hiện đang được chọn.
SystemParadox

20
@gcb: không, hướng dẫn sử dụng PHP nói rõ ràng là giống hệt nhau: "(boolean) var
Kornel

16
Phần không tạo phần cảnh báo là khá quan trọng ... trống ($ var) sẽ trả về true nếu nó là 0, '', mảng (), NULL hoặc thậm chí không được xác định. Đó là một thực tiễn tốt, đặc biệt là bạn có thể ghi lại các cảnh báo thực sự của mình mà không cần điền vào các tệp
Landons

3
Ok, câu trả lời tuyệt vời, nhưng cách đúng đắn để tránh điều này, có ai biết không?
Javatar

3
@EugenMihailescu nói chung đó là ok, nhưng nó không hoàn toàn tương đương để trống (), bởi vì "", 0vv là "trống rỗng", nhưng không phải null.
Kornel

330

Lưu ý: Đây là một câu trả lời được bình chọn rất cao với khả năng hiển thị cao, nhưng xin lưu ý rằng nó khuyến khích các thực hành mã hóa xấu, không cần thiết! Xem câu trả lời của @ Kornel cho cách chính xác.

Lưu ý # 2: Tôi tán thành các đề xuất sử dụng câu trả lời của @ Kornel . Khi tôi viết câu trả lời này ba năm trước, tôi chỉ muốn giải thích bản chất của lỗi, không nhất thiết phải chứng thực cho sự thay thế. Đoạn mã dưới đây không được khuyến khích.


Đó là một giới hạn của rỗng () trong các phiên bản PHP dưới 5.5.

Lưu ý: blank () chỉ kiểm tra các biến vì mọi thứ khác sẽ dẫn đến lỗi phân tích cú pháp. Nói cách khác, những điều sau đây sẽ không hoạt động: trống (trim ($ name)).

Bạn sẽ phải thay đổi điều này

// Not recommended, just illustrates the issue
$err = $r->getError();
if (!empty($err))

156
Điều này là cực kỳ phản tác dụng.
David Murdoch

47
Lưu ý: Điều tương tự cũng đúng với isset(). tức là: isset($this->foo->getBar())sẽ dẫn đến cùng một vấn đề.
Catchdave

7
Câu trả lời của porneL giải thích điều này chi tiết hơn, với một giải pháp tốt hơn
SystemParadox

5
@SystemParadox - Phụ thuộc vào ý của bạn là "tốt hơn". Câu trả lời của porneL được cho là kỹ lưỡng hơn với giải pháp "sạch" hơn, nhưng cũng không thực sự giải thích nguồn gốc của lỗi.
Peter Bailey

4
Bởi vì nó không sai, @deceze. Đó không phải là câu trả lời hay nhất, bạn sẽ không nhận được bất kỳ tranh luận nào từ tôi ở đó. Tôi thậm chí đã bỏ phiếu cho chính mình. Nó rất cũ câu trả lời nhưng nó không sai . Về số phiếu cao: hãy nhớ rằng, porneL đã đến gần 17 tháng sau lần này.
Peter Bailey

37

Theo các tài liệu PHP :

khoảng trống () chỉ kiểm tra các biến vì mọi thứ khác sẽ dẫn đến lỗi phân tích cú pháp

Bạn không thể sử dụng empty()trực tiếp trên giá trị trả về của hàm. Thay vào đó, đặt trả về từ getError()một biến và chạy empty()trên biến đó.


19

Tôi thường tạo một hàm toàn cục gọi là is_empty () chỉ để giải quyết vấn đề này

function is_empty($var)
{ 
 return empty($var);
}

Sau đó, bất cứ nơi nào tôi thường sử dụng rỗng () tôi chỉ sử dụng is_empty ()


2
Tốt hơn là không làm điều này và tuân thủ các tiêu chuẩn (khó chịu như chúng có thể).
tonyhb

1
@dynamism bạn có thể giải thích tại sao không?
Janis Veinbergs

1
Bởi vì các chức năng tiện lợi có thể là một nỗi đau để đọc mã của người khác. Thêm vào đó, trong kiến ​​trúc MVC / HMVC, nó có thể làm rối cấu trúc của bạn. Vào cuối ngày, các lập trình viên PHP nên biết các hạn chế của nó và có thể hiểu các cách giải quyết nhỏ mà không cần các chức năng tiện lợi.
tonyhb

14
Wow, bạn vừa phát minh ra một chức năng phủ định . Bạn biết PHP có !toán tử cho điều này? :)
Kornel

4

Như những người khác đã chỉ ra, đó là một giới hạn (kỳ lạ) của khoảng trống ().

Đối với hầu hết các cuộc tấn công, làm điều này tương đương với việc gọi trống, nhưng điều này hoạt động:

if ($r->getError() != '')

5
Điều này không đúng - empty()bao gồm nhiều khả năng hơn là một chuỗi trống
Robbie Averill

3
Đó là lý do tại sao nó nói "cho hầu hết các mục đích ", không phải tất cả
Jani Hartikainen

2

Vấn đề là đây, bạn muốn biết nếu lỗi không trống.

public function getError() {
    return $this->error;
}

Thêm một phương thức isErrorSet () sẽ giải quyết vấn đề.

public function isErrorSet() {
    if (isset($this->error) && !empty($this->error)) {
        return true;
    } else {
        return false;
    }
}

Bây giờ điều này sẽ hoạt động tốt với mã này mà không cần thông báo.

if (!($x->isErrorSet())) {
    echo $x->getError();
}

-3

Cách khác để kiểm tra xem một mảng có trống không:

count($array)>0

Nó hoạt động với tôi mà không có lỗi đó

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.