Tạo đối tượng mặc định từ giá trị trống trong PHP?


362

Tôi chỉ thấy lỗi này sau khi nâng cấp môi trường PHP của tôi lên PHP 5.4 trở lên. Lỗi chỉ ra dòng mã này:

Lỗi:

Tạo đối tượng mặc định từ giá trị rỗng

Mã số:

$res->success = false;

Trước tiên tôi có cần khai báo $resđối tượng của mình không?


11
Làm thế nào / bạn đang bắt đầu ở $res đâu?
Naveed

1
@NAVEED .
7heo.tk

Câu trả lời:


627

Môi trường mới của bạn có thể có E_STRICTcác cảnh báo được bật trongerror_reporting các phiên bản PHP <= 5.3.x hoặc đơn giản là đã error_reportingđặt thành ít nhất là E_WARNINGvới các phiên bản PHP> = 5.4. Lỗi mà được kích hoạt khi $resđang NULLhoặc chưa được khởi tạo:

$res = NULL;
$res->success = false; // Warning: Creating default object from empty value

PHP sẽ báo cáo một thông báo lỗi khác nếu $resđã được khởi tạo cho một số giá trị nhưng không phải là một đối tượng:

$res = 33;
$res->success = false; // Warning: Attempt to assign property of non-object

Để tuân thủ các E_STRICTtiêu chuẩn trước PHP 5.4 hoặc mức E_WARNINGlỗi thông thường trong PHP> = 5.4, giả sử bạn đang cố gắng tạo một đối tượng chung và gán thuộc tính success, bạn cần khai báo $reslà một đối tượng stdClasstrong không gian tên toàn cục:

$res = new \stdClass();
$res->success = false;

38
Bạn kiểm tra xem đối tượng đã tồn tại chưa : if (!isset($res)) $res = new stdClass();. Mặt khác, mã này không phải là sự thay thế tương đương cho việc tạo đối tượng ngầm "PHP cũ".
TMS

6
@Tomas Chúng ta có cần làm điều này một lần nữa không? Các mod đã dọn sạch luồng nhận xét lần trước vì nó thêm ít giá trị. Không có tạo đối tượng ngầm "PHP cũ". Đó luôn là một lỗi và luôn đưa ra cảnh báo, chỉ là nó đã được thay đổi từ E_STRICT thành E_WARNING trong 5.4, vì vậy một số người không bao giờ gặp phải nó không chú ý đến E_STRICT.
Michael Berkowski 23/11/13

4
@PeterAlfvin nó không được xác định trong lần chạy cụ thể đó ! Nhưng trong lần chạy khác nhau, tại cùng một vị trí trong mã , đối tượng có thể đã được xác định! Đây là sai lầm trong suy nghĩ mọi người thường mắc phải và đó là lý do tôi cố gắng nhấn mạnh điều đó.
TMS

2
Michael, việc tạo đối tượng ngầm luôn luôn tồn tại và vẫn còn hiện diện ngay cả trong 5.4. Và BTW Trong PHP <5.3, nó không phải là E_STRICT hay E_WARNING. Và BTW, các mod đã khôi phục bình luận và tôi được yêu cầu giảm âm lượng xuống, đó là lý do tại sao tôi đăng lại nó.
TMS

3
@tomas ơi, ok, tôi nghĩ tôi hiểu ý bạn rồi. Có vẻ lạ khi bạn / Michael không thể kết thúc chuyện này. BTW, sự trao đổi này đã khiến tôi nhận ra rằng chữ in nghiêng <đậm <allcaps về "sức mạnh" và trong khi allcaps = la hét và in nghiêng = politeEmphocation, đậm nằm ở giữa, nơi có thể chấp nhận được. :-)
Peter Alfvin

57

Thông báo này đã được E_STRICTdành cho PHP <= 5.3. Kể từ PHP 5.4, nó đã được thay đổi thành E_WARNING. Vì E_WARNINGtin nhắn rất hữu ích, bạn không muốn vô hiệu hóa chúng hoàn toàn.

Để thoát khỏi cảnh báo này, bạn phải sử dụng mã này:

if (!isset($res)) 
    $res = new stdClass();

$res->success = false;

Đây là sự thay thế hoàn toàn tương đương . Nó đảm bảo chính xác điều tương tự mà PHP đang âm thầm làm - không may mắn với cảnh báo bây giờ - tạo đối tượng ngầm. Bạn phải luôn luôn kiểm tra xem đối tượng đã tồn tại chưa, trừ khi bạn hoàn toàn chắc chắn rằng nó không tồn tại. Mã do Michael cung cấp nói chung là không tốt, bởi vì trong một số bối cảnh, đối tượng đôi khi có thể đã được xác định tại cùng một vị trí trong mã, tùy thuộc vào hoàn cảnh.


2
@carlosvini, Cái này sẽ cho bạn Undefined variable: res.
Pacerier

1
@Pacerier Bạn nói đúng, điều tốt nhất bạn có thể làm là: $ res = isset ($ res)? $ res: stdClass mới (); - đó là lý do tôi không kích hoạt E_NOTICE 6 tháng trước, vì nó quá dài dòng.
carlosvini

13

Đơn giản,

    $res = (object)array("success"=>false); // $res->success = bool(false);

Hoặc bạn có thể khởi tạo các lớp với:

    $res = (object)array(); // object(stdClass) -> recommended

    $res = (object)[];      // object(stdClass) -> works too

    $res = new \stdClass(); // object(stdClass) -> old method

và điền các giá trị với:

    $res->success = !!0;     // bool(false)

    $res->success = false;   // bool(false)

    $res->success = (bool)0; // bool(false)

Thêm thông tin: https://www.php.net/manual/en/lingu.types.object.php#lingu.types.object.casting


tại sao stdClass () mới được coi là một phương thức "cũ"? Là những người khác bằng cách nào đó tốt hơn?
Aaron

Nó chỉ đơn giản là từ phiên bản php cũ
cướp biển

trong trường hợp của tôi $this->route->uri = new stdClass();không làm việc cho tôi, tôi vẫn có cảnh báo. Lưu ý: $this->routehiện có.
Meloman

Có lẽ điều này không tương thích với các phiên bản mới của php? Phiên bản nào bạn đã sử dụng?
cướp biển

6

Nếu bạn đặt ký tự "@" bắt đầu dòng thì PHP sẽ không hiển thị bất kỳ cảnh báo / thông báo nào cho dòng này. Ví dụ:

$unknownVar[$someStringVariable]->totalcall = 10; // shows a warning message that contains: Creating default object from empty value

Để ngăn cảnh báo này cho dòng này, bạn phải đặt ký tự "@" bắt đầu dòng như thế này:

@$unknownVar[$someStringVariable]->totalcall += 10; // no problem. created a stdClass object that name is $unknownVar[$someStringVariable] and created a properti that name is totalcall, and it's default value is 0.
$unknownVar[$someStringVariable]->totalcall += 10; // you don't need to @ character anymore.
echo $unknownVar[$someStringVariable]->totalcall; // 20

Tôi đang sử dụng thủ thuật này khi phát triển. Tôi không thích vô hiệu hóa tất cả các thông báo cảnh báo nếu bạn không xử lý chính xác các cảnh báo thì chúng sẽ trở thành một lỗi lớn trong tương lai.


1
@ không ngăn chặn các cảnh báo bằng cách ngăn chặn nó, có vẻ ổn miễn là bạn có mã quản lý. Nhưng nếu mã của bạn phát triển thành một thứ gì đó lớn hơn và bạn gặp phải một vấn đề, bằng cách nào đó bạn sẽ hối hận khi sử dụng mã này. Bạn sẽ thấy mình đang tìm kiếm tất cả những "@" cho một cảnh báo mà bạn muốn bỏ qua vì tạm thời nó đã phục vụ mục đích của nó với suy nghĩ rằng bạn đã thực sự khắc phục vấn đề khi thực tế nó đang nói chuyện với bạn và bạn chỉ muốn nói t lắng nghe
Vincent Edward Gedaria Binua

Tôi đã biết rồi. Đây là câu trả lời ngắn và nhanh chóng. Có rất nhiều giải pháp cho việc này.
kodmanyagha

2
tuyệt vời! Tôi có thể lịch sự cầu xin để không đồng ý mặc dù, che giấu lỗi không thực sự khắc phục vấn đề (như những gì Ramy Nasr đã nhận xét là tốt).
Vincent Edward Gedaria Binua

Cách giải quyết này là công việc duy nhất cho tôi trên php 7.2.
Meloman

3

Hãy thử điều này nếu bạn có mảng và thêm các đối tượng vào nó.

$product_details = array();

foreach ($products_in_store as $key => $objects) {
  $product_details[$key] = new stdClass(); //the magic
  $product_details[$key]->product_id = $objects->id; 
   //see new object member created on the fly without warning.
}

Điều này sẽ gửi ARRAY của các đối tượng để sử dụng sau ~!


CẢM ƠN BẠN!!!! Đây là những gì đã giúp hoàn thành công việc. Tôi cần nói cho PHP từng bước từng yếu tố là gì. Cảm ơn đã nhắc nhở tôi không mã hóa lol lười biếng.
yanike

2

Thử cái này:

ini_set('error_reporting', E_STRICT);

1
Cảm ơn. cái này được sử dụng đầy đủ khi bạn đang sử dụng các thư viện của bên thứ ba như nusoap và không muốn / không thể thay đổi nguồn. Trong trường hợp đó, bạn có thể thay đổi lỗi thông báo thành mức E_STRICT ngay trước khi yêu cầu các tệp nguồn khác.
mtoloo

Mặc dù tôi chỉ thêm cái này vào đầu nusoap để khắc phục vấn đề của mình.
badweasel

11
Huh? Mã ở đây vô hiệu hóa tất cả các báo cáo E_STRICTlỗi ngoại trừ lỗi, bao gồm cả việc chặn các thông báo cho các lỗi nghiêm trọng. Đó không phải là một gợi ý hợp lý để giải quyết cảnh báo cụ thể này, và hơn thế nữa là điều bạn gần như không bao giờ muốn làm. Tại sao 5 người nêu lên điều này, tôi không có manh mối.
Đánh dấu Amery

1
Điều này là siêu xấu! sử dụng ini_set('error_reporting', -1);trong khi gỡ lỗi, nhưng không sử dụng ở trên, như mọi khi.
Kzqai

Ok, vì vậy bạn khắc phục một vấn đề bằng cách ẩn cái này? Không chắc chắn mã của bạn sẽ hoạt động như mong đợi ...
cướp biển

1

Tôi đã có vấn đề tương tự và điều này dường như để giải quyết vấn đề. Bạn chỉ cần khởi tạo đối tượng $ res thành một lớp. Giả sử ở đây tên lớp là kiểm tra.

class test
{
   //You can keep the class empty or declare your success variable here
}
$res = new test();
$res->success = false;

1

Đây là một cảnh báo mà tôi gặp phải trong PHP 7, cách khắc phục dễ dàng này là bằng cách khởi tạo biến trước khi sử dụng nó

$myObj=new \stdClass();

Một khi bạn đã xác định được nó rồi thì bạn có thể sử dụng nó cho các đối tượng

 $myObj->mesg ="Welcome back - ".$c_user;

0

Vấn đề này được gây ra bởi vì bạn đang gán cho một thể hiện của đối tượng không được bắt đầu. Ví dụ:

Trường hợp của bạn:

$user->email = 'exy@gmail.com';

Giải pháp:

$user = new User;
$user->email = 'exy@gmail.com';

không phải bạn cho rằng lớp "Người dùng" tồn tại sao? mà nó có thể không và bây giờ nó sẽ tạo ra một lỗi khác nhau?
Christopher Thomas

1
Trên thực tế tôi đã không tạo một thể hiện của đối tượng Người dùng nên tôi gặp lỗi. Nhưng sau khi tạo một ví dụ. Nó hoạt động .. đó là một vấn đề chung với khái niệm OOP :)
Bastin Robin

6
tốt, thực sự vấn đề thực sự là ví dụ của bạn giả định lớp người dùng được xác định, đây không phải là vấn đề chung về định hướng đối tượng, là yêu cầu chính của nó;)
Christopher Thomas

1
Tôi muốn đặt một "stdClass" chung chung thay thế tiền đề ngụ ý "Người dùng".
TechNyquist

0

Một cách đơn giản để nhận lỗi này là gõ (a) bên dưới, nghĩa là gõ (b)

(a) $this->my->variable

(b) $this->my_variable

Tầm thường, nhưng rất dễ bị bỏ qua và khó phát hiện nếu bạn không tìm kiếm nó.


Làm thế nào điều này có liên quan đến câu hỏi ban đầu? Không có sự pha trộn giữa _->
Nico Haase

0

Bạn có thể cần kiểm tra xem biến được khai báo và có đúng loại không.

if (!isset($res) || !is_object($res)) {
    $res = new \stdClass();
    // With php7 you also can create an object in several ways.
    // Object that implements some interface.
    $res = new class implements MyInterface {};
    // Object that extends some object.
    $res = new class extends MyClass {};
} 

$res->success = true;

Xem các lớp ẩn danh PHP .


0

Tôi đã gặp một vấn đề tương tự trong khi cố gắng thêm một biến vào một đối tượng được trả về từ API. Tôi đã lặp lại thông qua dữ liệu với một vòng lặp foreach.

foreach ( $results as $data ) {
    $data->direction = 0;
}

Điều này đã ném "Tạo đối tượng mặc định từ giá trị trống" Ngoại lệ trong Laravel.

Tôi đã sửa nó với một thay đổi rất nhỏ.

foreach ( $results as &$data ) {
    $data->direction = 0;
}

Bằng cách đơn giản làm cho dữ liệu $ trở thành một tài liệu tham khảo.

Tôi hy vọng điều đó sẽ giúp ai đó, điều đó thật khó chịu với tôi!


0
  1. Trước tiên, bạn nên tạo đối tượng $ res = new \ stdClass ();

  2. sau đó gán đối tượng với khóa và giá trị thay $ res-> thành công = false;


(Tôi không hiểu thay.) Trường hợp bạn muốn ngắt dòng sau một số nội dung, hãy thêm hai khoảng trắng vào nội dung hiển thị của dòng trước khi ngắt.
greybeard

-1

không bạn không .. nó sẽ tạo ra nó khi bạn thêm giá trị thành công vào đối tượng. Lớp mặc định được kế thừa nếu bạn không chỉ định một.


4
Mặc dù nó sẽ trả về thông điệp Tiêu chuẩn nghiêm ngặt ... đơn giản là bạn nên tạo đối tượng theo cách thủ công trước và trong khi PHP tương đối khoan dung với thực hành mã hóa kém chất lượng, bạn không nên bỏ qua việc thực hiện chính xác.
Mark Baker

4
hiểu, tôi chỉ trả lời câu hỏi bằng cách đơn giản hoặc không, không xác định hoặc bảo vệ các thực tiễn tốt nhất :)
Silvertiger

-1

Hãy thử sử dụng:

$user = (object) null;

2
Nói chung, câu trả lời sẽ hữu ích hơn nhiều nếu chúng bao gồm một lời giải thích về những gì mã được dự định làm và tại sao điều đó giải quyết vấn đề mà không giới thiệu người khác.
lucascaro

-12

Tôi đặt phần sau ở đầu tệp PHP bị lỗi và lỗi không còn hiển thị:

error_reporting(E_ERROR | E_PARSE);
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.