I want to add a new segmentId (with the same name) into my mapping array but with a different elementId but same method

As you can see here - const variable cannot be change or hold logic. Notice that interface cannot hold logic as well - so you cannot do that in your interface.

I think the better solution for your issue is to use a abstract class. I will be the same as your interface (you can see the discussion about the different here but I think it will be the same for your needs).

I would recommend to create abstract class as this:

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

}

Now you can declare object that inherited as:

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

Example for use is:

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

Note that it seems that your logic is not changing so I put new variable and set it during the construct. If you want you can dump it and just modify the return value of the getProcess function - put all the logic there.

Another option is to make the $mapToProcess public and access it directly but I guess better programing is to use the getter method.

Hope that helps!


You can't add an if-else statement inside the constant definition. The closest to what you are looking for is probably this:

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

Will output:

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

In other words, you will need to break your array apart into separate constants, then do all conditional defines, then construct the final MAPPING array from resulting constant values.