今天继续加深书籍详细信息页面的构造。
在G+上95对我的进展发了一个评论:
再加上点自动抓取网上共享章节的功能
对这个要求,我只能说我只能实现一点点。我将在详细信息页面中构造一个显示豆瓣对应书籍的信息的部分。
另外,我要实现一个功能是在这个页面中编辑书籍tags的功能。
先看实现的界面:
先讲在页面中编辑书籍tags。
这个其实很简单,在控制器中创建一个动作tagaddAction,用来处理“增加更多TAG”按钮的POST动作:
public function tagaddAction(Request $req)
{
$q=$req->request->all();
$q['newtags'];
$id=$q['id'];
$this->processTagAdd($tags, $id);
$url=$this->get('router')->generate('book_detail', array('id'=>$id));
return $this->redirect($url);
}
private function processTagAdd($tags, $id)
{
$em=$this->getDoctrine()-gt;getEntityManager();
$existing=$em->getRepository('trrsywxBundle:BookBook')->getTagsByBookId($id);
$existing=$this->convertTagsToArray($existing);
$book=$em->getRepository('trrsywxBundle:BookBook')->findOneBy(array('id'=>$id));
$tags=trim($tags);
$tagslist= explode(' ', $tags);
foreach ($tagslist as $tag)
{
if(!in_array($tag, $existing)) //This is a new tag
{
$booktaglist=new trrsywxBundleEntityBookTaglist();
$booktaglist->setId($book);
$booktaglist->setTag($tag);
$em->persist($booktaglist);
}
$em->flush();
}
}
这里有几个需要讲一讲的地方:
- 在控制器中生成一个url,然后重定向。这也是一般表单post后所需要进行的最后一步。
- 在processTagAdd中,需要注意$booktaglist->setId()的参数不是$book.id,而是$book本身。所以,虽然我传递进去的是$id,但是之前不得不用一个Repository函数来找出这本书。
- 注意一个新的taglist是怎样创建,赋值,持续化的。最后,将所有持续化后的对象一次性flush到数据库中去。
- 用in_array来判断要新加的tag是否已经存在于原来的taglist里,同时要将taglist对象中的tag提取出来变成一个数组——因为它本来是个对象数组。这个是由一个辅助函数convertTagsToArray完成的。
=====我是分割线=====
接下来讲一讲获得豆瓣的信息。
我用到了Snoopy这个库,关于如何在Symfony 2中加入第三方库的说明,参见这篇文章。
获得豆瓣信息的核心代码如下:
private function getDoubanRemote($isbn)
{
$bad_isbn = 'bad isbn';
$url = "http://api.douban.com/book/subject/isbn/$isbn?alt=json";
$s = new SnoopySnoopy();
$s->agent = 'RSYWX.net - http://www.rsywx.net';
$s->read_timeout = 1;
//$s->user = 'taylor.ren@gmail.com';
//$s->pass = 'xxxxxx';
$s->fetch($url);
$res = $s->results;
if ($res == $bad_isbn) // My isbn is not found in douban
return false;
else
return json_decode($res, true);
}
public function getDouban($isbn)
{
$ret = $this->createDummyReturn();
$res = $this->getDoubanRemote($isbn);
if (!$res) // The above call not successful
{
return $ret;
} else
{
if (array_key_exists('summary', $res))
$summary = $res['summary']['$t'];
else
$summary = '(豆瓣还没有简介)';
$ret['summary'] = $summary;
$ret['alternate'] = $res['link'][1]['@href'];
if (array_key_exists('db:tag', $res))
$tags = $res['db:tag'];
else
$tags[] = '豆瓣没有给出任何TAG';
$ret['tags'] = array(); //Clear up the dummy tag 'not found';
foreach ($tags as $t)
{
$ret['tags'][] = $t['@name'];
}
$rating = $res['gd:rating']['@average'];
if ($rating == 0)
$rating = '(还没有评分)';
$ret['rating'] = $rating;
}
return $ret;
}
其实没有什么技术含量,主要是从豆瓣API返回的数组中提取我用得着的数据而已。
到此,书籍详细页面已经完成。我接下来要做的是书籍列表部分。这个部分需要用到分页。可耻的是,Symfony 2没有内置分页部件,我需要自己来编写。这个会是一个挑战。
【本文收录于[go4pro.org]】
Leave a Reply