<p>Another approach is to use the following event to attach a behavior</p>

<pre><code>Event::on(Asset::class, Asset::EVENT_DEFINE_BEHAVIORS, 
function(DefineBehaviorsEvent $event) {
    $event-&gt;behaviors[] = MyBehavior::class;
});
</code></pre>

<h3>The behavior could look like</h3>

<pre><code>class MyBehavior extends Behavior { 
    public $downloads; 
}
</code></pre>

<p>This way you won't receive an exception and can access your property via</p>

<pre><code>$asset = Assets::find()-&gt;all();
$asset-&gt;downloads;
</code></pre>

<p>You can as well manipulate the value of <code>downloads</code> in the <code>Behaviors</code> init function in order to return the file or something like this</p>

CC BY-SA 4.0
2018-05-04T13:58:04.017Z
2018-05-04T13:58:04.017Z
Robin Schambach
<p>You can use the <code>asArray()</code> function in order to gain the raw query result and populate the entry on your own.</p>

<p>Just take a look at the <code>ElementQuery-&gt;populate()</code> function, copy it to you own service and attach your custom <code>Behavior</code> you can see how this works <a href="https://www.yiiframework.com/doc/guide/2.0/en/concept-behaviors#attaching-behaviors" rel="nofollow noreferrer">here</a> </p>

<pre><code>class MyBehavior extends Behavior { 

    public $prop1; 
    private $_prop2;

    public function getProp2() {
        return $this-&gt;_prop2; 
    } 

    public function setProp2($value) { 
         $this-&gt;_prop2 = $value;
    }
 }
</code></pre>

<p>Just include all values for the element in your custom behavior. </p>

<p>The key is to change <a href="https://github.com/craftcms/cms/blob/develop/src/elements/db/ElementQuery.php#L2055" rel="nofollow noreferrer">this</a> piece of code from </p>

<pre><code>$element = new $class($row);
</code></pre>

<p>To </p>

<pre><code>$element = new $class();
$element-&gt;attachBehavior('myBehavior1', new MyBehavior);
Craft::configure($element, $row);
</code></pre>

<p>In your custom service. </p>

CC BY-SA 3.0
2018-04-27T04:23:20.750Z
Thanks, but it's not what I need. I don't want to create my own copy of Assets service/variable, instead I want to add a property for all standard calls (to make it also available in CP)
Yuri Salimovskiy
CC BY-SA 3.0
2018-04-27T04:27:59.280Z
That's not possible because you'll always receive the exception that way. Another possibility is to load the data in your behavior
Robin Schambach
CC BY-SA 3.0
2018-04-26T20:13:33.313Z
2018-04-26T20:13:33.313Z
Robin Schambach
<p>Developing plugin for Craft 3, I want to add extra property to Assets (data being pulled from other table)</p>

<p>I am able to pull in the data by extending element query:</p>

<pre><code>Event::on(
            ElementQuery::class,
            ElementQuery::EVENT_AFTER_PREPARE,
            function(CancelableEvent $e) {
                if ($e-&gt;sender-&gt;elementType == 'craft\\elements\\Asset')
                {
                    $e-&gt;sender-&gt;query-&gt;addSelect('linkstats.downloads');

                    $subQuery = (new Query())
                        -&gt;select('assetId, SUM(downloads) AS downloads')
                        -&gt;from('{{%my_plugin_table}}')
                        -&gt;groupBy('assetId');

                    $e-&gt;sender-&gt;query-&gt;leftJoin(
                        ['linkstats' =&gt; $subQuery], 'assets.id = linkstats.assetId'
                    );
                }
            }
        );
</code></pre>

<p>However when trying to display the asset I get error:</p>

<blockquote>
  <p>Setting unknown property: craft\elements\Asset::downloads</p>
</blockquote>

<p>Question, how do I register this new property/attribute for Assets? I cannot find any event to do that, is it possible at all?</p>

<plugin-development><craft3><attribute><element>
Add custom attribute to standard element from plugin
# Add custom attribute to standard element from plugin

(Asked by: username_0 on 2018-04-26)

Developing plugin for Craft 3, I want to add extra property to Assets (data being pulled from other table)
I am able to pull in the data by extending element query:
Event::on(
            ElementQuery::class,
            ElementQuery::EVENT_AFTER_PREPARE,
            function(CancelableEvent $e) {
                if ($e->sender->elementType == 'craft\\elements\\Asset')
                {
                    $e->sender->query->addSelect('linkstats.downloads');

                    $subQuery = (new Query())
                        ->select('assetId, SUM(downloads) AS downloads')
                        ->from('{{%my_plugin_table}}')
                        ->groupBy('assetId');

                    $e->sender->query->leftJoin(
                        ['linkstats' => $subQuery], 'assets.id = linkstats.assetId'
                    );
                }
            }
        );

However when trying to display the asset I get error:

Setting unknown property: craft\elements\Asset::downloads

Question, how do I register this new property/attribute for Assets? I cannot find any event to do that, is it possible at all?

**Tags:** plugin-development, craft3, attribute, element


---

## 2 answers

### Answer by username_1 on 2018-05-04. Score: 3 | Accepted answer

Another approach is to use the following event to attach a behavior
Event::on(Asset::class, Asset::EVENT_DEFINE_BEHAVIORS, 
function(DefineBehaviorsEvent $event) {
    $event->behaviors[] = MyBehavior::class;
});

The behavior could look like
class MyBehavior extends Behavior { 
    public $downloads; 
}

This way you won't receive an exception and can access your property via
$asset = Assets::find()->all();
$asset->downloads;

You can as well manipulate the value of downloads in the Behaviors init function in order to return the file or something like this


---

### Answer by username_1 on 2018-04-26. Score: 0

You can use the asArray() function in order to gain the raw query result and populate the entry on your own.
Just take a look at the ElementQuery->populate() function, copy it to you own service and attach your custom Behavior you can see how this works here 
class MyBehavior extends Behavior { 

    public $prop1; 
    private $_prop2;

    public function getProp2() {
        return $this->_prop2; 
    } 

    public function setProp2($value) { 
         $this->_prop2 = $value;
    }
 }

Just include all values for the element in your custom behavior. 
The key is to change this piece of code from 
$element = new $class($row);

To 
$element = new $class();
$element->attachBehavior('myBehavior1', new MyBehavior);
Craft::configure($element, $row);

In your custom service.

> **Comments:**
> **username_0**: Thanks, but it's not what I need. I don't want to create my own copy of Assets service/variable, instead I want to add a property for all standard calls (to make it also available in CP)  
> **username_1**: That's not possible because you'll always receive the exception that way. Another possibility is to load the data in your behavior  

---

