Why do so few code examples use the ::load($id) method for loading entities?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
2
down vote

favorite












Over at How to get term name from a tid? the accepted answer for "how do I get the name for a Term" is this:



use DrupaltaxonomyEntityTerm;
...
$term = Term::load($tid);
...


That's really nice, easy to read code (and very easy to remember). It's also, as it turns out, applicable to all entity types in Drupal (just substitute the Term class for the type of entity you want).



Why then, do the overwhelming majority of the code examples and tutorials published around the place seem to advocate this monstrosity? ...



$term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);


That approach bakes in one of my [many] grievances with PHP in general - it's full of magic strings! How the hell am I supposed to know at "compile time" whether 'taxonomy_term' is the right argument to getStorage()?? There's not a PHP IDE in the land that'll catch me sticking 'taxonomy' in there instead.



Looking at the contents of that ::load method (which is defined in DrupalCoreEntityEntity and shared by all Drupal entities), it's got all the dependency-injection cleverness of that second-approach - plus it fills in the right argument to getStorage() for you automatically!



So why does more of the Drupal community not use it? Is there something I'm missing? Or is it just to teach us "first principles" so that we can write shared code that works with any entity type? (you'd need the long-hand way in a hook that was intended to work across all entity types).










share|improve this question



























    up vote
    2
    down vote

    favorite












    Over at How to get term name from a tid? the accepted answer for "how do I get the name for a Term" is this:



    use DrupaltaxonomyEntityTerm;
    ...
    $term = Term::load($tid);
    ...


    That's really nice, easy to read code (and very easy to remember). It's also, as it turns out, applicable to all entity types in Drupal (just substitute the Term class for the type of entity you want).



    Why then, do the overwhelming majority of the code examples and tutorials published around the place seem to advocate this monstrosity? ...



    $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);


    That approach bakes in one of my [many] grievances with PHP in general - it's full of magic strings! How the hell am I supposed to know at "compile time" whether 'taxonomy_term' is the right argument to getStorage()?? There's not a PHP IDE in the land that'll catch me sticking 'taxonomy' in there instead.



    Looking at the contents of that ::load method (which is defined in DrupalCoreEntityEntity and shared by all Drupal entities), it's got all the dependency-injection cleverness of that second-approach - plus it fills in the right argument to getStorage() for you automatically!



    So why does more of the Drupal community not use it? Is there something I'm missing? Or is it just to teach us "first principles" so that we can write shared code that works with any entity type? (you'd need the long-hand way in a hook that was intended to work across all entity types).










    share|improve this question























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      Over at How to get term name from a tid? the accepted answer for "how do I get the name for a Term" is this:



      use DrupaltaxonomyEntityTerm;
      ...
      $term = Term::load($tid);
      ...


      That's really nice, easy to read code (and very easy to remember). It's also, as it turns out, applicable to all entity types in Drupal (just substitute the Term class for the type of entity you want).



      Why then, do the overwhelming majority of the code examples and tutorials published around the place seem to advocate this monstrosity? ...



      $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);


      That approach bakes in one of my [many] grievances with PHP in general - it's full of magic strings! How the hell am I supposed to know at "compile time" whether 'taxonomy_term' is the right argument to getStorage()?? There's not a PHP IDE in the land that'll catch me sticking 'taxonomy' in there instead.



      Looking at the contents of that ::load method (which is defined in DrupalCoreEntityEntity and shared by all Drupal entities), it's got all the dependency-injection cleverness of that second-approach - plus it fills in the right argument to getStorage() for you automatically!



      So why does more of the Drupal community not use it? Is there something I'm missing? Or is it just to teach us "first principles" so that we can write shared code that works with any entity type? (you'd need the long-hand way in a hook that was intended to work across all entity types).










      share|improve this question













      Over at How to get term name from a tid? the accepted answer for "how do I get the name for a Term" is this:



      use DrupaltaxonomyEntityTerm;
      ...
      $term = Term::load($tid);
      ...


      That's really nice, easy to read code (and very easy to remember). It's also, as it turns out, applicable to all entity types in Drupal (just substitute the Term class for the type of entity you want).



      Why then, do the overwhelming majority of the code examples and tutorials published around the place seem to advocate this monstrosity? ...



      $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);


      That approach bakes in one of my [many] grievances with PHP in general - it's full of magic strings! How the hell am I supposed to know at "compile time" whether 'taxonomy_term' is the right argument to getStorage()?? There's not a PHP IDE in the land that'll catch me sticking 'taxonomy' in there instead.



      Looking at the contents of that ::load method (which is defined in DrupalCoreEntityEntity and shared by all Drupal entities), it's got all the dependency-injection cleverness of that second-approach - plus it fills in the right argument to getStorage() for you automatically!



      So why does more of the Drupal community not use it? Is there something I'm missing? Or is it just to teach us "first principles" so that we can write shared code that works with any entity type? (you'd need the long-hand way in a hook that was intended to work across all entity types).







      8 entities






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 7 hours ago









      Daniel Scott

      1214




      1214




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          2
          down vote













          There is actually an issue about adding this info to the docs.



          In short, the long winded version is unit test friendly.



          A comment by one of the Core's contributors fully detailed explains why. Just to highlight the main point:




          If we call Node::load() in OO code we are breaking this principle (dependency inversion),
          because we are hardcoding the specific implementation
          (DrupalnodeEntityNode::load() to be exact). This code path is hard
          coupled to Drupal::entityManager() which is hard coupled to
          Drupal::$container. So now our code becomes impossible to run outside
          of Drupal.



          Furthermore, since code that uses the dependency inversion principle
          is fully standalone it is very easy to unit test it by mocking the
          dependencies according to the requested interfaces. If we introduce
          Node::load() then it becomes really hard to "properly" unit test the
          class, since it will start polluting the test environment with
          external code, and the dependency injection container is not available
          in unit tests.




          Now if you wonder then why does Entity::load exists




          There were many loud voices at the time that D8 was going to be a DX
          disaster, that the OO approach was too difficult to understand and
          write, that it would never get adopted by the wider community. There
          was a huge push going on to make D8 more DX friendly, mainly driven by
          the Backdrop fork that was announced a few months earlier.



          So we created these static methods that wrap the loading of the entity
          manager from the container, and can be called directly from the
          procedural side. It was great, since it offers a drop-in replacement
          that works and looks very much like the original code. This made
          porting of procedural D7 code vastly easier:



          // Original D7 procedural code. 
          $node = node_load($nid);

          // New D8 procedural code.
          $node = Node::load($nid);






          share|improve this answer





























            up vote
            1
            down vote













            I think this is about the target audience of the code example. If it is for a hook, then I agree, use the first more easy to read approach.



            If it is for a service, then the correct approach would be to inject the entity type manager and use it instead of the static Drupal wrapper.



            $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid);


            Now the question is what if you want to provide a more universal code example, then



            $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);


            is probably the best approach, because it works in procedural code if you copy and paste it and can be easily adapted for a service where you want to inject the dependencies.






            share|improve this answer




















              Your Answer







              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "220"
              ;
              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',
              convertImagesToLinks: false,
              noModals: false,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













               

              draft saved


              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdrupal.stackexchange.com%2fquestions%2f270376%2fwhy-do-so-few-code-examples-use-the-loadid-method-for-loading-entities%23new-answer', 'question_page');

              );

              Post as a guest






























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              2
              down vote













              There is actually an issue about adding this info to the docs.



              In short, the long winded version is unit test friendly.



              A comment by one of the Core's contributors fully detailed explains why. Just to highlight the main point:




              If we call Node::load() in OO code we are breaking this principle (dependency inversion),
              because we are hardcoding the specific implementation
              (DrupalnodeEntityNode::load() to be exact). This code path is hard
              coupled to Drupal::entityManager() which is hard coupled to
              Drupal::$container. So now our code becomes impossible to run outside
              of Drupal.



              Furthermore, since code that uses the dependency inversion principle
              is fully standalone it is very easy to unit test it by mocking the
              dependencies according to the requested interfaces. If we introduce
              Node::load() then it becomes really hard to "properly" unit test the
              class, since it will start polluting the test environment with
              external code, and the dependency injection container is not available
              in unit tests.




              Now if you wonder then why does Entity::load exists




              There were many loud voices at the time that D8 was going to be a DX
              disaster, that the OO approach was too difficult to understand and
              write, that it would never get adopted by the wider community. There
              was a huge push going on to make D8 more DX friendly, mainly driven by
              the Backdrop fork that was announced a few months earlier.



              So we created these static methods that wrap the loading of the entity
              manager from the container, and can be called directly from the
              procedural side. It was great, since it offers a drop-in replacement
              that works and looks very much like the original code. This made
              porting of procedural D7 code vastly easier:



              // Original D7 procedural code. 
              $node = node_load($nid);

              // New D8 procedural code.
              $node = Node::load($nid);






              share|improve this answer


























                up vote
                2
                down vote













                There is actually an issue about adding this info to the docs.



                In short, the long winded version is unit test friendly.



                A comment by one of the Core's contributors fully detailed explains why. Just to highlight the main point:




                If we call Node::load() in OO code we are breaking this principle (dependency inversion),
                because we are hardcoding the specific implementation
                (DrupalnodeEntityNode::load() to be exact). This code path is hard
                coupled to Drupal::entityManager() which is hard coupled to
                Drupal::$container. So now our code becomes impossible to run outside
                of Drupal.



                Furthermore, since code that uses the dependency inversion principle
                is fully standalone it is very easy to unit test it by mocking the
                dependencies according to the requested interfaces. If we introduce
                Node::load() then it becomes really hard to "properly" unit test the
                class, since it will start polluting the test environment with
                external code, and the dependency injection container is not available
                in unit tests.




                Now if you wonder then why does Entity::load exists




                There were many loud voices at the time that D8 was going to be a DX
                disaster, that the OO approach was too difficult to understand and
                write, that it would never get adopted by the wider community. There
                was a huge push going on to make D8 more DX friendly, mainly driven by
                the Backdrop fork that was announced a few months earlier.



                So we created these static methods that wrap the loading of the entity
                manager from the container, and can be called directly from the
                procedural side. It was great, since it offers a drop-in replacement
                that works and looks very much like the original code. This made
                porting of procedural D7 code vastly easier:



                // Original D7 procedural code. 
                $node = node_load($nid);

                // New D8 procedural code.
                $node = Node::load($nid);






                share|improve this answer
























                  up vote
                  2
                  down vote










                  up vote
                  2
                  down vote









                  There is actually an issue about adding this info to the docs.



                  In short, the long winded version is unit test friendly.



                  A comment by one of the Core's contributors fully detailed explains why. Just to highlight the main point:




                  If we call Node::load() in OO code we are breaking this principle (dependency inversion),
                  because we are hardcoding the specific implementation
                  (DrupalnodeEntityNode::load() to be exact). This code path is hard
                  coupled to Drupal::entityManager() which is hard coupled to
                  Drupal::$container. So now our code becomes impossible to run outside
                  of Drupal.



                  Furthermore, since code that uses the dependency inversion principle
                  is fully standalone it is very easy to unit test it by mocking the
                  dependencies according to the requested interfaces. If we introduce
                  Node::load() then it becomes really hard to "properly" unit test the
                  class, since it will start polluting the test environment with
                  external code, and the dependency injection container is not available
                  in unit tests.




                  Now if you wonder then why does Entity::load exists




                  There were many loud voices at the time that D8 was going to be a DX
                  disaster, that the OO approach was too difficult to understand and
                  write, that it would never get adopted by the wider community. There
                  was a huge push going on to make D8 more DX friendly, mainly driven by
                  the Backdrop fork that was announced a few months earlier.



                  So we created these static methods that wrap the loading of the entity
                  manager from the container, and can be called directly from the
                  procedural side. It was great, since it offers a drop-in replacement
                  that works and looks very much like the original code. This made
                  porting of procedural D7 code vastly easier:



                  // Original D7 procedural code. 
                  $node = node_load($nid);

                  // New D8 procedural code.
                  $node = Node::load($nid);






                  share|improve this answer














                  There is actually an issue about adding this info to the docs.



                  In short, the long winded version is unit test friendly.



                  A comment by one of the Core's contributors fully detailed explains why. Just to highlight the main point:




                  If we call Node::load() in OO code we are breaking this principle (dependency inversion),
                  because we are hardcoding the specific implementation
                  (DrupalnodeEntityNode::load() to be exact). This code path is hard
                  coupled to Drupal::entityManager() which is hard coupled to
                  Drupal::$container. So now our code becomes impossible to run outside
                  of Drupal.



                  Furthermore, since code that uses the dependency inversion principle
                  is fully standalone it is very easy to unit test it by mocking the
                  dependencies according to the requested interfaces. If we introduce
                  Node::load() then it becomes really hard to "properly" unit test the
                  class, since it will start polluting the test environment with
                  external code, and the dependency injection container is not available
                  in unit tests.




                  Now if you wonder then why does Entity::load exists




                  There were many loud voices at the time that D8 was going to be a DX
                  disaster, that the OO approach was too difficult to understand and
                  write, that it would never get adopted by the wider community. There
                  was a huge push going on to make D8 more DX friendly, mainly driven by
                  the Backdrop fork that was announced a few months earlier.



                  So we created these static methods that wrap the loading of the entity
                  manager from the container, and can be called directly from the
                  procedural side. It was great, since it offers a drop-in replacement
                  that works and looks very much like the original code. This made
                  porting of procedural D7 code vastly easier:



                  // Original D7 procedural code. 
                  $node = node_load($nid);

                  // New D8 procedural code.
                  $node = Node::load($nid);







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 4 hours ago

























                  answered 5 hours ago









                  No Sssweat

                  19k73161




                  19k73161






















                      up vote
                      1
                      down vote













                      I think this is about the target audience of the code example. If it is for a hook, then I agree, use the first more easy to read approach.



                      If it is for a service, then the correct approach would be to inject the entity type manager and use it instead of the static Drupal wrapper.



                      $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid);


                      Now the question is what if you want to provide a more universal code example, then



                      $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);


                      is probably the best approach, because it works in procedural code if you copy and paste it and can be easily adapted for a service where you want to inject the dependencies.






                      share|improve this answer
























                        up vote
                        1
                        down vote













                        I think this is about the target audience of the code example. If it is for a hook, then I agree, use the first more easy to read approach.



                        If it is for a service, then the correct approach would be to inject the entity type manager and use it instead of the static Drupal wrapper.



                        $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid);


                        Now the question is what if you want to provide a more universal code example, then



                        $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);


                        is probably the best approach, because it works in procedural code if you copy and paste it and can be easily adapted for a service where you want to inject the dependencies.






                        share|improve this answer






















                          up vote
                          1
                          down vote










                          up vote
                          1
                          down vote









                          I think this is about the target audience of the code example. If it is for a hook, then I agree, use the first more easy to read approach.



                          If it is for a service, then the correct approach would be to inject the entity type manager and use it instead of the static Drupal wrapper.



                          $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid);


                          Now the question is what if you want to provide a more universal code example, then



                          $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);


                          is probably the best approach, because it works in procedural code if you copy and paste it and can be easily adapted for a service where you want to inject the dependencies.






                          share|improve this answer












                          I think this is about the target audience of the code example. If it is for a hook, then I agree, use the first more easy to read approach.



                          If it is for a service, then the correct approach would be to inject the entity type manager and use it instead of the static Drupal wrapper.



                          $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid);


                          Now the question is what if you want to provide a more universal code example, then



                          $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);


                          is probably the best approach, because it works in procedural code if you copy and paste it and can be easily adapted for a service where you want to inject the dependencies.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered 39 mins ago









                          4k4

                          47.7k35188




                          47.7k35188



























                               

                              draft saved


                              draft discarded















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdrupal.stackexchange.com%2fquestions%2f270376%2fwhy-do-so-few-code-examples-use-the-loadid-method-for-loading-entities%23new-answer', 'question_page');

                              );

                              Post as a guest













































































                              Comments

                              Popular posts from this blog

                              What does second last employer means? [closed]

                              List of Gilmore Girls characters

                              Confectionery