Good evening! If I understood correctly, then in your implementation, when you create an object of the Goods class, a call is initiated to the database to retrieve the data with which the object will be initialized. With this approach, when creating collections of objects, you will encounter the problem of (n + 1) queries, where n is the number of identifiers found, and 1 is the first query that looks for object identifiers that satisfy the filtering conditions. It is obvious that such a number of requests is redundant and all the necessary data can be collected in one request. It would be more appropriate to single out a separate GoodsFinder class, the responsibility of which would be to find relevant records in the database.
$finder = new GoodsFinder(); $goods = $finder->find($id);
The find method must return an initialized instance of the Goods class. In this case, you need to rewrite the constructor of the Goods class so that it takes as input parameters the data obtained from the database and passes their values ββto its internal properties. In this way, you place the interaction code with the database into a separate class, and your business model will be responsible only for compliance with business rules, you will get a clearer division of responsibility and the code will be easier to maintain in the future. Plus, this code is easier to cover with unit tests. So getting a collection of objects will look something like this:
$collection = $finder->findBy($filters); Class GoodsCollection { private $objects = []; public function __construct($data) { foreach ($data as $row) { $this->objects[] = new Goods($row); } } // ... ΠΌΠ΅ΡΠΎΠ΄Ρ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΠΈΠ· ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΠΈ }
There is, of course, the option to leave the code to interact with the database in the Goods class, overriding the constructor:
Class Goods { // ΠΡΠ»ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΠΌ ΠΌΠ°ΡΡΠΈΠ², ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΡΠ΅ΠΌ ΡΠ²ΠΎΠΉΡΡΠ²Π° ΠΊΠ»Π°ΡΡΠ°, Π΅ΡΠ»ΠΈ Π½Π΅Ρ, Π΄ΠΎΠΏΡΡΠΊΠ°Π΅ΠΌ, ΡΡΠΎ Π½Π° Π²Ρ
ΠΎΠ΄ ΠΏΡΠΈΡΠ΅Π» ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΈ ΠΈΡΠ΅ΠΌ Π΄Π°Π½Π½ΡΠ΅ Π² Π±Π°Π·Π΅ public function __construct($initData) { if (is_array($initData) { $this->setProperties($initData); } else { $this->find($initData); } } }
This method can be resorted to if too many components of the system rely on the terms of the contract designer. Although I would advise you not to be lazy and refactor the code with segregation of duties. These are general guidelines. I also advise you to read about object-relational mapping patterns, such as: ActiveRecord, TableGateway, and DataMapper. Also, do not forget that there are already ready-made solutions (for example, in Yii - ActiveRecord, Doctrine is a good example of the integrated application of object-relational mapping patterns), it may be too late to implement them in your project. In any case, a peek at the repository of ready-made solutions would be a great idea to see how they implemented it.