phpsymfonytagsentity-relationshiptag-cloud

Symfony2 - Setting up tag cloud using tagweights for popular tags


I am trying to setup a weighted tag cloud, that works when tags are a string property in the blog entity.

Now I've setup tags as it's own entity and related to blog as a bi-directional ManyToMany/ManyToMany relationship.

Needless to say it's not working, I'm guessing it's because tag is now it's own object.

My question: What am I doing wrong here now that tags is it's own entity and not a string property from blog entity?

When I dump $tagWeights from the controller below, I get an error when I should be seeing something like this:

array (size=78)

'Tag1' => float 1

'Tag2' => float 5

'Tag3' => float 2

error: (this line:

foreach ($tags as $tag) {

$tagWeights[$tag] = (isset($tagWeights[$tag])) ? $tagWeights[$tag] + 1 : 1;

}

ContextErrorException: Warning: Illegal offset type in isset or empty in /var/www/html/Satori/src/Symfony/AcmeBundle/Entity/TagRepository.php line 34

I'm calling tags in the following way in twig:

Twig

{% for tag, weight in tags %}
    <span class="weight-{{ weight }}"><a href="">{{ tag }}</a></span>
{% else %}
    <p>There are no tags</p>
{% endfor %}

Controller (dumping $tags works great shows all the tags)

public function footerAction()
{
    $em = $this->getDoctrine()->getManager();

    $tags = $em->getRepository('AcmeBundle:Tag')
        ->getTags();

    $tagWeights = $em->getRepository('AcmeBundle:Tag')
        ->getTagWeights($tags);
    var_dump($tagWeights); die();
    return array(
        'tags' => $tagWeights,

    );
}

Here is the getTags and getTagWeights:

public function getTags()
{
    $tags = $this->createQueryBuilder('t')
        ->select('t.tag')
        ->getQuery()
        ->getResult();

    return $tags;
}

public function getTagWeights($tags)
{
    $tagWeights = array();

    if (empty($tags))
        return $tagWeights;

    foreach ($tags as $tag)
    {
        $tagWeights[$tag] = (isset($tagWeights[$tag['tag']])) ? $tagWeights[$tag] + 1 : 1;
    }

    // Shuffle the tags
    uksort($tagWeights, function() {
        return rand() > rand();
    });

    $max = max($tagWeights);

    // Max of 5 weights
    $multiplier = ($max > 5) ? 5 / $max : 1;

    foreach ($tagWeights as &$tag)
    {
        $tag = ceil($tag * $multiplier);
    }

    return $tagWeights;
}

Tag entity

class Tag
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="tag", type="string", length=255)
     */
    private $tag;

    /**
     * @ORM\ManyToMany(targetEntity="Blog", mappedBy="tags")
     */
    protected $blogs;

    public function __construct()
    {
        $this->blogs = new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set tag
     *
     * @param string $tag
     * @return Tag
     */
    public function setTag($tag)
    {
        $this->tag = $tag;

        return $this;
    }

    /**
     * Get tag
     *
     * @return string 
     */
    public function getTag()
    {
        return $this->tag;
    }

    /**
     * Add blogs
     *
     * @param \AcmeBundle\Entity\Blog $blogs
     * @return Tag
     */
    public function addBlog(\AcmeBundle\Entity\Blog $blogs)
    {
        $this->blogs[] = $blogs;

        return $this;
    }

    /**
     * Remove blogs
     *
     * @param \AcmeBundle\Entity\Blog $blogs
     */
    public function removeBlog(\AcmeBundle\Entity\Blog $blogs)
    {
        $this->blogs->removeElement($blogs);
    }

    /**
     * Get blogs
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getBlogs()
    {
        return $this->blogs;
    }
}

Proposed solutions and results

Using (isset($tagWeights[$tag['tag']])) error:

ContextErrorException: Warning: Illegal offset type in /var/www/html/Satori/src/Symfony/AcmeBundle/Entity/TagRepository.php line 34

Using (isset($tagWeights[$tag[$tag->getTag()])) error:

ContextErrorException: Notice: Trying to get property of non-object in /var/www/html/Satori/src/Symfony/AcmeBundle/Entity/TagRepository.php line 34


Solution

  • I think I know what's happening here...

    When you make this call in your footerAction:

    $tags = $em->getRepository('AcmeBundle:Tag')
        ->getTags();
    

    your repository returns to you an array of arrays. So when you say:

    isset($tagWeights[$tag])
    

    ...that $tag is actually an associative array of the result set. I think what you mean to say here is:

    isset($tagWeights[$tag['tag']])
    

    That said, I'd advise against giving your Tag entity a property called tag. a tag doesn't have a tag, it has a name, or a description. And it'd make much more sense here to say

    isset($tagWeights[$tag['name']])
    

    ...or by having the repository return the Tag entities themselves (why do you even need to override the built-in getXyz() method?), and do:

    isset($tagWeights[$tag->getName()])