在symfony 1.4中创建一个“喜欢/不喜欢”按钮

时间:2022-10-25 19:15:24

I want to create a "like/dislike" button in Ajax with Symfony 1.4.

我想用Symfony 1.4在Ajax中创建一个“喜欢/不喜欢”按钮。

I have these tables :

我有这些表格:

| Song | ------- n --------------------------- n ---------- | sfGuardUser |
                               |
                          | LikeSong |                 `

I've read symfony AJAX documentation but it is 1.0 documentation. 1.4 is very light. So, here is what I tried to do first.

我读过symfony AJAX文档,但它是1.0文档。1.4很轻。这是我首先要做的。

In /app/frontend/module/likesong/_voting.php :

在/ app /前端/模块/ likesong / _voting。php:

<?php
    if($song->hasVote())
    {
        jq_link_to_remote('I do not like', array('complete' => '[??? Update my link]', 'url' => 'likesong/notlike?id_song='.$song->getId()));
    }
    else
    {
        jq_link_to_remote('I like', array('complete' => '[??? Update my link]', 'url' => 'likesong/like?id_song='.$song->getId()));
    }
    echo ' - '.$song->getNbVote();
?>

In /app/frontend/config/routing.yml :

在/ app /前端/ config /路由。yml:

song_like:
  url:      /song-like/:id
  param:    { module: song, action: like }

song_notlike:
  url:      /song-not-like/:id
  param:    { module: song, action: notLike }

In /app/frontend/module/likesong/actions.class.php

在/ app /前端/模块/ likesong / actions.class.php

public function executeLike(sfWebRequest $request)
{
  if ($request->isXmlHttpRequest())
  {                              
    if(USER HAS NOT YET VOTED)
    {
      $this->vote = new LikeSong();

      $this->vote->setSongId($this->song()->getId());
      $this->vote->setSfGuardUserId($this->getUser()->getId());
      $this->vote->save();

      return $this->renderText('notlike');
      else
      {
        // Display flash
      }
    }
 }

public function executeNotLike(sfWebRequest $request)
{
  if ($request->isXmlHttpRequest())
  {                              
     if(USER ALREADY VOTED)
     {
        // Delete form database

        return $this->renderText('like');
        else
        {
          // Display flash
        }
      }
}

When the user click, "I like this song" should be replaced by "I don't like this song".

当用户点击时,“我喜欢这首歌”应该被“我不喜欢这首歌”取代。

1 个解决方案

#1


3  

First, you should not have business logic in your controller.

首先,在控制器中不应该有业务逻辑。

Your templates code is weird too - I never used jq_link_to_remote() for anything ajax, and quick searching about this function, it seems to have many troubles. You'll probably have a lot of issues solved if you go back on conception.

您的模板代码也很奇怪——我从未对任何ajax使用jq_link_to_remote(),并且快速搜索这个函数,它似乎有很多问题。如果你回到概念上,你可能会解决很多问题。

  1. User like or doesn't like a song should be written in your Song class. I'd write something like this :

    用户喜欢或不喜欢一首歌应该写在你的歌曲类。我会这样写:

    class Song extends BaseSong
    {
    
        public function userLike($user_id)
        {
            return in_array($user_id, $this->getLikers()->getPrimaryKeys()));
        }
    
        public function switchLike($user_id)
        {
            if ($this->userLike($user_id))
            {
                $this->getLikers()->remove($user_id);
                $this->save();
                return 0;
            }
            else
            {
                $this->getLikers()->add(Doctrine::getTable('User')->find($user_id));
                $this->save();
                return 1;
            }
        }
    }
    
  2. You should always write clean controllers which can be called with or without AJAX. The isXmlHttpRequest() function can be very powerful, but it must NOT kill the accessibility of your website. Javascript must stay optional, your links must have functional fallbacks for standard http calls. I'd start with something like this:

    您应该始终编写干净的控制器,可以用AJAX调用,也可以不使用AJAX调用。isXmlHttpRequest()函数可能非常强大,但它不能破坏网站的可访问性。Javascript必须是可选的,您的链接必须具有标准http调用的功能性回退。我想从这样开始:

    public function executeIndex(sfWebRequest $request)
    {
          // Here the code for the whole song's page, which will include your _vote partial
    }
    
    public function executeSwitchLike(sfWebRequest $request)
    {
          $this->song = Doctrine::getTable('Song')->find($request->getParameter('id'));
          $this->song->switchLike($this->getUser()->getId());
          $this->redirect('song/index?id='.$request->getParameter('id'));
    }
    

Then, write your template with a simple http link for 'like' or 'don't like'. You should have the behavior of reloading the entire page, with just switching the 'like' status.

然后,用一个简单的http链接来写“喜欢”或“不喜欢”。您应该具有重载整个页面的行为,只需切换“like”状态。

Finally, overload this link with a simple jquery.load() call, which only replace the HTML element you're aiming to replace:

最后,使用一个简单的jquery.load()调用来重载这个链接,它只会替换您想要替换的HTML元素:

$('#like_block').load('/switchLike?id=<?php echo $song->id ?>');

It will result in the whole PHP executed, which is a good way to work with AJAX, but only your specific HTML element is reloaded.

它将导致执行整个PHP,这是使用AJAX的一种好方法,但只重新加载特定的HTML元素。

#1


3  

First, you should not have business logic in your controller.

首先,在控制器中不应该有业务逻辑。

Your templates code is weird too - I never used jq_link_to_remote() for anything ajax, and quick searching about this function, it seems to have many troubles. You'll probably have a lot of issues solved if you go back on conception.

您的模板代码也很奇怪——我从未对任何ajax使用jq_link_to_remote(),并且快速搜索这个函数,它似乎有很多问题。如果你回到概念上,你可能会解决很多问题。

  1. User like or doesn't like a song should be written in your Song class. I'd write something like this :

    用户喜欢或不喜欢一首歌应该写在你的歌曲类。我会这样写:

    class Song extends BaseSong
    {
    
        public function userLike($user_id)
        {
            return in_array($user_id, $this->getLikers()->getPrimaryKeys()));
        }
    
        public function switchLike($user_id)
        {
            if ($this->userLike($user_id))
            {
                $this->getLikers()->remove($user_id);
                $this->save();
                return 0;
            }
            else
            {
                $this->getLikers()->add(Doctrine::getTable('User')->find($user_id));
                $this->save();
                return 1;
            }
        }
    }
    
  2. You should always write clean controllers which can be called with or without AJAX. The isXmlHttpRequest() function can be very powerful, but it must NOT kill the accessibility of your website. Javascript must stay optional, your links must have functional fallbacks for standard http calls. I'd start with something like this:

    您应该始终编写干净的控制器,可以用AJAX调用,也可以不使用AJAX调用。isXmlHttpRequest()函数可能非常强大,但它不能破坏网站的可访问性。Javascript必须是可选的,您的链接必须具有标准http调用的功能性回退。我想从这样开始:

    public function executeIndex(sfWebRequest $request)
    {
          // Here the code for the whole song's page, which will include your _vote partial
    }
    
    public function executeSwitchLike(sfWebRequest $request)
    {
          $this->song = Doctrine::getTable('Song')->find($request->getParameter('id'));
          $this->song->switchLike($this->getUser()->getId());
          $this->redirect('song/index?id='.$request->getParameter('id'));
    }
    

Then, write your template with a simple http link for 'like' or 'don't like'. You should have the behavior of reloading the entire page, with just switching the 'like' status.

然后,用一个简单的http链接来写“喜欢”或“不喜欢”。您应该具有重载整个页面的行为,只需切换“like”状态。

Finally, overload this link with a simple jquery.load() call, which only replace the HTML element you're aiming to replace:

最后,使用一个简单的jquery.load()调用来重载这个链接,它只会替换您想要替换的HTML元素:

$('#like_block').load('/switchLike?id=<?php echo $song->id ?>');

It will result in the whole PHP executed, which is a good way to work with AJAX, but only your specific HTML element is reloaded.

它将导致执行整个PHP,这是使用AJAX的一种好方法,但只重新加载特定的HTML元素。