programmatically identify methods that override trait methods












4















I'm trying to generate an array of methods in a class that override trait methods. Here is a simplified example that shows the structure of methods of a typical class and trait in my app:



class demo
{
public function MethodA()
{
return 'method A from class';
}

public function MethodC()
{
return 'method C from class';
}

public function MethodE()
{
return 'method E from class';
}

use tGeneric;
}

trait tGeneric
{
public function MethodA()
{
return 'method A from trait';
}

public function MethodB()
{
return 'method B from trait';
}

public function MethodD()
{
return 'method D from trait';
}

public function MethodE()
{
return 'method E from trait';
}
}


Per the precedence rules listed in the PHP manual:




The precedence order is that methods from the current class override Trait methods, which in turn override methods from the base class.




this is behaving as expected because the output from this code:



$object = new demo();
$array = [
$object->MethodA(),
$object->MethodB(),
$object->MethodC(),
$object->MethodD(),
$object->MethodE()
];

$br = '<br>';
$msg = '';

foreach ($array as $value):
$msg .= $value . $br;
endforeach;
echo $msg . $br;


is:
enter image description here



The methods in the class demo that override the trait methods from tGeneric are MethodA() and MethodE(). Is there a way to programmatically generate an array of just these methods in the class that override the methods from the trait?



I have experimented with reflection but the GetMethods() method retrieves all methods for a class, regardless of whether they originated in the class or were obtained via the use of a trait.



This code:



$rc = new ReflectionClass('demo');
$d = $rc->GetMethods();

$traits = class_uses('demo');
foreach ($traits as $trait):
$reflection = new ReflectionClass($trait);
$t = $reflection->GetMethods();
endforeach;

DisplayInfo($d);
DisplayInfo($t);

function DisplayInfo($array)
{
$br = '<br>';
echo '<b>' . $array[0]->class . '</b>' . $br;
foreach ($array as $value):
echo $value->name . $br;
endforeach;
echo $br;
}


gives this output:
enter image description here










share|improve this question



























    4















    I'm trying to generate an array of methods in a class that override trait methods. Here is a simplified example that shows the structure of methods of a typical class and trait in my app:



    class demo
    {
    public function MethodA()
    {
    return 'method A from class';
    }

    public function MethodC()
    {
    return 'method C from class';
    }

    public function MethodE()
    {
    return 'method E from class';
    }

    use tGeneric;
    }

    trait tGeneric
    {
    public function MethodA()
    {
    return 'method A from trait';
    }

    public function MethodB()
    {
    return 'method B from trait';
    }

    public function MethodD()
    {
    return 'method D from trait';
    }

    public function MethodE()
    {
    return 'method E from trait';
    }
    }


    Per the precedence rules listed in the PHP manual:




    The precedence order is that methods from the current class override Trait methods, which in turn override methods from the base class.




    this is behaving as expected because the output from this code:



    $object = new demo();
    $array = [
    $object->MethodA(),
    $object->MethodB(),
    $object->MethodC(),
    $object->MethodD(),
    $object->MethodE()
    ];

    $br = '<br>';
    $msg = '';

    foreach ($array as $value):
    $msg .= $value . $br;
    endforeach;
    echo $msg . $br;


    is:
    enter image description here



    The methods in the class demo that override the trait methods from tGeneric are MethodA() and MethodE(). Is there a way to programmatically generate an array of just these methods in the class that override the methods from the trait?



    I have experimented with reflection but the GetMethods() method retrieves all methods for a class, regardless of whether they originated in the class or were obtained via the use of a trait.



    This code:



    $rc = new ReflectionClass('demo');
    $d = $rc->GetMethods();

    $traits = class_uses('demo');
    foreach ($traits as $trait):
    $reflection = new ReflectionClass($trait);
    $t = $reflection->GetMethods();
    endforeach;

    DisplayInfo($d);
    DisplayInfo($t);

    function DisplayInfo($array)
    {
    $br = '<br>';
    echo '<b>' . $array[0]->class . '</b>' . $br;
    foreach ($array as $value):
    echo $value->name . $br;
    endforeach;
    echo $br;
    }


    gives this output:
    enter image description here










    share|improve this question

























      4












      4








      4


      1






      I'm trying to generate an array of methods in a class that override trait methods. Here is a simplified example that shows the structure of methods of a typical class and trait in my app:



      class demo
      {
      public function MethodA()
      {
      return 'method A from class';
      }

      public function MethodC()
      {
      return 'method C from class';
      }

      public function MethodE()
      {
      return 'method E from class';
      }

      use tGeneric;
      }

      trait tGeneric
      {
      public function MethodA()
      {
      return 'method A from trait';
      }

      public function MethodB()
      {
      return 'method B from trait';
      }

      public function MethodD()
      {
      return 'method D from trait';
      }

      public function MethodE()
      {
      return 'method E from trait';
      }
      }


      Per the precedence rules listed in the PHP manual:




      The precedence order is that methods from the current class override Trait methods, which in turn override methods from the base class.




      this is behaving as expected because the output from this code:



      $object = new demo();
      $array = [
      $object->MethodA(),
      $object->MethodB(),
      $object->MethodC(),
      $object->MethodD(),
      $object->MethodE()
      ];

      $br = '<br>';
      $msg = '';

      foreach ($array as $value):
      $msg .= $value . $br;
      endforeach;
      echo $msg . $br;


      is:
      enter image description here



      The methods in the class demo that override the trait methods from tGeneric are MethodA() and MethodE(). Is there a way to programmatically generate an array of just these methods in the class that override the methods from the trait?



      I have experimented with reflection but the GetMethods() method retrieves all methods for a class, regardless of whether they originated in the class or were obtained via the use of a trait.



      This code:



      $rc = new ReflectionClass('demo');
      $d = $rc->GetMethods();

      $traits = class_uses('demo');
      foreach ($traits as $trait):
      $reflection = new ReflectionClass($trait);
      $t = $reflection->GetMethods();
      endforeach;

      DisplayInfo($d);
      DisplayInfo($t);

      function DisplayInfo($array)
      {
      $br = '<br>';
      echo '<b>' . $array[0]->class . '</b>' . $br;
      foreach ($array as $value):
      echo $value->name . $br;
      endforeach;
      echo $br;
      }


      gives this output:
      enter image description here










      share|improve this question














      I'm trying to generate an array of methods in a class that override trait methods. Here is a simplified example that shows the structure of methods of a typical class and trait in my app:



      class demo
      {
      public function MethodA()
      {
      return 'method A from class';
      }

      public function MethodC()
      {
      return 'method C from class';
      }

      public function MethodE()
      {
      return 'method E from class';
      }

      use tGeneric;
      }

      trait tGeneric
      {
      public function MethodA()
      {
      return 'method A from trait';
      }

      public function MethodB()
      {
      return 'method B from trait';
      }

      public function MethodD()
      {
      return 'method D from trait';
      }

      public function MethodE()
      {
      return 'method E from trait';
      }
      }


      Per the precedence rules listed in the PHP manual:




      The precedence order is that methods from the current class override Trait methods, which in turn override methods from the base class.




      this is behaving as expected because the output from this code:



      $object = new demo();
      $array = [
      $object->MethodA(),
      $object->MethodB(),
      $object->MethodC(),
      $object->MethodD(),
      $object->MethodE()
      ];

      $br = '<br>';
      $msg = '';

      foreach ($array as $value):
      $msg .= $value . $br;
      endforeach;
      echo $msg . $br;


      is:
      enter image description here



      The methods in the class demo that override the trait methods from tGeneric are MethodA() and MethodE(). Is there a way to programmatically generate an array of just these methods in the class that override the methods from the trait?



      I have experimented with reflection but the GetMethods() method retrieves all methods for a class, regardless of whether they originated in the class or were obtained via the use of a trait.



      This code:



      $rc = new ReflectionClass('demo');
      $d = $rc->GetMethods();

      $traits = class_uses('demo');
      foreach ($traits as $trait):
      $reflection = new ReflectionClass($trait);
      $t = $reflection->GetMethods();
      endforeach;

      DisplayInfo($d);
      DisplayInfo($t);

      function DisplayInfo($array)
      {
      $br = '<br>';
      echo '<b>' . $array[0]->class . '</b>' . $br;
      foreach ($array as $value):
      echo $value->name . $br;
      endforeach;
      echo $br;
      }


      gives this output:
      enter image description here







      php






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 28 '18 at 14:47









      knot22knot22

      5091722




      5091722
























          2 Answers
          2






          active

          oldest

          votes


















          2














          You could make almost sure a method overrides a trait method by comparing:




          • their file names
            (ReflectionFunctionAbstract::getFileName),

          • and their start lines (ReflectionFunctionAbstract::getStartLine)


          Condition



          if ($class_method->getFileName() !== $trait_method->getFileName() 
          || $class_method->getStartLine() !== $trait_method->getStartLine()) {
          $methods_overridden = $class_method->getName();
          }


          (of course, they also need to have the same name)



          Full function



          /**
          * Given a class name, retrieves the corresponding class' methods that override
          * trait methods.
          *
          * @param string $class_name
          * @return ReflectionMethod
          * @throws ReflectionException
          */
          function getMethodsOverriddenFromTraits(string $class_name): array
          {
          $class = new ReflectionClass($class_name);

          // Retrieve trait methods

          $trait_methods = ;
          foreach ($class->getTraits() as $trait) {
          foreach ($trait->getMethods() as $trait_method) {
          $trait_methods[$trait_method->getName()] = $trait_method;
          }
          }

          // Compute class methods that override them

          $methods_overridden = ;
          foreach ($class->getMethods() as $class_method) {
          if (array_key_exists($class_method->getName(), $trait_methods)) {
          $trait_method = $trait_methods[$class_method->getName()];
          if ($class_method->getFileName() !== $trait_method->getFileName()
          || $class_method->getStartLine() !== $trait_method->getStartLine()) {
          $methods_overridden = $class_method->getName();
          }
          }
          }

          return $methods_overridden;
          }


          Demo here: https://3v4l.org/EcFIC






          share|improve this answer


























          • In my app the classes and traits are in separate files, unlike the simplified example I provided in the original post. So is there any reason to include the getStartLine method in the condition that determines class methods that override trait methods in the code for the app? Just want to make sure I'm not overlooking something. My assumption is that getStartLine was included in your solution for this post so the original example would work correctly in the demo you provided...is that correct?

            – knot22
            Dec 28 '18 at 19:35








          • 1





            @knot22 That's exactly right. The idea is to have it work in as many different cases as possible, but you can omit the start line condition if your traits are always in distinct files.

            – Jeto
            Dec 28 '18 at 19:40











          • OK, excellent. Another thing in your solution I'm wondering about, that I haven't seen before, is the function getMethodsOverriddenFromTraits(string $class_name): array - specifically the : array part. Googling did not help me find an answer for the purpose of : array. What does that do?

            – knot22
            Dec 28 '18 at 19:44








          • 1





            It's the PHP7 way of stating what the function will return (unfortunately, you can't be more specific than array). You can omit it without any issues if you're not running PHP7 or if your other functions/methods don't use that syntax. See the docs for more info.

            – Jeto
            Dec 28 '18 at 19:46






          • 1





            A leading backslash before a class name means you're looking for a class of that name that exists within the default (root) namespace, such as ReflectionClass and any other class that is defined by PHP's standard library. If you omit it, PHP will look for the class in the current namespace. So for instance if you add namespace MyGreatApp; on top of your code, then referencing ReflectionClass without it will fail because it will look for MyGreatAppReflectionClass. Hope this makes sense.

            – Jeto
            Dec 28 '18 at 19:55





















          1














          One possible solution would be more applicable if it was more a real code scenario where your traits and classes where in individual files - which should be how you code anyway (IMHO)...



          So I put the trait code in a file (I've called it TraitTest.php). Then in my main script is the rest of the code you have, but of course using require_once 'TraitTest.php';. Then in the DisplayInfo() function, I've just added the value of getFileName(), which shows the filename where the method is defined...



          function DisplayInfo($array)
          {
          $br = PHP_EOL;
          echo '<b>' . $array[0]->class . '</b>' . $br;
          foreach ($array as $value) {
          echo $value->getFileName()."->".$value->name . $br;
          }
          echo $br;
          }


          which shows...



          <b>demo</b>
          /home/nigel/workspace2/Test/t1.php->MethodA
          /home/nigel/workspace2/Test/t1.php->MethodC
          /home/nigel/workspace2/Test/t1.php->MethodE
          /home/nigel/workspace2/Test/TraitTest.php->MethodB
          /home/nigel/workspace2/Test/TraitTest.php->MethodD

          <b>TraitTest</b>
          /home/nigel/workspace2/Test/TraitTest.php->MethodA
          /home/nigel/workspace2/Test/TraitTest.php->MethodB
          /home/nigel/workspace2/Test/TraitTest.php->MethodD
          /home/nigel/workspace2/Test/TraitTest.php->MethodE


          As you can see, MethodB is showing up as being defined in TraitTest.php.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53960295%2fprogrammatically-identify-methods-that-override-trait-methods%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2














            You could make almost sure a method overrides a trait method by comparing:




            • their file names
              (ReflectionFunctionAbstract::getFileName),

            • and their start lines (ReflectionFunctionAbstract::getStartLine)


            Condition



            if ($class_method->getFileName() !== $trait_method->getFileName() 
            || $class_method->getStartLine() !== $trait_method->getStartLine()) {
            $methods_overridden = $class_method->getName();
            }


            (of course, they also need to have the same name)



            Full function



            /**
            * Given a class name, retrieves the corresponding class' methods that override
            * trait methods.
            *
            * @param string $class_name
            * @return ReflectionMethod
            * @throws ReflectionException
            */
            function getMethodsOverriddenFromTraits(string $class_name): array
            {
            $class = new ReflectionClass($class_name);

            // Retrieve trait methods

            $trait_methods = ;
            foreach ($class->getTraits() as $trait) {
            foreach ($trait->getMethods() as $trait_method) {
            $trait_methods[$trait_method->getName()] = $trait_method;
            }
            }

            // Compute class methods that override them

            $methods_overridden = ;
            foreach ($class->getMethods() as $class_method) {
            if (array_key_exists($class_method->getName(), $trait_methods)) {
            $trait_method = $trait_methods[$class_method->getName()];
            if ($class_method->getFileName() !== $trait_method->getFileName()
            || $class_method->getStartLine() !== $trait_method->getStartLine()) {
            $methods_overridden = $class_method->getName();
            }
            }
            }

            return $methods_overridden;
            }


            Demo here: https://3v4l.org/EcFIC






            share|improve this answer


























            • In my app the classes and traits are in separate files, unlike the simplified example I provided in the original post. So is there any reason to include the getStartLine method in the condition that determines class methods that override trait methods in the code for the app? Just want to make sure I'm not overlooking something. My assumption is that getStartLine was included in your solution for this post so the original example would work correctly in the demo you provided...is that correct?

              – knot22
              Dec 28 '18 at 19:35








            • 1





              @knot22 That's exactly right. The idea is to have it work in as many different cases as possible, but you can omit the start line condition if your traits are always in distinct files.

              – Jeto
              Dec 28 '18 at 19:40











            • OK, excellent. Another thing in your solution I'm wondering about, that I haven't seen before, is the function getMethodsOverriddenFromTraits(string $class_name): array - specifically the : array part. Googling did not help me find an answer for the purpose of : array. What does that do?

              – knot22
              Dec 28 '18 at 19:44








            • 1





              It's the PHP7 way of stating what the function will return (unfortunately, you can't be more specific than array). You can omit it without any issues if you're not running PHP7 or if your other functions/methods don't use that syntax. See the docs for more info.

              – Jeto
              Dec 28 '18 at 19:46






            • 1





              A leading backslash before a class name means you're looking for a class of that name that exists within the default (root) namespace, such as ReflectionClass and any other class that is defined by PHP's standard library. If you omit it, PHP will look for the class in the current namespace. So for instance if you add namespace MyGreatApp; on top of your code, then referencing ReflectionClass without it will fail because it will look for MyGreatAppReflectionClass. Hope this makes sense.

              – Jeto
              Dec 28 '18 at 19:55


















            2














            You could make almost sure a method overrides a trait method by comparing:




            • their file names
              (ReflectionFunctionAbstract::getFileName),

            • and their start lines (ReflectionFunctionAbstract::getStartLine)


            Condition



            if ($class_method->getFileName() !== $trait_method->getFileName() 
            || $class_method->getStartLine() !== $trait_method->getStartLine()) {
            $methods_overridden = $class_method->getName();
            }


            (of course, they also need to have the same name)



            Full function



            /**
            * Given a class name, retrieves the corresponding class' methods that override
            * trait methods.
            *
            * @param string $class_name
            * @return ReflectionMethod
            * @throws ReflectionException
            */
            function getMethodsOverriddenFromTraits(string $class_name): array
            {
            $class = new ReflectionClass($class_name);

            // Retrieve trait methods

            $trait_methods = ;
            foreach ($class->getTraits() as $trait) {
            foreach ($trait->getMethods() as $trait_method) {
            $trait_methods[$trait_method->getName()] = $trait_method;
            }
            }

            // Compute class methods that override them

            $methods_overridden = ;
            foreach ($class->getMethods() as $class_method) {
            if (array_key_exists($class_method->getName(), $trait_methods)) {
            $trait_method = $trait_methods[$class_method->getName()];
            if ($class_method->getFileName() !== $trait_method->getFileName()
            || $class_method->getStartLine() !== $trait_method->getStartLine()) {
            $methods_overridden = $class_method->getName();
            }
            }
            }

            return $methods_overridden;
            }


            Demo here: https://3v4l.org/EcFIC






            share|improve this answer


























            • In my app the classes and traits are in separate files, unlike the simplified example I provided in the original post. So is there any reason to include the getStartLine method in the condition that determines class methods that override trait methods in the code for the app? Just want to make sure I'm not overlooking something. My assumption is that getStartLine was included in your solution for this post so the original example would work correctly in the demo you provided...is that correct?

              – knot22
              Dec 28 '18 at 19:35








            • 1





              @knot22 That's exactly right. The idea is to have it work in as many different cases as possible, but you can omit the start line condition if your traits are always in distinct files.

              – Jeto
              Dec 28 '18 at 19:40











            • OK, excellent. Another thing in your solution I'm wondering about, that I haven't seen before, is the function getMethodsOverriddenFromTraits(string $class_name): array - specifically the : array part. Googling did not help me find an answer for the purpose of : array. What does that do?

              – knot22
              Dec 28 '18 at 19:44








            • 1





              It's the PHP7 way of stating what the function will return (unfortunately, you can't be more specific than array). You can omit it without any issues if you're not running PHP7 or if your other functions/methods don't use that syntax. See the docs for more info.

              – Jeto
              Dec 28 '18 at 19:46






            • 1





              A leading backslash before a class name means you're looking for a class of that name that exists within the default (root) namespace, such as ReflectionClass and any other class that is defined by PHP's standard library. If you omit it, PHP will look for the class in the current namespace. So for instance if you add namespace MyGreatApp; on top of your code, then referencing ReflectionClass without it will fail because it will look for MyGreatAppReflectionClass. Hope this makes sense.

              – Jeto
              Dec 28 '18 at 19:55
















            2












            2








            2







            You could make almost sure a method overrides a trait method by comparing:




            • their file names
              (ReflectionFunctionAbstract::getFileName),

            • and their start lines (ReflectionFunctionAbstract::getStartLine)


            Condition



            if ($class_method->getFileName() !== $trait_method->getFileName() 
            || $class_method->getStartLine() !== $trait_method->getStartLine()) {
            $methods_overridden = $class_method->getName();
            }


            (of course, they also need to have the same name)



            Full function



            /**
            * Given a class name, retrieves the corresponding class' methods that override
            * trait methods.
            *
            * @param string $class_name
            * @return ReflectionMethod
            * @throws ReflectionException
            */
            function getMethodsOverriddenFromTraits(string $class_name): array
            {
            $class = new ReflectionClass($class_name);

            // Retrieve trait methods

            $trait_methods = ;
            foreach ($class->getTraits() as $trait) {
            foreach ($trait->getMethods() as $trait_method) {
            $trait_methods[$trait_method->getName()] = $trait_method;
            }
            }

            // Compute class methods that override them

            $methods_overridden = ;
            foreach ($class->getMethods() as $class_method) {
            if (array_key_exists($class_method->getName(), $trait_methods)) {
            $trait_method = $trait_methods[$class_method->getName()];
            if ($class_method->getFileName() !== $trait_method->getFileName()
            || $class_method->getStartLine() !== $trait_method->getStartLine()) {
            $methods_overridden = $class_method->getName();
            }
            }
            }

            return $methods_overridden;
            }


            Demo here: https://3v4l.org/EcFIC






            share|improve this answer















            You could make almost sure a method overrides a trait method by comparing:




            • their file names
              (ReflectionFunctionAbstract::getFileName),

            • and their start lines (ReflectionFunctionAbstract::getStartLine)


            Condition



            if ($class_method->getFileName() !== $trait_method->getFileName() 
            || $class_method->getStartLine() !== $trait_method->getStartLine()) {
            $methods_overridden = $class_method->getName();
            }


            (of course, they also need to have the same name)



            Full function



            /**
            * Given a class name, retrieves the corresponding class' methods that override
            * trait methods.
            *
            * @param string $class_name
            * @return ReflectionMethod
            * @throws ReflectionException
            */
            function getMethodsOverriddenFromTraits(string $class_name): array
            {
            $class = new ReflectionClass($class_name);

            // Retrieve trait methods

            $trait_methods = ;
            foreach ($class->getTraits() as $trait) {
            foreach ($trait->getMethods() as $trait_method) {
            $trait_methods[$trait_method->getName()] = $trait_method;
            }
            }

            // Compute class methods that override them

            $methods_overridden = ;
            foreach ($class->getMethods() as $class_method) {
            if (array_key_exists($class_method->getName(), $trait_methods)) {
            $trait_method = $trait_methods[$class_method->getName()];
            if ($class_method->getFileName() !== $trait_method->getFileName()
            || $class_method->getStartLine() !== $trait_method->getStartLine()) {
            $methods_overridden = $class_method->getName();
            }
            }
            }

            return $methods_overridden;
            }


            Demo here: https://3v4l.org/EcFIC







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 28 '18 at 16:09

























            answered Dec 28 '18 at 15:51









            JetoJeto

            5,03521018




            5,03521018













            • In my app the classes and traits are in separate files, unlike the simplified example I provided in the original post. So is there any reason to include the getStartLine method in the condition that determines class methods that override trait methods in the code for the app? Just want to make sure I'm not overlooking something. My assumption is that getStartLine was included in your solution for this post so the original example would work correctly in the demo you provided...is that correct?

              – knot22
              Dec 28 '18 at 19:35








            • 1





              @knot22 That's exactly right. The idea is to have it work in as many different cases as possible, but you can omit the start line condition if your traits are always in distinct files.

              – Jeto
              Dec 28 '18 at 19:40











            • OK, excellent. Another thing in your solution I'm wondering about, that I haven't seen before, is the function getMethodsOverriddenFromTraits(string $class_name): array - specifically the : array part. Googling did not help me find an answer for the purpose of : array. What does that do?

              – knot22
              Dec 28 '18 at 19:44








            • 1





              It's the PHP7 way of stating what the function will return (unfortunately, you can't be more specific than array). You can omit it without any issues if you're not running PHP7 or if your other functions/methods don't use that syntax. See the docs for more info.

              – Jeto
              Dec 28 '18 at 19:46






            • 1





              A leading backslash before a class name means you're looking for a class of that name that exists within the default (root) namespace, such as ReflectionClass and any other class that is defined by PHP's standard library. If you omit it, PHP will look for the class in the current namespace. So for instance if you add namespace MyGreatApp; on top of your code, then referencing ReflectionClass without it will fail because it will look for MyGreatAppReflectionClass. Hope this makes sense.

              – Jeto
              Dec 28 '18 at 19:55





















            • In my app the classes and traits are in separate files, unlike the simplified example I provided in the original post. So is there any reason to include the getStartLine method in the condition that determines class methods that override trait methods in the code for the app? Just want to make sure I'm not overlooking something. My assumption is that getStartLine was included in your solution for this post so the original example would work correctly in the demo you provided...is that correct?

              – knot22
              Dec 28 '18 at 19:35








            • 1





              @knot22 That's exactly right. The idea is to have it work in as many different cases as possible, but you can omit the start line condition if your traits are always in distinct files.

              – Jeto
              Dec 28 '18 at 19:40











            • OK, excellent. Another thing in your solution I'm wondering about, that I haven't seen before, is the function getMethodsOverriddenFromTraits(string $class_name): array - specifically the : array part. Googling did not help me find an answer for the purpose of : array. What does that do?

              – knot22
              Dec 28 '18 at 19:44








            • 1





              It's the PHP7 way of stating what the function will return (unfortunately, you can't be more specific than array). You can omit it without any issues if you're not running PHP7 or if your other functions/methods don't use that syntax. See the docs for more info.

              – Jeto
              Dec 28 '18 at 19:46






            • 1





              A leading backslash before a class name means you're looking for a class of that name that exists within the default (root) namespace, such as ReflectionClass and any other class that is defined by PHP's standard library. If you omit it, PHP will look for the class in the current namespace. So for instance if you add namespace MyGreatApp; on top of your code, then referencing ReflectionClass without it will fail because it will look for MyGreatAppReflectionClass. Hope this makes sense.

              – Jeto
              Dec 28 '18 at 19:55



















            In my app the classes and traits are in separate files, unlike the simplified example I provided in the original post. So is there any reason to include the getStartLine method in the condition that determines class methods that override trait methods in the code for the app? Just want to make sure I'm not overlooking something. My assumption is that getStartLine was included in your solution for this post so the original example would work correctly in the demo you provided...is that correct?

            – knot22
            Dec 28 '18 at 19:35







            In my app the classes and traits are in separate files, unlike the simplified example I provided in the original post. So is there any reason to include the getStartLine method in the condition that determines class methods that override trait methods in the code for the app? Just want to make sure I'm not overlooking something. My assumption is that getStartLine was included in your solution for this post so the original example would work correctly in the demo you provided...is that correct?

            – knot22
            Dec 28 '18 at 19:35






            1




            1





            @knot22 That's exactly right. The idea is to have it work in as many different cases as possible, but you can omit the start line condition if your traits are always in distinct files.

            – Jeto
            Dec 28 '18 at 19:40





            @knot22 That's exactly right. The idea is to have it work in as many different cases as possible, but you can omit the start line condition if your traits are always in distinct files.

            – Jeto
            Dec 28 '18 at 19:40













            OK, excellent. Another thing in your solution I'm wondering about, that I haven't seen before, is the function getMethodsOverriddenFromTraits(string $class_name): array - specifically the : array part. Googling did not help me find an answer for the purpose of : array. What does that do?

            – knot22
            Dec 28 '18 at 19:44







            OK, excellent. Another thing in your solution I'm wondering about, that I haven't seen before, is the function getMethodsOverriddenFromTraits(string $class_name): array - specifically the : array part. Googling did not help me find an answer for the purpose of : array. What does that do?

            – knot22
            Dec 28 '18 at 19:44






            1




            1





            It's the PHP7 way of stating what the function will return (unfortunately, you can't be more specific than array). You can omit it without any issues if you're not running PHP7 or if your other functions/methods don't use that syntax. See the docs for more info.

            – Jeto
            Dec 28 '18 at 19:46





            It's the PHP7 way of stating what the function will return (unfortunately, you can't be more specific than array). You can omit it without any issues if you're not running PHP7 or if your other functions/methods don't use that syntax. See the docs for more info.

            – Jeto
            Dec 28 '18 at 19:46




            1




            1





            A leading backslash before a class name means you're looking for a class of that name that exists within the default (root) namespace, such as ReflectionClass and any other class that is defined by PHP's standard library. If you omit it, PHP will look for the class in the current namespace. So for instance if you add namespace MyGreatApp; on top of your code, then referencing ReflectionClass without it will fail because it will look for MyGreatAppReflectionClass. Hope this makes sense.

            – Jeto
            Dec 28 '18 at 19:55







            A leading backslash before a class name means you're looking for a class of that name that exists within the default (root) namespace, such as ReflectionClass and any other class that is defined by PHP's standard library. If you omit it, PHP will look for the class in the current namespace. So for instance if you add namespace MyGreatApp; on top of your code, then referencing ReflectionClass without it will fail because it will look for MyGreatAppReflectionClass. Hope this makes sense.

            – Jeto
            Dec 28 '18 at 19:55















            1














            One possible solution would be more applicable if it was more a real code scenario where your traits and classes where in individual files - which should be how you code anyway (IMHO)...



            So I put the trait code in a file (I've called it TraitTest.php). Then in my main script is the rest of the code you have, but of course using require_once 'TraitTest.php';. Then in the DisplayInfo() function, I've just added the value of getFileName(), which shows the filename where the method is defined...



            function DisplayInfo($array)
            {
            $br = PHP_EOL;
            echo '<b>' . $array[0]->class . '</b>' . $br;
            foreach ($array as $value) {
            echo $value->getFileName()."->".$value->name . $br;
            }
            echo $br;
            }


            which shows...



            <b>demo</b>
            /home/nigel/workspace2/Test/t1.php->MethodA
            /home/nigel/workspace2/Test/t1.php->MethodC
            /home/nigel/workspace2/Test/t1.php->MethodE
            /home/nigel/workspace2/Test/TraitTest.php->MethodB
            /home/nigel/workspace2/Test/TraitTest.php->MethodD

            <b>TraitTest</b>
            /home/nigel/workspace2/Test/TraitTest.php->MethodA
            /home/nigel/workspace2/Test/TraitTest.php->MethodB
            /home/nigel/workspace2/Test/TraitTest.php->MethodD
            /home/nigel/workspace2/Test/TraitTest.php->MethodE


            As you can see, MethodB is showing up as being defined in TraitTest.php.






            share|improve this answer




























              1














              One possible solution would be more applicable if it was more a real code scenario where your traits and classes where in individual files - which should be how you code anyway (IMHO)...



              So I put the trait code in a file (I've called it TraitTest.php). Then in my main script is the rest of the code you have, but of course using require_once 'TraitTest.php';. Then in the DisplayInfo() function, I've just added the value of getFileName(), which shows the filename where the method is defined...



              function DisplayInfo($array)
              {
              $br = PHP_EOL;
              echo '<b>' . $array[0]->class . '</b>' . $br;
              foreach ($array as $value) {
              echo $value->getFileName()."->".$value->name . $br;
              }
              echo $br;
              }


              which shows...



              <b>demo</b>
              /home/nigel/workspace2/Test/t1.php->MethodA
              /home/nigel/workspace2/Test/t1.php->MethodC
              /home/nigel/workspace2/Test/t1.php->MethodE
              /home/nigel/workspace2/Test/TraitTest.php->MethodB
              /home/nigel/workspace2/Test/TraitTest.php->MethodD

              <b>TraitTest</b>
              /home/nigel/workspace2/Test/TraitTest.php->MethodA
              /home/nigel/workspace2/Test/TraitTest.php->MethodB
              /home/nigel/workspace2/Test/TraitTest.php->MethodD
              /home/nigel/workspace2/Test/TraitTest.php->MethodE


              As you can see, MethodB is showing up as being defined in TraitTest.php.






              share|improve this answer


























                1












                1








                1







                One possible solution would be more applicable if it was more a real code scenario where your traits and classes where in individual files - which should be how you code anyway (IMHO)...



                So I put the trait code in a file (I've called it TraitTest.php). Then in my main script is the rest of the code you have, but of course using require_once 'TraitTest.php';. Then in the DisplayInfo() function, I've just added the value of getFileName(), which shows the filename where the method is defined...



                function DisplayInfo($array)
                {
                $br = PHP_EOL;
                echo '<b>' . $array[0]->class . '</b>' . $br;
                foreach ($array as $value) {
                echo $value->getFileName()."->".$value->name . $br;
                }
                echo $br;
                }


                which shows...



                <b>demo</b>
                /home/nigel/workspace2/Test/t1.php->MethodA
                /home/nigel/workspace2/Test/t1.php->MethodC
                /home/nigel/workspace2/Test/t1.php->MethodE
                /home/nigel/workspace2/Test/TraitTest.php->MethodB
                /home/nigel/workspace2/Test/TraitTest.php->MethodD

                <b>TraitTest</b>
                /home/nigel/workspace2/Test/TraitTest.php->MethodA
                /home/nigel/workspace2/Test/TraitTest.php->MethodB
                /home/nigel/workspace2/Test/TraitTest.php->MethodD
                /home/nigel/workspace2/Test/TraitTest.php->MethodE


                As you can see, MethodB is showing up as being defined in TraitTest.php.






                share|improve this answer













                One possible solution would be more applicable if it was more a real code scenario where your traits and classes where in individual files - which should be how you code anyway (IMHO)...



                So I put the trait code in a file (I've called it TraitTest.php). Then in my main script is the rest of the code you have, but of course using require_once 'TraitTest.php';. Then in the DisplayInfo() function, I've just added the value of getFileName(), which shows the filename where the method is defined...



                function DisplayInfo($array)
                {
                $br = PHP_EOL;
                echo '<b>' . $array[0]->class . '</b>' . $br;
                foreach ($array as $value) {
                echo $value->getFileName()."->".$value->name . $br;
                }
                echo $br;
                }


                which shows...



                <b>demo</b>
                /home/nigel/workspace2/Test/t1.php->MethodA
                /home/nigel/workspace2/Test/t1.php->MethodC
                /home/nigel/workspace2/Test/t1.php->MethodE
                /home/nigel/workspace2/Test/TraitTest.php->MethodB
                /home/nigel/workspace2/Test/TraitTest.php->MethodD

                <b>TraitTest</b>
                /home/nigel/workspace2/Test/TraitTest.php->MethodA
                /home/nigel/workspace2/Test/TraitTest.php->MethodB
                /home/nigel/workspace2/Test/TraitTest.php->MethodD
                /home/nigel/workspace2/Test/TraitTest.php->MethodE


                As you can see, MethodB is showing up as being defined in TraitTest.php.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 28 '18 at 15:28









                Nigel RenNigel Ren

                25.8k61832




                25.8k61832






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53960295%2fprogrammatically-identify-methods-that-override-trait-methods%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Monofisismo

                    Angular Downloading a file using contenturl with Basic Authentication

                    Olmecas