[php] 매핑 배열에 같은 이름의 새 segmentId를 추가하고 싶지만 다른 elementId이지만 동일한 메소드를 사용하고 싶습니다.
아래는 MapperInterface.php입니다
const에 if-else 문을 추가하는 방법을 알아 내려고합니다. 매핑 배열. 다음과 같은 것 :
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”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()];
}
}
답변
당신이 볼 수 있듯이 여기 – 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
대중 을 만들고 직접 액세스하는 것이지만 더 나은 프로그래밍은 getter 메소드를 사용하는 것입니다.
희망이 도움이됩니다!
답변
상수 정의 안에 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 배열을 구성해야합니다.