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

CC BY-SA 4.0
2022-11-17T17:53:02.100Z
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?
Paul Hübner
CC BY-SA 4.0
2022-11-18T20:09:23.880Z
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.
andrew.welch
CC BY-SA 4.0
2022-11-18T20:15:40.430Z
I updated the original answer with links to videos showing how to update plugins from Craft 3 to Craft 4.
andrew.welch
CC BY-SA 4.0
2022-11-15T16:04:54.357Z
2022-11-18T20:13:29.153Z
2022-11-18T20:13:29.153Z
andrew.welch
<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>

<plugin-development><craft4><api>
Updating to Craft 4 breaks plugin settings: must not be accessed before initialization
# 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:
$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 and as far as I know we follow everything.
There exists a model:

Which is provided by the plugin class:
    protected function createSettingsModel(): ?Model
    {
        return new Settings();
    }

Furthermore, there exists a file config/pizza.php with the following:
 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:
class Settings extends Model
{
    public string $apiKey;
}

Should look like this:
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.:
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:

CraftQuest on Call 40: Rector Set Go!
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.  

---

