search

Home  >  Q&A  >  body text

Use polymorphism to return multiple results and use multiple behaviors at the same time

<p>I'm using Laravel 9 and I have a request that contains: </p> <ul> <li>Parameter named SEASON, value can be <code>array</code> or null So the <code>SEASON</code> parameter can be <code>array</code> or <code>null</code></li> <li>The parameter named EXPIRY can be either <code>array</code> or <code>null</code></li> </ul> <p>I have two classes, one for the <code>SEASON</code> functionality and another for <code>EXPIRY</code>, both from the <code>Repository</code> Extension. Both have a method called <code>execute</code> which returns an array</p> <pre class="brush:php;toolbar:false;">abstract class Repository { abstract public function execute(): array; } class Expiry extends Repository { public function execute() { return ['The Request contains Expiry Parameter, and seasonal behaviors is done']; } } class Season extends Repository { public function execute() { return ['The Request contain Season Parameter, and expiry behaviors is done']; } }</pre> <p>If my request contains SEASON, I want to call the execute method of the Season class, or if my request contains Expiry, I want to call the execute method of expiry. Or call them and merge the execution returns into an array so I can get the results. </p> <pre class="brush:php;toolbar:false;">['The Request contain Expiry Parameter, and seasonal behaviors is done', 'The Request contain Expiry Parameter, and expiry behaviors is done']</pre> ; <p>This is what I tried in the controller: </p> <pre class="brush:php;toolbar:false;">public function bootstrap($data) { $parseTopics = Helper::parseTopicsRequest(); $basicProgram = new BasicProgramRepository(); $seasonalProgram = new SeasonalProgramRepository($parseTopics['SEASONAL']); $object = count($parseTopics['SEASONAL']) ? $seasonalProgram : $basicProgram; // Polymorphism return $object->execute(); }</pre> <p>Question 1: I'm not sure if I should use this or something similar to solve my needs: </p> <pre class="brush:php;toolbar:false;">$employe = new Program(new BasicProgramRepository());</pre> <p>Expected results: The expected result depends on whether I have season parameters and expiry time. What I want to achieve is to use different behavior (execute method)</p>
P粉187677012P粉187677012449 days ago604

reply all(1)I'll reply

  • P粉086993788

    P粉0869937882023-09-06 18:46:06

    If you want to implement a polymorphic approach, it's better to create a repository or something just to manage that logic.

    This is an example.

    class SampleRepository
    {
        /**
         * repository instance value
         *
         * @var string[] | null
         */
        private $sampleArray; // maybe here is SEASON or EXPIRY or null
    
        /**
         * constructor
         *
         * @param string[] | null $sampleArray
         */
        public function __construct($sampleArray)
        {
            $this->sampleArray = $sampleArray;
        }
    
        /**
         * execute like class interface role
         *
         * @return array
         */
        public function execute()
        {
            return (!$this->sampleArray) ? [] : $this->getResult();
        }
    
        /**
         * get result
         *
         * @return array
         */
        private function getResult()
        {
            // maybe pattern will be better to manage another class or trait.
            $pattern = [
                "SEASON" => new Season(),
                "EXPIRY" => new Expiry()
            ];
            return collect($this->sampleArray)->map(function($itemKey){
                $requestClass = data_get($pattern,$itemKey);
                if (!$requestClass){ // here is space you don't expect class or canIt find correct class
                    return ["something wrong"];
                }
                return $requestClass->execute();
            })->flatten();
        }
    }

    You can call it like this.

    $sampleRepository  = new SampleRepository($sampleValue); // expect string[] or null like ["SEASON"],["SEASON","EXPIRY"],null
        $result = $sampleRepository->execute(); // [string] or [string,string] or []

    This method only works with your parameter specified values. If the return results of the Season class and the Expiry class are almost the same, it is best to manage them on traits. (i.e. $pattern in the example code)

    Try some.

    I read the comments, so follow..

    For example, it prefers to only get the result of getResult(). Therefore, certain patterns and so much logic should not be written on getResult();

    If you use traits, here is an example. First, you need to create the management behavior class.

    behavior.php

    <?php 
    namespace App\Repositories;
    
    class Behavior
    {
        use Behavior\BehaviorTrait;
        // if you need to add another pattern, you can add trait here.
    }

    Then, you need to create a Behavior directory at the same level. When you move this directory, you create such a signature file.

    <?php
    
    namespace App\Repositories\Behavior;
    
    trait BehaviorTrait
    {
        public static function findAccessibleClass(string $itemKey)
        {
          return data_get([
            "SEASON" => new Season(),
            "EXPIRY" => new Expiry()
          ],$itemKey);
        }
    }

    findAccessibleClass() method is responsible for finding the correct class.

    Then, you can call this method like this.

    private function getResult()
        {
            return collect($this->sampleArray)->map(function($itemKey){
                $requestClass = Behavior::findAccessibleClass($itemKey); // fix here.
                if (!$requestClass){ // here is space you don't expect class or canIt find correct class
                    return ["something wrong"];
                }
                return $requestClass->execute();
            })->flatten();
        }

    If there is too much code in getResult(), it is best to separate the responsible code.

    To create a Behavior Trait, getResult does not need to be responsible for the behavioral logic. In short, it will be easy to test or fix.

    hope everything is fine.

    reply
    0
  • Cancelreply