ฉันต้องการเพิ่มเซกเมนต์ใหม่ (ด้วยชื่อเดียวกัน) ลงในอาเรย์การทำแผนที่ของฉัน แต่ใช้ elementId ที่แตกต่างกัน แต่ใช้วิธีเดียวกัน


14

ด้านล่างนี้คือ MapperInterface.php

ฉันกำลังพยายามหาวิธีเพิ่มคำสั่ง if-else ลงใน const อาร์เรย์การแมป บางอย่างเช่น:

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;
}

ฉันหวังว่ามันสมเหตุสมผล ไม่แน่ใจว่ามีวิธีที่ดีกว่าในการดำเนินการเกี่ยวกับเรื่องนี้หรือไม่ แต่ในที่สุดฉันก็ต้องการเซ็กเมนต์ "LIN" มากกว่า 1 อัน อาจเพิ่มฟังก์ชันใหม่และใช้เงื่อนไขนี้หรือไม่

คำตอบไฟล์ใหม่ ***

    <?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()];
    }

}

ดังนั้นคุณต้องการอาร์เรย์ const MAPPING เป็นแบบไดนามิกหรือไม่ คุณไม่สามารถทำเช่นนั้นกับ const คุณสามารถใช้ฟังก์ชั่นอื่นเพื่อรับอาเรย์นั้นและแก้ไขหากจำเป็น
dWinder

ฉันไม่รู้จริงๆว่าคุณกำลังพยายามทำอะไร คุณต้องการทำอะไรให้สำเร็จ
เตฟาน Vierkant

คำตอบ:


6

อย่างที่คุณเห็นที่นี่ - ตัวแปร const ไม่สามารถเปลี่ยนแปลงหรือถือตรรกะได้ ขอให้สังเกตว่าอินเทอร์เฟซไม่สามารถถือตรรกะเช่นกัน - ดังนั้นคุณไม่สามารถทำได้ในอินเทอร์เฟซ

ผมคิดว่าทางออกที่ดีสำหรับปัญหาของคุณคือการใช้ระดับนามธรรม ฉันจะเหมือนกับอินเทอร์เฟซของคุณ (คุณสามารถดูการอภิปรายเกี่ยวกับสิ่งที่แตกต่างกันได้ที่นี่แต่ฉันคิดว่ามันจะเหมือนกันสำหรับความต้องการของคุณ)

ฉันอยากจะแนะนำให้สร้างระดับนามธรรมเช่นนี้

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];
    }

}

ตอนนี้คุณสามารถประกาศวัตถุที่สืบทอดเป็น:

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

ตัวอย่างการใช้งานคือ:

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

โปรดทราบว่าดูเหมือนว่าตรรกะของคุณจะไม่เปลี่ยนแปลงดังนั้นฉันจึงใส่ตัวแปรใหม่และตั้งค่าในระหว่างการสร้าง หากคุณต้องการคุณสามารถถ่ายโอนข้อมูลและเพียงแค่ปรับเปลี่ยนค่าส่งคืนของgetProcessฟังก์ชัน - ใส่ตรรกะทั้งหมดที่นั่น

อีกทางเลือกหนึ่งคือการ$mapToProcessเผยแพร่สู่สาธารณะและเข้าถึงโดยตรง แต่ฉันเดาว่าการวางโปรแกรมที่ดีกว่าคือการใช้วิธีการทะเยอทะยาน

หวังว่าจะช่วย!


ฉันควรจะสามารถรวม / เพิ่มระดับนามธรรมทั้งหมดในไฟล์เดียวกันของฉันด้านล่างฟังก์ชั่นฟังก์ชั่นที่สาธารณะฟังก์ชั่นล่าสุดแผนที่ (อาร์เรย์ $ เซกเมนต์): OrderUpdateInterface; } ที่ นี่
Singleton

ดังนั้นตอนนี้ฉันสามารถแทนที่รหัสเดิมทั้งหมดและใช้คลาสนามธรรมนี้ได้หรือไม่ ฉันทำเครื่องหมายคำตอบว่าถูกต้องและเป็นประโยชน์กับเพื่อนมาก @dWinder
Singleton

ใช่คุณสามารถ. มีความแตกต่างระหว่างอินเทอร์เฟซและคลาสนามธรรม แต่สำหรับกรณีส่วนใหญ่มันทำหน้าที่เหมือนกัน (คุณสามารถอ่านเกี่ยวกับมันในลิงค์ที่จุดเริ่มต้นของการโพสต์)
dWinder

ฉันคิดว่าในตรรกะฉันยังต้องเพิ่มถูกต้องหรือไม่ อื่นถ้า ($ this-> mapToProcess ['LIN'] ['LIN04'] == 'VN') $ this-> mapToProcess ['LIN'] ['LIN05'] = 'processSku';
ซิงเกิลที่

1
คุณควรเพิ่มสิ่งนั้นด้วย ฉันใส่เพียงบางอย่างเป็นตัวอย่างของตรรกะที่ควร ฉันจะแก้ไขด้วยเช่นกันเพื่อให้ครอบคลุมรหัส
dWinder

5

คุณไม่สามารถเพิ่มคำสั่ง if-else ภายในคำจำกัดความคงที่ สิ่งที่คุณกำลังมองหาใกล้เคียงที่สุดน่าจะเป็นสิ่งนี้:

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,
];

จะส่งออก:

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

กล่าวอีกนัยหนึ่งคุณจะต้องแยกอาร์เรย์ของคุณออกเป็นค่าคงที่แยกกันแล้วทำตามเงื่อนไขทั้งหมดจากนั้นสร้างอาร์เรย์ MAPPING สุดท้ายจากค่าคงที่ที่เกิดขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.