我想在我的映射数组中添加一个新的 segmentId(同名),但 elementId 不同但方法相同
Posted
技术标签:
【中文标题】我想在我的映射数组中添加一个新的 segmentId(同名),但 elementId 不同但方法相同【英文标题】:I want to add a new segmentId (with the same name) into my mapping array but with a different elementId but same method 【发布时间】:2020-04-30 23:29:01 【问题描述】:下面是 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;
我希望这是有道理的。不确定是否有更好的方法来解决它,但最终我需要超过 1 个“LIN”segmentId。也许添加一个新功能并使用这个条件?
新文件答案***
<?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 数组是动态的吗?你不能用 const 做到这一点。您可以使用另一个函数来获取该数组并根据需要进行修改 我真的不知道你想做什么。你想达到什么目标? 【参考方案1】:如您所见here - const 变量不能更改或保持逻辑。 请注意,界面也不能保存逻辑 - 因此您不能在界面中执行此操作。
我认为解决您的问题的更好方法是使用abstract class。我将和你的界面一样(你可以看到关于不同here的讨论,但我认为它会满足你的需求)。
我建议这样创建抽象类:
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
公开并直接访问它,但我想更好的编程是使用getter 方法。
希望有帮助!
【讨论】:
我应该能够将整个抽象类集成/添加到我的同一个文件中,就在最后一个函数 public function map(array $segments): OrderUpdateInterface; 这里 那么现在我可以重写所有旧代码并使用这个抽象类了吗?我将答案标记为正确且对我的朋友非常有帮助。 @dWinder 是的,你可以。接口和抽象类之间存在差异,但在大多数情况下,它的作用相同(您可以在文章开头的链接中阅读它)。 我认为在逻辑上我仍然需要添加这个正确吗? else if ($this->mapToProcess['LIN']['LIN04'] == 'VN') $this->mapToProcess['LIN']['LIN05'] = 'processSku'; 您也应该添加它。我只是把其中的一些作为逻辑应该在哪里的例子。我也会用它进行编辑以使代码覆盖它【参考方案2】:您不能在常量定义中添加 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 数组。
【讨论】:
以上是关于我想在我的映射数组中添加一个新的 segmentId(同名),但 elementId 不同但方法相同的主要内容,如果未能解决你的问题,请参考以下文章