Answers.Body: <p>This:</p>
  <pre class="lang-php prettyprint-override"><code>class Settings extends Model
  {
      public string $apiKey;
  }
  </code></pre>
  <p>Should look like this:</p>
  <pre class="lang-php prettyprint-override"><code>class Settings extends Model
  {
      public string $apiKey = '';
  }
  </code></pre>
  <p>What's happening is due to the way Yii2 models work, they interrogate a class for its properties in such a way that it accesses their values before the rest of your code even runs.</p>
  <p>So you need to initialize any typed values with some kind of default value, as per the above.</p>
  <p>You can also declare them as nullable, but you still have to explicitly initialize there, too. e.g.:</p>
  <pre class="lang-php prettyprint-override"><code>class Settings extends Model
  {
      public ?string $apiKey = null;
  }
  </code></pre>
  <p>It's due to Craft CMS using types (made available more fully in PHP 8) in their base classes, and method &amp; property signatures must match in child classes. This is a positive thing overall, but yes, requires some work to convert things over.</p>
  <p>We did a few videos on this on <a href="https://craftquest.io" rel="nofollow noreferrer">CraftQuest.io</a>:</p>
  <ul>
  <li><a href="https://craftquest.io/livestreams/craftquest-on-call-40-rector-set-go" rel="nofollow noreferrer">CraftQuest on Call 40: Rector Set Go!</a></li>
  <li><a href="https://craftquest.io/courses/adopt-a-plugin-guide" rel="nofollow noreferrer">Adopt-a-Plugin: Guide</a></li>
  </ul>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-11-17T17:53:02.100Z
Answers.Text: This indeed resolved it, thank you. However, I'm curious why this broke when upgrading to Craft 4. Is it because of something Craft 4 changed, or implicitly due to PHP8 being required?
Answers.UserDisplayName: Paul Hübner
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-11-18T20:09:23.880Z
Answers.Text: It's due to Craft CMS using types (made available more fully in PHP 8) in their base classes, and method & property signatures must match in child classes. This is a positive thing overall, but yes, requires some work to convert things over.
Answers.UserDisplayName: andrew.welch
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-11-18T20:15:40.430Z
Answers.Text: I updated the original answer with links to videos showing how to update plugins from Craft 3 to Craft 4.
Answers.UserDisplayName: andrew.welch
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-11-15T16:04:54.357Z
Answers.LastActivityDate: 2022-11-18T20:13:29.153Z
Answers.LastEditDate: 2022-11-18T20:13:29.153Z
Answers.UserDisplayName: andrew.welch
Body: <p>I maintain a plugin. Inside this plugin's <code>composer.json</code>, <code>extra</code>&gt;<code>handle</code> is set to <code>pizza</code> (not the real name).</p>
  <p>In one of the controllers, the following code is executed:</p>
  <pre class="lang-php prettyprint-override"><code>$apiKey = Plugin::$plugin-&gt;getSettings()-&gt;apiKey;
  </code></pre>
  <p>Prior to upgrading to Craft 4 (specifically, 4.3.1), this worked fine on Craft 3. Now, on Craft 4: <code>Typed property pizza\models\Settings::$apiKey must not be accessed before initialization</code>.</p>
  <p>I have read through <a href="https://craftcms.com/docs/4.x/extend/plugin-settings.html" rel="nofollow noreferrer">this article</a> and as far as I know we follow everything.</p>
  <p>There exists a model:</p>
  <pre class="lang-php prettyprint-override"><code>&lt;?php
  
  namespace pizza\models;
  
  use Craft;
  use craft\base\Model;
  
  class Settings extends Model
  {
      public string $apiKey;
  }
  </code></pre>
  <p>Which is provided by the plugin class:</p>
  <pre class="lang-php prettyprint-override"><code>    protected function createSettingsModel(): ?Model
      {
          return new Settings();
      }
  </code></pre>
  <p>Furthermore, there exists a file <code>config/pizza.php</code> with the following:</p>
  <pre class="lang-php prettyprint-override"><code>&lt;?php
  
  use craft\helpers\App;
  
  return [
      'apiKey' =&gt; App::env('PIZZA_API_KEY'),
  ];
  </code></pre>
  <p>On the admin page <code>example.com/admin/utilities/php-info</code> it shows that <code>$_ENV['PIZZA_API_KEY']</code> is set to a value, it is not null or empty.</p>
  <p>I'm lost as to why this property is not initialized. The same plugin, same version does not throw this error on another site that is Craft 4 (albeit 4.2.3, so perhaps there has been a change that breaks this?).</p>
  
Tags: <plugin-development><craft4><api>
Title: Updating to Craft 4 breaks plugin settings: must not be accessed before initialization
ThreadText: # Updating to Craft 4 breaks plugin settings: must not be accessed before initialization
  
  (Asked by: username_0 on 2022-11-15)
  
  I maintain a plugin. Inside this plugin's `composer.json`, `extra`>`handle` is set to `pizza` (not the real name).
  
  In one of the controllers, the following code is executed:
  
  ```php
  $apiKey = Plugin::$plugin->getSettings()->apiKey;
  
  ```
  
  Prior to upgrading to Craft 4 (specifically, 4.3.1), this worked fine on Craft 3. Now, on Craft 4: `Typed property pizza\models\Settings::$apiKey must not be accessed before initialization`.
  
  I have read through [this article](https://craftcms.com/docs/4.x/extend/plugin-settings.html) and as far as I know we follow everything.
  
  There exists a model:
  
  ```php
  <?php
  
  namespace pizza\models;
  
  use Craft;
  use craft\base\Model;
  
  class Settings extends Model
  {
      public string $apiKey;
  }
  
  ```
  
  Which is provided by the plugin class:
  
  ```php
      protected function createSettingsModel(): ?Model
      {
          return new Settings();
      }
  
  ```
  
  Furthermore, there exists a file `config/pizza.php` with the following:
  
  ```php
  <?php
  
  use craft\helpers\App;
  
  return [
      'apiKey' => App::env('PIZZA_API_KEY'),
  ];
  
  ```
  
  On the admin page `example.com/admin/utilities/php-info` it shows that `$_ENV['PIZZA_API_KEY']` is set to a value, it is not null or empty.
  
  I'm lost as to why this property is not initialized. The same plugin, same version does not throw this error on another site that is Craft 4 (albeit 4.2.3, so perhaps there has been a change that breaks this?).
  
  **Tags:** plugin-development, craft4, api
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2022-11-15. Score: 4 | Accepted answer
  
  This:
  
  ```php
  class Settings extends Model
  {
      public string $apiKey;
  }
  
  ```
  
  Should look like this:
  
  ```php
  class Settings extends Model
  {
      public string $apiKey = '';
  }
  
  ```
  
  What's happening is due to the way Yii2 models work, they interrogate a class for its properties in such a way that it accesses their values before the rest of your code even runs.
  
  So you need to initialize any typed values with some kind of default value, as per the above.
  
  You can also declare them as nullable, but you still have to explicitly initialize there, too. e.g.:
  
  ```php
  class Settings extends Model
  {
      public ?string $apiKey = null;
  }
  
  ```
  
  It's due to Craft CMS using types (made available more fully in PHP 8) in their base classes, and method & property signatures must match in child classes. This is a positive thing overall, but yes, requires some work to convert things over.
  
  We did a few videos on this on [CraftQuest.io](https://craftquest.io):
  
  * [CraftQuest on Call 40: Rector Set Go!](https://craftquest.io/livestreams/craftquest-on-call-40-rector-set-go)
  * [Adopt-a-Plugin: Guide](https://craftquest.io/courses/adopt-a-plugin-guide)
  
  > **Comments:**
  > **username_0**: This indeed resolved it, thank you. However, I'm curious why this broke when upgrading to Craft 4. Is it because of something Craft 4 changed, or implicitly due to PHP8 being required?  
  > **username_1**: It's due to Craft CMS using types (made available more fully in PHP 8) in their base classes, and method & property signatures must match in child classes. This is a positive thing overall, but yes, requires some work to convert things over.  
  > **username_1**: I updated the original answer with links to videos showing how to update plugins from Craft 3 to Craft 4.  
  
  ---
  
  