XF 2.0 TO_MANY relationship probably asked too many times :)

ludak

Active member
This was probably asked too many times but i am writing an add-on an trying to do simple things like joining tables with using with statement and failing misserably :)

I know what I want to achieve and I could do it in minutes in any other language but I am new to php and xenforo, so I am bit stuck. I will give you a scenario and let me know if I am doing anything wrong (this might be a lengthier post, apologize for that in advance). I have already gone through several plugins and documentation several time, but I cannot make sense of it at all :)

Here is the sample:

Lets say we have two entities Players and Games, and the tables are in such way to have them as.

Players Table -> player_id, player_name
Games Table -> game_id, game_name


I have the link table in such fashion.

PlayerGamesLink -> player_id, game_id

This is the link between these two tables. They do not have the foreign keys on the main tables but just the link table called PlayerGamesLink.

Many players can play many games, and also many games can be played by many players.

So if I have the entity Players here as this.

PHP:
$structure->table = 'xf__XX_players';
        $structure->shortName = 'XX:Players';
        $structure->primaryKey = 'player_id';
        $structure->columns = [
            'player_id' => ['type' => self::UINT, 'required' => true],
            'player_name' => ['type' => self::STR]
        ];

        $structure->getters = [];
        $structure->relations = [
            'PlayerGamesLink' => [
            'entity' => 'XX:PlayerGamesLink',
            'type' => self::TO_MANY,
            'conditions' => 'player_id',
            'primary' => true
        ]];

Then I have a Games entity as

PHP:
$structure->table = 'xf__XX_games';
        $structure->shortName = 'XX:Games';
        $structure->primaryKey = 'game_id';
        $structure->columns = [
            'game_id' => ['type' => self::UINT, 'required' => true],
            'game_name' => ['type' => self::STR]
        ];

        $structure->getters = [];
        $structure->relations = [
            'PlayerGamesLink' => [
            'entity' => 'XX:PlayerGamesLink',
            'type' => self::TO_MANY,
            'conditions' => 'game_id',
            'primary' => true
        ]];

and finally I have the PlayerGamesLink table entity

PHP:
$structure->table = 'xf__XX_player_games_link';
        $structure->shortName = 'XX:PlayerGamesLink';
        $structure->primaryKey = 'player_id';
        $structure->primaryKey = 'game_id';
        $structure->columns = [
            'game_id' => ['type' => self::UINT, 'required' => true],
            'player_id' => ['type' => self::UINT, 'required' => true]
        ];

        $structure->getters = [];
        $structure->relations = [
'Players' => [
    'entity' => 'XX:Players',
    'type' => self::TO_MANY,
    'conditions' => 'player_id',
    'primary' => true
],
'Games' => [
    'entity' => 'XX:Games',
    'type' => self::TO_MANY,
    'conditions' => 'game_id',
    'primary' => true
]];

PS. Code I am hand writing here as sample what I am trying to achieve, please ignore if there are some mistypes, I am trying to understand the overall Idea.

So now, I have a page where I am able to add/edit/delete/view Games, and page where i can do the same for the Players.

So I added in link table that game id 1 is played by users 1,2,3 lets say.

I would like to return based on the game ID, the entity USERS back to the view...

So, lets say when I click game 1 in view mode, I wanna have the list of the users in that view page that are playing the game.


So in my controller, I have something like this

PHP:
public function actionView(ParameterBag $params)
    {
        $game = $this->assertRecordExists($params['game_id'], null, null);
       

        $viewParams = [
            'game' => $game,
            'players' => $this->getGamesRepo()->getPlayersOfGame($game)
        ];
        return $this->view('XX:Games\View', 'game_view', $viewParams);
    }

So now in Games repository I have a method that will get me the players of the game... getPlayersOfGame by passing the Games Entity Object to it. I want this method to return TEAM Entity Object.

How do I do this??

I tried many things but I get exceptions telling me its imposible to do TO_MENY relationships in this version.

PHP:
$players = $this->finder('XX:Players')
            ->with('GamesPlayers', true)
            ->with('GamesPlayers|'.$game)
            ->fetch();

I am pretty sure I am on the right path, if somebody could just help me with this particular example. I have seen others on the board asking similar questions but I was not able to figure it out through those answers.

How would you write this method to return list of $players xx:players
 
Last edited:
Let me get some more info :)

So if I do this.
PHP:
$players = $this->finder('XX:Players')
            ->with('GamesPlayers', true)
            ->with('GamesPlayers|'.$game)
            ->fetch();
I get this error:)

LogicException: Attempting to get a specific value of a relation that doesn't support it in src\XF\Mvc\Entity\Finder.php at line 663

But if I do this...
PHP:
$players = $this->finder('XX:Players')
            ->with('GamesPlayers', true)
            ->where('GamesPlayers.game_id', $game->game_id)
            ->fetch();

Then I get the resultset back and its fine. I am just wondering if this is a proper way to do these things? Or I am missing something. I want to be able since this is one of the first joins I am doing to understand if there is a better way to do these things, so that I am not doing it wrong thoughout the code. PLease share your ideas.

Thanks,
 
Last edited:
I was hoping to get some info from the xenforo guys :) Do you guys have few minutes to tell me if I am doing this right? Can it be done better, improved?
 
Top Bottom