Created
August 25, 2014 08:53
-
-
Save summerblue/607a4072486f6790fac5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <h2>用例 Use Case</h2> | |
| <ul><li>会员可以对某个主题投票;</li> | |
| <li>会员可以对某个回复进行投票;</li> | |
| </ul> | |
| <p>Laravel 的 ORM Eloquent 对这一类型的业务逻辑有很好的支持, 如下面几个例子</p> | |
| <h4>一般 CMS 通用评论功能</h4> | |
| <ul><li>用户可以对文章进行评论;</li> | |
| <li>用户可以对用户进行评论;</li> | |
| <li>用户可以对专题进行评论;</li> | |
| </ul> | |
| <h4>标签功能</h4> | |
| <p>在某知名系统里面, 有 <code>post</code> 表和 <code>page</code> 表, 分别对应文章和页面.</p> | |
| <ul><li>管理员可以给 <code>post</code> 打标签;</li> | |
| <li>管理员可以对 <code>page</code> 打标签;</li> | |
| </ul> | |
| <p>这中类型的业务逻辑使用 Laravel 的 多态数据关系 (Polymorphic Relationship) 来解决那是最好不过了.</p> | |
| <h2>开始代码</h2> | |
| <h3>1. 添加 Route</h3> | |
| <pre><code class="language-php"># ------------------ Votes ------------------------ | |
| Route::get('/topics/{id}/upvote', [ | |
| 'as' => 'topics.upvote', | |
| 'uses' => 'TopicsController@upvote', | |
| 'before' => 'auth' // 需要登录用户才能访问. | |
| ]); | |
| Route::get('/topics/{id}/downvote', [ | |
| 'as' => 'topics.downvote', | |
| 'uses' => 'TopicsController@downvote', | |
| 'before' => 'auth' | |
| ]); | |
| Route::get('/replies/{id}/vote', [ | |
| 'as' => 'replies.vote', | |
| 'uses' => 'RepliesController@vote', | |
| 'before' => 'auth' | |
| ]); | |
| </code></pre> | |
| <p>我们使用了 <code>name route</code>, 这样在页面里面, 使用帮助函数</p> | |
| <pre><code class="language-php">route('topics.upvote', $topic->id) | |
| </code></pre> | |
| <p>就可以生成类似以下的链接了.</p> | |
| <pre><code>http://phphub.org/topics/20/upvote | |
| </code></pre> | |
| <h3>2. 添加页面入口</h3> | |
| <p>此代码省略..., 下面是效果图</p> | |
| <p><img src="http://ww1.sinaimg.cn/large/6d86d850gw1ejmov82c5sj20ku0biwfn.jpg" alt="" /></p> | |
| <h3>3. 创建 Migration</h3> | |
| <pre><code class="language-shell">php artisan generate:migration create_votes_table | |
| </code></pre> | |
| <p>上面命令会在 <code>app/database/migrations</code> 文件夹下生成类似于 <code>2014_08_20_130447_create_votes_table.php</code> 的文件.</p> | |
| <p>在 <code>up</code> 方法里面填入以下</p> | |
| <pre><code class="language-php">Schema::create('votes', function(Blueprint $table) | |
| { | |
| $table->increments('id'); | |
| $table->integer('user_id')->unsigned()->index(); | |
| $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | |
| $table->integer('votable_id')->index(); | |
| $table->string('votable_type')->index(); | |
| $table->string('is')->index(); | |
| $table->timestamps(); | |
| }); | |
| </code></pre> | |
| <p>可读性很好的代码, 这里不解释.</p> | |
| <h3>4. 创建 Model 文件</h3> | |
| <pre><code class="language-shell">php artisan generate:model Vote | |
| </code></pre> | |
| <p>上面命令会在 <code>app/model/</code> 文件夹下生成 <code>Vote.php</code> 文件, 在里面添加以下几行方法</p> | |
| <pre><code class="language-php">public function votable() | |
| { | |
| return $this->morphTo(); | |
| } | |
| </code></pre> | |
| <h3>5. 开始链接 Topic 和 Reply</h3> | |
| <p>在 <code>app/model/Topic.php</code> 和 <code>app/model/Reply</code> 文件中加入相同的方法</p> | |
| <pre><code class="language-php">public function votes() | |
| { | |
| return $this->morphMany('Vote', 'votable'); | |
| } | |
| </code></pre> | |
| <h3>6. 开始调用</h3> | |
| <h4>Topic 话题</h4> | |
| <p>以下是给 <code>Topic 话题</code> 投票的时候的调用, <code>TopicsController</code> 里面</p> | |
| <pre><code class="language-php">public function upvote($id) | |
| { | |
| $topic = Topic::find($id); | |
| $topic->votes()->create(['user_id' => Auth::user()->id, 'is' => 'upvote']); | |
| return Redirect::back(); | |
| } | |
| </code></pre> | |
| <p>通过上面的 <code>create</code> 方法, 创建了一个 vote, 看下数据库里面的内容, 注意 <code>votable</code> 字段:</p> | |
| <p><img src="http://ww4.sinaimg.cn/large/6d86d850gw1ejmq0sg3quj20on0fpwgi.jpg" alt="" /></p> | |
| <h4>Reply 评论</h4> | |
| <p>以下是给 <code>Reply 评论</code> 投票的时候的调用, <code>RepliesController</code> 里面</p> | |
| <pre><code class="language-php">public function vote($id) | |
| { | |
| $reply = Reply::find($id); | |
| $reply->votes()->create(['user_id' => Auth::user()->id, 'is' => 'upvote']); | |
| return Redirect::back(); | |
| } | |
| </code></pre> | |
| <p>通过上面的 <code>create</code> 方法, 创建了一个 vote, 看下数据库里面的内容, 同样注意 <code>votable</code> 字段:</p> | |
| <p><img src="http://ww4.sinaimg.cn/large/6d86d850gw1ejmq5wqpcpj20on0fpgnr.jpg" alt="" /></p> | |
| <h2>总结</h2> | |
| <p>介绍完了, 很神奇吧, 最少的代码, 兼顾可读性, 把一个复杂的逻辑轻轻松松的解决. 这就是 Laravel4. :+1:</p> | |
| <blockquote> | |
| <p>PHPHub 的 Vote 功能具体的代码请参照 <a href="https://github.com/summerblue/phphub">源码</a> .</p> | |
| </blockquote> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment