2

I need to match an associated model on a user id, I thought the below code would work since I do get the user_id back for ArticleUser, but it's not giving me the FavoriteArticle I need.

The data comes back as null for the FavoriteArticle model, and yes, there is a favorite_articles table in the DB.

public $hasOne = array(
    'ArticleUser',
    'FavoriteArticle' => array(
        'className' => 'FavoriteArticle',
        'conditions' => array(
            'FavoriteArticle.user_id' => 'ArticleUser.user_id'
        ),
        'dependent' => true
    ) 
);
AD7six
  • 63,116
  • 12
  • 91
  • 123
shonatodc
  • 21
  • 3
  • Two questions: 1. What version of CakePHP are you using? 2. Can you fetch the FavoriteArticle from the ArticleUsersController using `$this->ArticleUsers->FavoriteArticles->find('all', array('conditions' => array('user_id' => X)));`? – Lars Ebert Sep 03 '15 at 08:14
  • @LarsEbert it's version 2.6.1 and I'm not using an ArticleUsersController since the Article model hasOne ArticleUser. All the logic is in the ArticlesController. Also I was hoping there was some way to pass the current userId to the association property, but it seems there isn't a way without binding the model in the controller. – shonatodc Sep 04 '15 at 16:40
  • Then can you access the FavoriteArticle from the ArticleController using `$this->Article->ArticleUsers->FavoriteArticles->find('all', array('conditions' => array('user_id' => X)));`? – Lars Ebert Sep 04 '15 at 17:39
  • @LarsEbert Getting an error on the find doing it that way. Also, this logic would only get articles if they have favorites, what if articles don't have favorites tied to them? I need Articles and FavoriteArticles together, I understand I could do an AND or an OR operator, but was hoping I could just get this via the model on run time and not have to build a query in the action. btw i went with a separate function to handle if users have favorite articles. – shonatodc Sep 05 '15 at 21:00
  • Using `$this->Articles->ArticleUsers->FavoriteArticles->find` in the ArticlesController is equivalent to using `$this->FavoriteArticles->find` in the FavoriteArticlesController. So if you can run a very simple query (only `find('all')` in the FavoriteArticlesController but not from the ArticlesController, the association is not working. Also: What error are you getting? – Lars Ebert Sep 06 '15 at 09:43
  • @LarsEbert the error is, "Call to a member function find() on a non-object". – shonatodc Sep 09 '15 at 20:44

1 Answers1

0

Take a look at your executed sql.

Condition arrays are always escaped

When a condition is defined as an array, it's assumed by CakePHP that the key is "safe" and the value is user input, array values are always escaped. What that means here is that this code:

public $hasOne = array(
    'ArticleUser',
    'FavoriteArticle' => array(
        'conditions' => array(
            'FavoriteArticle.user_id' => 'ArticleUser.user_id' # <-
        ),
        'dependent' => true
    ) 
);

With a find call like this:

$stuff = $articles->find('all', [
    'contain' => [
       'ArticleUser',
       'FavoriteArticle'
    ]
]);

Would generate sql equivalent to:

SELECT 
    *
FROM 
    articles
LEFT JOIN
    article_user ON (
        favorite_articles.article_user_id = article_user.id
    )
LEFT JOIN
    favorite_articles ON (
        favorite_articles.articles_id = articles.id AND
        favorite_articles.user_id = 'ArticleUser.user_id' # <-
    )

Note that the join condition is comparing user_id to a string

How to compare two field values

To compare two field values, use an sql fragment:

public $hasOne = array(
    'ArticleUser',
    'FavoriteArticle' => array(
        'conditions' => array(
            'FavoriteArticle.user_id = ArticleUser.user_id'
                                    ^ ^ no quotes
        ),
        'dependent' => true
    ) 
);

Which would generate sql equivalent to:

SELECT 
    *
FROM 
    articles
LEFT JOIN
    article_user ON (
        favorite_articles.article_user_id = article_user.id
    )
LEFT JOIN
    favorite_articles ON (
        favorite_articles.articles_id = articles.id AND
        favorite_articles.user_id = articles_users.user_id # <-
    )
Community
  • 1
  • 1
AD7six
  • 63,116
  • 12
  • 91
  • 123
  • This did not work for me. still got null values in the favoriteArticles properties. Went a different route with this anyways, but TY. – shonatodc Oct 05 '15 at 20:40
  • `Take a look at your executed sql.` - You have still not added this to the question. Adding the sql that _will_ give you the data you want would also help. – AD7six Oct 06 '15 at 08:37