3

I'd like to ask what are your thought on deprecation of the TableRegistry::get() static call in CakePHP 3.6?

In my opinion it was not a good idea.

First of all, using LocatorAwareTrait is wrong on many levels. Most important, using traits in such way can break the Single Responsibility and Separation of Concerns principles. In addition some developers don't want to use traits as all because they thing that it breaks the object oriented design pattern. They prefer delegation.

I prefer to use delegation as well with combination of flyweight/singleton approach. I know that the delegation is encapsulated by the LocatorAwareTrait but the only problem is that it exposes the (get/set)TableLocator methods that can be used incorrectly.

In other words if i have following facade:

class Fruits {
    use \Cake\ORM\Locator\LocatorAwareTrait;

    public function getApples() { ... }
    public function getOranges() { ... }
    ...
}

$fruits = new Fruits();

I don't want to be able to call $fruits->getTableLocator()->get('table') outside of the scope of Fruits.

The other thing you need to consider when you make such changes is the adaptation of the framework. Doing TableRegistry::getTableLocator()->get('table') every time i need to access the model is not the best thing if i have multiple modules in my application that move beyond simple layered architecture.

Having flyweight/singleton class like TableRegistry with property get to access desired model just makes the development more straight forward and life easier.

Ideally, i would just like to call TR::get('table'), although that breaks the Cake's coding standards. (I've created that wrapper for myself anyways to make my app bullet proof from any similar changes)

What are your thoughts?

mbryja
  • 61
  • 1
  • 8
  • *Doing TableRegistry::getTableLocator()->get('table') every time i need to access the model* ofc it is wrong as you should do `$this->loadModel("modelName)` and later on `$this->ModelName` – Antoniossss May 25 '18 at 03:22
  • It's strange that you want singletons, they're most of the time also a bad choice. Also where do you have to use so much TableRegistry? However I totally agree about your critic that the traits aren't nice and that the way some things are done break the SRP. It's OK that you can instantiate the locator but without a DI container that can be used to automatically inject it when needed but using a trait instead feels indeed wrong. Actually I'm trying to build a hexagonal app with cake https://github.com/burzum/hexagonal-cake for learning purpose. – floriank May 25 '18 at 09:49
  • @Antoniossss, you are correct $this->loadModel() works great in controllers. Now what about custom modules? Often there is a requirement to encapsulate group of similar logic. It is commonly done with the event driven applications. What if you need to access other table in one of your models and there is no relation between objects other than business logic? Of course, you can say that business logic should go into components but they are not obvious choice for every developer. – mbryja May 25 '18 at 13:34
  • As you wrote, bussiness should be in services (Cake->component) and should. From there I no drawbacks of writing common easy to use table getter. – Antoniossss May 25 '18 at 13:39
  • @Antoniossss, but if you come from other frameworks they may not be the first choice. There is a popular, sometimes misleading assumption that business logic should be in the model. It's popular in frameworks like Symfony, Laravel or CodeIgniter. Maybe this should be more documented in cake little better. – mbryja May 25 '18 at 13:45
  • @burzum, singletons are powerful tool if used correctly and they should to be used with DI. I often use TableRegistry in models and custom libraries/packages. I've created microservice oriented application with cake and it works very well, especially when applied proper caching techniques. – mbryja May 25 '18 at 13:51
  • @mbryja I'm aware of that. Why shouldn't the business logic not be in the model? In DDD it should be in the domain model, but *only* logic that is 100% related to your business and describes the rules and checks. AFAIK the application layer then glues everything together. The model layer shouldn't be aware of the application layer, nor depend on it in *any* way. Where do you put the business logic? Or what is business logic for you? If you like to discuss this further because it's interesting and I like to hear other opinions, joint the cakephp Slack channel. :) – floriank May 25 '18 at 15:35
  • @burzum, that is a good question? It really depends on the architecture. In my case it can be described as manipulation of data before it is being persisted. Sometimes I need to access different models or make additional api calls before I save the data. and from that perspective it should be fine to place business logic in the model. But the problem is that you cannot easily access other models in cake without relations. – mbryja May 25 '18 at 16:27
  • "Sometimes I need to access different models or make additional api calls before I save the data." This is what a domain service or an application service (I'm not 100% sure on this) should do. So you need instances of models that are not associated? You could define the models you want as typed arg of the constructor and build your own locator that uses reflection to construct it or simply use an existing solution like league/container that will do that for you. $container->get('my-service') and it will do the job for you. – floriank May 25 '18 at 21:22
  • Create your own TableRegistry Class load there the LocatorAwareTrait and everything is like it was before. Next time consider using Laravel in that framework they use a lot facades and it is accepted and they don't change fundamental things like this. – TatzyXY Oct 11 '18 at 13:58

0 Answers0