Announcement

Collapse
No announcement yet.

Custom services no longer recommended

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Custom services no longer recommended

    From this page: Note: Not recommended since v6.0.

    I don't really understand how services are supposed to be used yet, but I'm thinking about creating a custom service to share code between custom hooks and jobs. For example, I need to collect information about related entities in a hook and job for one of my entities. It's literally the same code copied from the custom hook into the custom job. There has to be a better way, right? How would I share this code between a hook and job?

    Code:
    48 private function getUnits($entity) {
    49   $timesheetData = $this->getTimesheetData($service);
    50
    51   $unitsUsed = 0;
    52   foreach($timesheetData as $td) {
    53     $unitsUsed += $td->get("unitsBilled");
    54   }
    55   return $unitsUsed;
    56 }
    57
    58 private function getTimesheetData($service) {
    59   return $this->getEntityManager()->getRepository('Service')->getRelation($service, 'timesheetData')->find();
    60 }

  • #2
    Before v6.0 when we didn't have sane dependency injection framework it was supposed to write business logic in service classes (located in Services directory). This service classes are supposed to be created by ServiceFactory.

    As of v6.1 we have mature dependency injection framework that allows to have business logic wherever we want. You can have it in a class Espo\Service\MyService, or Espo\Tools\MyTool\Service, or any other. You just require this class in the constructor of your Hook (or Controller, Job, whatever).

    PHP Code:
    <?php

    namespace Espo\Custom\Hooks\MyEntity;

    use 
    Espo\Custom\MyCustomService;

    class 
    MyHook
    {
        private 
    $service;

        public function 
    __construct(MyCustomService $service)
        {
             
    $this->service $service;
        }


        public function 
    afterSave(Entity $entity): void
        
    {
            
    $this->service->doSomethingWithEntity($entity);
        }
    }

    I should rephrase in the docs, that using Service Factory is not recommended rather than Services.
    Last edited by yuri; 07-22-2021, 07:24 AM.

    Comment


    • #3
      Thanks for the reply. I tried to implement your instructions for an entity called Service; it works in Hooks, but not Jobs. The test function emits a message to the log, but the rest of the calls stop working. Is it because I added code to the custom/Espo/Custom/Services/Service.php file? That file was generated automatically when I created the Service entity.

      This test code in custom/Espo/Custom/Services/Service.php:
      PHP Code:
      <?php
      2
      3  
      namespace Espo\Custom\Services;
      4
      5  
      class Service extends \Espo\Core\Templates\Services\Base
      6  
      {
      7    public function test($str) {
      8      $GLOBALS['log']->debug($str);
      9    }
      10 }

      The hook, which works, in custom/Espo/Custom/Hooks/Service/SaveService.php:

      PHP Code:
      <?php
      2
      3  
      namespace Espo\Custom\Hooks\Service;
      4
      5  
      use \Espo\Core\Exceptions\Error;
      6  use Espo\ORM\Entity;
      7
      8  
      use Espo\Custom\Services\Service;
      9
      10 
      class SaveService extends \Espo\Core\Hooks\Base
      11 
      {
      12   private $serviceTest;
      13
      14   
      public function __construct(Service $service) {
      15     $this->serviceTest $service;
      16   }
      17
      18   
      public function beforeSave(Entity $en, array $options = array()) {
      19     $GLOBALS['log']->debug("SaveService: beforeSave");
      20     $this->serviceTest->test("hello2");
             ...
      49   }
      50 }

      Log:
      Code:
      [2021-07-22 16:26:06] DEBUG: SaveService: beforeSave [] []
      [2021-07-22 16:26:06] DEBUG: hello2 [] []

      The job, which does not work, in custom/Espo/Custom/Jobs/UpdateServiceUnits.php:
      PHP Code:
      <?php
      2
      3  
      namespace Espo\Custom\Jobs;
      4
      5  
      use Espo\Custom\Services\Service;
      6
      7  
      class UpdateServiceUnits extends \Espo\Core\Jobs\Base
      8  
      {
      9    private $serviceTest;
      10
      11   
      public function __construct(Service $service) {
      12     $this->serviceTest $service;
      13   }
      14
      15   
      public function run()
      16   {
      17     $this->serviceTest->test("hello");
      18     $services $this->getEntityManager()->getRepository('Service')
      19       ->where(['status' => ['Active''Future']])->find();
      20   }
      21 }

      Log:
      Code:
      [2021-07-22 16:33:43] DEBUG: hello [] []
      [2021-07-22 16:33:43] ERROR: CronManager: Failed job running, job [60f99de774b2a066a]. Error Details: Call to a member function get() on null at /var/www/aba/application/Espo/Core/Jobs/Base.php:45 [] []

      Comment


      • #4
        You should not use class inheritance as of v6.0. Moreover Espo\Core\Jobs\Base is deprecated.

        You have overridden the constructor that caused getEntityManager() not working.

        How it should be:

        PHP Code:
        namespace Espo\Custom\Jobs;

        use 
        Espo\Custom\MyCustomService;
        use 
        Espo\ORM\EntityManager;

        class 
        MyJob // no extending here
        {
            private 
        $service;

            private 
        $entityManager;

            public function 
        __construct(MyCustomService $serviceEntityManager $entityManager)
            {
                 
        $this->service $service;
                 
        $this->entityManager $entityManager;
            }

            ...

        Comment


        • #5
          Thanks for the response. I see what you mean now about the constructor.

          Are you saying class inheritance should not be used at all or only in jobs? I'm following the documentation on the website and it looks like inheritance is still used for hooks, but maybe I'm not understanding.

          Comment

          Working...
          X