L'opérateur Conditions de défaut peut-il être modifié de ou vers et sur l'extension tagible?

StackOverflow https://stackoverflow.com//questions/12679389

  •  12-12-2019
  •  | 
  •  

Question

$tagged = Os :: model()-> withTags("windows, windows7, windowsXp")-> find();

Je veux récupérer les enregistrements étiquetés avec l'un des éléments suivants Windows , Windows7 , WindowsXP .

Par défaut, les tags génèrent une condition qui sont et éd.Je veux utiliser l'opérateur ou l'opérateur pour les balises.Donc, si l'enregistrement contient Windows, Windows7 mais pas WindowsXP, il ne sera pas récupéré.

J'ai réussi à trouver une solution de contournement, en modifiant la getfindbytagscriteria () dans le etaggablebehavior.php qui vient dans le dossier d'extension.

/**
     * Get criteria to limit query by tags.
     * @access private
     * @param array $tags
     * @return CDbCriteria
     */
    protected function getFindByTagsCriteria($tags) {
            $criteria = new CDbCriteria();

            $pk = $this->getOwner()->tableSchema->primaryKey;

            if(!empty($tags)){
                    $conn = $this->getConnection();
                    $criteria->select = 't.*';

                    if(count($tags) >0){
                            $criteria -> join .= "
                                    JOIN {$this->getTagBindingTableName()} bt 
                                    ON t.{$pk} = bt.{$this->getModelTableFkName()}

                                    JOIN {$this->tagTable} tag0 
                                    ON tag0.{$this->tagTablePk} = bt.{$this->tagBindingTableTagId} AND (";


                            for($i = 0, $count = count($tags); $i < $count; $i++){
                                    $tag = $conn->quoteValue($tags[$i]);
                                    $criteria->join .= " tag0.`{$this->tagTableName}` = $tag OR";
                            }
                            $criteria -> join = rtrim($criteria -> join, "OR");
                            $criteria -> join .= ")";
                    }
            }

            if($this->getScopeCriteria()){
                    $criteria->mergeWith($this->getScopeCriteria());
            }

            return $criteria;
    }

J'apprécierais vraiment tout autre moyen sans avoir à modifier le plugin lui-même.

Était-ce utile?

La solution 2

Sam de l'équipe de développement de Yii m'a aidé à résoudre ceci en ajoutant deux autres fonctions à la etaggablebehavior.php

/**
 * Get criteria to limit query to match any of tags specified
 * @access private
 * @param array $tags
 * @return CDbCriteria
 */
protected function getFindByAnyTagsCriteria($tags) {
    $criteria = new CDbCriteria();

    $pk = $this->getOwner()->tableSchema->primaryKey;

    if(!empty($tags)){
        $conn = $this->getConnection();
        foreach($tags as &$tag) {
            $tag = $conn->quoteValue($tag);
        }
        unset($tag);
        $tags = implode(', ', $tags);

        $criteria->select = 't.*';
        $criteria->join .=
            "JOIN {$this->getTagBindingTableName()} bt ON t.{$pk} = bt.{$this->getModelTableFkName()}
            JOIN {$this->tagTable} tag ON tag.{$this->tagTablePk} = bt.{$this->tagBindingTableTagId} AND tag.`{$this->tagTableName}` IN ($tags)";
        }
    }

    if($this->getScopeCriteria()){
        $criteria->mergeWith($this->getScopeCriteria());
    }

    return $criteria;
}

/**
 * Limit current AR query to have any of tags specified.
 * @param string|array $tags
 * @return CActiveRecord
 */
public function taggedWithAnyOf($tags) {
    $tags = $this->toTagsArray($tags);

    if(!empty($tags)){
        $criteria = $this->getFindByAnyTagsCriteria($tags);
        $this->getOwner()->getDbCriteria()->mergeWith($criteria);
    }

    return $this->getOwner();
}

Autres conseils

Que ferais ici est défini la méthode withTags () dans votre modèle pour prendre une valeur de matrice, par exemple quelque chose comme ceci:

/**
 * @param array $tags List of tags to search for
 * @return named scope
 */
public function withTags($tags)
{
    $condition = '1';
    $params = array();
    foreach($tags as $key=>$value)
    {
        $condition.=' OR tag = :tag'.$key;
        $params[':tag'.$key] = $value;
    }
    $this->getDbCriteria()->mergeWith(array(
        'condition'=>$condition,
        'params'=>$params,
    ));

    return $this;
}

De cette façon, vous devriez pouvoir appeler votre portée nommée comme si:

$tags = array('windows', 'windows7', 'windowsXp'),
$tagged = Os::model()->withTags($tags)->findAll();

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top