Any Symfony gurus out there? Advice needed.

DrJohnZoidberg

Honorary Master
Joined
Jul 24, 2006
Messages
28,267
Reaction score
7,774
Location
Table View
Hey guys, I am trying to get my head around doing things properly in Symfony2. I'm still really an OOP noob and I would love to get some input from some people that actually know what they're doing.

The project I'm working on (hobby project) uses two main components:

1. A sqlite database (I'm using Doctrine in Symfony for this).
2. An external web service to retrieve supplemental data (I have written my own connector class for this).

Basically I'm retrieving historical data from the sqlite database then I need to fetch extra information on each of these records from the web service and then I output the combined result to a page.

Here is what I'm currently doing:

1. I have created a repository for my entities called HelperRepository, this contains custom methods for queries I need to run. I have something like this in there:

Code:
<?php

namespace PWW\DataFactoryBundle\Repository;

use Doctrine\ORM\EntityRepository;

class HelperRepository extends EntityRepository
{
    
    private $em;
    private $class;
    
    public function __construct($em, \Doctrine\ORM\Mapping\ClassMetadata $class) {
        parent::__construct($em, $class);
        $this->class = $class->name;
        $this->em = $em;
    }
    
    public function queryTop10All()
    {
        $query = $this->getEntityManager($this->em)
            ->createQueryBuilder('u')
                ->select('u.ratingkey, u.origTitle, u.origTitleEp, u.episode, u.season, u.year, u.xml, count(u.title) as playCount')
                ->from($this->class, 'u')
                ->groupBy('u.title')
                ->orderBy('playCount', 'desc')
                ->addOrderBy('u.ratingkey', 'desc')
                ->setMaxResults(10)
                ->getQuery();
        
        return $query->getResult();
    }
}

2. I then need to take the results from the above queries and add the additional data which I retrieve from the web service. I'm doing this outside my controller so I need to inject Doctrine to my class using a service:

Code:
// config.yml

services:
    pww.datafactorybundle.model.charts_data_model:
        class: PWW\DataFactoryBundle\Model\ChartsDataModel
        arguments: [ @doctrine.orm.entity_manager ]

And I have created a "Model" class to process this data as so:

Code:
<?php

namespace PWW\DataFactoryBundle\Model;

use Doctrine\ORM\EntityManager;
use PWW\DataFactoryBundle\Connector\XMLExtractor;
use PWW\DataFactoryBundle\Connector\WebConnector;
use PWW\ContentBundle\Entity\Settings;

class ChartsDataModel {
    
    private $settings;
    private $repository;
    private $em;
    
    public function __construct(EntityManager $em)
    {
        $this->settings = new Settings();
        $this->repository = $this->settings->getGroupingCharts() ? 'PWWDataFactoryBundle:Grouped' : 'PWWDataFactoryBundle:Processed';
        $this->em = $em;
    }
    
    public function getChartsTop10All()
    {
        $xmlExtractor = new XMLExtractor();
        $webConnector = new WebConnector();
        
        $results = $this->em->getRepository($this->repository)->queryTop10All();
        $xml = $xmlExtractor->unXmlArray($results);
        
        $outputArray = array();
        
        foreach($xml as $item) {
            $outputArray[] = array(
                "ratingKey" => $item['ratingkey'],
                "origTitle" => $item['origTitle'],
                "origTitleEp" => $item['origTitleEp'],
                "playCount" => $item['playCount'],
                "episode" => $item['episode'],
                "season" => $item['season'],
                "year" => $item['year'],
                "type" => $item['media']['type'],
                "parent" => $webConnector->getMetaData($webConnector->getMetaDataParentKey($item['ratingkey'])),
                "metadata" => $webConnector->getMetaData($item['ratingkey'])
            );
        }
        
        return $outputArray;
    }
}

3. I can now call this method from my controller and keep everything in the controller nice and tidy:

Code:
<?php

namespace PWW\ContentBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
...
use PWW\DataFactoryBundle\Model\ChartsDataModel;

class DefaultController extends Controller
{

    public function chartsAction()
    {
        
        $charts = new ChartsDataModel($this->getDoctrine()->getManager());
        $top10Array = $charts->getChartsTop10All();
        
        return $this->render('PWWContentBundle:Default:charts.html.twig', array('page' => 'charts', 'top10' => $top10Array));
    }

}

This all works fine, but I'm not sure if I'm following best practices here. How would you implement something like this? Am I on the right track?

TIA
 
not sympony related, but conceptually the webservice, and sqlite db are both datasources.

The sqlite DB you are accessing via a EntityRepository implements Doctrine\Common\Persistence\ObjectRepository
You could access the webservice via a "Webservice Repository"


A common pattern in Spring Data (a Java framework that allows you to quickly use repository instances, defining only interfaces):

simple CRUD JPA repository:
Code:
//gives you findOne, findAll, save, delete, etc for free
interface ChartRepository extends JpaRepository<Chart, Long> {
}

need to add metadata from another datasource
Code:
interface ChartRepository extends JpaRepository<Chart, Long>, ChartMetaDataRepository {
}

interface ChartMetaDataRepository {
   SomeResultObject findMetadata(String ratingKey)
}

class ChartMetaDataRepositoryImpl {
    @Autowired
    private RestTemplate restTemplate;

    public SomeResultObject findMetadata(String ratingKey) {
        return call_your_webservice_here;
    }

}

in your service
Code:
List<Chart> charts = chartRepository.findAll();
foreach (Chart chart: charts) {
   SomeResultObject metadata = chartRepository.findMetadata(chart.getRatingKey);
   chart.setMetadata(metadata);
}
 
Last edited:
Top
Sign up to the MyBroadband newsletter
X