Cách thêm thuộc tính vào đối tượng trong chế độ nghiêm ngặt PHP> = 5.3 mà không tạo ra lỗi


81

Điều này phải đơn giản, nhưng tôi dường như không thể tìm ra câu trả lời ...

Tôi có một đối tượng stdClass chung chung $fookhông có thuộc tính nào. Tôi muốn thêm một thuộc tính mới $barvào nó mà nó chưa được xác định. Nếu tôi làm điều này:

$foo = new StdClass();
$foo->bar = '1234';

PHP ở chế độ nghiêm ngặt phàn nàn.

Cách thích hợp (bên ngoài khai báo lớp) để thêm thuộc tính vào một đối tượng đã được khởi tạo là gì?

LƯU Ý: Tôi muốn giải pháp hoạt động với đối tượng PHP chung kiểu stdClass.

Một chút nền tảng về vấn đề này. Tôi đang giải mã một chuỗi json là một mảng các đối tượng json. json_decode()tạo một mảng đối tượng StdClass. Tôi cần thao tác các đối tượng này và thêm một thuộc tính cho mỗi đối tượng.


Hãy thử chuyển TRUEdưới dạng tham số thứ 2 tới json_decode. Nó sẽ cung cấp cho bạn một mảng liên kết thay vì một mảng đối tượng.
Rocket Hazmat

1
PHP ở chế độ nghiêm ngặt không phàn nàn về điều đó. 3v4l.org/kn0hi
hakre

3
Tôi không biết tại sao điều này đã bị đóng lại vì đây là một câu hỏi hoàn toàn hợp lệ. Tôi có một câu hỏi chính xác tương tự ngay bây giờ.
Steven

Câu trả lời:


130

Nếu bạn nhất thiết phải thêm thuộc tính vào đối tượng, tôi tin rằng bạn có thể ép kiểu nó dưới dạng một mảng, thêm thuộc tính của bạn (dưới dạng khóa mảng mới), sau đó truyền nó trở lại dưới dạng một đối tượng. Lần duy nhất bạn gặp phải stdClasscác đối tượng (tôi tin) là khi bạn ép kiểu một mảng như một đối tượng hoặc khi bạn tạo một stdClassđối tượng mới từ đầu (và tất nhiên là khi bạn làm json_decode()điều gì đó - tôi thật ngớ ngẩn vì đã quên!).

Thay vì:

$foo = new StdClass();
$foo->bar = '1234';

Bạn sẽ làm:

$foo = array('bar' => '1234');
$foo = (object)$foo;

Hoặc nếu bạn đã có một đối tượng stdClass hiện tại:

$foo = (array)$foo;
$foo['bar'] = '1234';
$foo = (object)$foo;

Cũng như một lớp lót 1:

$foo = (object) array_merge( (array)$foo, array( 'bar' => '1234' ) );

1
Một nơi bạn gặp phải StdClass là khi bạn giải mã json, điều này khá phổ biến.
Ray

1
@Ray Tôi đang lắc đầu buồn bã vì không nghĩ đến chuyện đó. =)
Crontab

3
Giải pháp của bạn hiệu quả, nhưng nó làm tổn thương trái tim OO của tôi :) Tôi đã hy vọng vào một số kiểu phản chiếu hào nhoáng kung foo hay gì đó ... Tôi sẽ giữ câu hỏi mở lâu hơn một chút và hy vọng vào một số phép thuật PHP ít được biết đến.
Ray

1
@Ray hehehe ... Tôi ước gì tôi có một cái gì đó trang nhã hơn cho bạn. Ngẫu nhiên, cài đặt rõ ràng error_reporting(E_STRICT);trên PHP 5.3.15-1~dotdeb.0 with Suhosin-Patch, tôi không gặp bất kỳ lỗi hoặc thông báo nào khi cố gắng đặt thuộc tính không tồn tại trên đối tượng stdClass. Bạn đang sử dụng phiên bản PHP nào?
Crontab

Ha, gần ba năm sau và tôi nhận được một phiếu giảm giá lái xe mà không có lời giải thích vì lý do gì. Cảm ơn bạn.
Crontab

111

Làm như thế này:

$foo = new stdClass();
$foo->{"bar"} = '1234';

bây giờ cố gắng:

echo $foo->bar; // should display 1234

2
Hoạt động như một sự quyến rũ. Đây nên là giải pháp được chấp nhận.
Tarrakis

Làm cách nào để bạn thêm thuộc tính vào một trường trên một đối tượng bằng cú pháp này?
Big Money

'Cố gắng để sở hữu assign của phi vật thể' Lỗi trong Laravel
Rejaul

thậm chí chuỗi "bar" có thể nằm trong một biến: $ foo -> {$ any_variable} = '1234';
Salar

Đây chắc chắn phải là câu trả lời được chấp nhận, vì nó giữ nguyên tham chiếu đối tượng (trong trường hợp của tôi là rất quan trọng).
Johan Fredrik Varen

11

Nếu bạn muốn chỉnh sửa JSON đã giải mã, hãy thử lấy nó dưới dạng một mảng liên kết thay vì một mảng đối tượng.

$data = json_decode($json, TRUE);

2

Tôi luôn sử dụng cách này:

$foo = (object)null; //create an empty object
$foo->bar = "12345";

echo $foo->bar; //12345

1

bạn nên sử dụng các phương pháp ma thuật __Set và __get. Ví dụ đơn giản:

class Foo
{
    //This array stores your properties
private $content = array();

public function __set($key, $value)
{
            //Perform data validation here before inserting data
    $this->content[$key] = $value;
    return $this;
}

public function __get($value)
{       //You might want to check that the data exists here
    return $this->$content[$value];
}

}

Tất nhiên, không sử dụng ví dụ này như sau: không có bảo mật nào cả :)

CHỈNH SỬA: đã xem nhận xét của bạn, đây có thể là một giải pháp thay thế dựa trên sự phản ánh và người trang trí:

 class Foo
 {
private $content = array();
private $stdInstance;

public function __construct($stdInstance)
{
    $this->stdInstance = $stdInstance;
}

public function __set($key, $value)
{
    //Reflection for the stdClass object
    $ref = new ReflectionClass($this->stdInstance);
    //Fetch the props of the object

    $props = $ref->getProperties();

    if (in_array($key, $props)) {
        $this->stdInstance->$key = $value;
    } else {
        $this->content[$key] = $value;
    }
    return $this;
}

public function __get($value)
{
    //Search first your array as it is faster than using reflection
    if (array_key_exists($value, $this->content))
    {
        return $this->content[$value];
    } else {
        $ref = new ReflectionClass($this->stdInstance);

        //Fetch the props of the object
        $props = $ref->getProperties();

        if (in_array($value, $props)) {

        return $this->stdInstance->$value;
    } else {
        throw new \Exception('No prop in here...');
    }
}
 }
}

Tái bút: Tôi không kiểm tra mã của mình, chỉ là ý tưởng chung ...


3
Benjamin, tôi muốn sử dụng lớp đối tượng chung của PHP: StdClass. Tôi không thể sửa đổi lớp này.
Ray

Ray, tôi cập nhật câu trả lời của tôi với một giải pháp tương ứng với nhu cầu của bạn, nhưng nó nặng: - /
Benjamin Dubois

1

Tôi không biết liệu nó có phải là phiên bản php mới hơn hay không, nhưng điều này hoạt động. Tôi đang sử dụng php 5.6

    <?php
    class Person
    {
       public $name;

       public function save()
       {
          print_r($this);
       }
    }

   $p = new Person;
   $p->name = "Ganga";
   $p->age = 23;

   $p->save();

Đây là kết quả. Phương thức lưu thực sự nhận được thuộc tính mới

    Person Object
    (
       [name] => Ganga
       [age] => 23
    )

Tôi đã chạy một số thử nghiệm cho mã trên các phiên bản php và kết quả cho thấy nó chỉ hoạt động cho php 5 trở lên. bất kỳ phiên bản nào bên dưới php5 đều có lỗi.
Big Tree

-6

Có, có thể thêm động các thuộc tính vào một đối tượng PHP.

Điều này rất hữu ích khi một phần đối tượng được nhận từ javascript.

Bên JAVASCRIPT:

var myObject = { name = "myName" };
$.ajax({ type: "POST", url: "index.php",
    data: myObject, dataType: "json",
    contentType: "application/json;charset=utf-8"
}).success(function(datareceived){
    if(datareceived.id >= 0 ) { /* the id property has dynamically added on server side via PHP */ }
});

PHP bên:

$requestString = file_get_contents('php://input');
$myObject = json_decode($requestString); // same object as was sent in the ajax call
$myObject->id = 30; // This will dynamicaly add the id property to the myObject object

HOẶC CHỈ GỬI MỘT SỞ HỮU DUMMY từ javascript mà bạn sẽ điền vào PHP.


Tôi nghĩ rằng gửi một thuộc tính giả từ JS và điền vào bên PHP là giải pháp dễ dàng thông minh hơn. Cảm ơn!
Adrian P.

8
o_O O_o o_O O_o
theflowersoftime
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.