Bebop
Bebop

Reputation: 11

Where to place a database query in model? (Symfony framework)

I'm new to PHP programing and Symfony. English isn't my native language so sorry if it sounds strange how I write...

I have two entities: Article and Category, where each Article has a Category. And I need to show how many articles I have for a given category:

Category ------------------

Vehicles -------------------- 4

Electronics ---------------- 20

Food ----------------------- 15

Furniture ------------------ 8

With Doctrine I've made the CRUD files for both entities.

 php app/console doctrine:generate:crud 

Like I said, the problem is that I want to show a table with properties of a Category (name, description, etc) and how many articles of it are in the inventory.

The SQL query is very simple:

SELECT count(*) FROM Articles a WHERE a.id_category = $id_category

Where to put that?! I'm very confused and don't want to brake best practice rules. Doctrine generated lots of files: ArticleController.php, ArticleType.php (Form), and all the .twig for the views. Same for Category.

Upvotes: 0

Views: 1710

Answers (3)

frumious
frumious

Reputation: 1575

In the spirit of giving a direct answer to your question: what you need is a custom Doctrine Repository, in this case an ArticleRepository.

e.g. ArticleRepository.php

namespace ACME\DemoBundle\Article;

use Doctrine\ORM\EntityRepository;

class ArticleRepository extends EntityRepository
{
    public function countForCategory($id)
    {
        $result= $this->createQueryBuilder('a')
            ->join('a.category', 'c')
            ->where('c.category_id = :id')
            ->setParameter('id', $id)
            ->select('count(a')
            ->getQuery()
            ->getSingleScalarResult();

        return $result;
    }
}

And then you set your Article entity to use that ArticleRepository

Article.php

/**
 * @ORM\Entity
 * @ORM\Table(name="article")
 * @ORM\Entity(repositoryClass="ACME\DemoBundle\Entity\ArticleRepository")
 */
class Article
{
/// etc...

You can then get the Repository for the Entity in e.g. your Controller (although as suggested elsewhere you can hide this away in some kind of service to avoid filling your Controller with business logic; it just needs to be reachable somehow from inside your Controller), and run the query:

ArticleController

class ArticleController extends Controller
{
    public function countAction($id)
    {

        $articleRepo = $this->getDoctrine()->getRepository('DemoBundle:Article');

        $count = $articleRepo->countForCategory();
        //etc...

NB If you really want exactly the output in your example, it may be more efficient to do one query for the whole table, probably in a CategoryRepository, performing a count and grouping by Category. The query would return an array containing Category name and count.

Upvotes: 2

lxg
lxg

Reputation: 13107

When using Symfony2 + Doctrine2,

  1. don't think (so much) about the database. Think of persistent data objects, so called entities, and let Doctrine handle them. Spend some time on cleanly defining the relations between those objects, though.

  2. forget about the term “MVC”. MVC is a rather abstract concept, things are more complex in reality. Fabian (lead dev of SF) has a nice write-up about this topic: http://fabien.potencier.org/article/49/what-is-symfony2

If you wonder where to put what in your Symfony bundles, read this Cookbook article: http://symfony.com/doc/current/cookbook/bundles/best_practices.html

Upvotes: 1

Nadir Belhaj
Nadir Belhaj

Reputation: 12063

Create a CategoryManager class in your service layer, and handle any business logic there. You can pass the router to it through dependency injection.

For your example, CategoryManager would have a getUrl(Article $article) method which would use the router instance (that you either injected through __construct or a separate setter method) to generate the Url based on properties of $article, and return it.

This method will ensure that your business logic doesn't pollute the view or controller layers.

Check this link Services Symfony

Upvotes: 0

Related Questions