<p>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:</p>

<pre><code>foreach ($sectionLocales as $localeId =&gt; $sectionLocale)
...
</code></pre>

<p>Which I assume then means your array needs to look like this:</p>

<pre><code>array(
 'en' =&gt; // model
)
</code></pre>

<p>Whereas yours was looking like this:</p>

<pre><code>array(
 0 =&gt; // model
)
</code></pre>

<p>So craft was seeing <code>0</code> as the locale id and it was failing.</p>

<p>So I managed to get this to work by using the following code:</p>

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

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

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

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

  $section-&gt;setLocales($locales);

  $response = craft()-&gt;sections-&gt;saveSection($section);
}
</code></pre>

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

<p><strong>Edit</strong></p>

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

<pre><code>$specificLocales = array();

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

$section-&gt;setLocales($specificLocales);
</code></pre>

CC BY-SA 3.0
2017-09-11T11:24:20.697Z
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
CC BY-SA 3.0
2015-06-10T07:43:22.090Z
2015-06-10T07:50:25.563Z
2015-06-10T07:50:25.563Z
Alec Ritson
<p>I'm trying to create a structure using <code>onBeforeInstall()</code> that will be ready for a client to use after the plugin is installed.</p>

<p>Here's my code for <code>onBeforeInstall()</code>:</p>

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

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

<p>Unfortunately I get a <code>CDbException</code></p>

<blockquote>
  <p>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'`</p>
</blockquote>

<p>I was basing my code loosely on <a href="https://craftcms.stackexchange.com/questions/6799/best-way-to-programmatically-create-categories">this Stack Exchange question and answer</a>, but for some reason I can't get structures to cooperate.</p>

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

<plugin-development><error-message><php>
Create Structure on Plugin Install
# Create Structure on Plugin Install

(Asked by: username_0 on 2015-06-09)

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?

**Tags:** plugin-development, error-message, php


---

## 1 answers

### Answer by username_1 on 2015-06-10. Score: 2 | Accepted answer

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);

> **Comments:**
> **username_2**: 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).  

---

