logo
Ask your Symfony questions! Pay money and get answers fast! (more info)

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.

$10
Is this a bug in sfPropelActAsTaggableBehavior plugin?

I am having a problem with sfPropelActAsTaggableBehavior plugin.

My code:

$arrayOfProjects = TagPeer::getModelsTaggedWith($arrayOfTags);



The error:

Fatal error: Undefined class constant 'COUNT' in /home/lawrence/domains/dev9/public_html/plugins/sfPropelActAsTaggableBehaviorPlugin/lib/model/TagPeer.php on line 185


TagPeer has this code:

    $c = new Criteria();
$c->addJoin(TagPeer::ID, TaggingPeer::TAG_ID);
$c->add(TagPeer::NAME, $tags, Criteria::IN);
$c->addGroupByColumn(TaggingPeer::TAGGABLE_ID);
$having = $c->getNewCriterion(TagPeer::COUNT, count($tags), Criteria::GREATER_EQUAL);
$c->addHaving($having);
$c->clearSelectColumns();
$c->addSelectColumn(TaggingPeer::TAGGABLE_MODEL);
$c->addSelectColumn(TaggingPeer::TAGGABLE_ID);


The line causing the problem is the one with COUNT in it.

I opened up BaseTagPeer and, sure enough, there is no constant called COUNT. Is this a bug? Am I missing something obvious?

UPDATE:

I am trying to write my own version of this method. This is what I've got so far:

  public static function getModelsTaggedWithTheseTags($tags = array())
{
if (count(tags)) {
$c = new Criteria();
$c->addJoin(TagPeer::ID, TaggingPeer::TAG_ID);
$c->add(TagPeer::NAME, $tags, Criteria::IN);
$c->addGroupByColumn(TaggingPeer::TAGGABLE_ID);
$c->addSelectColumn(TaggingPeer::TAGGABLE_MODEL);
$c->addSelectColumn(TaggingPeer::TAGGABLE_ID);

$params = array();
$sql = BasePeer::createSelectSql($c, $params);
echo $sql;
$con = Propel::getConnection();
$stmt = $con->prepare($sql);
$position = 1;

foreach ($tags as $tag) {
$stmt->bindValue($position, $tag);
$position++;
}

$stmt->bindValue($position, count($tags));
$rs = $stmt->execute($tags);

$models = array();

while ($object = $rs->fecth(PDO::FETCH_OBJ)) {
$models[] = $object;
}

return $models;
}
}


The SQL is:

SELECT sf_tagging.TAGGABLE_MODEL, sf_tagging.TAGGABLE_ID FROM `sf_tagging`, `sf_tag` WHERE sf_tag.NAME IN (:p1,:p2) AND sf_tag.ID=sf_tagging.TAG_ID GROUP BY sf_tagging.TAGGABLE_ID



The tokens correctly get replaced by the 2 tags that I'm handing in. However, I get this error on execute():

SQLSTATE[HY093]: Invalid parameter number: parameter was not defined

stack trace
at ()
in SF_SYMFONY_LIB_DIR/plugins/sfPropelPlugin/lib/vendor/propel/util/DebugPDOStatement.php line 61 ...
public function execute($input_parameters = null)

{

$this->pdo->incrementQueryCount();

return parent::execute($input_parameters);

}



I tried this:

      $stmt->bindValue($position, count($tags));
$rs = $stmt->execute();


and I tried commenting out the last bindValue:

    //   $stmt->bindValue($position, count($tags));
$rs = $stmt->execute($tags);



I feel like I'm missing something obvious. Any suggestions?


ANOTHER UPDATE

I got this working, but it is a bit ugly, especially how I'm creating the "position" values. I'll leave this question open for another 12 hours. If anyone wants to suggest a clean up, it would be welcome. I will then email whatever we have to Lacot, just in case he ever updates the plugin.

  public static function getModelsTaggedWithTheseTags($tags = array())
{
if (count(tags)) {
$c = new Criteria();
$c->addJoin(TagPeer::ID, TaggingPeer::TAG_ID);
$c->add(TagPeer::NAME, $tags, Criteria::IN);
$c->addGroupByColumn(TaggingPeer::TAGGABLE_ID);
$c->addSelectColumn(TaggingPeer::TAGGABLE_MODEL);
$c->addSelectColumn(TaggingPeer::TAGGABLE_ID);

$params = array();
$sql = BasePeer::createSelectSql($c, $params);
$con = Propel::getConnection();
$stmt = $con->prepare($sql);
$position = 1;

foreach ($tags as $tag) {
$stmt->bindValue(":p$position", $tag);
$position++;
}

// $stmt->bindValue($position, count($tags));
$stmt->execute();
$models = array();

while ($object = $stmt->fetch(PDO::FETCH_OBJ)) {
$models[] = $object;
}

return $models;
}
}



This question has been answered.

Lawrence Krubner | 03/01/10 at 2:55pm Edit


(5) Possible Answers Submitted...

See a chronological view of answers?

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

  • avatar
    Last edited:
    03/01/10
    3:16pm
    Kiril Angov says:

    Yes, looks like it: http://svn.symfony-project.com/plugins/sfPropelActAsTaggableBehaviorPlugin/trunk/config/schema.yml

    There is no database field "count" defined at all.

    Try this:

    $having = $c->getNewCriterion('COUNT('.TagPeer::NAME.')', count($tags), Criteria::GREATER_EQUAL);

    Previous versions of this answer: 03/01/10 at 3:16pm

    • 03/01/10 3:14pm

      Kiril Angov says:

      Try this:

      $having = $c->getNewCriterion('COUNT('.TagPeer::NAME.')', count($tags), Criteria::GREATER_EQUAL);

    • 03/01/10 5:03pm

      Lawrence Krubner says:

      The error then becomes:

      Fatal error: Call to undefined method DebugPDO::prepareStatement() in /home/lawrence/domains/dev9/public_html/plugins/sfPropelActAsTaggableBehaviorPlugin/lib/model/TagPeer.php on line 195

    • 03/01/10 5:08pm

      Lawrence Krubner says:

      TagPeer tries to handle Propel version 1.3 with this block of code:

          if (Propel::VERSION >= '1.3')
      {
      $rs = $stmt->query();

      while ($rs->fecth(PDO::FETCH_NUM))
      {
      $models[] = $rs->getString(1);
      }
      }
      else
      {
      $rs = $stmt->executeQuery(ResultSet::FETCHMODE_NUM);

      while ($rs->next())
      {
      $models[] = $rs->getString(1);
      }
      }


      I'm unclear why this does not work.

  • avatar
    Last edited:
    03/01/10
    3:19pm
    michalg says:

    Hello,

    I think that you're using version of propel which this plugin don't support. Look at this:

    http://propel.phpdb.org/trac/changeset/1068/trunk/generator/classes/propel/engine/builder/om/php5/PHP5PeerBuilder.php

    addCountConstants method has been removed in peer builder

    • 03/01/10 3:26pm

      michalg says:

      Here are more information:

      http://propel.phpdb.org/trac/changeset/939/branches/1.3/generator/classes/propel/engine/builder/om/php5/PHP5PeerBuilder.php

    • 03/01/10 4:31pm

      michalg says:

      Symfony 1.2.5 uses propel 1.3:

      http://propel.mirror.svn.symfony-project.com/branches/1.3/generator/classes/propel/engine/builder/om/php5/PHP5PeerBuilder.php

      Clearly in this version there isn't addCountConstants method.

  • avatar
    Last edited:
    03/01/10
    3:32pm
    Scott Meves says:

    The constant should be defined on line 125 of your generated BaseTagPeer.php file, right above the doCount() definition:


    const COUNT = 'COUNT(sf_tag.ID)';
    const COUNT_DISTINCT = 'COUNT(DISTINCT sf_tag.ID)';


    This is with symfony 1.0.22. Perhaps you are trying to use the plugin with symfony 1.2?

    • 03/01/10 4:13pm

      Lawrence Krubner says:

      Scott, yes, Symfony version 1.2.5. The plugin says it supports 1.2:

      http://www.symfony-project.org/plugins/sfPropelActAsTaggableBehaviorPlugin

    • 03/01/10 5:36pm

      Lawrence Krubner says:

      Off topic: Scott, do you still use Symfony 1.0.22 ?

  • avatar
    Last edited:
    03/05/10
    10:27pm
    Gert Findel says:

    I use the Plugin in a project with sf 1.2.9 and works good
    I had many problems with COUNT because I use in sqlite my dev env. Switching to MySQL solved it for me.

    When I had problems with COUNT and this Plugin I used the following code to get things working for my "tag_cloud"


    $criteria = DebatePeer::addCriteriaDebatesActivos();
    $criteria->addJoin(DebatePeer::ID, TaggingPeer::TAGGABLE_ID, Criteria::INNER_JOIN);
    $criteria->addJoin(TaggingPeer::TAG_ID, TagPeer::ID, Criteria::INNER_JOIN);

    $criteria->addSelectColumn(TagPeer::NAME);
    $criteria->add(TaggingPeer::TAGGABLE_MODEL, 'Debate');
    // $criteria->add(TaggingPeer::TAGGABLE_ID, DebatePeer::ID.'='.TaggingPeer::TAGGABLE_ID, Criteria::CUSTOM);
    $criteria->addAsColumn('cnt', 'count('.TaggingPeer::TAGGABLE_ID.')');
    $criteria->addGroupByColumn(TagPeer::NAME);
    $criteria->addDescendingOrderByColumn( 'cnt' , Criteria::CUSTOM);
    $criteria->setLimit(7);
    $this->tags = BasePeer::doSelect($criteria);


    And in the view

    <? foreach($tags as $tag): ?>
    <li><span>
    <?= link_to($tag['NAME'], '@debates_tag?tag='.$tag['NAME'],
    array('rel'=>'tag', 'title' => 'Debates etiquetados como '.$tag['NAME']))?> (<?=$tag['cnt']?>)
    </span></li>
    <? endforeach; ?>


    I know it was a workarround but it worked

    • 03/01/10 7:42pm

      Gert Findel says:

      Im my version the code works with


      foreach ($tags as $tag)
      {
      $stmt->setString($position, $tag);
      $position++;
      }

      $stmt->setString($position, count($tags));
      $models = array();

      if (Propel::VERSION >= '1.3')
      {
      $rs = $stmt->query();

      while ($rs->fecth(PDO::FETCH_NUM))
      {
      $models[] = $rs->getString(1);
      }


      So I would say your approuch is not much uglier than the author's implementation.

    • 03/01/10 9:19pm

      Gert Findel says:

      with the following query in my action

       
      $criteria = new Criteria();
      $criteria->addJoin(TaggingPeer::TAG_ID, TagPeer::ID, Criteria::INNER_JOIN);

      $criteria->addSelectColumn(TaggingPeer::TAGGABLE_MODEL);
      $criteria->add(TagPeer::NAME, array('toto','tutu'), Criteria::IN);
      $criteria->addAsColumn('cnt', 'count('.TaggingPeer::TAGGABLE_ID.')');
      $criteria->addGroupByColumn(TaggingPeer::TAGGABLE_MODEL);
      $criteria->addDescendingOrderByColumn( 'cnt' , Criteria::CUSTOM);
      $this->models = BasePeer::doSelect($criteria);


      I obtained (print_r($models))

      SELECT sf_tagging.TAGGABLE_MODEL, count(sf_tagging.TAGGABLE_ID) AS cnt FROM sf_tagging INNER JOIN sf_tag ON (sf_tagging.TAG_ID=sf_tag.ID) WHERE sf_tag.NAME IN (:p1,:p2) GROUP BY sf_tagging.TAGGABLE_MODEL ORDER BY cnt

      And inside of a foreach($models as $model) "print_r($model)" returns

      Array (
      [taggable_model] => BlogPost
      [0] => BlogPost
      [cnt] => 6
      [1] => 6
      )

      and

      Array (
      [taggable_model] => Debate
      [0] => Debate
      [cnt] => 2
      [1] => 2
      )


      Maybe you could try something like this.

    • 03/01/10 9:20pm

      Gert Findel says:

      IMHO this is cleaner

  • avatar
    Last edited:
    03/02/10
    3:04am
    Taboubi Issam says:

    make sure that when you build your model , check in your propel.ini if propel.builder.addBehaviors = true . clear cache it should be correct

This question has expired.





Current status of this question: Completed



Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.