PHPでやってみよう!テストだけじゃない、デシジョンテーブル(決定表)実装の勘所

20.8K Views

July 18, 25

スライド概要

https://fortee.jp/phpcon-kansai2025/proposal/44d7c3a3-1137-482a-9f44-33c0371dbfb9

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

PHP PHP 2025 Jul 19, 2025. v0.0.6 @katzumi( ) Press Space for next page

2.

katzumi LITALICO katzchum k2tzumi katzumi

4.

if if, switch Enum

5.

Condition Yes/No Action True/False

6.

1 2 3 4 5 6 7 8 9 Y Y Y Y N N N N N N N N N Y Y Y Y N N N N N N N N N Y 3 Y Y N N Y Y N N - 500 Y N Y N Y N Y N - X - - - - - - - - - X X - X - - - -

7.

1 2 3 4 5 6 7 8 9 Y Y Y Y N N N N N N N N N Y Y Y Y N N N N N N N N N Y 3 Y Y N N Y Y N N - 500 Y N Y N Y N Y N - X - - - - - - - - - X X - X - - - -

8.

1 2 3 4 5 6 7 8 9 Y Y Y Y N N N N N N N N N Y Y Y Y N N N N N N N N N Y 3 Y Y N N Y Y N N - 500 Y N Y N Y N Y N - X - - - - - - - - - X X - X - - - -

9.

1 2 3 4 5 6 7 8 9 Y Y Y Y N N N N N N N N N Y Y Y Y N N N N N N N N N Y 3 Y Y N N Y Y N N - 500 Y N Y N Y N Y N - X - - - - - - - - - X X - X - - - -

10.

1 2 3 4 5 6 7 8 9 Y Y Y Y N N N N N N N N N Y Y Y Y N N N N N N N N N Y 3 Y Y N N Y Y N N - 500 Y N Y N Y N Y N - X - - - - - - - - - X X - X - - - -

11.

1 2 3 4 5 6 7 8 9 Y Y Y Y N N N N N N N N N Y Y Y Y N N N N N N N N N Y 3 Y Y N N Y Y N N - 500 Y N Y N Y N Y N - X - - - - - - - - - X X - X - - - -

18.

1.5K 3 1

20.

https://www.mhlw.go.jp/content/12200000/001205331.pdf#page=2

25.

if switch

26.

[1] [2] [3] 1. (Essential) 2. (Accidental) 3.

30.

PHP

31.

Enum Enum Enum : EmploymentStatus:: , EmploymentStatus:: Enum : AnnualIncome:: , AnnualIncome:: - , AnnualIncome::

32.

Enum Enum ( [ EmploymentStatus:: , Tenure:: , AnnualIncome:: Enum 1 2 3 4 5 6 7 8 9 10 11 12 13 enum AnnualIncome { case ; case case ; ; public static function convert(int $value) : self { return match(true) { $value >= 500 => self:: , $value >= 300 => self:: , default => self:: }; 3 500 ] )

33.

Enum Enum ( [ EmploymentStatus:: , Tenure:: , AnnualIncome:: Enum 1 2 3 4 5 6 7 8 9 10 11 12 13 enum AnnualIncome { case ; case case ; ; public static function convert(int $value) : self { return match(true) { $value >= 500 => self:: , $value >= 300 => self:: , default => self:: }; 3 500 ] )

34.

Enum Enum ( [ EmploymentStatus:: , Tenure:: , AnnualIncome:: Enum 1 2 3 4 5 6 7 8 9 10 11 12 13 enum AnnualIncome { case ; case case ; ; public static function convert(int $value) : self { return match(true) { $value >= 500 => self:: , $value >= 300 => self:: , default => self:: }; 3 500 ] )

35.

Enum Enum ( [ EmploymentStatus:: , Tenure:: , AnnualIncome:: Enum 1 2 3 4 5 6 7 8 9 10 11 12 13 enum AnnualIncome { case ; case case ; ; public static function convert(int $value) : self { return match(true) { $value >= 500 => self:: , $value >= 300 => self:: , default => self:: }; 3 500 ] )

36.

Generator Generator yield yield from Generator

37.
[beta]
Generator
1
2
3
4
5

/** @return Generator<array{ 0: string, 1: list<Condition>}> 0:
, 1:
public function generateRules(): Generator
{
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::

6
7
8
9

yield from generateDisapprovalRules();

if ($reviewIn >= '202507') //
2025 7
yield ['
', [EmploymentStatus::

, Tenure::

}
private function generateDisapprovalRules(): Generator

12
13
14

{
foreach (Tenure::cases() as $t)
foreach (AnnualIncome::cases() as $i)
yield ['
}

', [EmploymentStatus::

-

]];
]];

//

10
11

15
16

*/

, $t, $i]];

, AnnualIncome::

]];

38.
[beta]
Generator
1
2
3
4
5

/** @return Generator<array{ 0: string, 1: list<Condition>}> 0:
, 1:
public function generateRules(): Generator
{
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::

6
7
8
9

yield from generateDisapprovalRules();

if ($reviewIn >= '202507') //
2025 7
yield ['
', [EmploymentStatus::

, Tenure::

}
private function generateDisapprovalRules(): Generator

12
13
14

{
foreach (Tenure::cases() as $t)
foreach (AnnualIncome::cases() as $i)
yield ['
}

', [EmploymentStatus::

-

]];
]];

//

10
11

15
16

*/

, $t, $i]];

, AnnualIncome::

]];

39.
[beta]
Generator
1
2
3
4
5

/** @return Generator<array{ 0: string, 1: list<Condition>}> 0:
, 1:
public function generateRules(): Generator
{
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::

6
7
8
9

yield from generateDisapprovalRules();

if ($reviewIn >= '202507') //
2025 7
yield ['
', [EmploymentStatus::

, Tenure::

}
private function generateDisapprovalRules(): Generator

12
13
14

{
foreach (Tenure::cases() as $t)
foreach (AnnualIncome::cases() as $i)
yield ['
}

', [EmploymentStatus::

-

]];
]];

//

10
11

15
16

*/

, $t, $i]];

, AnnualIncome::

]];

40.
[beta]
Generator
1
2
3
4
5

/** @return Generator<array{ 0: string, 1: list<Condition>}> 0:
, 1:
public function generateRules(): Generator
{
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::

6
7
8
9

yield from generateDisapprovalRules();

if ($reviewIn >= '202507') //
2025 7
yield ['
', [EmploymentStatus::

, Tenure::

}
private function generateDisapprovalRules(): Generator

12
13
14

{
foreach (Tenure::cases() as $t)
foreach (AnnualIncome::cases() as $i)
yield ['
}

', [EmploymentStatus::

-

]];
]];

//

10
11

15
16

*/

, $t, $i]];

, AnnualIncome::

]];

41.
[beta]
Generator
1
2
3
4
5

/** @return Generator<array{ 0: string, 1: list<Condition>}> 0:
, 1:
public function generateRules(): Generator
{
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::
yield ['
', [EmploymentStatus::
, Tenure::
, AnnualIncome::

6
7
8
9

yield from generateDisapprovalRules();

if ($reviewIn >= '202507') //
2025 7
yield ['
', [EmploymentStatus::

, Tenure::

}
private function generateDisapprovalRules(): Generator

12
13
14

{
foreach (Tenure::cases() as $t)
foreach (AnnualIncome::cases() as $i)
yield ['
}

', [EmploymentStatus::

-

]];
]];

//

10
11

15
16

*/

, $t, $i]];

, AnnualIncome::

]];

42.
[beta]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

public function createRuleInstances(): Generator
{
foreach ($this->generateRules() as [$action, $conditions]) {
yield new Rule($action, $conditions);
}
}
public function getMatchAction(array $facts): ?Action
{
foreach ($this->createRuleInstances() as $ruleInstance) {
if ($ruleInstance->canMatch($facts))
return $ruleInstance->makeAction(); //
}
return null; //
}

43.
[beta]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

public function createRuleInstances(): Generator
{
foreach ($this->generateRules() as [$action, $conditions]) {
yield new Rule($action, $conditions);
}
}
public function getMatchAction(array $facts): ?Action
{
foreach ($this->createRuleInstances() as $ruleInstance) {
if ($ruleInstance->canMatch($facts))
return $ruleInstance->makeAction(); //
}
return null; //
}

44.
[beta]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

public function createRuleInstances(): Generator
{
foreach ($this->generateRules() as [$action, $conditions]) {
yield new Rule($action, $conditions);
}
}
public function getMatchAction(array $facts): ?Action
{
foreach ($this->createRuleInstances() as $ruleInstance) {
if ($ruleInstance->canMatch($facts))
return $ruleInstance->makeAction(); //
}
return null; //
}

45.
[beta]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

public function createRuleInstances(): Generator
{
foreach ($this->generateRules() as [$action, $conditions]) {
yield new Rule($action, $conditions);
}
}
public function getMatchAction(array $facts): ?Action
{
foreach ($this->createRuleInstances() as $ruleInstance) {
if ($ruleInstance->canMatch($facts))
return $ruleInstance->makeAction(); //
}
return null; //
}

46.
[beta]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

public function createRuleInstances(): Generator
{
foreach ($this->generateRules() as [$action, $conditions]) {
yield new Rule($action, $conditions);
}
}
public function getMatchAction(array $facts): ?Action
{
foreach ($this->createRuleInstances() as $ruleInstance) {
if ($ruleInstance->canMatch($facts))
return $ruleInstance->makeAction(); //
}
return null; //
}

47.
[beta]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

public function createRuleInstances(): Generator
{
foreach ($this->generateRules() as [$action, $conditions]) {
yield new Rule($action, $conditions);
}
}
public function getMatchAction(array $facts): ?Action
{
foreach ($this->createRuleInstances() as $ruleInstance) {
if ($ruleInstance->canMatch($facts))
return $ruleInstance->makeAction(); //
}
return null; //
}

48.

1 2 3 interface Condition {} enum AnnualIncome implements Condition { // .. snip .. 4 5 6 } /** @param list<Condition> $facts */ public function getMatchAction(array $facts): ?Action

49.

1 2 3 interface Condition {} enum AnnualIncome implements Condition { // .. snip .. 4 5 6 } /** @param list<Condition> $facts */ public function getMatchAction(array $facts): ?Action

50.

1 2 3 interface Condition {} enum AnnualIncome implements Condition { // .. snip .. 4 5 6 } /** @param list<Condition> $facts */ public function getMatchAction(array $facts): ?Action

51.

1 2 3 interface Condition {} enum AnnualIncome implements Condition { // .. snip .. 4 5 6 } /** @param list<Condition> $facts */ public function getMatchAction(array $facts): ?Action

52.

1 2 3 interface Condition {} enum AnnualIncome implements Condition { // .. snip .. 4 5 6 } /** @param list<Condition> $facts */ public function getMatchAction(array $facts): ?Action

53.

1 2 3 interface Condition {} enum AnnualIncome implements Condition { // .. snip .. 4 5 6 } /** @param list<Condition> $facts */ public function getMatchAction(array $facts): ?Action :

54.

1 2 3 interface Condition {} enum AnnualIncome implements Condition { // .. snip .. 4 5 6 } /** @param list<Condition> $facts */ public function getMatchAction(array $facts): ?Action : :

55.
[beta]
1
1
2
3
4
5

interface DiscountCondition extends Condition
{
public function getDiscountRate(): float;
}
enum MemberRank implements DiscountCondition

6
7
8
9

{
case
case
case

10
11

public function getDiscountRate(): float

12
13
14
15
16
17
18
19

A;
B;
C;

{
return match($this) { //
self::
A => 0.3,
self::
self::
};
}
}

B => 0.15,
C => 0.0

DiscountCondition

56.
[beta]
1
1
2
3
4
5

interface DiscountCondition extends Condition
{
public function getDiscountRate(): float;
}
enum MemberRank implements DiscountCondition

6
7
8
9

{
case
case
case

10
11

public function getDiscountRate(): float

12
13
14
15
16
17
18
19

A;
B;
C;

{
return match($this) { //
self::
A => 0.3,
self::
self::
};
}
}

B => 0.15,
C => 0.0

DiscountCondition

57.
[beta]
1
1
2
3
4
5

interface DiscountCondition extends Condition
{
public function getDiscountRate(): float;
}
enum MemberRank implements DiscountCondition

6
7
8
9

{
case
case
case

10
11

public function getDiscountRate(): float

12
13
14
15
16
17
18
19

A;
B;
C;

{
return match($this) { //
self::
A => 0.3,
self::
self::
};
}
}

B => 0.15,
C => 0.0

DiscountCondition

58.
[beta]
1
1
2
3
4
5

interface DiscountCondition extends Condition
{
public function getDiscountRate(): float;
}
enum MemberRank implements DiscountCondition

6
7
8
9

{
case
case
case

10
11

public function getDiscountRate(): float

12
13
14
15
16
17
18
19

A;
B;
C;

{
return match($this) { //
self::
A => 0.3,
self::
self::
};
}
}

B => 0.15,
C => 0.0

DiscountCondition

59.
[beta]
1
1
2
3
4
5

interface DiscountCondition extends Condition
{
public function getDiscountRate(): float;
}
enum MemberRank implements DiscountCondition

6
7
8
9

{
case
case
case

10
11

public function getDiscountRate(): float

12
13
14
15
16
17
18
19

A;
B;
C;

{
return match($this) { //
self::
A => 0.3,
self::
self::
};
}
}

B => 0.15,
C => 0.0

DiscountCondition

60.

1 2 3 4 5 6 7 8 9 10 interface RepeatableCondition extends Condition { public function getCount(): int; } enum RepeatCount: int implements RepeatableCondition { case = 0; case = 1; case = 2; 11 public function getCount(): int 12 13 14 { 15 16 } // return $this->value; }

61.

1 2 3 4 5 6 7 8 9 10 interface RepeatableCondition extends Condition { public function getCount(): int; } enum RepeatCount: int implements RepeatableCondition { case = 0; case = 1; case = 2; 11 public function getCount(): int 12 13 14 { 15 16 } // return $this->value; }

62.

1 2 3 4 5 6 7 8 9 10 interface RepeatableCondition extends Condition { public function getCount(): int; } enum RepeatCount: int implements RepeatableCondition { case = 0; case = 1; case = 2; 11 public function getCount(): int 12 13 14 { 15 16 } // return $this->value; }

63.

1 2 3 4 5 6 7 8 9 10 interface RepeatableCondition extends Condition { public function getCount(): int; } enum RepeatCount: int implements RepeatableCondition { case = 0; case = 1; case = 2; 11 public function getCount(): int 12 13 14 { 15 16 } // return $this->value; }

64.

Enum SRP I/O

65.

Enum <<interface>> Condition implements extends <<enum>> <<enum>> <<interface>> EmploymentStatus AnnualIncome DiscountCondition + getDiscountRate(): float // - + convert(int): self uses uses uses InputData ConditionConverter + employmentType: string DecisionTable + convert(data: InputData): + yearsOfService: int list<Condition> + annualIncome: int // // RuleEvaluator + generateRules(): Generator // →Enum // + createRuleInstances(): Generator + getMatchAction(facts: list<Condition>): ?Action Generator // // // // Enum : - DiscountCondition: - RepeatableCondition: // // creates returns Rule Action - action: string + execute(): void - conditions: list<Condition> // + canMatch(facts): bool 4 1. : I/O 2. : →Enum 3. : 4. :

66.

Enum Enum Enum Enum = cases

68.

if switch

70.

PICT

71.

JISX0125:1986 kikakurui.com PHP5.5 PHP5.5 3 SlideShare media.shaho.co.jp (Generator) http://www.slideshare.net/kwatch/php55 - Download as a PDF, PPTX …