-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ActiveRecord instantiate way #5771
Comments
why? this is completely unexpected behavior even if it was possible... |
actually because
i mentioned 2 solutions in first post |
I am more interested in the why than in the how. Please elaborate about your use case. What is |
This was examples of problem when i want to use constructor, but cant without overriding Now what i am doing : $profile = new Profile();
#add some attributes, etc
$user = new User($profile);
#perform some user management
$user->create(); //saving and raising event class User extends ActiveRecord
{
public function __construct(Profile $profile = null)
{
#save in create() method and raise event UserCreated
if ($profile) {
$this->profile = $profile;
}
}
} This is bad, because This a common issue to ORM and usually handles it in the way i've described, so the user dont want to worry about fetching entities and that they will spoil their domain . You never pass arguments to AR constructor or what was the question since as for me it is very often used ? |
@lynicidn you suggested a little bit different thing , however i see your point , yes general purpose is to avoid unneded creating of models through constructor when fething , modern ORM should not do this , yes ;D |
It is quite common to do initialization in init() method which is called in constructor so I do not think we should skip this step. |
what kind of initialization ? Cant it be done via |
Initialization that is used for every record, meaning newly instantiated as well as fetched from the database is best placed in When your business logic has to ensure that a model is always related with some other record, you already have this ensurance by using a NOT NULL constraint on the database field, don't you? |
dont understand, i gave you correct solutions almost on every your argument. Why then having before / after save and so on methods ? Can you give me correct
we are talking about different things here, i am talking about domain while you see entities relationships only as
when you will stop seeing AR only as simple mapper but as a unit for logic and entity you will understand what i am talking about ;) When you create new entity and pass to it needed dependencies on other entities it is part of domain, but when you fetch it you dont need it to do it again. Just dont think of AR as simple class |
I understand that it is possible to create a class without a constructor. My point is that if I write a constructor, I'd expect it to be called every time an object is created (see question below).
I am just trying to understand your idea, nothing more. It seems we have a communication problem so that you do not find the words to explain in a way that I understand or I am not able to express my questions in a way that you understand ;)
I do not really get why you are passing objects to the constructor. As far as I understood these objects are related records, aren't they? Maybe you could show some more code or link to some resources that explain this kind of programming style. As far as I understood you are proposing to pass related objects to constructor to ensure the relation is always there. However when fetched from the DB you propose to skip the constructor. This way you circumvent your own logic of ensuring an object is always passed, don't you? |
Well, i have, i am not sure if you will understand them since their from DDD and not sure if you up to it (not an offense of course), the problem that i want to avoid is
Simple example is
no, when i create |
What about using some kind of factory methods instead of constructors when creating models on domain level?
instead of
This could be a project specific convention on top of Yii standards that is easy to implement without changing the Yii code itself. As far as I understood it, the DDD repository concept does not exactly map to Yii's ActiveRecord and ActiveQuery (and also relies on non-Yii features like identity map)? |
you can implement an identity map by overriding the instantiate method btw. |
no, factory only needed when it is a real situaton for it, there are some holywar things going on this one like
the point is that The question for this issue is only to avoid this vital and main PI issue - reconstituting entity through the constructor. Afaik java allows you to have different constructors so there is no problem there, in php you do it by unserializing from string or reflection |
I totally agree that Yii2 AR and Doctrine2 are two different approaches. When you call it a "vital" issue, does that mean that the current constructor implementation would also break the alternative approach using factory methods? BTW: I'm far from advocating any holy "must only be done like this because it must" mantra. Factory methods just seemed like a pragmatic solution ;-) |
dont quite understand what are trying to say. However lets stick closer to Yii2 and this issue, and dont get far away, since discussion could get hijacked |
I was olny tying to say: If the way constructors are used in current ActiveRecord implementation prevented common approaches like factory methods, then I would agree that there is a vital issue with constructors. But this is not the case, right? Both processes, fetching existing models AND creating new models, might want to claim the constructor for their needs. We should imho refuse it to both of them and use separate methods for each. |
yes, as was said in java you can have different constructors so there is no problem there
we should not refuse it to the domain layer, so it can use it for their needs, however fetching and other things should be done avoiding calling excplicitly constructor, see some links above.
in your example and to what you are trying to refer |
So far it boils down to the question: What is the better tradeof? A) Using serialize/reflection for infrastructure layer (for everyone) While A certainly looks better for DDD, I'd still prefer B as a simple general purpose implementation, as Yii2 is not a genuine DDD framework. Do you see advantages of a serialize/reflection approach other than enabling entity constructors? |
it is not As for question |
I dont want to discuss when to use factories or not. My point is, that serialize/reflection is introducing some complexity. So I'm interested if these approaches also have any are other advantages. |
It dont introduce complexity since you will not be using it , it is only used when fetching entity , internally by fw. And it looks like you totally missed the point about PI and other things discussed above ) Lets stop for now and wait some other developers . Thanks |
The whole idea does not seem right to me. Avoiding invokation of the constructor, while fetching existing records, sounds like a hack. With such appraoch we attempting to get something from programming language, which it does not actually provide. Another point is overriding constructor is not a common practice for Yii. Yii objects and components are configured via public fields and virtual properties. Just remember your application config: [
'controllerPath' => '/path/to/controllers', // virtual property
'components' => [
'db' => [
'dsn' => 'yii\db\Connection',
'dsn' => 'somedsn', // public field
],
],
] Widgets are created in the similar way: <?= DatePicker::widget([
'model' => $model,
'attribute' => 'from_date',
'language' => 'ru',
'clientOptions' => [
'dateFormat' => 'yy-mm-dd',
],
]) ?> Using constructor to pass some configuration is just not "Yii style". In the particular example:
situation can be solved via
Also, I don't think 'Doctrine' is a good example in this matter: it processes relations in different way, so it uses a different notation and syntax, which is not common for Yii. |
@klimov-paul actually
i dont think that there will be some problems here, since the last one argument can always be
It is a different ORM, it keeps point on domain yes, however i think that some basic persistence ignorance issues can be solved by You noticed that for |
@samdark can you vote on this one ? If "No", then more then 50% developers are against and i will close this one, to not to introduce any confusion ;) |
I haven't seen this one. Can't vote on it now. I need to understand it first... |
Moved to new issue since discussion here went in totally wrong direction. |
I think it is better to create new active records when fetching them from the repository without calling the constructor, it can be done through the reflection . The big advantage here is that we dont need to spread our application logic and separate it from simple fetching entities that has nothing to do with real logic, and we dont need to override
instantiate()
method.I dont think there will be a lot of problems with speed, since we can save already processed classes reflections and just clone new object from one created by reflection. Even more, i dont think that there will be involved more then 10 entities per request, usually it is not so big .
Doctrine 2
uses other approach but very similar and this , afaik it is also used inphpunit
and other fw to create class not through reflectionWhat do you think @qiangxue @samdark @cebe ?
The text was updated successfully, but these errors were encountered: