2

I'm trying to create a structure using onBeforeInstall() that will be ready for a client to use after the plugin is installed.

Here's my code for onBeforeInstall():

public function onBeforeInstall()
{
    $section = new SectionModel();
    $section->name = 'Demo';
    $section->handle = 'demo';
    $section->type = 'structure';
    $section->hasUrls = 1;
    $section->template = 'demo/page';
    $section->enableVersioning = 1;
    $locale = craft()->sections->getSectionLocales(1)[0];
    $locale->urlFormat = 'demo/{slug}';
    $locale->nestedUrlFormat = '{parent.uri}/{slug}';
    $section->setLocales([ $locale ]);

    $response = craft()->sections->saveSection($section);
    if ($response) {
        var_dump("IT WORKED!");
        var_dump($response);
    } else {
        var_dump("nope.avi");
        var_dump($response);
    }
}

Unfortunately I get a CDbException

CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`craft`.`craft_sections_i18n`, CONSTRAINT `craft_sections_i18n_locale_fk` FOREIGN KEY (`locale`) REFERENCES `craft_locales` (`locale`) ON DELETE CASCADE ON UPDATE CASCADE). The SQL statement executed was: INSERT INTO `craft_sections_i18n` (`sectionId`, `locale`, `enabledByDefault`, `urlFormat`, `nestedUrlFormat`, `dateCreated`, `dateUpdated`, `uid`) VALUES (:row0_col0, :row0_col1, :row0_col2, :row0_col3, :row0_col4, :row0_col5, :row0_col6, :row0_col7). Bound with :row0_col0='7', :row0_col1=0, :row0_col2=1, :row0_col3='demo/{slug}', :row0_col4='{parent.uri}/{slug}', :row0_col5='2015-06-09 20:33:00', :row0_col6='2015-06-09 20:33:00', :row0_col7='864207ba-6e43-46cf-9fdb-3a72cda4c2df'`

I was basing my code loosely on this Stack Exchange question and answer, but for some reason I can't get structures to cooperate.

I think I'm not setting the locale properly. Is there a better way to set the locale, or am I overlooking something else?

2

I haven't used locales before so i'm not entirely sure, but when I looked in the craft service that saves a section there is a bit that looks like:

foreach ($sectionLocales as $localeId => $sectionLocale)
...

Which I assume then means your array needs to look like this:

array(
 'en' => // model
)

Whereas yours was looking like this:

array(
 0 => // model
)

So craft was seeing 0 as the locale id and it was failing.

So I managed to get this to work by using the following code:

public function onBeforeInstall()
{
  // Get the current locales ID
  $currentLocale = craft()->locale->getId();

  $section = new SectionModel();
  $section->name = 'Demo';
  $section->handle = 'demo';
  $section->type = 'structure';
  $section->hasUrls = 1;
  $section->template = 'demo/page';
  $section->enableVersioning = 1;

  // Index the locales by their ID e.g en returns array
  $locales = craft()->sections->getSectionLocales(1, 'locale');

  // Target the locale we want by the key in the array
  $locales[$currentLocale]->urlFormat = 'demo/{slug}';
  $locales[$currentLocale]->nestedUrlFormat = '{parent.uri}/{slug}';

  $section->setLocales($locales);

  $response = craft()->sections->saveSection($section);
}

The Demo section was added and I got the 'IT WORKED' response, I hope that helps!

Edit

I suppose if you didn't want all the locales to be saved to a section you could just do something like:

$specificLocales = array();

// After setting the locale attributes
$specificLocales[$currentLocale] = $locales[$currentLocale];

$section->setLocales($specificLocales);
  • This solution works providing a section with id of 1 exists, if you do not have a section at this point, you will need to create a SectionLocaleModel, set the urlFormat & nestedUrlFormat on that. Then that model can be the value of the array (where the key is the locale id). – joep Sep 11 '17 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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