Answers.Body: <p>You can use <a href="https://craftcms.com/docs/3.x/extend/extending-system-components.html#behaviors" rel="nofollow noreferrer">behaviors</a> to add new methods to system components. See the link above for documentation. A behavior is a class that extends <a href="https://www.yiiframework.com/doc/api/2.0/yii-base-behavior" rel="nofollow noreferrer">yii\base\Behavior</a> and is attached to a component using the <code>EVENT_DEFINE_BEHAVIORS</code> event.</p>
  <p>First you define the class that provides your custom method:</p>
  <pre class="lang-php prettyprint-override"><code>use yii\base\Behavior;
  
  class FullNameBehavior extends Behavior {
      public function fullName() {
          return &quot;{$this-&gt;owner-&gt;firstName} {$this-&gt;owner-&gt;lastName}&quot;;
      }
  }
  </code></pre>
  <p>The attach that behavior to the <code>Entry</code> class:</p>
  <pre class="lang-php prettyprint-override"><code>use craft\elements\Entry;
  use craft\events\DefineBehaviorsEvent;
  use yii\base\Event;
  
  // init() method in a module
  Event::on(
      Entry::class,
      Entry::EVENT_DEFINE_BEHAVIORS,
      function (DefineBehaviorsEvent $e) {
          $e-&gt;sender-&gt;attachBehaviors([
              FullNameBehavior::class,
          ]);
      }
  );
  </code></pre>
  <p>Now you can use the method in Twig:</p>
  <pre class="lang-twig prettyprint-override"><code>{{ entry.fullName }}
  </code></pre>
  <p>You can put the behavior class and the event hook in a <a href="https://craftcms.com/docs/3.x/extend/module-guide.html#preparation" rel="nofollow noreferrer">module</a>.</p>
  <h3>Alternative approaches</h3>
  <p>I don't really like behaviors in general, as it's very hard to find out where their methods are defined if you don't know about them. Also, tacking endless additional methods onto a class that doesn't really have anything to do with them is kind of bad design.</p>
  <p>Instead, consider the following solutions:</p>
  <ul>
  <li>Use a <a href="https://twig.symfony.com/doc/3.x/tags/macro.html" rel="nofollow noreferrer">macro</a> or a <a href="https://craftcms.com/docs/3.x/extend/extending-twig.html#register-a-twig-extension" rel="nofollow noreferrer">Twig filter or function</a> to display the full name consistently.</li>
  <li>Install the <a href="https://plugins.craftcms.com/preparse-field" rel="nofollow noreferrer">Preparse Field</a> plugin and store the full name in a preparse field.</li>
  <li>If feasible, you could represent people as <a href="https://craftcms.com/docs/3.x/users.html" rel="nofollow noreferrer">Users</a> instead of Entries – they come with a computed <a href="https://docs.craftcms.com/api/v3/craft-elements-user.html#fullname" rel="nofollow noreferrer">fullName property</a> by default.</li>
  </ul>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-10-28T07:50:46.827Z
Answers.LastActivityDate: 2021-10-28T07:50:46.827Z
Answers.UserDisplayName: MoritzLost
Body: <p>What is the best practice for defining an attribute on an Entry that isn't persistent? For example, I want to create a formatted string from two separate values stored in fields on the entry, but don't need to store the computed value in a field or in the database.</p>
  <p>I realize I can do this in a template variable like so:</p>
  <p><code>{% set fullName = entry.firstName ~ &quot; &quot; ~ entry.lastName %}</code></p>
  <p>... but, it would be much better if I could define this in a more global way so it can be used any time I'm dealing with an Entry within a specific Section like so:</p>
  <p><code>{{ entry.fullName }}</code></p>
  <p>I've read about custom Modules but that seems like overkill. Also, Craft may not offer any API to do something like this, but Yii might?</p>
  <p>Halp.</p>
  
Tags: <entrymodel><attribute>
Title: What's the best practice for creating computed (dynamic/virtual) attributes on entries?
ThreadText: # What's the best practice for creating computed (dynamic/virtual) attributes on entries?
  
  (Asked by: username_0 on 2021-10-27)
  
  What is the best practice for defining an attribute on an Entry that isn't persistent? For example, I want to create a formatted string from two separate values stored in fields on the entry, but don't need to store the computed value in a field or in the database.
  
  I realize I can do this in a template variable like so:
  
  `{% set fullName = entry.firstName ~ " " ~ entry.lastName %}`
  
  ... but, it would be much better if I could define this in a more global way so it can be used any time I'm dealing with an Entry within a specific Section like so:
  
  `{{ entry.fullName }}`
  
  I've read about custom Modules but that seems like overkill. Also, Craft may not offer any API to do something like this, but Yii might?
  
  Halp.
  
  **Tags:** entrymodel, attribute
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-10-28. Score: 1
  
  You can use [behaviors](https://craftcms.com/docs/3.x/extend/extending-system-components.html#behaviors) to add new methods to system components. See the link above for documentation. A behavior is a class that extends [yii\base\Behavior](https://www.yiiframework.com/doc/api/2.0/yii-base-behavior) and is attached to a component using the `EVENT_DEFINE_BEHAVIORS` event.
  
  First you define the class that provides your custom method:
  
  ```php
  use yii\base\Behavior;
  
  class FullNameBehavior extends Behavior {
      public function fullName() {
          return "{$this->owner->firstName} {$this->owner->lastName}";
      }
  }
  
  ```
  
  The attach that behavior to the `Entry` class:
  
  ```php
  use craft\elements\Entry;
  use craft\events\DefineBehaviorsEvent;
  use yii\base\Event;
  
  // init() method in a module
  Event::on(
      Entry::class,
      Entry::EVENT_DEFINE_BEHAVIORS,
      function (DefineBehaviorsEvent $e) {
          $e->sender->attachBehaviors([
              FullNameBehavior::class,
          ]);
      }
  );
  
  ```
  
  Now you can use the method in Twig:
  
  ```twig
  {{ entry.fullName }}
  
  ```
  
  You can put the behavior class and the event hook in a [module](https://craftcms.com/docs/3.x/extend/module-guide.html#preparation).
  
  ### Alternative approaches
  
  I don't really like behaviors in general, as it's very hard to find out where their methods are defined if you don't know about them. Also, tacking endless additional methods onto a class that doesn't really have anything to do with them is kind of bad design.
  
  Instead, consider the following solutions:
  
  * Use a [macro](https://twig.symfony.com/doc/3.x/tags/macro.html) or a [Twig filter or function](https://craftcms.com/docs/3.x/extend/extending-twig.html#register-a-twig-extension) to display the full name consistently.
  * Install the [Preparse Field](https://plugins.craftcms.com/preparse-field) plugin and store the full name in a preparse field.
  * If feasible, you could represent people as [Users](https://craftcms.com/docs/3.x/users.html) instead of Entries – they come with a computed [fullName property](https://docs.craftcms.com/api/v3/craft-elements-user.html#fullname) by default.
  
  
  ---
  
  