We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Conditions on relation

Hi everyone!

I have small problem. If is it duplicate of some other topic I am sorry from top.

I have two models: Auctions and Items and obviously these models have relation.

Auctions.php

public function initialize()
{
  $this->belongsTo('char_id', 'Characters', 'id', array('alias' => 'Characters'));
  $this->belongsTo('item_id', 'Items', 'id', array('alias' => 'Items'));
  $this->belongsTo('winner_id', 'Character', 'id', array('alias' => 'Winner'));
}

Items.php

public function initialize()
{
  $this->hasMany('id', 'TeamsItems', 'item_id', array('alias' => 'TeamItems'));
  $this->hasMany('id', 'ItemsStats', 'item_id', array('alias' => 'ItemsStats'));
  $this->hasMany('id', 'Loot', 'item_id', array('alias' => 'Loot'));
  $this->hasMany('id', 'CharsItems', 'item_id', array('alias' => 'CharsItems'));
  $this->hasMany('id', 'Auctions', 'item_id', array('alias' => 'Auctions'));
}

And here I have code of my controller to these:

$items = Auctions::find(array(
    'Items.id = 1'
));

All of that unfortunately give me something like this:

Unknown model or alias 'Items' (11), when preparing: SELECT [Auctions].* FROM [Auctions] WHERE Items.id = 1

Here is my question. Can I do this way or maybe there is more complicated but running solution?

Thanks for answers

edited Aug '15

You can use modelsManager like this:

$modelsManager->createBuilder()
    ->columns(whatever columns you want)
    ->from(array('Auctions'=>'Namespace of model'))
    ->leftJoin('namespace of related model',null,'Items')
    ->where('Items.id = 1')
    ->getQuery()
    ->execute()
    ->toArray(); - or dont if you dont wanna array

instead of $modelsManager you can use Auctions::query() which is wrapper of modelsManager for selected model(so you dont have to use from,getQuery and createBuilder - rest is the same)

Also you can overrite find and write your own version of it witch will auto-join related models if there are any - but i dont think its a good idea, its bad to lazyload them.

Im just using modelsManager, but i think i will change it someday to wrappers from ::query()

What are you wanting to find? Judging by your code snippet, you want a list of Items, but you're using Auctions::find() to do it. A little more information on your goal would be helpful.

edited Aug '15

Oh sorry i didnt read what you wanna find.

Just write :

$items = Auctions::find(array( 'item_id = 1' ));

also im not sure its working like this, im using it like this in my project:

Auctions::find(array( 'conditions'=>'item_id = :item_id:', 'bind'=>array('item_id'=>1) ));

and it should work

edited Aug '15

After moment of thinking, I understood it was stupid example ;) My really goal is select every item on auctions where (in Items model) kind is ... for example 'shoes', so controller's code is looking like this:


$items = Auctions::find(array(
    'Items.kind = :kind:',
    'bind' => array('kind' => $kind)
));

Sorry for not complete question

You don't need to involve the Auctions model at all - you're dealing entirely with Items

$items = Items::find(array(
    'kind = :kind:',
    'bind'=>array(
        'kind'=>$kind)
    ));


145.0k
Accepted
answer
edited Aug '15

You don't need to involve the Auctions model at all - you're dealing entirely with Items

$items = Items::find(array(
  'kind = :kind:',
  'bind'=>array(
      'kind'=>$kind)
  ));

But i think he wants to retrieve Auctions WHERE kind of related Items is $kind, this gonna get all Items where kind = $kind

I wrote right answer higher.

You can do what you want by:

$modelsManager->createBuilder()
    ->columns('*')
      ->from(array('Auctions'=>'Namespace of Auctions'))
      ->leftJoin('Namespace of Items',null,'Items')
      ->where('Items.kind = :kind:',array('kind'=>$kind))
      ->getQuery()
      ->execute();

earlier setting modelsManager example from di OR:

    Auctions::query()
        ->leftJoin('Items')
        ->where('Items.kind = :kind:',array('kind'=>$kind))
        ->execute()

Second method looks better cuz you dont have to use full namespaces beacause its using your relations if you made them right.

I just dont like static methods - thats why im using modelsManager in my project.

Also calling models Auctions and Items is pretty bad - you should call them Auction and Item

You don't need to involve the Auctions model at all - you're dealing entirely with Items

$items = Items::find(array(
 'kind = :kind:',
 'bind'=>array(
     'kind'=>$kind)
 ));

But i think he wants to retrieve Auctions WHERE kind of related Items is $kind, this gonna get all Items where kind = $kind

I wrote right answer higher.

You can do what you want by:

$modelsManager->createBuilder()
   ->columns('*')
    ->from(array('Auctions'=>'Namespace of Auctions'))
    ->leftJoin('Namespace of Items',null,'Items')
    ->where('Items.kind = :kind:',array('kind'=>$kind))
    ->getQuery()
    ->execute();

earlier setting modelsManager example from di OR:

  Auctions::query()
      ->leftJoin('Items')
      ->where('Items.kind = :kind:',array('kind'=>$kind))
      ->execute()

Second method looks better cuz you dont have to use full namespaces beacause its using your relations if you made them right.

I just dont like static methods - thats why im using modelsManager in my project.

Also calling models Auctions and Items is pretty bad - you should call them Auction and Item

Yes, it is exactly what I'm looking for. Thank you very much. Maybe In future we would have solution like mine previously? ;)