• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

XF 2.0 Some questions about this whole "Entity" thing...

Xon

Well-known member
#43
Then you could use a regular property to store the result of the calculation, e.g.
PHP:
protected $streamChat;

public function getStreamChat()
{
    if ($this->streamChat === NULL)
    {
        // Calculate streamchat
        $streamChat = 'something';
      
        $this->streamChat = $streamChat;
    }

    return $this->streamChat;
}
From the looks of your example previously, you were doing the calculations for streamChat outside of the entity and setting it into the entity, and that's the difference - with the entities, you're trying to make your code as portable and reusable as possible by putting these kind of calculations inside the entity.

Since you're essentially creating a fake property, pretending stream_chat is a column in your database, you'd do the calculations inside the entity. That means if I wanted to integrate with your mod, I wouldn't need to copy all your OTHER code in order to get the necessary data to calculate stream_chat, then set it into the entity, then get it later in the template.

That leads to code duplication as soon as you need to access your Stream entity in more than one location :)


Fillip
FYI, XenForo 2.x entities have built in caching support.

PHP:
protected $streamChat;

public function getStreamChat()
{
        // Calculate streamchat
        $streamChat = 'something';
      
        return $streamChat;
}

public static function getStructure(Structure $structure)
{
...

        $structure->getters = [
            'StreamChat' => true
        ];
...
}
Getters can have a structure like
Code:
'StreamChat' => ['getter' => 'getStreamChat', 'cache' => true]
.
 

Jaxel

Well-known member
#45
Okay, I got another complication... Can I order a fetch based on a getter?

For instance, I have a getter:
Code:
    public function getStreamFeatured()
    {
        return ($this->Game->game_featured || $this->Channel->channel_featured) ? 1 : 0;
    }

Then in my controller I have:
Code:
$streamRepo->findStreams()
    ->limitByPage($page, $perPage)
    ->order('stream_featured', 'DESC')
    ->order('stream_viewers', 'DESC')
    ->fetch();

This however, returns an error:
InvalidArgumentException: Unknown column stream_featured on EWR\Rio:Stream in src/XF/Mvc/Entity/Finder.php at line 1394

I was able to do this in XF1 with a CONCAT in a select:
Code:
SELECT EWRrio_games.*, EWRrio_channels.*, EWRrio_streams.*,
    IF(EWRrio_games.game_featured, EWRrio_games.game_featured,
        IF(EWRrio_channels.channel_featured, EWRrio_channels.channel_featured, 0)
    ) AS stream_featured
 

DragonByte Tech

Well-known member
#49
Okay, I got another complication... Can I order a fetch based on a getter?

For instance, I have a getter:
Code:
    public function getStreamFeatured()
    {
        return ($this->Game->game_featured || $this->Channel->channel_featured) ? 1 : 0;
    }

Then in my controller I have:
Code:
$streamRepo->findStreams()
    ->limitByPage($page, $perPage)
    ->order('stream_featured', 'DESC')
    ->order('stream_viewers', 'DESC')
    ->fetch();

This however, returns an error:



I was able to do this in XF1 with a CONCAT in a select:
Code:
SELECT EWRrio_games.*, EWRrio_channels.*, EWRrio_streams.*,
    IF(EWRrio_games.game_featured, EWRrio_games.game_featured,
        IF(EWRrio_channels.channel_featured, EWRrio_channels.channel_featured, 0)
    ) AS stream_featured
I would recommend you change your code and add a stream_featured column on the streams table.

Then, whenever you change the contents of the channel_featured or game_featured columns, also update the stream_featured column.

You should do this with _postSave functions in your Channel and Game entities.

I’m on mobile right now so I can’t pseudocode, but hopefully you get where I’m going with this :)

If not, let me know your relations between those 3 tables.


Fillip
 

Jaxel

Well-known member
#50
I would recommend you change your code and add a stream_featured column on the streams table.

Then, whenever you change the contents of the channel_featured or game_featured columns, also update the stream_featured column.

You should do this with _postSave functions in your Channel and Game entities.

I’m on mobile right now so I can’t pseudocode, but hopefully you get where I’m going with this :)

If not, let me know your relations between those 3 tables.


Fillip
Yeah... a simple solution... one I didn't want to do because of the amount of extra queries it would add. This is how I did it:
Code:
\XF::db()->emptyTable('EWRrio_streams');

if (!empty($streams))
{
    \XF::db()->insertBulk('EWRrio_streams', $streams);
   
    $fGames = \XF::finder('EWR\Rio:Game')->where('game_featured', '1')->fetch();
    foreach ($fGames AS $fGame)
    {
        \XF::db()->update('EWRrio_streams', ['stream_featured'=>1], 'game_id='.$fGame['game_id']);
    }
}
 

Jaxel

Well-known member
#51
Is it possible to do a COUNT() and GROUP BY with the Finder system?

I want to do something like this:
Code:
SELECT games.*, COUNT(streams.game_id)
    FROM games
        INNER JOIN streams ON (streams.game_id = games.game_id)
GROUP BY streams.game_id