Eşleme dizime ancak farklı bir elementId ama aynı yöntemle yeni bir segmentId (aynı ada sahip) eklemek istiyorum


14

MapperInterface.php aşağıdadır

Ben const içine if-else deyimi eklemek nasıl anlamaya çalışıyorum. eşleme dizisi. Böyle bir şey:

if (LIN02 == VN”) 
o   Treat LIN03 as the SKU
·         else if (LIN04 == VN”) 
o   Treat LIN05 as the SKU

<?php

declare(strict_types=1);

namespace Direct\OrderUpdate\Api;

use Direct\OrderUpdate\Api\OrderUpdateInterface;

/**
 * Interface MapperInterface
 * Translates parsed edi file data to a \Direct\OrderUpdate\Api\OrderUpdateInterface
 * @package Direct\OrderUpdate\Api
 */
interface MapperInterface
{
    /**
     * Mapping array formatted as MAPPING[segemntId][elemntId] => methodNameToProcessTheValueOfElement
     * @var array
     */
    const MAPPING = [
        'DTM' => ['DTM02' => 'processCreatedAt'],   // shipment.created_at
        'PRF' => ['PRF01' => 'processIncrementId'], // order.increment_id
        'LIN' => ['LIN05' => 'processSku'],         // shipment.items.sku
        'SN1' => ['SN102' => 'processQty'],         // shipment.items.qty
        'REF' => ['REF02' => 'processTrack']        // shipment.tracks.track_number, shipment.tracks.carrier_code
    ];

    /**
     * Mapping for carrier codes
     * @var array
     */
    const CARRIER_CODES_MAPPING = ['FED' => 'fedex'];

    /**
     * @return array
     */
    public function getMapping(): array;

    /**
     * @param array $segments
     * @return OrderUpdateInterface
     */
    public function map(array $segments): OrderUpdateInterface;
}

Umarım bu mantıklıdır. Bu konuda daha iyi bir yol olup olmadığından emin değilim ama sonuçta fazla 1 "LIN" segmentId gerekir. Belki yeni bir işlev ekleyin ve bu koşulu kullanın?

YENİ DOSYA CEVAP ***

    <?php

    declare(strict_types=1);

    namespace Direct\OrderUpdate\Api;

    use Direct\OrderUpdate\Api\OrderUpdateInterface;

    /**
     * Abstract Mapper
     * Translates parsed edi file data to a \Direct\OrderUpdate\Api\OrderUpdateInterface
     * @package Direct\OrderUpdate\Api
     */

    abstract class AbstractMapper{
    // Here we add all the methods from our interface as abstract
    public abstract function getMapping(): array;
    public abstract function map(array $segments): OrderUpdateInterface;

    // The const here will behave the same as in the interface
    const CARRIER_CODES_MAPPING = ['FED' => 'fedex'];

    // We will set our default mapping - notice these are private to disable access from outside
    private const MAPPING = ['LIN' => [
    'LIN02' => 'VN',
    'LIN01' => 'processSku'],
    'PRF' => ['PRF01' => 'processIncrementId'],
    'DTM' => ['DTM02' => 'processCreatedAt'],
    'SN1' => ['SN102' => 'processQty'],
    'REF' => ['REF02' => 'processTrack']];

    private $mapToProcess = [];

    // When we initiate this class we modify our $mapping member according to our new logic
    function __construct() {
    $this->mapToProcess = self::MAPPING; // init as
    if ($this->mapToProcess['LIN']['LIN02'] == 'VN')
    $this->mapToProcess['LIN']['LIN03'] = 'processSku';
    else if ($this->mapToProcess['LIN']['LIN04'] == 'VN')
        $this->mapToProcess['LIN']['LIN05'] = 'processSku';
    }

    // We use this method to get our process and don't directly use the map
    public function getProcess($segemntId, $elemntId) {
    return $this->mapToProcess[$segemntId][$elemntId];
    }

   }

class Obj extends AbstractMapper {
    // notice that as interface it need to implement all the abstract methods
    public function getMapping() : array {
        return [$this->getMapping()];
    }
    public function map() : array {
        return [$this->map()];
    }

}

class Obj extends AbstractMapper {
    // notice that as interface it need to implement all the abstract methods
    public function getMapping() : array {
        return [$this->getMapping()];
    }
    public function map() : array {
        return [$this->map()];
    }

}

MAPPING const dizisinin dinamik olmasını mı istiyorsunuz? bunu const ile yapamazsınız. Bu diziyi almak ve gerekirse değiştirmek için başka bir işlev kullanabilirsiniz
dWinder

Gerçekten ne yapmaya çalıştığını bilmiyorum. Ne elde etmek istiyorsun?
Stephan Vierkant

Yanıtlar:


6

Gördüğünüz gibi burada - const değişken değişimi veya muhafaza mantık olamaz . Arayüzün mantığa da sahip olamayacağına dikkat edin - böylece arayüzünüzde bunu yapamazsınız.

Sorununuz için en iyi çözümün soyut bir sınıf kullanmak olduğunu düşünüyorum . Arayüzünüzle aynı olacağım ( burada farklı olanla ilgili tartışmayı görebilirsiniz, ancak ihtiyaçlarınız için aynı olacağını düşünüyorum).

Bu şekilde soyut bir sınıf yaratmanızı tavsiye ederim:

abstract class AbstractMapper{
    // here add all the method from your interface as abstract
    public abstract function getMapping(): array;
    public abstract function map(array $segments): OrderUpdateInterface;

    // the const here will behave the same as in the interface
    const CARRIER_CODES_MAPPING = ['FED' => 'fedex'];

    // set your default mapping - notice those are private to disable access from outside
    private const MAPPING = ['LIN' => [
                                'LIN02' => 'NV', 
                                'LIN01' => 'processSku'], 
                             'PRF' => [
                                'PRF01' => 'processIncrementId']];
    private $mapToProcess = [];


    // when initiate this class modify your $mapping member according your logic
    function __construct() {
        $this->mapToProcess = self::MAPPING; // init as 
        if ($this->mapToProcess['LIN']['LIN02'] == 'NV')
            $this->mapToProcess['LIN']['LIN03'] = 'processSku';
        else if ($this->mapToProcess['LIN']['LIN04'] == 'NV')
            $this->mapToProcess['LIN']['LIN05'] = 'processSku';
     }

    // use method to get your process and don't use directly the map
    public function getProcess($segemntId, $elemntId) {
        return $this->mapToProcess[$segemntId][$elemntId];
    }

}

Artık devralınan nesneyi şu şekilde bildirebilirsiniz:

class Obj extends AbstractMapper {
    // notice that as interface it need to implement all the abstract methods
    public function getMapping() : array {
        return [];
    }
}

Kullanım örneği:

$obj  = New Obj();
print_r($obj->getProcess('LIN', 'LIN01'));

Mantık değişmiyor gibi görünüyor, bu yüzden yeni değişken koymak ve yapı sırasında ayarlayın. İsterseniz onu dökebilir ve sadece getProcessişlevin dönüş değerini değiştirebilirsiniz - tüm mantığı oraya koyun.

Başka bir seçenek $mapToProcesshalk yapmak ve doğrudan erişmek için ama sanırım daha iyi programlama getter yöntemini kullanmaktır.

Umarım yardımcı olur!


Entegre edebilmeliyim / tüm soyut sınıfı, son işlev ortak işlevi haritasının (dizi $ segmentleri) hemen altındaki aynı dosyama ekleyebilmeliyim: OrderUpdateInterface; } HERE
Singleton

Şimdi tüm eski kodu geçersiz kılabilir ve bu soyut sınıfı kullanabilir miyim? Cevabı doğru ve çok yardımcı olarak işaretledim arkadaşım. @dWinder
Singleton

Evet yapabilirsin. Arayüz ve soyut sınıf arasında fark vardır, ancak davanın çoğu için aynı şekilde hareket eder (yazının başındaki bağlantıda bunu okuyabilirsiniz).
dWinder

Sanırım mantığa hala bunu doğru şekilde eklemem gerekiyor mu? else if ($ this-> mapToProcess ['LIN'] ['LIN04'] == 'VN') $ this-> mapToProcess ['LIN'] ['LIN05'] = 'processSku';
Singleton

1
Bunu da eklemelisin. Bazılarını mantığın nerede olması gerektiğine örnek olarak koydum. Kodun kapsanması için de bununla birlikte düzenleme yapacağım
dWinder

5

Sabit tanım içine if-else deyimi ekleyemezsiniz. Aradığınız şeye en yakın olan muhtemelen:

const A = 1;
const B = 2;

// Value of C is somewhat "more dynamic" and depends on values of other constants
const C = self::A == 1 ? self::A + self::B : 0;

// MAPPING array inherits "more dynamic" properties of C
const MAPPING = [
    self::A,
    self::B,
    self::C,
];

Çıktı olacak:

0 => 1
1 => 2
2 => 3

Başka bir deyişle, dizinizi ayrı sabitlere ayırmanız, ardından tüm koşullu tanımlamaları yapmanız ve ardından nihai MAPPING dizisini sonuçta elde edilen sabit değerlerden yapılandırmanız gerekir.

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.