Answers.Body: <p>The answer below is mostly taken from Brandon Kelly's answer on Github which I suggest to read for more detailed information: <a href="https://github.com/craftcms/cms/issues/12847" rel="nofollow noreferrer">https://github.com/craftcms/cms/issues/12847</a></p>
  <p>The reason for the endless recursion is that fetching globals creates an element query. Element queries need to fetch all custom fields to give them a chance to modify the query. Therefore, fetching Globals in the <code>init()</code> of a Custom Field creates an endless recursion.</p>
  <p>The solution is to fetch the Globals elsewhere, for example in <code>inputHtml()</code> or <code>settingsHtml()</code>. However, the <code>Dropdown</code> and alike expect their <code>options</code> to be set from the <code>init()</code> and not change dynamically. To avoid problems, one can inherit from <code>Field</code> directly, for example:</p>
  <pre class="lang-php prettyprint-override"><code>use craft\base\ElementInterface;
  use craft\base\Field;
  use craft\helpers\Cp;
  
  class SphColorField extends Field
  {
      /**
       * @var array
       */
      private $options;
  
      protected function inputHtml($value, ElementInterface $element = null): string
      {
          return Cp::selectFieldHtml([
              'id' =&gt; $this-&gt;getInputId(),
              'describedBy' =&gt; $this-&gt;describedBy,
              'name' =&gt; $this-&gt;handle,
              'value' =&gt; $value,
              'options' =&gt; $this-&gt;options(),
          ]);
      }
  
      private function options(): array
      {
          if (!isset($this-&gt;options)) {
              $this-&gt;options = [];
              $global = Craft::$app-&gt;globals-&gt;getSetByHandle('globalTest');
              if ($global) {
                  foreach ($global-&gt;entries as $entry) {
                      $this-&gt;options[] = [
                          'label' =&gt; $entry['title'],
                          'value' =&gt; $entry['id']
                      ];
                  }
              }
          }
  
          return $this-&gt;options;
      }
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-10T15:38:00.103Z
Answers.LastActivityDate: 2023-03-10T15:38:00.103Z
Answers.UserDisplayName: Roman Sobkuliak
Answers.Body: <p>When running code inside the init() function for a field type, you're running it every time the field is instantiated. Typically you would put Event functions inside of the init, which tells the system when to run that code. Here's the docs:</p>
  <p><a href="https://craftcms.com/docs/4.x/extend/field-types.html#registering-custom-field-types" rel="nofollow noreferrer">https://craftcms.com/docs/4.x/extend/field-types.html#registering-custom-field-types</a></p>
  <pre><code>Event::on(
              Fields::class,
              Fields::EVENT_REGISTER_FIELD_TYPES,
              function(RegisterComponentTypesEvent $event) {
                  $event-&gt;types[] = MyField::class;
              }
          );
  </code></pre>
  <p>I think for your use case you might want this EVENT_REGISTER_FIELD_TYPES but the other event codes can be found here:</p>
  <p><a href="https://craftcms.com/docs/4.x/extend/events.html#event-code-generator" rel="nofollow noreferrer">https://craftcms.com/docs/4.x/extend/events.html#event-code-generator</a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-08T20:05:56.807Z
Answers.Text: I linked to Craft 4.x documents but for this, its the same for 3.x, if you need to swap docs there is a drop down on the top left for Craft CMS version number.
Answers.UserDisplayName: cherrykoda
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-08T20:04:07.173Z
Answers.LastActivityDate: 2023-03-08T20:04:07.173Z
Answers.UserDisplayName: cherrykoda
Body: <p>I'm creating a Custom Field Type whose possible values depend on the Globals. Therefore, I'm querying the Globals from the Custom Field's <code>init()</code>:</p>
  <pre class="lang-php prettyprint-override"><code>class CustomField extends Checkboxes
  {
      public function init()
      {
          // This line causes 502 Bad Gateway.
          $image = Craft::$app-&gt;globals-&gt;getSetByHandle('general')-&gt;image-&gt;one();
          // The rest is removed for clarity.
      }
  }
  
  class CustomFieldTypes extends Module {
    public function init()
    {
        // Register our Field
        Event::on(
            Fields::class,
            Fields::EVENT_REGISTER_FIELD_TYPES,
            function (RegisterComponentTypesEvent $event) {
                Craft::debug(
                    'Fields::EVENT_REGISTER_FIELD_TYPES',
                    __METHOD__
                );
                $event-&gt;types[] = CustomField::class;
            }
        );
    }
  
  }
  </code></pre>
  <p>However, the above results in <code>502 Bad Gateway</code>. When I place the query into the <code>CustomFieldTypes</code> module, it works as expected.</p>
  <p>When looking at the <a href="https://drive.google.com/file/d/18okzRLZ6XfkK90Rv-pmoTARDsx3DL_z_/view" rel="nofollow noreferrer">logs</a>, the following query</p>
  <pre><code>SELECT `fields`.`id`, `fields`.`dateCreated`, `fields`.`dateUpdated`, `fields`.`groupId`, `fields`.`name`, `fields`.`handle`, `fields`.`context`, `fields`.`instructions`, `fields`.`translationMethod`, `fields`.`translationKeyFormat`, `fields`.`type`, `fields`.`settings`, `fields`.`uid`, `fields`.`searchable`, `fields`.`columnSuffix`
  FROM `fields` `fields`
  ORDER BY `fields`.`name`, `fields`.`handle`
  </code></pre>
  <p>gets ran almost 2000 times, among others.</p>
  <p>Can you please help me find what's causing the error and what workaround should I use?</p>
  <h2>Extra info</h2>
  <p>I'm using Craft Pro 3.7.67 with plugins:</p>
  <pre><code>Control Panel CSS   2.4.0
  Excerptify  1.0.1
  Freeform    3.13.25
  Mailchimp Subscribe 3.1.1.1
  Navigation  1.4.31
  Neo 2.13.16
  Opening Hours   1.0.0
  Redactor    2.10.11
  Redactor Custom Styles  3.0.4
  Redirect Manager    1.1.1
  SS Entry Importer   1.0.3
  Super Table
  </code></pre>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-03-06T16:38:49.037Z
Comments.Text: Are you seeing any error messages in the logs?
Comments.UserDisplayName: MoritzLost
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-03-06T16:57:27.680Z
Comments.Text: Good point, here's the full log: https://drive.google.com/file/d/18okzRLZ6XfkK90Rv-pmoTARDsx3DL_z_/view
  
  There's one query repeated almost 2000 times, I updated my answer. I'll be very grateful if you can think of why this is the case.
Comments.UserDisplayName: Roman Sobkuliak
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-03-07T11:19:52.493Z
Comments.Text: Probably not a good idea to execute an element query in a custom field type's `init()` method. Can you describe the use case for when/where/why the `$image` asset is needed in your field type?
Comments.UserDisplayName: Mats Mikkel Rummelhoff
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-03-07T18:11:47.437Z
Comments.Text: Thanks a lot for chiming in. The image example is made up, but basically, I'm trying to give our Content Creators an option from the Admin Panel through the use of Globals to affect options of a Checkbox field. For example, having a Color checkbox field whose options can be altered from the Admin Panel.
  
  What would you say is the idiomatic way to achieve this in CraftCMS? (I'm a new maintainer of the project and I don't have a lot of experience with Craft)
Comments.UserDisplayName: Roman Sobkuliak
Tags: <craft3><custom-fieldtype><globals>
Title: Querying Globals from a Custom Field Type gives 502 Bad Gateaway
ThreadText: # Querying Globals from a Custom Field Type gives 502 Bad Gateaway
  
  (Asked by: username_0 on 2023-03-06)
  
  I'm creating a Custom Field Type whose possible values depend on the Globals. Therefore, I'm querying the Globals from the Custom Field's `init()`:
  
  ```php
  class CustomField extends Checkboxes
  {
      public function init()
      {
          // This line causes 502 Bad Gateway.
          $image = Craft::$app->globals->getSetByHandle('general')->image->one();
          // The rest is removed for clarity.
      }
  }
  
  class CustomFieldTypes extends Module {
    public function init()
    {
        // Register our Field
        Event::on(
            Fields::class,
            Fields::EVENT_REGISTER_FIELD_TYPES,
            function (RegisterComponentTypesEvent $event) {
                Craft::debug(
                    'Fields::EVENT_REGISTER_FIELD_TYPES',
                    __METHOD__
                );
                $event->types[] = CustomField::class;
            }
        );
    }
  
  }
  
  ```
  
  However, the above results in `502 Bad Gateway`. When I place the query into the `CustomFieldTypes` module, it works as expected.
  
  When looking at the [logs](https://drive.google.com/file/d/18okzRLZ6XfkK90Rv-pmoTARDsx3DL_z_/view), the following query
  
  ```
  SELECT `fields`.`id`, `fields`.`dateCreated`, `fields`.`dateUpdated`, `fields`.`groupId`, `fields`.`name`, `fields`.`handle`, `fields`.`context`, `fields`.`instructions`, `fields`.`translationMethod`, `fields`.`translationKeyFormat`, `fields`.`type`, `fields`.`settings`, `fields`.`uid`, `fields`.`searchable`, `fields`.`columnSuffix`
  FROM `fields` `fields`
  ORDER BY `fields`.`name`, `fields`.`handle`
  
  ```
  
  gets ran almost 2000 times, among others.
  
  Can you please help me find what's causing the error and what workaround should I use?
  
  ## Extra info
  
  I'm using Craft Pro 3.7.67 with plugins:
  
  ```
  Control Panel CSS   2.4.0
  Excerptify  1.0.1
  Freeform    3.13.25
  Mailchimp Subscribe 3.1.1.1
  Navigation  1.4.31
  Neo 2.13.16
  Opening Hours   1.0.0
  Redactor    2.10.11
  Redactor Custom Styles  3.0.4
  Redirect Manager    1.1.1
  SS Entry Importer   1.0.3
  Super Table
  
  ```
  
  **Tags:** craft3, custom-fieldtype, globals
  
  > **Comments:**
  > **username_1**: Are you seeing any error messages in the logs?  
  > **username_0**: Good point, here's the full log: https://drive.google.com/file/d/18okzRLZ6XfkK90Rv-pmoTARDsx3DL_z_/view  There's one query repeated almost 2000 times, I updated my answer. I'll be very grateful if you can think of why this is the case.  
  > **username_2**: Probably not a good idea to execute an element query in a custom field type's `init()` method. Can you describe the use case for when/where/why the `$image` asset is needed in your field type?  
  > **username_0**: Thanks a lot for chiming in. The image example is made up, but basically, I'm trying to give our Content Creators an option from the Admin Panel through the use of Globals to affect options of a Checkbox field. For example, having a Color checkbox field whose options can be altered from the Admin Panel.  What would you say is the idiomatic way to achieve this in CraftCMS? (I'm a new maintainer of the project and I don't have a lot of experience with Craft)  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_0 on 2023-03-10. Score: 2 | Accepted answer
  
  The answer below is mostly taken from Brandon Kelly's answer on Github which I suggest to read for more detailed information: <https://github.com/craftcms/cms/issues/12847>
  
  The reason for the endless recursion is that fetching globals creates an element query. Element queries need to fetch all custom fields to give them a chance to modify the query. Therefore, fetching Globals in the `init()` of a Custom Field creates an endless recursion.
  
  The solution is to fetch the Globals elsewhere, for example in `inputHtml()` or `settingsHtml()`. However, the `Dropdown` and alike expect their `options` to be set from the `init()` and not change dynamically. To avoid problems, one can inherit from `Field` directly, for example:
  
  ```php
  use craft\base\ElementInterface;
  use craft\base\Field;
  use craft\helpers\Cp;
  
  class SphColorField extends Field
  {
      /**
       * @var array
       */
      private $options;
  
      protected function inputHtml($value, ElementInterface $element = null): string
      {
          return Cp::selectFieldHtml([
              'id' => $this->getInputId(),
              'describedBy' => $this->describedBy,
              'name' => $this->handle,
              'value' => $value,
              'options' => $this->options(),
          ]);
      }
  
      private function options(): array
      {
          if (!isset($this->options)) {
              $this->options = [];
              $global = Craft::$app->globals->getSetByHandle('globalTest');
              if ($global) {
                  foreach ($global->entries as $entry) {
                      $this->options[] = [
                          'label' => $entry['title'],
                          'value' => $entry['id']
                      ];
                  }
              }
          }
  
          return $this->options;
      }
  }
  
  ```
  
  
  ---
  
  ### Answer by username_3 on 2023-03-08. Score: 1
  
  When running code inside the init() function for a field type, you're running it every time the field is instantiated. Typically you would put Event functions inside of the init, which tells the system when to run that code. Here's the docs:
  
  <https://craftcms.com/docs/4.x/extend/field-types.html#registering-custom-field-types>
  
  ```
  Event::on(
              Fields::class,
              Fields::EVENT_REGISTER_FIELD_TYPES,
              function(RegisterComponentTypesEvent $event) {
                  $event->types[] = MyField::class;
              }
          );
  
  ```
  
  I think for your use case you might want this EVENT\_REGISTER\_FIELD\_TYPES but the other event codes can be found here:
  
  <https://craftcms.com/docs/4.x/extend/events.html#event-code-generator>
  
  > **Comments:**
  > **username_3**: I linked to Craft 4.x documents but for this, its the same for 3.x, if you need to swap docs there is a drop down on the top left for Craft CMS version number.  
  
  ---
  
  