PHP : 배열을 사용하는시기와 대부분의 데이터 저장 코드 구성에 객체를 사용하는시기?


37

PHP는 혼합 패러다임 언어이므로 배열과 같은 객체가 아닌 데이터 유형을 사용하고 반환 할 수 있습니다. 특정 상황에서 사용할 프로그래밍 구조를 결정할 때 배열 대 객체 선택에 대한 몇 가지 지침을 명확히하려고합니다.

이것은 실제로 PHP 언어 구조를 사용하여 데이터를 인코딩하는 방법과 데이터 전달 목적 (예 : 서비스 지향 아키텍처 또는 웹 서비스)을 위해 다른 방법을 선택하는 방법에 대한 질문입니다.

{cost, name, part_number, item_count}로 구성된 항목 유형이 있다고 가정하십시오. 프로그램은 배열 을 외부 컨테이너로 사용하여 각 항목 유형을 보유 하기로 결정한 여러 항목 유형의 표시를 요구합니다 . [당신은 또한 PHP이야 사용할 수 있습니다 ArrayObjectOO 패러다임에 대한,하지만 내 질문에 대해 아닙니다 (외부) 배열]. 내 질문은 항목 유형 데이터를 인코딩하는 방법과 사용할 패러다임에 관한 것입니다. PHP는 사용할 수 있습니다 PHP Native Arrays또는 PHP Objects.

다음과 같이 두 가지 방법으로 이러한 데이터를 인코딩 할 수 있습니다.

//PHP's associative arrays:
$ret = array(
    0 => array(
        'cost' => 10.00, 
        'name' => 'item1',
        'part_number' => 'zyz-100', 
        'item_count' => 15
        ),
    1 => array(
        'cost' => 34.00, 
        'name' => 'item2', 
        'part_number' => 'abc-230', 
        'item_count' => 42
        ),
  );

vs

//here ItemType is encapsulated into an object
$ret = array(
  0 => new ItemType(10.00, 'item1', 'zyz-100', 15),
  1 => new ItemType(34.00, 'item2', 'abc-230', 42),
);

class ItemType
{
    private $price;
    private $name;
    private $partNumber;
    private $itemCount;

    function __construct($price, $name, $partNumber, $itemCount) {..}
}

내가 생각하는 것

배열 인코딩은 가볍고 JSON을 더 많이 사용할 수 있지만 엉망이되기 쉽습니다. 연관 배열 키 중 하나를 잘못 입력하면 잡기가 더 어려운 오류가있을 수 있습니다. 그러나 변덕스런 변화가 더 쉽습니다. item_count더 이상 저장하고 싶지 않다면 텍스트 처리 소프트웨어를 사용 item_count하여 배열의 모든 인스턴스 를 쉽게 제거한 다음 그에 따라 사용하는 다른 기능을 업데이트 할 수 있습니다. 더 지루한 과정 일 수 있지만 간단합니다.

객체 지향 인코딩은 IDE 및 PHP 언어 기능을 호출하며 미리 오류를 쉽게 잡을 수 있지만 처음에는 프로그래밍 및 코딩하기가 더 어렵습니다. 객체에 대해 조금 생각하고, 미리 생각해야하고, OO 코딩은 배열 구조를 입력하는 것보다 약간 높은 인지력을 필요로하기 때문에 더 열심히 말합니다. 즉, 일단 코드화되면 일부 변경은 구현하기가 더 쉬울 수 item_count있는데, 예 를 들어을 제거 하면 더 적은 코드 행을 변경해야합니다. 그러나 높은 수준의 OO 기능이 관련되어 있으므로 변경 방법 자체는 어레이 방법에 비해 여전히 높은인지 부하를 요구할 수 있습니다.

질문

데이터에 대한 조작을 수행 해야하는 경우와 같이 어떤 경우에는 분명합니다. 그러나 몇 줄의 "항목 유형"데이터 만 저장해야하는 경우에는 배열 사용 여부 또는 객체 구성 여부를 결정할 때 고려해야 할 명확한 지침이나 고려 사항이 없습니다. 동전을 던져 버릴 수있을 것 같습니다. 이 경우입니까?


2
배열을 객체로 캐스팅하면 경량 객체를 얻을 수 있습니다 (object)['foo'=>'bar']. 결과 값은 class StdClass이며 전체적으로 JSON으로 인코딩되며 json_encode()속성은 배열 인덱스처럼 쉽게 이름을 바꿀 수 있습니다 (변수를 통해 간접적으로 액세스 할 때 항상 쉽지는 않습니다). 그러나 이러한 값에는 다른 작업이 있습니다. 예를 들어, 배열 공용체가 있으므로 개체 공용체가 없으며 array_*()함수를 직접 사용할 수 없습니다 .
outis

3
3 가지 옵션이 있습니다 : 1 : array , 2 : User-defined Class , 3 : stdClass . 비교할 때 속도면에서 성능은 거의 동일 arraya와 User-defined class(예로서 ItemType)하지만, 정의 classES를 사용하는 것보다 적은 메모리를 사용하는 경향이 array들. stdClass반면에 세 가지 옵션 중 가장 느리고 메모리도 가장 많이 사용합니다.
Andy

답변:


33

내가 보는 방식은 나중에 데이터로 무엇을 하려는지에 달려 있습니다. 몇 가지 간단한 검사를 통해 두 가지 데이터 구조 중 어느 것이 더 적합한 지 결정할 수 있습니다.

  1. 이 데이터와 관련된 논리가 있습니까?

    예를 들면, $price센트의 정수로 저장, 그래서 $ 9.99의 가격으로 제품을 것 price = 999하지 price = 9.99? (아마도 예) 아니면 partNumber특정 정규식과 일치해야합니까? 또는 itemCount재고가 있는지 쉽게 확인할 수 있어야 합니까? 앞으로 이러한 기능을 수행해야합니까? 그렇다면 가장 좋은 방법은 지금 수업을 만드는 것입니다. 이는 데이터 구조에 내장 된 제약 조건과 논리를 정의 할 수 있음을 의미합니다. private $myPrice로 설정 999되었지만 $item->getPriceString()반환 $9.99되며 $item->inStock()응용 프로그램에서 호출 할 수 있습니다.

  2. 이 데이터를 여러 PHP 함수에 전달할 예정입니까?

    그렇다면 클래스를 사용하십시오. 이 데이터를 한 번 생성하여 변환을 수행하거나 JSON 데이터로 다른 애플리케이션 (JavaScript 또는 기타)으로 전송하는 경우 배열이 더 쉬운 선택입니다. 그러나이 데이터를 매개 변수로 받아들이는 PHP 함수가 두 개 이상인 경우 클래스를 사용하십시오. 다른 것이 없으면 정의 할 수 someFunction(MyProductClass $product) {있으며 함수가 입력으로 기대하는 것을 매우 분명하게 알 수 있습니다. 코드를 확장하고 더 많은 함수를 가질수록 각 함수가 어떤 유형의 데이터를 허용하는지 쉽게 알 수 있습니다. 보는 someFunction($someArrayData) {것만 큼 ​​명확하지 않습니다. 또한 이것은 유형 일관성을 강요하지 않으며 배열의 유연한 구조가 나중에 개발 고통을 유발할 수 있음을 의미합니다.

  3. 라이브러리 또는 공유 코드 기반을 구축하고 있습니까?

    그렇다면 클래스를 사용하십시오! 라이브러리를 사용하는 새로운 개발자 나 이전에 코드를 사용한 적이없는 회사의 다른 개발자를 생각해보십시오. 클래스 정의를보고 해당 클래스의 기능을 이해하거나 특정 클래스의 객체를 허용하는 라이브러리의 여러 함수를 보는 것이 훨씬 더 쉽습니다. 배열 수 또한 이것은 # 1의 데이터 일관성 문제를 다룹니다. 라이브러리 또는 공유 코드 기반을 개발하는 경우 사용자에게 반가워 : 데이터 일관성을 강화하고 데이터 디자인으로 오류가 발생하지 않도록 클래스를 제공하십시오. .

  4. 이것은 응용 프로그램의 작은 부분입니까, 아니면 데이터 변환입니까? 위의 어느 것에도 맞지 않습니까?

    수업이 너무 많을 수 있습니다. 자신에게 적합하고 쉽게 찾을 수 있다면 배열을 사용하십시오. 위에서 언급했듯이 JSON, YAML 또는 XML 등으로 보낼 구조적 데이터를 생성하는 경우 필요하지 않은 한 클래스를 신경 쓰지 마십시오. 더 큰 응용 프로그램에서 작은 모듈을 작성하고 다른 모듈 / 팀이 코드와 인터페이스 할 필요가없는 경우 배열이면 충분합니다.

궁극적으로 코드의 스케일링 요구를 고려하고 구조화 된 배열이 빠른 해결책 일 것보다 고려하지만 클래스는 훨씬 탄력적이고 확장 가능한 솔루션입니다.

또한 다음 사항을 고려하십시오. 클래스가 있고 JSON으로 출력하려는 ​​경우 클래스에서 json_data()메소드를 정의 할 수있는 클래스 의 메소드를 정의 할 수없는 이유는 없습니다 . 이것은 클래스 데이터를 JSON으로 보내야하는 PHP 응용 프로그램에서 수행 한 작업입니다. 예로서:

class Order {
    private $my_total;
    private $my_lineitems;

    public function getItems() { return $this->my_lineitems; }
    public function addItem(Product $p) { $this->my_lineitems[] = $p; }
    public function getTotal() { return $this->my_total; }

    public function forJSON() {
        $items_json = array();
        foreach($this->my_lineitems as $item) $items_json[] = $item->forJSON();
        return array(
            'total' => $this->getTotal(),
            'items' => $items_json
        );
    }
}

$o = new Order();
// do some stuff with it
$json = json_encode($o->forJSON());

의 요소는 변경하지 않으므로 my_lineitems참조로 가져 오는 것은 불필요합니다. 특히 변수는 객체 자체가 아니라 객체에 대한 식별자 만 보유하기 때문입니다. php.net/manual/en/language.oop5.references.php
Chinoto Vokro

동의했다. 그 이유는 무엇인가에 대한 참조가 필요한 훨씬 더 큰 응용 프로그램의 일부라고 생각합니다.
Josh

2

JsonSerializable 인터페이스를 사용 하여 json 구조를 구현 하고 어떤 식 으로든 중첩 배열 / 클래스를 사용할 수 있습니다. 클래스 는 get / set 작업이 빠르며 디버깅하기가 더 쉽습니다. Array 를 사용하면 선언이 필요하지 않습니다.

class Order implements \JsonSerializable{
    private $my_total;
    private $my_lineitems;

    public function getItems() { return $this->my_lineitems; }
    public function addItem(Product $p) { $this->my_lineitems[] = $p; }
    public function getTotal() { return $this->my_total; }

    public function jsonSerialize(){
        return [
            'total'=>$this->my_total,
            'products'=>$this->my_lineitems;
        ];
    }
}

class Product implements \JsonSerializable{
    private $name;
    private $price;

    public function jsonSerialize(){ 
        return [
            'name'=>$this->name, 
            'price'=>$this->price
        ];
    }
}

$order = new Order();
$order->addProduct(new Product('Product1', 15));
$order->addProduct(new Product('Product2', 35));
$order->addProduct(new Product('Product3', 42));
$json = json_encode(['order'=>$order, 'username'=>'Eughen']);
/*
json = {
    order: {
        total: 92, 
        products: [
            {
                name: 'Product1',
                price: 15
            }, 
            {
                name: 'Product2',
                price: 35
            },
            {
                name: 'Product3',
                price: 42
            }
        ]
    }, 
    username: 'Eughen'
}
*/

이 질문에 기존의 대답이 무엇이 추가 되었습니까?
esoterik

@esoterik 중첩. json_encode(['order'=>$o]);기존에 허용 된 답변이 비어 있습니다 : {"order":{}}. 물론 $o->forJSON()모든 레벨의 모든 객체에서 사용할 수는 있지만 실제로는 좋은 디자인은 아닙니다. 항상 다음과 같은 내용을 작성해야하기 때문입니다. $items_json = array(); foreach($this->my_lineitems as $item) $items_json[] = $item->forJSON();
El '
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.