Search code examples
symfonydoctrinerelationships

symfony2 and doctrine populating with data from api, relationship creation


I am storing data from an external api into doctrine, i have created tables for the various API calls.

To keep things simple for the question i will explain a few entities:

  • Players - stores information on players available for selection (has a PlayerID)
  • Game - list of games that will be played (has a GameID)
  • PlayerGame - stores stats for players for a particular game (has a PlayerID and GameID)

My question is about defining relationships, and whether or not persisting the data from an api call is sufficient to generate the relationships.

i persist the data from the Player Feed and The Game Feed

When i pull the data for PlayerGame and persist it (it has the playerID and GameID which will be a ManyToOne relationship ) will this reference the related data correctly just by persisting the data from the feed?

Is simply defining the relationships in the entity enough to ensure i can perform something like $player->getGames()


Extra Info

i have set up builders responsible for creating the entities i need to persist:

<?php

namespace FantasyPro\DataBundle\Builder;

use FantasyPro\DataBundle\Entity\Player;
use FantasyPro\DataBundle\Helpers\DateHelper;

class PlayerBuilder
{
    /**
     * @var DateHelper $dateHelper
     */
    private $dateHelper;

    public function __construct( DateHelper $dateHelper )
    {
        $this->dateHelper = $dateHelper;
    }

    public function buildPlayer( $currentPlayer = null, $player )
    {
        if ( ! $currentPlayer) {
            $currentPlayer = new Player();
        }

        // set the new values for the player
        $currentPlayer->setPlayerID( $player['PlayerID'] );
        $currentPlayer->setTeam( $player['Team'] );
        $currentPlayer->setNumber( $player['Number'] );
        $currentPlayer->setFirstName( $player['FirstName'] );
        $currentPlayer->setLastName( $player['LastName'] );
        $currentPlayer->setPosition( $player['Position'] );
        $currentPlayer->setStatus( $player['Status'] );
        $currentPlayer->setHeight( $player['Height'] );
        $currentPlayer->setWeight( $player['Weight'] );
        $currentPlayer->setBirthDate( $this->dateHelper->parseDate( $player['BirthDate'] ) );
        $currentPlayer->setCollege( $player['College'] );
        $currentPlayer->setExperience( $player['Experience'] );
        $currentPlayer->setFantasyPosition( $player['FantasyPosition'] );
        $currentPlayer->setActive( $player['Active'] );
        $currentPlayer->setPositionCategory( $player['PositionCategory'] );
        $currentPlayer->setName( $player['Name'] );
        $currentPlayer->setAge( $player['Age'] );
        $currentPlayer->setExperienceString( $player['ExperienceString'] );
        $currentPlayer->setBirthDateString( $player['BirthDateString'] );
        $currentPlayer->setPhotoUrl( $player['PhotoUrl'] );
        $currentPlayer->setByeWeek( $player['ByeWeek'] );
        $currentPlayer->setUpcomingGameOpponent( $player['UpcomingGameOpponent'] );
        $currentPlayer->setUpcomingGameWeek( $player['UpcomingGameWeek'] );
        $currentPlayer->setShortName( $player['ShortName'] );
        $currentPlayer->setAverageDraftPosition( $player['AverageDraftPosition'] );
        $currentPlayer->setDepthPositionCategory( $player['DepthPositionCategory'] );
        $currentPlayer->setDepthPosition( $player['DepthPosition'] );
        $currentPlayer->setDepthOrder( $player['DepthOrder'] );
        $currentPlayer->setDepthDisplayOrder( $player['DepthDisplayOrder'] );
        $currentPlayer->setCurrentTeam( $player['CurrentTeam'] );
        $currentPlayer->setCollegeDraftTeam( $player['CollegeDraftTeam'] );
        $currentPlayer->setCollegeDraftYear( $player['CollegeDraftYear'] );
        $currentPlayer->setCollegeDraftRound( $player['CollegeDraftRound'] );
        $currentPlayer->setCollegeDraftPick( $player['CollegeDraftPick'] );
        $currentPlayer->setIsUndraftedFreeAgent( $player['IsUndraftedFreeAgent'] );
        $currentPlayer->setHeightFeet( $player['HeightFeet'] );
        $currentPlayer->setHeightInches( $player['HeightInches'] );
        $currentPlayer->setUpcomingOpponentRank( $player['UpcomingOpponentRank'] );
        $currentPlayer->setUpcomingOpponentPositionRank( $player['UpcomingOpponentPositionRank'] );
        $currentPlayer->setCurrentStatus( $player['CurrentStatus'] );
        $currentPlayer->setUpcomingSalary( $player['UpcomingSalary'] );

        return $currentPlayer;
    }

}

And the persister:

    namespace FantasyPro\DataBundle\Persisters;

    use Doctrine\ORM\EntityManager;
    use FantasyPro\DataBundle\Builder\PlayerBuilder;
    use FantasyPro\DataBundle\Entity\Player;

    class PlayerPersister
    {

        /**
         * @var EntityManager $em
         */
        private $em;
        /**
         * @var PlayerBuilder $builder
         */
        private $builder;

        public function __construct( EntityManager $em, PlayerBuilder $builder )
        {
            $this->em      = $em;
            $this->builder = $builder;
        }

        public function Persist( $player )
        {

            //get the player repository
            $repo = $this->em->getRepository( 'DataBundle:Player' );
            $uow  = $this->em->getUnitOfWork();

            // Set the current player to fetch from the db
            $criteria = array( 'playerID' => $player['PlayerID'] );

            //get the player from the repo
            /**
             * @var Player $currentPlayer
             */
            $currentPlayer = $repo->FindOneBy( $criteria );

            //build the player entity
            $currentPlayer = $this->builder->buildPlayer( $currentPlayer, $player );
            $exists        = $uow->isEntityScheduled( $currentPlayer );
            if ( ! $exists) {
                //persist the player
                $this->em->persist( $currentPlayer );

$this->em->flush();
                $this->em->clear();

            }

        }

I have these set up for Game and PlayerGame

Providing i use the correct annotations:

/**
     * @ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\PlayerGame")
     * @ORM\JoinColumn(name="playerGame_playerID", referencedColumnName="playerID")
     */
    private $playerID;

What about with ManyToMany would that work too?

/**
     * @ORM\ManyToMany(targetEntity="FantasyPro\DataBundle\Entity\Player", inversedBy="playerID")
     * @ORM\JoinTable(
     *     name="player_playerGame",
     *     joinColumns={@ORM\JoinColumn(name="playerID", referencedColumnName="playerID", nullable=false)},
     *     inverseJoinColumns={@ORM\JoinColumn(name="playerGameID", referencedColumnName="playerGameID", nullable=false)}
     * )
     */
public $playerID;

i can still use the builder and persister i have to store the data and everything will be related ok?

So to make sure the entities are stored correctly, in my builder for the PlayerGame i can use:

// set the new values for the player
 $playerToStore = $em->getRepository('DataBundle:Player')->findBy($player['PlayerID']);

 $currentPlayer->setPlayerID( $playerToStore );

Solution

  • If I understood right, you want to know, if storing data you pulled from an API directly to the table (via SQL) will work with Doctrine, the answer is yes.

    You can populate the tables via SQL, Doctrine will lookup IDs, based on your configuration (annotations for example) and load the entities.

    If you want to to persist PlayerGame entities, you will have to create (or load) the entities for Player and Game and use the setters in your PlayerGame entity before you call persist() and flush().