2010-07-07 55 views
60

Ở giữa thời kỳ tái cấu trúc lớn tại nơi làm việc, tôi muốn giới thiệu stdClass ***** như một cách để trả về dữ liệu từ các hàm và tôi đang cố gắng tìm các đối số không chủ quan để hỗ trợ quyết định của tôi.Khi nào tôi nên sử dụng stdClass và khi nào tôi nên sử dụng một mảng trong mã php oo?

Có bất kỳ trường hợp nào tốt nhất khi sử dụng cái này thay vì cái kia không?

Lợi ích nào tôi có thể sử dụng stdClass thay vì mảng ??


Một số người nói rằng các chức năng phải ít và cụ thể để có thể trả về một giá trị duy nhất. Quyết định của tôi để sử dụng stdClass là thời gian, vì tôi hy vọng sẽ tìm thấy các đối tượng giá trị phù hợp cho mỗi quá trình về lâu dài.

+0

xem: http://stackoverflow.com/questions/2056931/value-objects-vs-associative-arrays-in-php Nó không trả lời câu hỏi của tôi. Ông nói rằng một lớp "thực sự" sẽ là cách tiếp cận tốt nhất, mà (tôi nghĩ) tất cả chúng ta đều đồng ý. Tôi vẫn muốn biết "khi nào" việc sử dụng các giá trị trả về stdClass là tốt hơn so với mảng. – JonG

+0

bạn có thể muốn làm rõ khái niệm về các đối tượng giá trị. [Trong DDD một đối tượng giá trị là không thay đổi] (http://domaindrivendesign.org/node/135) và mục đích là khá khác với [VO trong Java.] (Http://java.sun.com/j2ee/patterns/ ValueObject.html) – Gordon

+0

@Gordon Ý tôi là, một hướng dẫn trả về "VO" giống với các chức năng. Có một VO là một đối tượng nhỏ (tốt), chỉ có những thuộc tính của anh ta là quan trọng, không phải là bản sắc của anh ta. Giới thiệu về các liên kết của bạn, bạn có đang cố gắng tìm hiểu xem liệu tôi (câu hỏi của tôi) các cuộc thảo luận về "VO nên không thay đổi Vs VO có thể thay đổi được" là quan trọng? Btw, ngày nay VO là TO (Transfer Objects) cho mặt trời. http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html – JonG

Trả lời

52

Cách tiếp cận thông thường là

  • Sử dụng đối tượng khi trở về một cấu trúc dữ liệu được xác định với các ngành cố định:

    $person 
        -> name = "John" 
        -> surname = "Miller" 
        -> address = "123 Fake St" 
    
  • Sử dụng mảng khi trả về một danh sách:

    "John Miller" 
        "Peter Miller" 
        "Josh Swanson" 
        "Harry Miller" 
    
  • Sử dụng một mảng đối tượng khi trả lại ing một danh sách các thông tin có cấu trúc:

    $person[0] 
        -> name = "John" 
        -> surname = "Miller" 
        -> address = "123 Fake St" 
    
        $person[1] 
        -> name = "Peter" 
        -> surname = "Miller" 
        -> address = "345 High St" 
    

Đối tượng không phù hợp để giữ danh sách các dữ liệu, bởi vì bạn luôn cần một chìa khóa để giải quyết chúng. Mảng có thể thực hiện cả hai hàm - giữ danh sách tùy ý và cấu trúc dữ liệu.

Vì vậy, bạn có thể sử dụng mảng kết hợp trên đối tượng cho ví dụ đầu tiên và thứ ba nếu bạn muốn. Tôi muốn nói đó thực sự chỉ là một câu hỏi về phong cách và sở thích.

@Deceze thực hiện một số điểm tốt về thời điểm sử dụng đối tượng (Xác thực, kiểm tra loại và các phương pháp trong tương lai).

+0

+1 câu trả lời chi tiết tốt. – Sarfraz

+0

Tôi thực sự thích/đồng ý về các đối số số 1 và 2. – JonG

+1

Tôi đã yêu cầu đối số "không phải chủ quan". Đáng buồn thay, không ai được đưa ra. Tôi gắn bó với câu trả lời của bạn (theo các phiếu bầu khác) vì nó cho thấy những gì tôi sẽ tiếp tục theo dõi từ bây giờ: Mảng dành cho các danh sách; stdClass cho "nhiều giá trị"/thuộc tính. – JonG

37

Sử dụng stdClass để thực hiện chức năng giống như một mảng không phải là IMHO rất hữu ích, nó chỉ thêm phí trên của một đối tượng mà không có bất kỳ lợi ích thực sự nào. Bạn cũng bỏ lỡ nhiều chức năng mảng hữu ích (ví dụ: array_intersect). Bạn nên ít nhất tạo ra lớp của riêng bạn để cho phép kiểm tra kiểu, hoặc thêm các phương thức cho đối tượng để làm cho nó có giá trị bằng cách sử dụng một đối tượng.

+1

Tôi đặc biệt thích/đồng ý với những gì bạn nói về "thêm phương pháp vào đối tượng để làm cho nó đáng sử dụng". – JonG

3

Vâng, có 3 điểm khác biệt:

  • họ có một bản sắc. đó là lý do tại sao mặc định cho truyền đối số mảng là gọi theo giá trị và đối tượng gọi bằng cách chia sẻ.
  • có sự khác biệt ngữ nghĩa. Nếu bạn sử dụng một đối tượng, bất kỳ ai đọc mã hiểu rằng giá trị đại diện cho mô hình một số loại quyền lợi, trong khi mảng được coi là một bộ sưu tập hoặc bản đồ
  • Và cuối cùng nhưng không kém phần quan trọng, việc tái cấu trúc trở nên dễ dàng hơn một cách dễ dàng hơn . Nếu bạn muốn sử dụng một lớp cụ thể hơn là stdClass, tất cả những gì bạn phải làm là tạo một lớp khác. Mà cũng cho phép bạn thêm các phương pháp.

Greetz
back2dos

16

Tôi không nghĩ có bất kỳ lợi thế hợp lý của việc sử dụng một stdClass trên một mảng miễn là mục đích duy nhất của bạn là để trả lại nhiều kiểu dữ liệu tùy ý từ một cuộc gọi chức năng.

Vì bạn không thể trả về nhiều giá trị một cách tự nhiên, bạn phải sử dụng vùng chứa có thể chứa tất cả các kiểu dữ liệu khác có sẵn trong PHP. Đó sẽ là một đối tượng hoặc một mảng.

function fn1() { return array(1,2); } 
function fn2() { return array('one' => 1, 'two' => 2); } 
function fn3() { return (object) array(1,2); } 
function fn4() { return (object) array('one' => 1, 'two' => 2); } 

Tất cả những điều trên sẽ hiệu quả. Mảng là một phần nhỏ không đáng kể nhanh hơn và ít hoạt động hơn. Nó cũng có một mục đích xác định rõ ràng trái ngược với stdClass chung (đó là một chút wishywashy, isnt nó). Cả hai chỉ có một giao diện ngầm, vì vậy bạn sẽ phải xem các tài liệu hoặc cơ quan chức năng để biết những gì chúng sẽ chứa. Nếu bạn muốn sử dụng các đối tượng bằng bất kỳ giá nào, bạn có thể sử dụng ArrayObject hoặc SplFixedArray, nhưng nếu bạn xem API của họ, bạn có cần chức năng của họ cho nhiệm vụ trả về nhiều giá trị ngẫu nhiên không? Không. Tôi không nghĩ vậy. Tuy nhiên, đừng hiểu sai về tôi: nếu bạn muốn sử dụng stdClass, hãy sử dụng nó. Nó không giống như nó sẽ phá vỡ bất cứ điều gì. Nhưng bạn cũng sẽ không đạt được gì cả. Để thêm ít nhất một số lợi ích, bạn có thể tạo một lớp riêng biệt có tên là ReturnValues ​​cho việc này.

Có thể là một lớp gắn thẻ đơn giản

class ReturnValues {} 

hoặc một cái gì đó thêm chức năng

class ReturnValues implements Countable 
{ 
    protected $values; 
    public function __construct() { $this->values = func_get_args(); } 
    public function __get($key) return $this->values[$key]; } 
    public function count() { return count($this->values); } 
} 

Cấp, nó không làm được gì nhiều và nhận được các giá trị ra khỏi nó vẫn thực hiện thông qua một giao diện implict , nhưng ít nhất lớp học có trách nhiệm được xác định rõ ràng hơn bây giờ. Bạn có thể mở rộng từ lớp này để tạo các đối tượng returnValue cho các hoạt động cụ thể và đưa ra những một giao diện rõ ràng:

class FooReturnValues extends ReturnValues 
{ 
    public function getFoo() { return $this->values['foo']; } 
    public function getBar() { return $this->values['foo']; } 
} 

Bây giờ các nhà phát triển chỉ có nhìn vào API để biết được nhiều giá trị foo() sẽ trở lại. Tất nhiên, phải viết các lớp ReturnValue cụ thể cho mỗi và mọi hoạt động có thể trả về nhiều giá trị có thể trở nên tẻ nhạt một cách nhanh chóng. Và cá nhân, tôi thấy điều này đã được overengineered cho mục đích ban đầu.

Dù sao, hy vọng có ý nghĩa gì.

+1

thú vị với đề xuất "ReturnValues" của bạn. – JonG

+0

@JonG Cảm ơn. Tôi đoán hai điểm chính của tôi cho nó là: làm cho đối tượng trả về ngữ nghĩa rõ ràng hơn và làm cho giao diện cho nó rõ ràng. Nếu không có vấn đề gì quan trọng, thì nó thực sự không sử dụng để đi theo con đường đó. – Gordon

+0

Tôi thích ý tưởng này của một lớp chung chung, nhưng chung chung trong một miền/mục đích cụ thể. Nó có tiềm năng để thực sự thêm sức mạnh, trong khi 'stdClass' là ít hơn một đại diện thay thế của một mảng kết hợp. – IMSoP

2

Tôi thấy các đối tượng stdClass trên mảng hữu ích khi tôi cần giữ mã của mình rõ ràng và có phần dễ đọc. Lấy ví dụ hàm getProperties() trả về một tập hợp các thuộc tính, nói dữ liệu về một người (tên, tuổi, giới tính).Nếu getProperties() sẽ trả về một mảng kết hợp, khi bạn muốn sử dụng một trong những thuộc tính trở lại, bạn sẽ viết hai hướng dẫn:

$data = getProperties(); 
echo $data['name']; 

Mặt khác, nếu getProperties() trả về một stdClass sau đó bạn có thể viết rằng chỉ trong một hướng dẫn:

echo getProperties()->name; 
+3

Lưu ý rằng điều này không còn áp dụng nếu bạn đang sử dụng PHP 5.4 hoặc mới hơn, vì nó chỉ là một trình phân tích cú pháp ngắn của PHP. Bây giờ bạn có thể viết 'echo getProperties() ['name'];' http://3v4l.org/t6i0r – IMSoP

+0

@IMSoP, bạn có thể, ngoại trừ rất nhiều hệ thống vẫn sử dụng PHP 5.3, điều này sẽ gây ra lỗi một số nhà phát triển :). – musicliftsme

+1

@ laketuna Yep, do đó "nếu" trong bình luận của tôi :) Lưu ý rằng 5.3 hiện giờ không được hỗ trợ chính thức, vì vậy mọi người nên làm phiền máy chủ/quản trị viên của họ để nâng cấp: http://php.net/eol.php – IMSoP

2

các chỉ MỤC TIÊU phiếu tín nhiệm tôi có thể tìm thấy là:

json_decode sử dụng stdClass theo mặc định nên chúng tôi con người trong Userland nên sử dụng stdClass cho các tình huống tương tự.

+3

bạn có thể chỉ cần sử dụng 'json_decode ($ json, true);' nếu bạn muốn nhận mảng thay vì đối tượng – Peter

+0

, chúng ta sẽ không ghi đè các giá trị param mặc định. – tishma

1

Trong các thử nghiệm của mảng so với stdclass, chúng xử lý các thuộc tính động chậm hơn các mảng kết hợp. Tôi không nói điều này để tranh luận tối ưu hóa vi mô mà là nếu bạn sẽ làm điều này tốt hơn của bạn ra xác định một dataclass không có phương pháp và thiết lập các thuộc tính công cộng. Esp nếu bạn đang sử dụng php 5.4+. Thuộc tính mui xe được xác định được ánh xạ trực tiếp vào một mảng c mà không có hashtable, nơi như những người năng động cần phải sử dụng một bảng băm.

Điều này có thêm tiền thưởng sau này trở thành một lớp học đầy đủ mà không cần phải thực hiện lại bất kỳ giao diện chính nào.

+0

Các đặc tính hiệu suất của việc thay đổi PHP với mọi phiên bản. –

Các vấn đề liên quan