Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-09-11T11:24:20.697Z
Answers.Text: 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).
Answers.UserDisplayName: joep
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-06-10T07:43:22.090Z
Answers.LastActivityDate: 2015-06-10T07:50:25.563Z
Answers.LastEditDate: 2015-06-10T07:50:25.563Z
Answers.UserDisplayName: Alec Ritson
Body: <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>
  
Tags: <plugin-development><error-message><php>
Title: Create Structure on Plugin Install
ThreadText: # 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](https://craftcms.stackexchange.com/questions/6799/best-way-to-programmatically-create-categories), 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).  
  
  ---
  
  