How should we be using Models & Records? #10063
-
This has been a repeated topic of discussion over the years; however, I wanted to bring it up again to try to make sure it's clear; because based on the conversations I've recently had, there's still a lot of confusion. The docs from Craft 2 say we should only be using ActiveRecords in our services, but I couldn't find updated docs for Craft 3 on this topic. Based on how things are currently structured, it seems like this is the idiomatic approach (based on how a Site is saved):
Based on this, these are the assumptions I would make:
So my question is, are these assumptions correct, and if so, how could I more easily explain this reasoning and why it makes sense to a new developer extending Craft? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
I recall having a conversation with @brandonkelly about this some time ago; the details are fuzzy, but I believe they went with using I'm assuming they did the performance timings on ActiveRecord, and using it throughout resulted in worse performance than the aforementioned pattern. |
Beta Was this translation helpful? Give feedback.
-
It's difficult to make it short, isn't it? I'm trying to find ways to simplify these concepts too because Craft is new to my organization and we might be using it more. The docs provide a bunch of this info already, but here's how I have it organized in my head. Please let me know if I misunderstand anything. Given that "model" implies "Element"... Elements are models and a lot moreElements have validation rules and scenarios, so they are the model, just with a ton of functionality around custom fields, and more. Element QueriesExample: Element Queries come with custom field chaining, assume you only want enabled status (use ActiveRecordIf you just need to write something quick to the database, use ActiveRecord. It's relatively slow, but writes don't happen often (hopefully) and you end up with really clean, readable code which is another kind of optimization. You'll find it in the You don't have to use ActiveRecord, it's just quick to write and easy to read. Query BuilderIf you don't need the overhead of either of those, then a An example from Craft's own code: $this->groupId = (new Query())
->select(['id'])
->from([Table::USERGROUPS])
->where(Db::parseParam('handle', $value))
->column(); It's not a huge leap from ActiveRecord and you'll find places in Craft core where it's used for quick writes and reads in place of ActiveRecord. The Yii Query Builder docs are very helpful. DB Commands
// with great power...
Craft::$app->getDb()->createCommand('delete * from elements')->execute(); |
Beta Was this translation helpful? Give feedback.
-
There’s nothing inherently wrong with using ActiveRecord, and it’s not something I feel super strongly about one way or the other. But we have avoided it for a few reasons:
If you want to follow our lead, then yes. Saving data is basically the only reason we keep Craft’s own AR classes around, as they still provide a little value there (e.g. tracking changed values) and are more elegant than manually constructing an
Correct. No reason to validate twice, and validation should always happen as early as possible, before we’ve committed to saving something to the database. That’s particularly important for things getting stored to the Project Config, where the PC data has already been updated by the time the DB gets written to.
If performance could benefit from AR eager-loading, it might be worth considering. Craft doesn’t offer any better solutions, besides for elements.
Probably, given AR’s caveats.
No opinion here. If something like
Great question. It seems to me like part of the solution might be that we need to become a bit more dogmatic: avoid AR entirely in Craft’s own code, and come up with a better solution for keeping models, the database, and the project config data in sync. Unlikely that we’ll have time to address that in time for 4.0, but maybe after that ships. In the meantime, we are open to ideas on how the docs could be improved. |
Beta Was this translation helpful? Give feedback.
There’s nothing inherently wrong with using ActiveRecord, and it’s not something I feel super strongly about one way or the other. But we have avoided it for a few reasons:
D…