Làm cách nào để viết động tên thuộc tính đối tượng PHP?


81

Tôi có các thuộc tính đối tượng trong mã của mình trông như thế này:

$obj ->field_name_cars[0];
$obj ->field_name_clothes[0];

Vấn đề là tôi có 100 tên trường và cần phải viết động tên thuộc tính. Nếu không, tên đối tượng và các khóa của thuộc tính sẽ luôn giống nhau. Vì vậy, tôi đã thử:

$obj -> $field[0];

Hy vọng rằng tên của thuộc tính sẽ được thay đổi động và truy cập các giá trị chính xác. Nhưng, tôi tiếp tục nhận được 'trường thuộc tính không xác định $ trong trường stdClass :: $;

Ít nhiều thì tôi đang cố gắng viết động php trước khi nó thực thi để nó có thể xuất ra các giá trị thích hợp. Suy nghĩ về cách tiếp cận điều này?

Câu trả lời:


206

Cập nhật cho PHP 7.0

PHP 7 đã giới thiệu những thay đổi đối với cách xử lý các biến và thuộc tính gián tiếp ở cấp trình phân tích cú pháp (xem RFC tương ứng để biết thêm chi tiết). Điều này đưa hành vi thực tế gần hơn với dự kiến ​​và có nghĩa là trong trường hợp $obj->$field[0]này sẽ tạo ra kết quả mong đợi.

Trong trường hợp hành vi mặc định (hiện đã được cải thiện) không mong muốn, dấu ngoặc nhọn vẫn có thể được sử dụng để ghi đè nó như được hiển thị bên dưới.

Câu trả lời ban đầu

Viết quyền truy cập như thế này:

$obj->{$field}[0]

Thủ thuật "kèm theo dấu ngoặc nhọn" này rất hữu ích trong PHP bất cứ khi nào có sự mơ hồ do các biến có thể thay đổi.

Hãy xem xét mã ban đầu $obj->$field[0]- điều này có nghĩa là "truy cập thuộc tính có tên được cung cấp $field[0]" hay "truy cập phần tử có khóa 0của thuộc tính có tên được cung cấp $field"? Niềng răng cho phép bạn rõ ràng.


Câu lệnh thô này hoạt động trong mã của tôi: echo $ json_dump-> Hình học [6] -> obs [2] -> hayabusa2-> delay_from; Nhưng tôi không thể "mô phỏng" nó bằng cách gán "hình học [6] -> obs [2] -> hayabusa2-> delay_from" cho $ path và sử dụng echo $ json_dump -> {$ path}, tôi nhận được "Thuộc tính không xác định: stdClass: : $ hình học [6] "
jumpjack

31

Tôi nghĩ rằng bạn đang tìm kiếm ký hiệu kiểu biến-biến, khi truy cập giá trị từ các mảng / đối tượng khác, tốt nhất đạt được bằng cách sử dụng cú pháp dấu ngoặc nhọn như sau:

$obj->{field[0]}

12

Phương pháp kỳ diệu __get là bạn:

class MyClass
{
   private $field = array();

   public function __get($name)
   {
      if(isset($this->field[$name]))
        return $this->field[$name];
      else
        throw new Exception("$name dow not exists");
   }
}

Sử dụng:

$myobj = new MyClass();
echo $myobj->myprop;

Giải thích: Tất cả dữ liệu trường của bạn được lưu trữ trong một mảng. Khi bạn truy cập thuộc tính $myobj->mypropđó rõ ràng không tồn tại trong lớp. Đó là nơi __getđược gọi là. __gettra cứu tên trong fieldmảng và trả về giá trị chính xác.


3
Đừng làm điều này. Hàm __get là các hàm hiệu suất mà bạn nên tránh sử dụng khi có thể, ngoài việc tạo ra một số vấn đề nghiêm trọng với hành vi không mong muốn. Ví dụ này đặc biệt đáng sợ vì nó ném ra một ngoại lệ có thể gây ra hành vi phá vỡ ứng dụng nghiêm trọng nếu nhà phát triển không có kế hoạch truy cập vào một thuộc tính không tồn tại để ném một ngoại lệ, biến một quyền truy cập thuộc tính đơn giản thành một lỗi nghiêm trọng tiềm ẩn.
moberemk

0

aboulfazl, vì các phương thức PHP 5.3.3 có cùng tên với lớp sẽ không được coi là phương thức khởi tạo!

    YourClass
    {
        public $any = false;

        public function __construct($any = null)
        {
            $this->any = (is_null($any) ? $this->any : $any);
        }
    }

Điều này hoạt động nhưng không được chủ chủ đề yêu cầu, Jon đưa cho người chờ!


0

Tôi đã làm việc trên một số mã sử dụng các thuộc tính đối tượng được tạo động. Tôi nghĩ rằng việc sử dụng các thuộc tính đối tượng được tạo động là khá tuyệt (theo ý kiến ​​của tôi là đúng). Tuy nhiên, chương trình của tôi mất 7 giây để chạy. Tôi đã xóa các thuộc tính đối tượng động và thay thế chúng là các thuộc tính đối tượng được khai báo như một phần của mỗi lớp (công khai trong trường hợp này). Thời gian CPU tăng từ hơn 7 giây xuống 0,177 giây. Đó là khá quan trọng.

Có thể là tôi đã làm sai cách sử dụng thuộc tính đối tượng động. Cũng có thể cấu hình của tôi bị hỏng theo một cách nào đó. Tất nhiên, tôi nên nói rằng tôi có một cấu hình PHP vani rất đơn giản trên máy tính của mình.


0

hôm nay tôi phải đối mặt với thách thức đó. Tôi đã kết thúc với phong cách phát triển đó

$countTickets = new \stdClass;

foreach ($tickets as $key => $value) {

    if(!isset($countTickets->total)){
        $countTickets->total = 0;
    }

    if(!isset($countTickets->{$value['categoryname']})){
        $countTickets->{$value['categoryname']} = 0;
    }

    $countTickets->total += $value['number'];
    $countTickets->{$value['categoryname']} += $value['number']; 
}

-4

Cách tốt nhất bạn có thể sử dụng phiên bản của Đối tượng lớp mặc định PHP để gán động các thuộc tính cho nó

$inst=new \StdClass;
$inst->any_property = '';

-6

Với sự kế thừa. ví dụ:

YourClass extends stdClass {
   public function YourClass() {
      $this->AnyProperty="any";
   }
}

Bây giờ AnyProperty được khai báo động.

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.