我们优先开发的 Blog 页面是「我的博客」页面,页面功能:

  1. 如果用户已经创建了 Blog 那么就 302 到当前登录用户的博客页面
  2. 如果用户没有创建 Blog 则显示创建页面

创建博客页面

我们先不着急开发跳转判断逻辑,先开发创建博客页面,首先,我们应该定一个路由,我们打开包的 routes/web.php 在之前定义的一个函数中定义一个「我的博客」路由:

  1. // 我的博客
  2. $route
  3. ->get('me', Web\HomeController::class.'@me')
  4. ->name('blog:me')
  5. ;

然后我们打开包的 src/Web/Controllers/HomeController.php 修改其内容如下:

  1. <?php
  2. declare(strict_types=1);
  3. namespace SlimKit\Plus\Packages\Blog\Web\Controllers;
  4. use Illuminate\Routing\Controller;
  5. class HomeController extends Controller
  6. {
  7. /**
  8. * Create the controller instance.
  9. */
  10. public function __construct()
  11. {
  12. $this
  13. ->middleware('auth:web')
  14. ->only(['me']);
  15. }
  16. /**
  17. * Home.
  18. */
  19. public function index()
  20. {
  21. return view('plus-blog::home');
  22. }
  23. /**
  24. * Create my blog page.
  25. * @param \Illuminate\Http\Request $request
  26. * @return mixed
  27. */
  28. public function me(\Illuminate\Http\Request $request)
  29. {
  30. return view('plus-blog::create-blog');
  31. }
  32. }

然后我们打开 resources/views/header.blade.php<li class=""><a href="#">我的博客</a></li> 替换为下面的内容:

  1. <li class="{{ Route::currentRouteName() === 'blog:me' ? 'active' : '' }}">
  2. <a href="{{ route('blog:me') }}">我的博客</a>
  3. </li>

我们在包的 resources/views 下面创建一个名为 create-blog.blade.php 的文件,内容如下:

  1. @extends('plus-blog::layout')
  2. @section('title', '创建博客')
  3. @section('container')
  4. <div class="row">
  5. <div class="col-md-8">
  6. <div class="panel panel-default">
  7. <div class="panel-heading">创建博客</div>
  8. <div class="panel-body">
  9. <form class="form-horizontal" method="POST" action="{{ route('blog:me') }}" enctype="multipart/form-data">
  10. @csrf
  11. <!-- 唯一标识 -->
  12. <div class="form-group {{ $errors->has('slug') ? 'has-error': '' }}">
  13. <label class="col-sm-2 control-label">标识</label>
  14. <div class="col-sm-10">
  15. <input name="slug" type="text" class="form-control" placeholder="博客唯一标识" value="{{ old('slug') }}">
  16. <span class="help-block">
  17. {{
  18. $errors->has('slug')
  19. ? $errors->first('slug')
  20. : '输入你博客的唯一标识,一旦创建将不再允许修改'
  21. }}
  22. </span>
  23. </div>
  24. </div>
  25. <!-- 名称 -->
  26. <div class="form-group {{ $errors->has('name') ? 'has-error': '' }}">
  27. <label class="col-sm-2 control-label">名称</label>
  28. <div class="col-sm-10">
  29. <input name="name" type="text" class="form-control" placeholder="博客名称" value="{{ old('name') }}">
  30. <span class="help-block">
  31. {{
  32. $errors->has('name')
  33. ? $errors->first('name')
  34. : '输入博客名称'
  35. }}
  36. </span>
  37. </div>
  38. </div>
  39. <!-- 博客描述 -->
  40. <div class="form-group {{ $errors->has('desc') ? 'has-error': '' }}">
  41. <label class="col-sm-2 control-label">描述</label>
  42. <div class="col-sm-10">
  43. <textarea name="desc" class="form-control" rows="3" placeholder="博客描述">{{ old('desc') }}</textarea>
  44. <span class="help-block">
  45. {{
  46. $errors->has('desc')
  47. ? $errors->first('desc')
  48. : '请输入你博客的描述,好的描述让你的博客更有魅力哦!'
  49. }}
  50. </span>
  51. </div>
  52. </div>
  53. <!-- 博客 Logo -->
  54. <div class="form-group {{ $errors->has('logo') ? 'has-error': '' }}">
  55. <label class="col-sm-2 control-label">图标</label>
  56. <div class="col-sm-10">
  57. <input name="logo" type="file" class="form-control" >
  58. <span class="help-block">
  59. {{
  60. $errors->has('logo')
  61. ? $errors->first('logo')
  62. : '请选择博客所使用的图标'
  63. }}
  64. </span>
  65. </div>
  66. </div>
  67. <!-- 提交按钮 -->
  68. <div class="form-group">
  69. <div class="col-sm-offset-2 col-sm-10">
  70. <button type="submit" class="btn btn-primary">创建</button>
  71. </div>
  72. </div>
  73. </form>
  74. </div>
  75. </div>
  76. </div>
  77. <div class="col-md-4">
  78. <div class="alert alert-warning" role="alert">你还没有创建属于你的博客,你可以在这里创建一个属于你自己的博客,博客创建完成后你可以发布你的文章了!</div>
  79. </div>
  80. </div>
  81. @endsection

创建博客逻辑

首先,我们应该创建一个「表单验证我的博客 - 图1」,我们创建一个文件 src/Web/Requests/CreateBlog.php

  1. <?php
  2. declare(strict_types=1);
  3. namespace SlimKit\Plus\Packages\Blog\Web\Requests;
  4. use Illuminate\Validation\Rule;
  5. use Illuminate\Foundation\Http\FormRequest;
  6. class CreateBlog extends FormRequest
  7. {
  8. /**
  9. * Get request authorize.
  10. *
  11. * @return bool
  12. */
  13. public function authorize(): bool
  14. {
  15. return true;
  16. }
  17. /**
  18. * Get custom message from validateor rules.
  19. *
  20. * @return array
  21. */
  22. public function rules(): array
  23. {
  24. return [
  25. 'slug' => ['required', 'string', 'min:4', 'max:26', 'regex:/[a-z][a-z0-9]/s', Rule::unique('blogs', 'slug')],
  26. 'name' => ['required', 'string', 'max:100'],
  27. 'desc' => ['nullable', 'string', 'max:250'],
  28. 'logo' => ['nullable', 'file', 'image'],
  29. ];
  30. }
  31. /**
  32. * Get custom messages for validator errors.
  33. *
  34. * @return array
  35. */
  36. public function messages(): array
  37. {
  38. return [
  39. 'slug.regex' => ':attribute必须是字母开头仅含有字母和数字的小写字符串'
  40. ];
  41. }
  42. /**
  43. * Get custom attributes for validator errors.
  44. *
  45. * @return array
  46. */
  47. public function attributes(): array
  48. {
  49. return [
  50. 'slug' => '博客唯一标识',
  51. 'name' => '博客名称',
  52. 'desc' => '博客描述',
  53. 'logo' => '博客图标'
  54. ];
  55. }
  56. }

为了之后的快捷获取,以及创建的时候更加优雅,我们为 User 模型附加一个 blog 关系,我们打开包的 src/Providers/ModelServiceProvider.php 文件,在 namespace 下面,插入下面的代码:

  1. use Zhiyi\Plus\Models\User;
  2. use SlimKit\Plus\Packages\Blog\Models\Blog;

然后我们找到 registerUserMacros 方法,插入下面的内容:

  1. User::macro('blog', function () {
  2. return $this->hasOne(Blog::class, 'owner_id');
  3. });

接下来,我们打开 src/Web/Controllers/HomeController.php 在类的 namespace 下面添加代码:

  1. use Zhiyi\Plus\FileStorage\Storage;
  2. use SlimKit\Plus\Packages\Blog\Web\Requests\CreateBlog;

然后我们在 __construct 方法的 auth:web 中间件下面的 only 数组中增加 createBlog。完成后,我们在类里面写入下面的方法:

  1. /**
  2. * create a blog.
  3. * @param \SlimKit\Plus\Packages\Blog\Web\Requests\CreateBlog $request
  4. * @param \Zhiyi\Plus\FileStorage\Storage $storage
  5. * @return mixed
  6. */
  7. public function createBlog(CreateBlog $request, Storage $storage)
  8. {
  9. // 判断是否已有博客,如果有,跳转到博客页面并提示!
  10. if ($blog = $request->user()->blog) {
  11. return redirect()
  12. ->route('blog:profile', ['blog' => $blog])
  13. ->with('tip', [
  14. 'type' => 'warning',
  15. 'message' => '您已有博客,无法继续创建!'
  16. ]);
  17. }
  18. $blog = new \SlimKit\Plus\Packages\Blog\Models\Blog();
  19. $blog->slug = $request->input('slug');
  20. $blog->name = $request->input('name');
  21. $blog->desc = $request->input('desc');
  22. // 上传 Logo
  23. if ($logo = $request->file('logo')) {
  24. $resource = $storage->createResource(
  25. 'public', $storage->makePath($logo->hashName())
  26. );
  27. $storage->put($resource, $logo->get());
  28. $blog->logo = (string) $resource;
  29. }
  30. // 创建 Blog 记录
  31. $request->user()->blog()->save($blog);
  32. // 创建成功,跳转到博客页面并提示
  33. return redirect()
  34. ->route('blog:profile', ['blog' => $blog])
  35. ->with('tip', [
  36. 'type' => 'success',
  37. 'message' => '创建博客成功!'
  38. ])
  39. ;
  40. }

跳转功能

上面我们拟定了用户在没有博客的情况下创建了博客,现在我们假设用户已经有了博客,点击将跳转到我的博客页面。

我们打开包的 routes/web.php 文件,增加一个路由定义:

  1. // 博客主页
  2. $route
  3. ->get('{blog}', Web\BlogController::class.'@show')
  4. ->name('blog:profile');

然后我们打开包的博客 Model(src/Models/Blog.php),我们修改路由查找使用的 slug 进行博客查找,在模型类中写入下面的代码:

  1. /**
  2. * Get the route key for the model.
  3. *
  4. * @return string
  5. */
  6. public function getRouteKeyName()
  7. {
  8. return 'slug';
  9. }

然后我们创建在包里面创建 src/Web/Controllers/BlogController.php 文件:

  1. <?php
  2. declare(strict_types=1);
  3. namespace SlimKit\Plus\Packages\Blog\Web\Controllers;
  4. use Illuminate\Routing\Controller;
  5. use SlimKit\Plus\Packages\Blog\Models\Blog as BlogModel;
  6. class BlogController extends Controller
  7. {
  8. /**
  9. * Create the controller instance.
  10. */
  11. public function __construct()
  12. {
  13. // todo.
  14. }
  15. /**
  16. * Get the blog profile.
  17. * @param SlimKit\Plus\Packages\Blog\Models\Blog $blog
  18. * @return mixed
  19. */
  20. public function show(BlogModel $blog)
  21. {
  22. return view('plus-blog::blog-profile', [
  23. 'blog' => $blog,
  24. 'articles' => $blog->articles()->paginate(15),
  25. ]);
  26. }
  27. }

文章关系

在上一节中,我们调用了 $blog->articles() 关系,但是这个关系现在还是不存在的,我们打开 src/Models/Blog.php 在下面的添加方法:

  1. /**
  2. * The blog has many articles.
  3. */
  4. public function articles()
  5. {
  6. return $this->hasMany(Article::class, 'blog_id');
  7. }

好了,我们整个我的博客逻辑就完成了!

页面预览

我的博客 - 图2