3

My question is re: localization of ElementTypes in a plugin. I have the records all working fine in multiple locales.

The part that I'm not "getting" is I think there should be one Element in craft_elements and then for each localization, there should be one record in craft_elements_i18n yes? And then for each localization, there should be a separate record in my craft_seomatic_meta table for each localized version yes?

This is where in my controller it saves the ElementType: https://github.com/khalwat/seomatic/blob/master/controllers/SeomaticController.php#L173

And here is the function is calls in my service to save the element & record: https://github.com/khalwat/seomatic/blob/master/services/SeomaticService.php#L683

When I call $result = craft()->elements->getElementById($metaId, 'Seomatic_Meta', $locale); how does it "know" which record to look up to load the returned Seomatic_MetaElementType with data?

I'm clearly missing something basic regarding how this should all work

1 Answer 1

5

The part that I'm not "getting" is I think there should be one Element in craft_elements and then for each localization, there should be one record in craft_elements_i18n yes?

Yes.

And then for each localization, there should be a separate record in my craft_seomatic_meta table for each localized version yes?

Only if the values in that table need to be stored on a per-locale basis, which to my knowledge has never been the case until now with SEOmatic.

When I call $result = craft()->elements->getElementById($metaId, 'Seomatic_Meta', $locale); how does it "know" which record to look up to load the returned Seomatic_MetaElementType with data?

Any time you run an element query (which getElementById() does), the element type’s modifyElementsQuery() method will be called, which gives the element type a chance to make changes to the query. In yours, you have the following code:

$query
    ->addSelect('seomatic_meta.*')
    ->join('seomatic_meta seomatic_meta', 'seomatic_meta.elementid = elements.id')
    ->andWhere(DbHelper::parseParam('seomatic_meta.locale', $criteria->locale, $query->params));

That condition you’re adding to the query on the seomatic_meta.locale column is what is ensuring that the correct localized row in your seomatic_meta table will be included in the result.

That’s just for selecting elements though. I might be missing something, but looking at your SeomaticService::saveMeta() method, it doesn’t look like you’re ever ensuring that all of the localized rows are actually getting saved. If you take a look through ElementsService::saveElement(), you will see that one of the things it does is loop through the locales returned by $element->getLocales() and make sure that there’s an ElementLocaleRecord (elements_i18n row) for the element in each of those locales. If you want to store rows for each locale in your own craft_seomatic_meta table, it’s the plugin’s responsibility to do that, not Craft’s.

5
  • I was planning to store different data on a per-locale basis, just as I do with my regular old records. You saying that no one else has needed/wanted to do this makes me think that I'm doing something wrong? Should I not be storing this data in my own table? The "normal" way to do this would be to make a FieldType, and just have Craft handle the gory details, storing it in craft_content? I feel like perhaps I'm doing something wrong, if it's something no one else is doing. Commented Dec 24, 2015 at 8:22
  • 1
    @khalwat No to be clear I think you’re going about it the right way. This is just the first plugin (that I can think of) that needs to provide fields that store content, but not via custom fields. Commented Dec 24, 2015 at 15:46
  • @khalwat: If it makes you feel better, I've recently gotten the feature request to make Smart Map's "Address" field translatable... But Brandon's right, AFAIK you're the first plugin dev to actually try it. This is all great info, thanks to both of you guys!
    – Lindsey D
    Commented Dec 26, 2015 at 5:32
  • @BrandonKelly - Above you say that we can add support for grabbing a particular locale using the modifyElementsQuery() method. You point to the example coding adding an andWhere clause to do so. In looking at the EntryElementType and CategoryElementType, neither of those Elements seems to be limiting the result by locale in the modifyElementsQuery() method. Why are the above example and the Entry and Category Elements different? What am I missing? Commented Sep 1, 2016 at 23:41
  • @BenParizek Because none of the built-in element types need to store data on a per-locale basis, besides whatever’s in elements_i18n and content (and those tables are already joined in before modifyElementsQuery() is even called). Commented Sep 2, 2016 at 12:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.