用 10 分鐘在 Cloud9 開發一個 Laravel 5 的 Blog
Cloud9是一個雲端Web開發平台,它提供了一些開發環境給我們(例如安裝了PHP、Ruby、Python等),讓我們省卻配置伺服器及開發環境的時間,可以立即開發Web App。Cloud9 是免費的,每個開發環境有1個CPU、512MB RAM 及 2GB HDD,對小型 project 是夠用的,很適合用來學習各種 Web App 的開發。
選擇開發環境
等待 Cloud9 建立開發環境
建立完畢便進入了我們的開發環境
因為 Laravel 會提供 public 資料夾 的檔案給 Client,所以我們要(透過一個文字編緝器nano)修改 Apache Config
改完請按 F2 儲存,然後 'Y' 及 'Enter'。
最後是取得最新版本的 Laravel(筆者安裝的版本是 5.2)
至此 Laravel 5 已成功安裝,看看左邊已經多了 Laravel framework 的檔案
終於可以正式開發網誌網頁應用程式了。
請注意,本系列教學只會以最精簡的方式列出完成開發時必要的步驟,並在適當的地方加插圖片輔助,希望讀者能在最短時間親自完成教學。因此,當中的說明或解釋將會省略,如欲了解,請參考原文 Simple blog application in laravel 5。 這個日誌會有以下功能:
1. 任何人都可登入/註冊
2. 用戶可分類為「admin」、「author」或「subscriber」
3. 「author」可以撰寫/更新/刪除帖子
4. 「admin」擁有網站全部存取權限及可以閱讀/撰寫/更新/刪除任何帖子
5. 任何人都可閱讀帖子
6. 用戶可以(登入後)在帖子內留言
完成品如下圖所示,可到示範網站參看:
這個教學將分作 5 部份:
1) Setup database
- Connect with mysql database
- Create posts and comments tables
2) Make routes and models
- Routes
- Create post model
- Create comment model
- Create User model
3) Controllers
- PostController
- CommentController
4) Build front end
- Customize app.blade.php
- make home view
- Create posts
- Show posts
- Edit posts
5) Add tinymce and Make user profile
- Add tinymce to posts
- Make profile backend
- View for profile
到 blog >> config >> database.php , 找到 default, 改為
改完請儲存所有檔案
在 Terminal 輸入以下程式碼安裝 MySQL:
現在用 migrations
留意 blog >> database >> migrations 多了 2 個檔案
Migration 的作用是數據庫版本控制(database version control),原理與程式碼版本控制一樣,Migration 有 up() 和 down() 2 個 function,migration 執行的時候會執行up(),down() 則是 up() 的相反,還原 up() 所做過的。例如這裡的 up() 我們 create 了 posts 的 table ,down() 的時候便要把 posts 這個 table drop 走。
Schema 是另一個在建立/修改數據庫表格會用到的Class,create() function 有 2 個 arguments,第 1 個是數據庫名稱,另一個是開 column 的 closure。$table 是這個表格的 instance 。
儲存所有更改
最後是 generate 表格,在 Terminal 輸入:
數據庫設置完成
Cloud9 IDE是一個免費的在線集成開發環境,支持四十多種程式語言,例如 PHP、Ruby、Python、Go、JavaScript(包括Node.js)等。它可以使開發者在一個事先安裝好的環境中快速進入開發、與其他人協作並且在Web開發中做到實時預覽和瀏覽器兼容性測試等。
- Wiki
我們會用一個熱門的 PHP 框架 - Laravel(版本:5.2),在 Cloud9 建立一個簡單的 Blog 網站應用程式,所以請先到 Cloud9 註冊戶口。 開完戶口就可以立即建立開發環境
選擇開發環境
等待 Cloud9 建立開發環境
建立完畢便進入了我們的開發環境
安裝 Laravel 5
接下來會安裝最熱門的 PHP Framework - Laravel 5
在 Terminal 輸入以下指令(可以一次過複製以下指令並在 Terminal 貼上)rm README.md php.ini hello-world.php sudo composer self-update composer create-project laravel/laravel ./laravel --prefer-dist shopt -s dotglob mv laravel/* ./ rm -rf laravel
因為 Laravel 會提供 public 資料夾 的檔案給 Client,所以我們要(透過一個文字編緝器nano)修改 Apache Config
sudo nano /etc/apache2/sites-enabled/001-cloud9.conf把
DocumentRoot /home/ubuntu/workspace改為
DocumentRoot /home/ubuntu/workspace/public
改完請按 F2 儲存,然後 'Y' 及 'Enter'。
最後是取得最新版本的 Laravel(筆者安裝的版本是 5.2)
sudo composer update
至此 Laravel 5 已成功安裝,看看左邊已經多了 Laravel framework 的檔案
終於可以正式開發網誌網頁應用程式了。
請注意,本系列教學只會以最精簡的方式列出完成開發時必要的步驟,並在適當的地方加插圖片輔助,希望讀者能在最短時間親自完成教學。因此,當中的說明或解釋將會省略,如欲了解,請參考原文 Simple blog application in laravel 5。 這個日誌會有以下功能:
1. 任何人都可登入/註冊
2. 用戶可分類為「admin」、「author」或「subscriber」
3. 「author」可以撰寫/更新/刪除帖子
4. 「admin」擁有網站全部存取權限及可以閱讀/撰寫/更新/刪除任何帖子
5. 任何人都可閱讀帖子
6. 用戶可以(登入後)在帖子內留言
完成品如下圖所示,可到示範網站參看:
這個教學將分作 5 部份:
1) Setup database
- Connect with mysql database
- Create posts and comments tables
2) Make routes and models
- Routes
- Create post model
- Create comment model
- Create User model
3) Controllers
- PostController
- CommentController
4) Build front end
- Customize app.blade.php
- make home view
- Create posts
- Show posts
- Edit posts
5) Add tinymce and Make user profile
- Add tinymce to posts
- Make profile backend
- View for profile
Part 1: 建立數據庫
首先我們會建立數據庫表格用作儲存資料,當中會用到 migrations 及 schema builder。 建立數據庫表格前要先配置好連接數據庫的資訊,請在應用程式的根目錄(root)找到 .env (.env是一個隱藏檔案),並更新連接數據庫的資訊DB_HOST=localhost DB_DATABASE=your_database_name DB_USERNAME=database_username DB_PASSWORD=database_passwordCloud9用戶可參考以下配置,只需把 DB_USERNAME 改為你的登入名稱就可以:
DB_HOST=localhost DB_DATABASE=c9 DB_USERNAME=amzfree DB_PASSWORD=
到 blog >> config >> database.php , 找到 default, 改為
'default' => env('DB_CONNECTION', 'mysql'),
改完請儲存所有檔案
在 Terminal 輸入以下程式碼安裝 MySQL:
mysql-ctl install或者輸入以下程式碼安裝 MySQL:
mysql-ctl cli安裝完畢後退出 MySQL
exit
現在用 migrations
php artisan make:migration posts php artisan make:migration comments
留意 blog >> database >> migrations 多了 2 個檔案
建立 posts 表格
打開 建立時間_posts.php,清除所有程式碼並貼上以下(用作在數據庫建立一個名為 posts 的表格的)程式碼<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class Posts extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// blog table
Schema::create('posts', function(Blueprint $table)
{
$table->increments('id');
$table -> integer('author_id') -> unsigned() -> default(0);
$table->foreign('author_id')
->references('id')->on('users')
->onDelete('cascade');
$table->string('title')->unique();
$table->text('body');
$table->string('slug')->unique();
$table->boolean('active');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
// drop blog table
Schema::drop('posts');
}
}
Migration 的作用是數據庫版本控制(database version control),原理與程式碼版本控制一樣,Migration 有 up() 和 down() 2 個 function,migration 執行的時候會執行up(),down() 則是 up() 的相反,還原 up() 所做過的。例如這裡的 up() 我們 create 了 posts 的 table ,down() 的時候便要把 posts 這個 table drop 走。
Schema 是另一個在建立/修改數據庫表格會用到的Class,create() function 有 2 個 arguments,第 1 個是數據庫名稱,另一個是開 column 的 closure。$table 是這個表格的 instance 。
建立 comments 表格
同樣地將以下程式碼貼到 建立時間_comments.php<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class Comments extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//id, on_blog, from_user, body, at_time
Schema::create('comments', function(Blueprint $table)
{
$table->increments('id');
$table -> integer('on_post') -> unsigned() -> default(0);
$table->foreign('on_post')
->references('id')->on('posts')
->onDelete('cascade');
$table -> integer('from_user') -> unsigned() -> default(0);
$table->foreign('from_user')
->references('id')->on('users')
->onDelete('cascade');
$table->text('body');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
// drop comment
Schema::drop('comments');
}
}
User 表格:
User 表格的 migration 已經存在,但我們想增加用戶身份角色,所以要加多一行:$table->string('password', 60);
// add this one line
$table->enum('role',['admin','author','subscriber'])->default('author');
$table->rememberToken();
儲存所有更改
最後是 generate 表格,在 Terminal 輸入:
php artisan migrate
數據庫設置完成
Part 2: Route 路由控制 與 Model
現在是管理 blog 的路徑,我們會用 Route 類別將 url 與 Controller 聯繫,Route 類別有 get(), post(), delete(), put(), all() 及 match() 共6個 function,我們只會用到 get() 和 post()。把 app/Http/routes.php 改成以下程式碼:<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
Route::get('/','PostController@index');
Route::get('/home',['as' => 'home', 'uses' => 'PostController@index']);
//authentication
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
// check for logged in user
Route::group(['middleware' => ['auth']], function()
{
// show new post form
Route::get('new-post','PostController@create');
// save new post
Route::post('new-post','PostController@store');
// edit post form
Route::get('edit/{slug}','PostController@edit');
// update post
Route::post('update','PostController@update');
// delete post
Route::get('delete/{id}','PostController@destroy');
// display user's all posts
Route::get('my-all-posts','UserController@user_posts_all');
// display user's drafts
Route::get('my-drafts','UserController@user_posts_draft');
// add comment
Route::post('comment/add','CommentController@store');
// delete comment
Route::post('comment/delete/{id}','CommentController@distroy');
});
//users profile
Route::get('user/{id}','UserController@profile')->where('id', '[0-9]+');
// display list of posts
Route::get('user/{id}/posts','UserController@user_posts')->where('id', '[0-9]+');
// display single post
Route::get('/{slug}',['as' => 'post', 'uses' => 'PostController@show'])->where('slug', '[A-Za-z0-9-_]+');
建立 Model
1. Posts
現在會建立 Model。在 app 資料夾新增 2 個檔案:Posts.php 及 Comments.php。在 Posts.php 貼上以下程式碼:<?php namespace App;
use Illuminate\Database\Eloquent\Model;
// instance of Posts class will refer to posts table in database
class Posts extends Model {
//restricts columns from modifying
protected $guarded = [];
// posts has many comments
// returns all comments on that post
public function comments()
{
return $this->hasMany('App\Comments','on_post');
}
// returns the instance of the user who is author of that post
public function author()
{
return $this->belongsTo('App\User','author_id');
}
}
2) Comments
同樣原理在 Comments.php 貼上以下程式碼:<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Comments extends Model {
//comments table in database
protected $guarded = [];
// user who has commented
public function author()
{
return $this->belongsTo('App\User','from_user');
}
// returns post of any comment
public function post()
{
return $this->belongsTo('App\Posts','on_post');
}
}
3) User
把 app/User.php 改成:<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = ['password', 'remember_token'];
// user has many posts
public function posts()
{
return $this->hasMany('App\Posts','author_id');
}
// user has many comments
public function comments()
{
return $this->hasMany('App\Comments','from_user');
}
public function can_post()
{
$role = $this->role;
if($role == 'author' || $role == 'admin')
{
return true;
}
return false;
}
public function is_admin()
{
$role = $this->role;
if($role == 'admin')
{
return true;
}
return false;
}
}
Part 3: Controllers
我們可用以下指令讓 Artisan 幫助我們自動產生 controllers:php artisan make:controller UserController php artisan make:controller PostController php artisan make:controller CommentController這些指令會在 app/Http/Controllers 產生 3 個檔案:UserController.php、PostController.php 及 CommentController.php
PostController
:<?php namespace App\Http\Controllers;
use App\Posts;
use App\User;
use Redirect;
use App\Http\Controllers\Controller;
use App\Http\Requests\PostFormRequest;
use Illuminate\Http\Request;
class PostController extends Controller {
// 顯示所有文章
public function index()
{
//fetch 5 posts from database which are active and latest
$posts = Posts::where('active',1)->orderBy('created_at','desc')->paginate(5);
//page heading
$title = 'Latest Posts';
//return home.blade.php template from resources/views folder
return view('home')->withPosts($posts)->withTitle($title);
}
// 建立新文章
public function create(Request $request)
{
// if user can post i.e. user is admin or author
if($request->user()->can_post())
{
return view('posts.create');
}
else
{
return redirect('/')->withErrors('You have not sufficient permissions for writing post');
}
}
// 儲存文章
public function store(PostFormRequest $request)
{
$post = new Posts();
$post->title = $request->get('title');
$post->body = $request->get('body');
$post->slug = str_slug($post->title);
$post->author_id = $request->user()->id;
if($request->has('save'))
{
$post->active = 0;
$message = 'Post saved successfully';
}
else
{
$post->active = 1;
$message = 'Post published successfully';
}
$post->save();
return redirect('edit/'.$post->slug)->withMessage($message);
}
// 顯示一篇文章及它的留言
public function show($slug)
{
$post = Posts::where('slug',$slug)->first();
if(!$post)
{
return redirect('/')->withErrors('requested page not found');
}
$comments = $post->comments;
return view('posts.show')->withPost($post)->withComments($comments);
}
// 編輯文章
public function edit(Request $request,$slug)
{
$post = Posts::where('slug',$slug)->first();
if($post && ($request->user()->id == $post->author_id || $request->user()->is_admin()))
return view('posts.edit')->with('post',$post);
return redirect('/')->withErrors('you have not sufficient permissions');
}
// 更新資料庫的文章
public function update(Request $request)
{
//
$post_id = $request->input('post_id');
$post = Posts::find($post_id);
if($post && ($post->author_id == $request->user()->id || $request->user()->is_admin()))
{
$title = $request->input('title');
$slug = str_slug($title);
$duplicate = Posts::where('slug',$slug)->first();
if($duplicate)
{
if($duplicate->id != $post_id)
{
return redirect('edit/'.$post->slug)->withErrors('Title already exists.')->withInput();
}
else
{
$post->slug = $slug;
}
}
$post->title = $title;
$post->body = $request->input('body');
if($request->has('save'))
{
$post->active = 0;
$message = 'Post saved successfully';
$landing = 'edit/'.$post->slug;
}
else {
$post->active = 1;
$message = 'Post updated successfully';
$landing = $post->slug;
}
$post->save();
return redirect($landing)->withMessage($message);
}
else
{
return redirect('/')->withErrors('you have not sufficient permissions');
}
}
// 刪除文章
public function destroy(Request $request, $id)
{
//
$post = Posts::find($id);
if($post && ($post->author_id == $request->user()->id || $request->user()->is_admin()))
{
$post->delete();
$data['message'] = 'Post deleted Successfully';
}
else
{
$data['errors'] = 'Invalid Operation. You have not sufficient permissions';
}
return redirect('/')->with($data);
}
CommentController:
<?php namespace App\Http\Controllers;
use App\Posts;
use App\Comments;
use Redirect;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class CommentController extends Controller {
public function store(Request $request)
{
//on_post, from_user, body
$input['from_user'] = $request->user()->id;
$input['on_post'] = $request->input('on_post');
$input['body'] = $request->input('body');
$slug = $request->input('slug');
Comments::create( $input );
return redirect($slug)->with('message', 'Comment published');
}
}
UserController 會稍後完成
Part 4: 前端網頁
之前主要完成了日誌的後端程式,現在會完成前端版面設計。把 resources/views/app.blade.php 改成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Blog Demo | Find All Together</title>
<link href="{{ asset('/css/app.css') }}" rel="stylesheet">
<!-- Fonts -->
<link href='//fonts.googleapis.com/css?family=Roboto:400,300' rel='stylesheet' type='text/css'>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle Navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="http://www.findalltogether.com">Find All Together</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li>
<a href="{{ url('/') }}">Home</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
@if (Auth::guest())
<li>
<a href="{{ url('/auth/login') }}">Login</a>
</li>
<li>
<a href="{{ url('/auth/register') }}">Register</a>
</li>
@else
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ Auth::user()->name }} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
@if (Auth::user()->can_post())
<li>
<a href="{{ url('/new-post') }}">Add new post</a>
</li>
<li>
<a href="{{ url('/user/'.Auth::id().'/posts') }}">My Posts</a>
</li>
@endif
<li>
<a href="{{ url('/user/'.Auth::id()) }}">My Profile</a>
</li>
<li>
<a href="{{ url('/auth/logout') }}">Logout</a>
</li>
</ul>
</li>
@endif
</ul>
</div>
</div>
</nav>
<div class="container">
@if (Session::has('message'))
<div class="flash alert-info">
<p class="panel-body">
{{ Session::get('message') }}
</p>
</div>
@endif
@if ($errors->any())
<div class='flash alert-danger'>
<ul class="panel-body">
@foreach ( $errors->all() as $error )
<li>
{{ $error }}
</li>
@endforeach
</ul>
</div>
@endif
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-default">
<div class="panel-heading">
<h2>@yield('title')</h2>
@yield('title-meta')
</div>
<div class="panel-body">
@yield('content')
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<p>Copyright © 2015 | <a href="http://www.findalltogether.com">Find All Together</a></p>
</div>
</div>
</div>
<!-- Scripts -->
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
</body>
</html>
首頁版面 home.blade.php :
@extends('app')
@section('title')
{{$title}}
@endsection
@section('content')
@if ( !$posts->count() )
There is no post till now. Login and write a new post now!!!
@else
<div class="">
@foreach( $posts as $post )
<div class="list-group">
<div class="list-group-item">
<h3><a href="{{ url('/'.$post->slug) }}">{{ $post->title }}</a>
@if(!Auth::guest() && ($post->author_id == Auth::user()->id || Auth::user()->is_admin()))
@if($post->active == '1')
<button class="btn" style="float: right"><a href="{{ url('edit/'.$post->slug)}}">Edit Post</a></button>
@else
<button class="btn" style="float: right"><a href="{{ url('edit/'.$post->slug)}}">Edit Draft</a></button>
@endif
@endif
</h3>
<p>{{ $post->created_at->format('M d,Y \a\t h:i a') }} By <a href="{{ url('/user/'.$post->author_id)}}">{{ $post->author->name }}</a></p>
</div>
<div class="list-group-item">
<article>
{!! str_limit($post->body, $limit = 1500, $end = '....... <a href='.url("/".$post->slug).'>Read More</a>') !!}
</article>
</div>
</div>
@endforeach
{!! $posts->render() !!}
</div>
@endif
@endsection
在 resources/views 新增一個 posts 資料夾
在 resources/views/posts 建立一個新文件 create.blade.php
@extends('app')
@section('title')
Add New Post
@endsection
@section('content')
<form action="/new-post" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<input required="required" value="{{ old('title') }}" placeholder="Enter title here" type="text" name = "title"class="form-control" />
</div>
<div class="form-group">
<textarea name='body'class="form-control">{{ old('body') }}</textarea>
</div>
<input type="submit" name='publish' class="btn btn-success" value = "Publish"/>
<input type="submit" name='save' class="btn btn-default" value = "Save Draft" />
</form>
@endsection
在 resources/views/posts 建立另一個新文件 show.blade.php
@extends('app')
@section('title')
@if($post)
{{ $post->title }}
@if(!Auth::guest() && ($post->author_id == Auth::user()->id || Auth::user()->is_admin()))
<button class="btn" style="float: right"><a href="{{ url('edit/'.$post->slug)}}">Edit Post</a></button>
@endif
@else
Page does not exist
@endif
@endsection
@section('title-meta')
<p>{{ $post->created_at->format('M d,Y \a\t h:i a') }} By <a href="{{ url('/user/'.$post->author_id)}}">{{ $post->author->name }}</a></p>
@endsection
@section('content')
@if($post)
<div>
{!! $post->body !!}
</div>
<div>
<h2>Leave a comment</h2>
</div>
@if(Auth::guest())
<p>Login to Comment</p>
@else
<div class="panel-body">
<form method="post" action="/comment/add">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="on_post" value="{{ $post->id }}">
<input type="hidden" name="slug" value="{{ $post->slug }}">
<div class="form-group">
<textarea required="required" placeholder="Enter comment here" name = "body" class="form-control"></textarea>
</div>
<input type="submit" name='post_comment' class="btn btn-success" value = "Post"/>
</form>
</div>
@endif
<div>
@if($comments)
<ul style="list-style: none; padding: 0">
@foreach($comments as $comment)
<li class="panel-body">
<div class="list-group">
<div class="list-group-item">
<h3>{{ $comment->author->name }}</h3>
<p>{{ $comment->created_at->format('M d,Y \a\t h:i a') }}</p>
</div>
<div class="list-group-item">
<p>{{ $comment->body }}</p>
</div>
</div>
</li>
@endforeach
</ul>
@endif
</div>
@else
404 error
@endif
@endsection
resources/views/posts/edit.blade.php
@extends('app')
@section('title')
Edit Post
@endsection
@section('content')
<form method="post" action='{{ url("/update") }}'>
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="post_id" value="{{ $post->id }}{{ old('post_id') }}">
<div class="form-group">
<input required="required" placeholder="Enter title here" type="text" name = "title" class="form-control" value="@if(!old('title')){{$post->title}}@endif{{ old('title') }}"/>
</div>
<div class="form-group">
<textarea name='body'class="form-control">
@if(!old('body'))
{!! $post->body !!}
@endif
{!! old('body') !!}
</textarea>
</div>
@if($post->active == '1')
<input type="submit" name='publish' class="btn btn-success" value = "Update"/>
@else
<input type="submit" name='publish' class="btn btn-success" value = "Publish"/>
@endif
<input type="submit" name='save' class="btn btn-default" value = "Save As Draft" />
<a href="{{ url('delete/'.$post->id.'?_token='.csrf_token()) }}" class="btn btn-danger">Delete</a>
</form>
@endsection
Part 5: 增添 tinyMCE 及 用戶個人檔案
這個系列最後一篇教學是在建立文章的版面嵌入 tinyMCE(所見即所得編輯器)及完成用戶個人檔案的前後端。增添 tinyMCE
到 http://www.tinymce.com/download/download.php 下載 tinyMCE 共解壓縮至 public/js 把 resources/views/posts/edit.blade.php 改成@extends('app')
@section('title')
Edit Post
@endsection
@section('content')
<script type="text/javascript" src="{{ asset('/js/tinymce/tinymce.min.js') }}"></script>
<script type="text/javascript">
tinymce.init({
selector : "textarea",
plugins : ["advlist autolink lists link image charmap print preview anchor", "searchreplace visualblocks code fullscreen", "insertdatetime media table contextmenu paste"],
toolbar : "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
});
</script>
<form method="post" action='{{ url("/update") }}'>
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="post_id" value="{{ $post->id }}{{ old('post_id') }}">
<div class="form-group">
<input required="required" placeholder="Enter title here" type="text" name = "title" class="form-control" value="@if(!old('title')){{$post->title}}@endif{{ old('title') }}"/>
</div>
<div class="form-group">
<textarea name='body'class="form-control">
@if(!old('body'))
{!! $post->body !!}
@endif
{!! old('body') !!}
</textarea>
</div>
@if($post->active == '1')
<input type="submit" name='publish' class="btn btn-success" value = "Update"/>
@else
<input type="submit" name='publish' class="btn btn-success" value = "Publish"/>
@endif
<input type="submit" name='save' class="btn btn-default" value = "Save As Draft" />
<a href="{{ url('delete/'.$post->id.'?_token='.csrf_token()) }}" class="btn btn-danger">Delete</a>
</form>
@endsection
同樣地,把 resources/views/posts/create.blade.php 改成
@extends('app')
@section('title')
Add New Post
@endsection
@section('content')
<script type="text/javascript" src="{{ asset('/js/tinymce/tinymce.min.js') }}"></script>
<script type="text/javascript">
tinymce.init({
selector : "textarea",
plugins : ["advlist autolink lists link image charmap print preview anchor", "searchreplace visualblocks code fullscreen", "insertdatetime media table contextmenu paste"],
toolbar : "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
});
</script>
<form action="/new-post" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<input required="required" value="{{ old('title') }}" placeholder="Enter title here" type="text" name = "title"class="form-control" />
</div>
<div class="form-group">
<textarea name='body'class="form-control">{{ old('body') }}</textarea>
</div>
<input type="submit" name='publish' class="btn btn-success" value = "Publish"/>
<input type="submit" name='save' class="btn btn-default" value = "Save Draft" />
</form>
@endsection
用戶個人檔案
把 UserController.php 改成<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\User;
use App\Posts;
use Illuminate\Http\Request;
class UserController extends Controller {
/*
* Display active posts of a particular user
*
* @param int $id
* @return view
*/
public function user_posts($id)
{
//
$posts = Posts::where('author_id',$id)->where('active',1)->orderBy('created_at','desc')->paginate(5);
$title = User::find($id)->name;
return view('home')->withPosts($posts)->withTitle($title);
}
/*
* Display all of the posts of a particular user
*
* @param Request $request
* @return view
*/
public function user_posts_all(Request $request)
{
//
$user = $request->user();
$posts = Posts::where('author_id',$user->id)->orderBy('created_at','desc')->paginate(5);
$title = $user->name;
return view('home')->withPosts($posts)->withTitle($title);
}
/*
* Display draft posts of a currently active user
*
* @param Request $request
* @return view
*/
public function user_posts_draft(Request $request)
{
//
$user = $request->user();
$posts = Posts::where('author_id',$user->id)->where('active',0)->orderBy('created_at','desc')->paginate(5);
$title = $user->name;
return view('home')->withPosts($posts)->withTitle($title);
}
/**
* profile for user
*/
public function profile(Request $request, $id)
{
$data['user'] = User::find($id);
if (!$data['user'])
return redirect('/');
if ($request -> user() && $data['user'] -> id == $request -> user() -> id) {
$data['author'] = true;
} else {
$data['author'] = null;
}
$data['comments_count'] = $data['user'] -> comments -> count();
$data['posts_count'] = $data['user'] -> posts -> count();
$data['posts_active_count'] = $data['user'] -> posts -> where('active', '1') -> count();
$data['posts_draft_count'] = $data['posts_count'] - $data['posts_active_count'];
$data['latest_posts'] = $data['user'] -> posts -> where('active', '1') -> take(5);
$data['latest_comments'] = $data['user'] -> comments -> take(5);
return view('admin.profile', $data);
}
}
前端版面:
在 resources/views 新增一個 admin 資料夾,然後在此資料夾新增一個 profile.blade.php 檔案@extends('app')
@section('title')
{{ $user->name }}
@endsection
@section('content')
<div>
<ul class="list-group">
<li class="list-group-item">
Joined on {{$user->created_at->format('M d,Y \a\t h:i a') }}
</li>
<li class="list-group-item panel-body">
<table class="table-padding">
<style>
.table-padding td{
padding: 3px 8px;
}
</style>
<tr>
<td>Total Posts</td>
<td> {{$posts_count}}</td>
@if($author && $posts_count)
<td><a href="{{ url('/my-all-posts')}}">Show All</a></td>
@endif
</tr>
<tr>
<td>Published Posts</td>
<td>{{$posts_active_count}}</td>
@if($posts_active_count)
<td><a href="{{ url('/user/'.$user->id.'/posts')}}">Show All</a></td>
@endif
</tr>
<tr>
<td>Posts in Draft </td>
<td>{{$posts_draft_count}}</td>
@if($author && $posts_draft_count)
<td><a href="{{ url('my-drafts')}}">Show All</a></td>
@endif
</tr>
</table>
</li>
<li class="list-group-item">
Total Comments {{$comments_count}}
</li>
</ul>
</div>
<div class="panel panel-default">
<div class="panel-heading"><h3>Latest Posts</h3></div>
<div class="panel-body">
@if(!empty($latest_posts[0]))
@foreach($latest_posts as $latest_post)
<p>
<strong><a href="{{ url('/'.$latest_post->slug) }}">{{ $latest_post->title }}</a></strong>
<span class="well-sm">On {{ $latest_post->created_at->format('M d,Y \a\t h:i a') }}</span>
</p>
@endforeach
@else
<p>You have not written any post till now.</p>
@endif
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading"><h3>Latest Comments</h3></div>
<div class="list-group">
@if(!empty($latest_comments[0]))
@foreach($latest_comments as $latest_comment)
<div class="list-group-item">
<p>{{ $latest_comment->body }}</p>
<p>On {{ $latest_comment->created_at->format('M d,Y \a\t h:i a') }}</p>
<p>On post <a href="{{ url('/'.$latest_comment->post->slug) }}">{{ $latest_comment->post->title }}</a></p>
</div>
@endforeach
@else
<div class="list-group-item">
<p>You have not commented till now. Your latest 5 comments will be displayed here</p>
</div>
@endif
</div>
</div>
@endsection
快速入門教學到此為止,完整文檔請到 Laravel 官方網站查看。
留言
張貼留言