PHP: ne zaman diziler kullanılır ve çoğunlukla veri depolayan kod yapıları için nesneler ne zaman kullanılır?


37

PHP, diziler gibi nesne olmayan veri türlerinin kullanılmasına ve döndürülmesine izin veren karma bir paradigma dilidir. Belirli bir durumda hangi programlama yapısının kullanılacağına karar verirken, dizilerin veya nesnelerin seçilmesiyle ilgili bazı yönergeleri netleştirmeye çalışıyorum.

Bu, PHP dili yapıları kullanarak verileri kodlamanın yolları hakkında ve bir yolun veri aktarma amacıyla (örneğin Servis Odaklı Mimari veya web servisleri) başka bir yoldan daha fazla seçilmesi gerektiğiyle ilgili bir sorudur.

Örnek

{Cost, name, part_number, item_count} 'dan oluşan bir öğe türünüz olduğunu varsayalım. Programınız, her bir öğe türünü tutmak için dış kap olarak bir dizi kullanmaya karar verdiğiniz, bu tür birkaç öğe türünün görüntülenmesini gerektirir. [Ayrıca PHP var kullanabilirsiniz ArrayObjectOO paradigma için değil, benim sorum ilgili değil bu (dış) diziden]. Sorum, madde tipi verilerinin nasıl kodlanacağı ve hangi paradigmanın kullanılacağı ile ilgili. PHP kullanmanıza izin verir PHP Native Arraysveya PHP Objects.

Bu gibi verileri burada iki şekilde kodlayabilirim:

//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) {..}
}

Ne düşünüyorum

Dizi kodlaması hafif ve daha JSON'a hazır, ancak karışıklık yaratması daha kolay olabilir. İlişkisel dizi tuşlarından birini yanlış yazdığınızda, yakalanması daha zor bir hata olabilir. Ancak bir hevesle değiştirmek de daha kolaydır. item_countArtık depolamak istemediğimi söyleyin item_count, dizideki tüm örnekleri kolayca kaldırmak ve ardından onu kullanan diğer işlevleri güncellemek için herhangi bir metin işleme yazılımını kullanabilirim. Daha sıkıcı bir süreç olabilir, ama basittir.

Nesneye yönelik kodlama IDE ve PHP dil olanaklarını çağırır ve önceden herhangi bir hatayı yakalamayı kolaylaştırır, ancak ilk başta programlamak ve kodlamak daha zordur. Daha sert diyorum, çünkü nesneleriniz hakkında biraz düşünmek zorundasınız, ileriyi düşünün ve OO kodlaması dizi yapılarını yazmaktan biraz daha yüksek bilişsel yük alır. Bununla birlikte, bir kez kodlandıktan sonra, bazı değişikliklerin uygulanması, belki de bir anlamda, item_countörneğin daha az kod satırının değiştirilmesini gerektirecek şekilde daha kolay olabilir. Ancak, değişikliklerin kendileri, daha yüksek OO tesisleri söz konusu olduğundan, dizi yöntemine kıyasla daha yüksek bir bilişsel yük gerektirebilir.

Soru

Bazı durumlarda, verilerde manipülasyon yapmak zorunda kalacağım durumlar gibi açıktır. Ancak bazı durumlarda, yalnızca "Item Type" verisi satırlarını depolamam gereken bazı durumlarda, dizileri kullanıp kullanmayacağınıza veya nesneler oluşturup oluşturmayacağınıza karar verirken, üzerine eğilmek için net yönergelerim veya düşüncelerim yok. Görünüşe bakılırsa yazı tura atıp bir tane seçebilirim. Buradaki durum bu mu?


2
Bir nesneye bir dizi döküm yoluyla hafif bir nesne alabilirsiniz Not: (object)['foo'=>'bar']. Elde edilen değer sınıfa sahiptir StdClass, JSON bütünüyle tarafından kodlanacaktır json_encode()ve özellikler, dizi indeksleri kadar kolay bir şekilde yeniden adlandırılabilir (bu, bir değişken aracılığıyla dolaylı olarak erişildiğinde her zaman bu kadar kolay değildir). Ancak, bu değerler üzerinde farklı işlemler var; örneğin, dizi sendikalarınız olduğu için nesne sendikalarınız yoktur ve array_*()işlevleri doğrudan kullanamazsınız .
outis

3
: 3 seçeneğiniz bulunuyor 1: array , 2: User-defined Class , 3: stdClass . Hız açısından performans karşılaştırırken arrayve bir User-defined class(sizin gibi ItemType) hemen hemen aynıdır , ancak tanımlanmış classes arrays kullanmaktan daha az bellek kullanma eğilimindedir . stdClassÖte yandan, üç seçeneğin en yavaş olanıdır ve aynı zamanda en çok belleği kullanır.
Andy,

Yanıtlar:


33

Bunu görme biçimim, daha sonra verilerle ne yapmak istediğinize bağlı. Birkaç basit çeke dayanarak, iki veri yapısından hangisinin sizin için daha iyi olduğunu belirleyebilirsiniz:

  1. Bu verinin kendisiyle ilişkili herhangi bir mantığı var mı?

    Örneğin, $pricebir tam sayıdaki kuruş olarak depolanır, bu yüzden 9.99 $ 'lık fiyatı olan bir üründe olur price = 999ve olmaz price = 9.99? (Muhtemelen, evet) Veya partNumberbelirli bir regex ile eşleşmesi mi gerekiyor? Veya itemCountenvanterinizde mevcut olup olmadığını kolayca kontrol edebilmeniz mi gerekiyor ? Bu işlevleri gelecekte yapmanız gerekecek mi? Öyleyse, en iyi bahis, şimdi bir sınıf oluşturmaktır. Eğer veri yapısı içine inşa kısıtları ve mantık tanımlayabileceğinizi Bu araçlar: private $myPriceayarlandığında 999ancak $item->getPriceString()iadeler $9.99ve $item->inStock()uygulamanızda çağrılacak mevcuttur.

  2. Bu verileri birden fazla PHP işlevine aktarıyor musunuz?

    Eğer öyleyse, o zaman bir sınıf kullanın. Üzerinde bazı dönüşümler yapmak için bir kez bu verileri oluşturuyorsanız veya yalnızca başka bir uygulamaya JSON verileri olarak göndermek için (JavaScript veya başka şekilde), bir dizi daha kolay bir seçimdir. Ancak, bu verileri parametre olarak kabul eden ikiden fazla PHP işleviniz varsa, bir sınıf kullanın. Başka bir şey yoksa, bu sizin tanımlamanıza izin verir someFunction(MyProductClass $product) {ve fonksiyonlarınızın girdi olarak ne beklediğini çok net bir şekilde gösterir. Kodunuzu ölçeklendirdiğinizde ve daha fazla işleve sahip olduğunuzda, her işlevin ne tür verileri kabul ettiğini bilmek çok daha kolay olacaktır. Görmek someFunction($someArrayData) {neredeyse net değil. Ayrıca, bu, tür tutarlılığını zorlamaz ve dizinin esnek yapısının daha sonra gelişim ağrısına neden olabileceği anlamına gelir.

  3. Bir kütüphane mi yoksa paylaşımlı kod tabanı mı inşa ediyorsunuz?

    Eğer öyleyse, bir sınıf kullanın! Kütüphanenizi kullanan yeni bir geliştiriciyi veya şirkette daha önce kodunuzu hiç kullanmayan başka bir geliştiriciyi düşünün. Bir sınıf tanımına bakmaları ve o sınıfın ne yaptığını anlamaları veya kütüphanenizde belirli bir sınıfın nesnelerini kabul eden bir takım işlevleri görmeleri, bir yapıda ne tür bir yapı oluşturmaları gerektiğini tahmin etmekten çok daha kolay olacaktır. dizilerin sayısı. Ayrıca, # 1 ile veri tutarlılığı sorunlarına da değiniyor: bir kütüphane veya paylaşılan bir kod tabanı geliştiriyorsanız, kullanıcılarınıza iyi davranın: onlara veri tutarlılığını zorlayan sınıflar verin ve verilerinizin tasarımında hata yapmalarını engelleyin .

  4. Bu bir uygulamanın küçük bir parçası mı yoksa sadece veri dönüşümü mü? Yukarıdakilerin hiçbirine uymuyor musunuz?

    Bir sınıf çok fazla olabilir; Size uygunsa bir dizi kullanın ve daha kolay bulursunuz. Yukarıda belirtildiği gibi, yalnızca JSON veya YAML veya XML olarak göndermek üzere yapılandırılmış veri oluşturuyorsanız veya gerekmedikçe bir sınıfla uğraşmayın. Daha büyük bir uygulamada küçük bir modül yazıyorsanız ve kodunuzla arabirim kurmak için başka bir modül / ekip gerekmez, belki bir dizi yeterlidir.

Sonuçta, kodunuzun ölçeklendirme ihtiyaçlarını göz önünde bulundurun ve yapılandırılmış bir dizinin hızlı bir düzeltme olabileceğini düşünün, ancak bir sınıf çok daha esnek ve ölçeklenebilir bir çözümdür.

Ayrıca, aşağıdakileri göz önünde bulundurun: bir sınıfınız varsa ve json_data()JSON'a yazdırmak istiyorsanız, sınıfınızdaki sınıfın içindeki verilerin JSON-ifiable dizisini döndüren bir yöntem tanımlayamazsınız . Bu benim PHP uygulamalarımda sınıf verilerini JSON olarak göndermem gereken şeydi. Örnek olarak:

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());

Öğelerini değiştirmiyorsunuz my_lineitems, bu nedenle bunları referans olarak almak gereksizdir, çünkü değişkenler nesnenin kendisinde değil yalnızca nesnede bir tanımlayıcı tutar. php.net/manual/en/language.oop5.references.php
Chinoto Vokro

Kabul. Bence, bir sebep için referans gerektiren çok daha büyük bir uygulama parçacığıydı ...
Josh

2

JsonSerializable arabirimini kullanarak json yapısını uygulayabilir ve herhangi bir şekilde iç içe dizi / sınıfı kullanabilirsiniz. Sınıf alma / ayarlama işlemlerinde daha hızlı ve hata ayıklamak daha kolaydır. Array ile bildirime ihtiyacınız yoktur.

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'
}
*/

Bu soru var olan kabul edilmiş cevabın ne olduğunu ekler?
esoterik

@esoterik iç içe geçme. json_encode(['order'=>$o]);var olan kabul edilmiş cevap boş {"order":{}}. Tabii ki kullanabilirsiniz: $o->forJSON()her seviyedeki her nesnede her zaman, ama gerçekten iyi bir tasarım değil. Çünkü her zaman şöyle bir şey yazmanız gerekir: $items_json = array(); foreach($this->my_lineitems as $item) $items_json[] = $item->forJSON();
El '
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.