1

With symfony && doctrine 1.2 in an action, i try to display the top ranked website for a user.

I did :

 public function executeShow(sfWebRequest $request)
  {
    $this->user = $this->getRoute()->getObject();
    $this->websites = $this->user->Websites; 
  }

The only problem is that it returns a Doctrine collection with all the websites in it and not only the Top ranked ones.

I already setup a method (getTopRanked()) but if I do :

$this->user->Websites->getTopRanked()

It fails.

If anyone has an idea to alter the Doctrine collection to filter only the top ranked.

Thanks

PS: my method looks like (in websiteTable.class.php) :

   public function getTopRanked()
{
  $q = Doctrine_Query::create()
       ->from('Website')
      ->orderBy('nb_votes DESC')
       ->limit(5);
  return $q->execute();

}
sf_tristanb
  • 8,725
  • 17
  • 74
  • 118
  • Where did you put `getTopRanked()` and how does it look like? – DrColossos Jan 09 '11 at 10:06
  • See my edit, i've added the function. :-) – sf_tristanb Jan 09 '11 at 11:08
  • You are reading the values for all websites, not all websites that belong to a certain user. ALtough you call it from within a user object your query doesn't use a user value... I don't think Doctrine will add the required JOINs on its own. – DrColossos Jan 09 '11 at 12:39
  • the $this->user->x() methods are the ones in your user model. you placed this function in your websiteTable model, which is entirely different. You should either create a function in the website model that takes in a userid (eg toprankedbyuser($user) ) or, if you want to access it like you do above, create a function in the user model. – MrGlass Jan 09 '11 at 18:41

4 Answers4

5

I'd rather pass Doctrine_Query between methods:

//action
public function executeShow(sfWebRequest $request)   
{
   $this->user = $this->getRoute()->getObject();
   $this->websites = $this->getUser()->getWebsites(true);  
}

//user
  public function getWebsites($top_ranked = false)
  {
    $q = Doctrine_Query::create()
     ->from('Website w')
     ->where('w.user_id = ?', $this->getId());
    if ($top_ranked)
    {
      $q = Doctrine::getTable('Website')->addTopRankedQuery($q);
    }
    return $q->execute();
  }

//WebsiteTable
public function addTopRankedQuery(Doctrine_Query $q)
{
  $alias = $q->getRootAlias();
  $q->orderBy($alias'.nb_votes DESC')
    ->limit(5)
  return $q
}
Dziamid
  • 11,225
  • 12
  • 69
  • 104
1

If getTopRanked() is a method in your user model, then you would access it with $this->user->getTopRanked()

MrGlass
  • 9,094
  • 17
  • 64
  • 89
1

In your case $this->user->Websites contains ALL user websites. As far as I know there's no way to filter existing doctrine collection (unless you will iterate through it and choose interesting elements).

I'd simply implement getTopRankedWebsites() method in the User class:

class User extends BaseUser
{
  public function getTopRankedWebsites()
  {
    WebsiteTable::getTopRankedByUserId($this->getId());
  }
}

And add appropriate query in the WebsiteTable:

class WebsiteTable extends Doctrine_Table
{
  public function getTopRankedByUserId($userId)
  {
    return Doctrine_Query::create()
     ->from('Website w')
     ->where('w.user_id = ?', array($userId))
     ->orderBy('w.nb_votes DESC')
     ->limit(5)
     ->execute();
  }
}
Jakub Zalas
  • 35,761
  • 9
  • 93
  • 125
1

You can also use the getFirst() function

$this->user->Websites->getTopRanked()->getFirst()

http://www.doctrine-project.org/api/orm/1.2/doctrine/doctrine_collection.html#getFirst()

CamelBlues
  • 3,444
  • 5
  • 29
  • 37