Decorating Entity Manager to Avoid Inheritance - Build Expense Tracker App With PHP 8

Поделиться
HTML-код
  • Опубликовано: 9 апр 2023
  • In this video, we do a little more refactoring to get rid of inheritance and replace it with composition by decorating the internal entity manager.
    SOME OF THE WAYS YOU CAN SUPPORT THE CHANNEL
    👍 Smash the like button
    🤝 Subscribe to the channel & turn the notifications on
    💬 Post comments, any feedback is greatly appreciated
    ⭐ Become a Patreon: / programwithgio
    THANK YOU!
    🛠️ TOOLS & SERVICES I USE
    Digital Ocean Hosting - Get 100$ credit - m.do.co/c/38b935ad74e5
    Domains on Namecheap - namecheap.pxf.io/rnRjdQ
    Envato Elements - 1.envato.market/c/2937311/298...
    LESSON P.26
    Starting Source Code - github.com/ggelashvili/expenn...
    Ending Source Code - github.com/ggelashvili/expenn...
    Course Outline - github.com/ggelashvili/learnp...
    Course Playlist - • Learn PHP The Right Wa...
    ** Affiliate Disclaimer: Some of the above links may be affiliate links, which may generate me a sales commission at no additional cost to you.

Комментарии • 29

  • @rezalaal
    @rezalaal Год назад +5

    You are the best person who can teach PHP programming concepts in the best way possible. Thank you😍

  • @adelhishem1
    @adelhishem1 Год назад +5

    Highest php tutorials quality on RUclips, hands down. Thank you for the effort and for sharing your great content 👍

  • @Zubbee
    @Zubbee Год назад +1

    Wow I really have some catching up to do. Then I see your posting days have changed a bit. No problem at all. Thanks Gio. Your channel is special...

    • @ProgramWithGio
      @ProgramWithGio  Год назад

      Thank you. Experimenting with different days, will be back to usual Tuesdays for new videos soon

  • @Zubbee
    @Zubbee Год назад

    I took a while with this video. The decisions that precede refactoring is intriguing and requires a lot of understanding. Decorating entity manager with the entitymanagerservice class and interface was so cool but I couldn't get @mixin to work on vscode so autocomplete for the other entity manager methods isn't working. I am still reading up, searching, trying to figure out how to make it work in vscode. Never the less this is a great lesson. Thanks Gio

    • @ProgramWithGio
      @ProgramWithGio  Год назад

      Thank you. Yea not sure if mixin works in vscode, maybe there is alternative.

  • @barneysmith
    @barneysmith Год назад

    great! i am learning a lot through your explanations.👍

  • @mortezaayashi9581
    @mortezaayashi9581 День назад

    9:58 Why we didn't use persist method?

  • @amitkumargupta3715
    @amitkumargupta3715 3 месяца назад

    Great

  • @al.e.k
    @al.e.k Год назад +1

    Hi there! What do you think about moving calls to entity manager service from controller to specific service? So, controller will have less dependencies and would be more lightweight. Also, data manipulation will be closer to data itself in services. And incapsulation principle would not be broken.

    • @ProgramWithGio
      @ProgramWithGio  Год назад +1

      Hey, sure there are many ways to structure it. EntityManagerService is that service class that handles entity manager calls. If you mean moving entity manager method calls within individual services like CategoryService then no because it creates coupling between Category and entity manager, that's why I refactored it. I want to avoid too much abstraction & am ok with the trade offs. If you mean having another layer of abstraction between each service that also contains entity manager then yea but again might be too much abstraction for a small app we are building.

    • @al.e.k
      @al.e.k Год назад

      @@ProgramWithGio Hi again!
      >EntityManagerService is that service class that handles entity manager calls.
      Yes, the idea of wrapping (decorating) EntityManager into EntityManagerService is good, because it simplifies usage of db tools.
      > If you mean moving entity manager method calls within individual services like CategoryService then no because it creates coupling between Category and entity manager, that's why I refactored it.
      Hmm, unfortunately, I don't understand what do you mean about coupling, because CategoryService after refactoring depends on EntityManagerServiceInterface.
      But it's ok, because CategoryService needs EntityManager anyway to manipulate data.
      As I see, before refactoring CategoryController was dependent on CategoryService.
      After refactoring it depends not only on CategoryService but on EntityManagerServiceInterface.
      So, coupling was even raised, wasn't it?
      Imho, all actions using EntityManagerService should be done inside corresponding service, not in controller.
      Because it's a responsibility of the CategoryService to manipulate its Entities.
      In your case this responsibility partially placed in controller instead of CategoryService and I don't understand the reasons of it.
      What if you will need to create Entities, for example, inside Jobs or Commands?
      You have to do it also in 2 lines of code like in controller:
      $category = $this->categoryService->create(...);
      $this->entityManagerService->sync($category);
      Therefore, you have to embed EntityManagerServiceInterface contract into Job or Command too. This will increase coupling.
      If you will make tests for this controller, you will have to mock not only CategoryService but EntityManagerService too.
      As for me, it's better to encapsulate all store & sync in CategoryService method and do work in just one line of code:
      $category = $this->categoryService->create(...);
      There is no coupling increasing, because CategoryService needs EntityManagerServiceInterface anyway.

    • @ProgramWithGio
      @ProgramWithGio  Год назад

      Yea in general I agree but here it's a bit different. Having to call flush & persist within CategoryService creates a problem where you can't use those methods within a loop for example. What if you had to create categories within a loop, you would be calling create method on category service which calls flush for each create and that is anti pattern and bad for performance as demonstrated in previous lessons. That's what I meant by coupling. Another example is if you had to create a category and also a transaction at the same time within maybe a job or command, you would be calling create on category service & create on transaction service, with your approach you would be calling flush twice which is not ideal.
      Injecting as a dependency is fine, using inheritance is not because with injection you can pass any implementation of entirymanager interface but with inheritance it would cause problems with testing as you mentioned. Now it's easier to test this because you can simply create a testing manager service and implement the interface and pass that as dependency.
      As I mentioned there are pros & cons with each approach. This way individual service class does not care about persisting with database, instead a job or command or controller will do that at the end once all operations is complete. Hope that makes sense.

    • @al.e.k
      @al.e.k Год назад

      @@ProgramWithGio Thanks for explanations, now I got it.
      It's possible to go deeper and create new class like that:
      =======
      class CategoryServiceWithAutoSave implements CategoryServiceInterface
      {
      public function __construct(
      private readonly EntityManagerServiceInterface $entityManager,
      private readonly CategoryService $categoryService
      )
      {
      }
      public function create(string $name, User $user): Category
      {
      $category = $this->categoryService->create($name, $user);
      $this->entityManagerService->sync($category);
      return $category
      }
      }
      =======
      In simple controllers/jobs/commands we can use CategoryServiceWithAutoSave, but in complex places or when we need bulk create, insert or update, we can use current CategoryService.

    • @ProgramWithGio
      @ProgramWithGio  Год назад

      Yup, that's another option. Multiple ways to structure it. I decided to keep it simple for this project to not overcomplicate. You are asking the right questions & have the right ideas so good job 🙌

  • @Th3Firebird
    @Th3Firebird Год назад

    Hi Gio, did you make a separate video about a resource type in php?

    • @ProgramWithGio
      @ProgramWithGio  Год назад

      No, by resource in this video I mean entities

  • @user-us5vw5br6g
    @user-us5vw5br6g Год назад

    all is good, just one question (may be it will be in the next videos) - why EM sync/delete are using in controllers and not in services ? I mean if we have some service for some entities and logic then controllers is should has just IO role (only on my opinion). Thx.

    • @ProgramWithGio
      @ProgramWithGio  Год назад

      Check the replies to Alexander's comment on this video. We discussed that. Multiple ways to structure it, I just decided to go with this way to avoid over abstraction.

  • @ScorpusMugnes
    @ScorpusMugnes Год назад +1

    Hello Gio, I was working with routers and views, but I got stack because Iam not capable of loading assets like JavaScript, CSS and images and the template engine Iam using is .php files and I don't want to change to other templating engines like twig and blade. How can I load and include those assets with Apache configurations of virtual hosting. Because at first, I tried to include them by requiring them normally as files but that can't work with images Can you please help me with that.

    • @ProgramWithGio
      @ProgramWithGio  Год назад +1

      They should work fine, in apache vhost you define document root so your assets will just be relative to that path. For example if your js is in public/js/app.js then you can load it in code by /app.js because document root is /public.

    • @ScorpusMugnes
      @ScorpusMugnes Год назад +1

      @@ProgramWithGio I did that and tried but nothing happens my document root is called education and my images directory is in education/images but it's seems impossible to load them into my templates and tried using your method but nothing changed I need something else to try 😵😵😵help me please

    • @ProgramWithGio
      @ProgramWithGio  Год назад +1

      @@ScorpusMugnes where is your index.php located? DM me on Twitter and send me screenshots of your code structure as well as your vhosts config and I can help troubleshoot it

    • @ScorpusMugnes
      @ScorpusMugnes Год назад +1

      @@ProgramWithGio thanks a lot for that am gonna do it

    • @ScorpusMugnes
      @ScorpusMugnes Год назад +1

      I tried sending you a DM on twitter but due to a network connection issue in my location it couldn't be sent Iam very sorry for that But I will try to resend it again with the screenshots of my code structure and configurations tomorrow or later thanks again for your generosity and patience 👌👌👌👌👌👌👌👌👌👌