[note] It is strongly recommended that implementation Classes use full private property vars with protected lazy creation/configuration methods (rather than just local variables) ! It has many advantages and is UML friendly ! (TIP: use code template expansion.)

Please when working with OOE = Object Oriented Examples = One Of Each code like this, with explicit private Interface variables that are "lazily" (as needed) assigned implementations and configured in protected lazy creation/configuration methods. And please only then access the Interfaces via their matching lazy methods:

  /**
   *
   * @var \Drupal\ooe\Demo\OoePageController
   *   A demo welcome page controller.
   */
  private $ooePageController;
 
  /**
   *
   * @return \Drupal\ooe\Page\IPageController
   *   A lazily created demo welcome page controller.
   */
  protected function ooePageController() {
    if (empty($this->ooePageController)) {
      $this->ooePageController = new OoePageController();
    }
    return $this->ooePageController;
  }
 
  /**
   *
   * @var \Drupal\ooe\Page\IPageMenuItem 
   *   A menu item for the welcome page.
   */
  private $menuItemWelcome;
 
  /**
   *
   * @return \Drupal\ooe\Page\IPageMenuItem 
   *   A lazily created and configured menu item for the welcome page.
   */
  protected function menuItemWelcome() {
    if (empty($this->menuItemWelcome)) {
      $this->menuItemWelcome = $this->factory()->newPageMenuItem(
          $this->ooePageController(), 
          $this->getModule(), 
          $this->getModuleDisplayName() . ': Demonstrations welcome page', 
          $this->getModule() //'Since we are not using the admin/config path, our item will appear in the Navigation menu.'
      );
      $this->menuItemWelcome->forceAccessCallbackTRUE();
      $this->menuItemWelcome->setExpanded(true); //!
    }
    return $this->menuItemWelcome;
  }

Please note that:

- Because explicit private variables (rather than say variables local to a method) are used, the variables can be caught by PEAR: PHP UML and represented as Property attributes in the graphical UML model !

- A lazy creation method must NEVER return null; it must always return at least a valid object.

- A lazy creation method should usually return an Interface; in some special cases - like a simple demo class - lazy creation methods that return an implementation Class may be acceptable (see for example DemoOfMenuTabs).

- The lazy creation method ooePageController() does not need to perform any configuration, however if it did need any default configuration, that is where it would go, NOT in the constructor !

- The lazy creation method menuItemWelcome() not only lazily (as needed) creates an IPageMenuItem (via a factory) it also performs additional configuration beyond that offered by the factory method.

IMPORTANT: when menuItemWelcome() needs to access the IPageController of $ooePageController, it does it via the lazy creation/configuration method $this->ooePageController(), not via the variable $this->ooePageController ! That way it is absolutely, 100% certain that it is fetching something that is non-null and correctly configured !

This UML-friendly strategy is known as cascading lazy instantiation/configuration, and it is extremely powerful. It means you always know exactly where Interface variables are created (and where/how the implementation is chosen) and configured, and where they are documented, including type information. It is worth the effort, and long term, it is much easier and tidier than not using cascading lazy instantiation.

IDEs like NetBeans offer dynamic code templates that can be customised to generated much of the above code easily:
/**
 *
 * @var ${type}
 *   A ${desc}.
 */
private $$${var};
 
/**
 *
 * @return ${type}
 *   A lazily created and configured ${desc}.
 */
protected function ${var}() {
  if (empty($this->${var})) {
    $this->${var} = $this->factory()->new${Var}();
    // $this->${var}->..
  }
  return $this->${var};
}

The code template above works like a charm, except there seems to be a bug in NetBeans, PHP code templates only work outside a Class, so I perform the expansion in a scratch file them copy it into the Class file.

One also has to ensure the types are fully namespace expanded for them to be recognised by PEAR: PHP UML, so after expansion in NetBeans simply place the cursor after the type and press CTRL+SPACE, then choose the same type from the prompting list, and it will be automatically namespace expanded.

Note applies to ...
Visit also