教程源于:Laravel学院

继文件上传后呢,咱来搞一搞文章的事情。


1 更改数据表

我们需要改改数据表的结构 因为涉及到重命名列名 所以咱需要引入一个包:Doctrine:

composer require "doctrine/dbal"

1.1 新建迁移文件

php artisan make:migration restructure_posts_table --table=posts

1.2 编辑迁移文件

class RestructurePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('posts', function (Blueprint $table) {
// 在title字段后添加subtitle 文章的副标题
$table->string('subtitle')->after('title');
// 把content改为content_raw Markdown格式的文本
$table->renameColumn('content', 'content_raw');
// 在content字段后添加content_html 使用 Markdown 编辑内容但同时保存 HTML 版本
$table->text('content_html')->after('content');
// 在content_html字段后添加page_image 文章使用到缩略图
$table->string('page_image')->after('content_html');
// 在page_image字段后添加meta_description 文章说明
$table->string('meta_description')->after('page_image');
// 在meta_description字段后添加is_draft 是否是草稿
$table->boolean('is_draft')->after('meta_description');
// 在is_draft字段后添加layout 并设置默认值 使用的布局
$table->string('layout')->after('is_draft')->default('blog.layouts.post');
});
} /**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('subtitle');
$table->dropColumn('content_html');
$table->dropColumn('page_image');
$table->dropColumn('meta_description');
$table->dropColumn('is_draft');
$table->dropColumn('layout');
$table->renameColumn('content_raw', 'content');
});
}
}

1.3 运行迁移

运行命令后看眼数据库是否已经修改成功:

php artisan migrate   

2 和Tag关联

文章和标签是多对多的关系,所以先创建迁移文件,然后记得运行迁移:

class CreatePostTagPivot extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('post_tag_pivot', function (Blueprint $table) {
$table->increments('id');
$table->integer('tag_id')->unsigned()->index();
$table->integer('post_id')->unsigned()->index();
});
} /**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('post_tag_pivot');
}
}

2.1 编辑Tag模型

class Tag extends Model
{
protected $fillable = ['tag', 'title', 'subtitle', 'page_image', 'meta_description', 'layout', 'reverse_direction']; // 定义关系
public function posts()
{
return $this->belongsToMany(Post::class, 'post_tag_pivot');
} /**
* 批量创建需要的tag
*
* @param array $tags
*/
public static function addNeededTags(array $tags)
{
if (count($tags) === 0){
return;
} // 通过tag字段在$tags数组中查找,把找到的模型通过lists来获取所有的tag字段
$found = static::WhereIn('tag', $tags)->lists('tag')->all(); foreach (array_diff($tags, $found) as $tag) {
// 把不存在的tag进行创建 其他字段先自动填充
static::create([
'tag' => $tag,
'title' => $tag,
'subtitle' => 'Subtitle for '.$tag,
'page_image' => '',
'meta_description' => '',
'reverse_direction' => false,
]);
}
}
}

3 展示文章

我们一步步的来,首先先来展示我们的文章吧。

3.1 修改PostController的index方法

    public function index()
{
return view('admin.post.index')->withPosts(Post::all());
}

3.2 修改post/index.blade.php

@extends('admin.layout')

@section('content')
<div class="container-fluid">
<div class="row page-title-row">
<div class="col-md-6">
<h3>Post <small> >> Listing</small></h3>
</div>
<div class="col-md-6 text-right">
<a href="/admin/post/create" class="btn btn-success btn-md">
<i class="fa fa-plus-circle"></i> New Post
</a>
</div>
</div> <div class="row">
<div class="col-sm-12">
@include('admin.partials.error')
@include('admin.partials.success') <table id="posts-table" class="table table-bordered table-striped">
<thead>
<tr>
<td>Published</td>
<td>Title</td>
<td>Subtitle</td>
<td data-sortable="false">Published</td>
</tr>
</thead>
<tbody>
@foreach($posts as $post)
<tr>
<td data-order="{{ $post->published_at->timestamp }}">
{{ $post->published_at->format('j-M-y g:ia') }}
</td>
<td>{{ $post->title }}</td>
<td>{{ $post->subtitle }}</td>
<td>
<a href="/admin/post/{{ $post->id }}/edit" class="btn btn-xs btn-info">
<i class="fa fa-edit"></i> Edit
</a>
<a href="/blog/{{ $post->slug }}" class="btn btn-xs btn-warning">
<i class="fa fa-eye"></i> View
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@endsection @section('scripts')
<script>
$(function () {
$("#posts-table").DataTable({
order: [[0, "desc"]]
});
});
</script>
@endsection

4 创建文章

4.1 编辑create方法

    public function create()
{
$data = $this->dispatch(new PostFormFields());
return view('admin.post.create', $data);
}

在上面的代码中我们使用到了一个任务,这个任务就是返回每个字段的默认值

4.2 创建Job

创建create方法中用到的job:

php artisan make:job PostFormFields

在app/Jobs中找到刚刚创建的job编辑如下:

class PostFormFields extends Job implements SelfHandling
{
protected $id; protected $fieldList = [
'title' => '',
'subtitle' => '',
'page_image' => '',
'content' => '',
'meta_description' => '',
'is_draft' => "0",
'publish_date' => '',
'publish_time' => '',
'layout' => 'blog.layouts.post',
'tags' => [],
]; /**
* Create a new job instance.
*
* @return void
*/
public function __construct($id = null)
{
$this->id = $id;
} /**
* Execute the job.
*
* @return void
*/
public function handle()
{
$fields = $this->fieldList;
if ($this->id){
$fields = $this->fieldsFromModel($this->id, $fields);
} else {
$when = Carbon::now()->addHour();
$fields['publish_date'] = $when->format('M-j-Y');
$fields['publish_time'] = $when->format('g:i A');
}
foreach ($fields as $fieldName => $fieldValue) {
$fields[$fieldName] = old($fieldName, $fieldValue);
}
return array_merge($fields, ['allTags' => Tag::lists('tag')->all()]);
} /**
* 取出模型中的数据
*
* @param $id
* @param array $fields
* @return array
*/
protected function fieldsFromModel($id, array $fields)
{
$post = Post::findOrFail($id);
$fieldNames = array_keys(array_except($fields, ['tags']));
$fields = ['id' => id];
foreach ($fieldNames as $field) {
$fields[$field] = $post->$field;
}
$fields['tags'] = $post->tags()->lists('tag')->all(); return $fields;
}
}

4.3 添加方法到Post模型

在job中我们使用了publishe_date和time,我们来实现这些get:

    /**
* 设置ContentRaw的同时设置ContentHTML。
*
* @param $value
*/
public function setContentRawAttribute($value)
{
$this->attributes['content_raw'] = $value;
$this->attributes['content_html'] = Markdown::convertToHtml($value);
} /**
* 使用content快捷的返回content_raw
*
* @param $value
* @return mixed
*/
public function getContentAttribute($value)
{
return $this->content_raw;
} /**
* 快捷返回publish_time
*
* @param $value
* @return mixed
*/
public function getPublishTimeAttribute($value)
{
return $this->published_at->format('g:i A');
} /**
* 快捷返回publish_date
*
* @param $value
* @return mixed
*/
public function getPublishDateAttribute($value)
{
return $this->published_at->format('M-j-Y');
}

4.4 下载需要用到的两个前端资源

我们在create视图中需要用到两个前端资源:Selectize.js(下拉列表功能)和Pickadate.js(日期插件),我们来使用Bower下载:

bower install selectize --save
bower install pickadate --save

使用Gulp来整理前端资源:

var gulp = require('gulp');
var rename = require('gulp-rename');
var elixir = require('laravel-elixir'); /*
|--------------------------------------------------------------------------
| Elixir Asset Management
|--------------------------------------------------------------------------
|
| Elixir provides a clean, fluent API for defining some basic Gulp tasks
| for your Laravel application. By default, we are compiling the Less
| file for our application, as well as publishing vendor resources.
|
*/ /**
* 拷贝操作
*/
gulp.task("copyfiles", function(){
// js
gulp.src("vendor/bower_dl/jquery/dist/jquery.js")
.pipe(gulp.dest("resources/assets/js/"));
// bootstrap
gulp.src("vendor/bower_dl/bootstrap/less/**")
.pipe(gulp.dest("resources/assets/less/bootstrap"));
gulp.src("vendor/bower_dl/bootstrap/dist/js/bootstrap.js")
.pipe(gulp.dest("resources/assets/js/"));
// font 不用编译和合并 直接复制到public就可以
gulp.src("vendor/bower_dl/bootstrap/fonts/**")
.pipe(gulp.dest("public/assets/fonts")); // awesome
gulp.src("vendor/bower_dl/font-awesome/less/**")
.pipe(gulp.dest("resources/assets/less/fontawesome")); gulp.src("vendor/bower_dl/font-awesome/fonts/**")
.pipe(gulp.dest("public/assets/fonts")); // 拷贝 datatables
var dtDir = 'vendor/bower_dl/datatables.net-plugins/integration/'; gulp.src("vendor/bower_dl/datatables/media/js/jquery.dataTables.js")
.pipe(gulp.dest('resources/assets/js/')); gulp.src(dtDir + 'bootstrap/3/dataTables.bootstrap.css')
.pipe(rename('dataTables.bootstrap.less'))
.pipe(gulp.dest('resources/assets/less/others/')); gulp.src(dtDir + 'bootstrap/3/dataTables.bootstrap.js')
.pipe(gulp.dest('resources/assets/js/')); // 拷贝selectize
gulp.src("vendor/bower_dl/selectize/dist/css/**")
.pipe(gulp.dest("public/assets/selectize/css"));
gulp.src("vendor/bower_dl/selectize/dist/js/standalone/selectize.min.js")
.pipe(gulp.dest("public/assets/selectize/")); // 拷贝 pickadate
gulp.src("vendor/bower_dl/pickadate/lib/compressed/themes/**")
.pipe(gulp.dest("public/assets/pickadate/themes/")); gulp.src("vendor/bower_dl/pickadate/lib/compressed/picker.js")
.pipe(gulp.dest("public/assets/pickadate/")); gulp.src("vendor/bower_dl/pickadate/lib/compressed/picker.date.js")
.pipe(gulp.dest("public/assets/pickadate/")); gulp.src("vendor/bower_dl/pickadate/lib/compressed/picker.time.js")
.pipe(gulp.dest("public/assets/pickadate/"));
}); elixir(function(mix) { // 合并脚本文件
mix.scripts([
'js/jquery.js',
'js/bootstrap.js',
'js/jquery.dataTables.js',
'js/dataTables.bootstrap.js'
],
'public/assets/js/admin.js',
'resources/assets'
); // 编译 Less
mix.less('admin.less', 'public/assets/css/admin.css');
});

运行Gulp:

gulp copyfiles
gulp

4.5 创建create视图

@extends("admin.layout")
{{-- 样式表 --}}
@section('styles')
<link rel="stylesheet" href="/assets/selectize/css/selectize.css">
<link rel="stylesheet" href="/assets/selectize/css/selectize.bootstrap3.css">
<link rel="stylesheet" href="/assets/pickadate/themes/default.css">
<link rel="stylesheet" href="/assets/pickadate/themes/default.date.css">
<link rel="stylesheet" href="/assets/pickadate/themes/default.time.css">
@endsection
{{--content--}}
@section("content")
<div class="container-fluid">
<div class="row page-title-row">
<div class="col-md-12">
<h3>Posts <small> >> Add New Post</small></h3>
</div>
</div> <div class="row">
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">New Post Form</h3>
</div>
<div class="panel-body"> @include('admin.partials.error') <form action="{{ route("admin.post.store") }}" method="POST" class="form-horizontal">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
@include('admin.post._form')
<div class="col-md-8">
<div class="form-group">
<div class="col-md-10 col-md-offset-2">
<button class="btn btn-primary btn-lg" type="submit">
<i class="fa fa-disk-o"></i>
Save New Post
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
{{--scripts--}}
@section('scripts')
<script src="/assets/pickadate/picker.js"></script>
<script src="/assets/pickadate/picker.date.js"></script>
<script src="/assets/pickadate/picker.time.js"></script>
<script src="/assets/selectize/selectize.min.js"></script>
<script>
$(function() {
$("#publish_date").pickadate({
format: "mmm-d-yyyy"
});
$("#publish_time").pickatime({
format: "h:i A"
});
$("#tags").selectize({
create: true
});
});
</script>
@endsection

创建我们在上面用到的_form.blade.php:

<div class="row">
<div class="col-md-8">
<div class="form-group">
<label for="title" class="col-md-2 control-label">
Title
</label>
<div class="col-md-10">
<input type="text" class="form-control" name="title" autofocus id="title" value="{{ $title }}">
</div>
</div>
<div class="form-group">
<label for="subtitle" class="col-md-2 control-label">
Subtitle
</label>
<div class="col-md-10">
<input type="text" class="form-control" name="subtitle" id="subtitle" value="{{ $subtitle }}">
</div>
</div>
<div class="form-group">
<label for="page_image" class="col-md-2 control-label">
Page Image
</label>
<div class="col-md-10">
<div class="row">
<div class="col-md-8">
<input type="text" class="form-control" name="page_image" id="page_image" onchange="handle_image_change()" alt="Image thumbnail" value="{{ $page_image }}">
</div>
<script>
function handle_image_change() {
$("#page-image-preview").attr("src", function () {
var value = $("#page_image").val();
if ( ! value) {
value = {!! json_encode(config('blog.page_image')) !!};
if (value == null) {
value = '';
}
}
if (value.substr(0, 4) != 'http' && value.substr(0, 1) != '/') {
value = {!! json_encode(config('blog.uploads.webpath')) !!} + '/' + value;
}
return value;
});
}
</script>
<div class="visible-sm space-10"></div>
<div class="col-md-4 text-right">
<img src="{{ page_image($page_image) }}" class="img img_responsive" id="page-image-preview" style="max-height:40px">
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="content" class="col-md-2 control-label">
Content
</label>
<div class="col-md-10">
<textarea class="form-control" name="content" rows="14" id="content">{{ $content }}</textarea>
</div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="publish_date" class="col-md-3 control-label">
Pub Date
</label>
<div class="col-md-8">
<input class="form-control" name="publish_date" id="publish_date" type="text" value="{{ $publish_date }}">
</div>
</div>
<div class="form-group">
<label for="publish_time" class="col-md-3 control-label">
Pub Time
</label>
<div class="col-md-8">
<input class="form-control" name="publish_time" id="publish_time" type="text" value="{{ $publish_time }}">
</div>
</div>
<div class="form-group">
<div class="col-md-8 col-md-offset-3">
<div class="checkbox">
<label>
<input {{ checked($is_draft) }} type="checkbox" name="is_draft">
Draft?
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="tags" class="col-md-3 control-label">
Tags
</label>
<div class="col-md-8">
<select name="tags[]" id="tags" class="form-control" multiple>
@foreach ($allTags as $tag)
<option @if (in_array($tag, $tags)) selected @endif value="{{ $tag }}">
{{ $tag }}
</option>
@endforeach
</select>
</div>
</div>
<div class="form-group">
<label for="layout" class="col-md-3 control-label">
Layout
</label>
<div class="col-md-8">
<input type="text" class="form-control" name="layout" id="layout" value="{{ $layout }}">
</div>
</div>
<div class="form-group">
<label for="meta_description" class="col-md-3 control-label">
Meta
</label>
<div class="col-md-8">
<textarea class="form-control" name="meta_description" id="meta_description" rows="6">{{ $meta_description }}</textarea>
</div>
</div>
</div>
</div>

上面使用到了一个帮助函数,我们在helper.php中添加这个方法:

/**
* 如果传进来的参数是true 则返回checked,false放回空字符串。
*
* @param $value
* @return string
*/
function checked($value)
{
return $value ? 'checked' : '';
} /**
* Return img url for headers
*/
function page_image($value = null)
{
if (empty($value)) {
$value = config('blog.page_image');
}
if (! starts_with($value, 'http') && $value[0] !== '/') {
$value = config('blog.uploads.webpath') . '/' . $value;
} return $value;
}

4.6 创建表单请求类

class PostCreateRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
} /**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required',
'subtitle' => 'required',
'content' => 'required',
'publish_date' => 'required',
'publish_time' => 'required',
'layout' => 'required',
];
} /**
* 返回创建模型所需要用的数据。
*
* @return array
*/
public function postFillData()
{
$published_at = new Carbon(
$this->publish_date.' '.$this->publish_time
);
return [
'title' => $this->title,
'subtitle' => $this->subtitle,
'page_image' => $this->page_image,
'content_raw' => $this->get('content'),
'meta_description' => $this->meta_description,
'is_draft' => (bool)$this->is_draft,
'published_at' => $published_at,
'layout' => $this->layout,
];
}
}

4.7 实现store方法

    public function store(Requests\PostCreateRequest $request)
{
$post = Post::create($request->postFillData());
$post->syncTags($request->get('tags', [])); return redirect()
->route('admin.post.index')
->withSuccess('New Post Successfully Created.');
}

4.8 实现syncTags方法

在store方法中使用了Post模型的syncTags方法 用于同步标签,在Post模型中创建这个方法:

    public function syncTags(array $tags)
{
Tag::addNeededTags($tags); if (count($tags)){
$this->tags()->sync(Tag::whereIn('tag', $tags)->lists('id')->all());
return;
}
$this->tags()->detach();
}

4.9 实现store方法

现在我们可以实现PostController上的store方法了:

    public function store(Requests\PostCreateRequest $request)
{
$post = Post::create($request->postFillData());
$post->syncTags($request->get('tags', [])); return redirect()
->route('admin.post.index')
->withSuccess('New Post Successfully Created.');
}

5 更新Post

5.1 创建edit视图

@extends('admin.layout')

@section('styles')
<link href="/assets/pickadate/themes/default.css" rel="stylesheet">
<link href="/assets/pickadate/themes/default.date.css" rel="stylesheet">
<link href="/assets/pickadate/themes/default.time.css" rel="stylesheet">
<link href="/assets/selectize/css/selectize.css" rel="stylesheet">
<link href="/assets/selectize/css/selectize.bootstrap3.css" rel="stylesheet">
@stop @section('content')
<div class="container-fluid">
<div class="row page-title-row">
<div class="col-md-12">
<h3>Posts <small>» Edit Post</small></h3>
</div>
</div> <div class="row">
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Post Edit Form</h3>
</div>
<div class="panel-body"> @include('admin.partials.error')
@include('admin.partials.success') <form class="form-horizontal" role="form" method="POST" action="{{ route('admin.post.update', $id) }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="_method" value="PUT"> @include('admin.post._form') <div class="col-md-8">
<div class="form-group">
<div class="col-md-10 col-md-offset-2">
<button type="submit" class="btn btn-primary btn-lg" name="action" value="continue">
<i class="fa fa-floppy-o"></i>
Save - Continue
</button>
<button type="submit" class="btn btn-success btn-lg" name="action" value="finished">
<i class="fa fa-floppy-o"></i>
Save - Finished
</button>
<button type="button" class="btn btn-danger btn-lg" data-toggle="modal" data-target="#modal-delete">
<i class="fa fa-times-circle"></i>
Delete
</button>
</div>
</div>
</div> </form> </div>
</div>
</div>
</div> {{-- 确认删除 --}}
<div class="modal fade" id="modal-delete" tabIndex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
×
</button>
<h4 class="modal-title">Please Confirm</h4>
</div>
<div class="modal-body">
<p class="lead">
<i class="fa fa-question-circle fa-lg"></i>
Are you sure you want to delete this post?
</p>
</div>
<div class="modal-footer">
<form method="POST" action="{{ route('admin.post.destroy', $id) }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="_method" value="DELETE">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-danger">
<i class="fa fa-times-circle"></i> Yes
</button>
</form>
</div>
</div>
</div>
</div>
</div> @stop @section('scripts')
<script src="/assets/pickadate/picker.js"></script>
<script src="/assets/pickadate/picker.date.js"></script>
<script src="/assets/pickadate/picker.time.js"></script>
<script src="/assets/selectize/selectize.min.js"></script>
<script>
$(function() {
$("#publish_date").pickadate({
format: "mmm-d-yyyy"
});
$("#publish_time").pickatime({
format: "h:i A"
});
$("#tags").selectize({
create: true
});
});
</script>
@stop

5.2 生成edit方法

我们创建好edit视图后要生成对应的方法:PostController下的edit方法。

    public function edit($id)
{
$data = $this->dispatch(new PostFormFields($id));
return view('admin.post.edit', $data);
}

5.3 创建修改用的Request

php artisan make:request PostUpdateRequest

我们的修改用的Request和创建用的Request很相像,所以直接继承就好:

class PostUpdateRequest extends PostCreateRequest
{ }

5.4 编辑update方法

    public function update(Requests\PostUpdateRequest $request, $id)
{
$data = $request->postFillData();
$post = Post::findOrFail($id);
$post->fill($data);
$post->save();
$post->syncTags($request->get('tags', [])); if ($request->get('action') === 'continue'){
return redirect()->back()->withSuccess('Post saved.');
} return redirect()->route('admin.post.index')->withSuccess('Post saved.');
}

6 删除Post

修改destroy方法:

    public function destroy($id)
{
$post = Post::findOrFail($id);
// 删除中间表的数据。
$post->tags()->detach();
$post->delete(); return redirect()
->route('admin.post.index')
->withSuccess('Post deleted.');
}

Laravel5.1 搭建博客 --文章的增删改查的更多相关文章

  1. 夺命雷公狗---Thinkphp----12之文章的增删改查(图片上传和关联查询)

    我们由于表分析的不够完善,所以我们来加多一个tid的字段,到时候主要目的是为了更好的遍历出文章是属于那个分类下的,表如下所示: 那么下一步我们就开始创建一个ArticleController.clas ...

  2. Laravel5.1 搭建博客 --编译前端文件

    上篇文章写了Gulp编译前端文件,这篇记录下在搭建博客中使用Gulp 1 引入bootstrap和js 1.1 首先先在项目本地安装Bower sudo npm install bower 1.2 创 ...

  3. Laravel5.1 搭建博客 --展示简单的首页

    今天起开始搭建博客,把之前学的东西运用下. 1 创建 配置项目 1.1 创建项目 composer create-project laravel/laravel blog 5.1.1 1.2 配置数据 ...

  4. .net core项目搭建swagger接口实现简单增删改查

    .net core搭建swagger 1,新建立.net core项目(这里不再细说) 2,引入NuGet程序包 3,建立项目之后在Startup类中配置swagger 这里我直接把代码贴出来: 在C ...

  5. Laravel5.1 搭建博客 --构建标签

    博客的每篇文章都是需要有标签的,它与文章也是多对多的关系 这篇笔记也是记录了实现标签的步骤逻辑. 在我们之前的笔记中创建了Tag的控制器和路由了 所以这篇笔记不在重复 1 创建模型与迁移文件 迁移文件 ...

  6. Django搭建博客文章---模型层

    页面展示所需字段 1.文章标题---文本类型 2.文章摘要---文本类型 3.文章内容--文本类型 4.唯一的ID标记---int数字类型(自增.主键) 5.发布日期--日期类型 模型层定义字段 1. ...

  7. Laravel5.1 搭建博客 --后台登录

    今天咱来实现后台的登录. 首先我们的后台需要三个控制器: PostController:管理文章. TagController:管理文章标签. UploadController:上传文件. 当我们访问 ...

  8. Laravel5.1 搭建博客 --上传文件及文件管理

    教程源自:Laravel学院 这一节 咱来说说上传文件的功能实现,我们会把上传的文件保存到项目本地,不仅上传 还有删除和预览功能. 1 配置 我们先从配置开始做起,先修改我们自己创建的 blog.ph ...

  9. 基于 abp vNext 和 .NET Core 开发博客项目 - 自定义仓储之增删改查

    上一篇文章(https://www.cnblogs.com/meowv/p/12913676.html)我们用Code-First的方式创建了博客所需的实体类,生成了数据库表,完成了对EF Core的 ...

随机推荐

  1. linux命令:tail 命令

    tail 命令从指定点开始将文件写到标准输出.使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不但刷新, ...

  2. Axure 蚂蚁设计团队组件库 让交互稿美美"搭"

    Github资源:https://github.com/ant-design/ant-design-pro English | 简体中文 技术实践篇 https://pro.ant.design/do ...

  3. IE提示console未定义问题解决

    在页面加入如下代码: if (!window.console || !console.firebug){    var names = ["log", "debug&qu ...

  4. 如何用nodejs 开发一个命令行交互工具

    参考地址1 参考地址2 一.npm package.json bin 1.package.json { "name": "test", "versio ...

  5. struts2实现简单文件上传

    struts2 在内部已经帮我们做了很多封装的工作,我们只需要简单的写一些配置即可. 1 表单页面 <form action="${pageContext.request.contex ...

  6. Redis(十五):哨兵Sentinel

    Redis哨兵 Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务: 监控(Monitoring): Sentinel 会不断地检查你 ...

  7. CLoadScene类

    #ifndef __LOADSCENE_H__ #define __LOADSCENE_H__ #include "GameFrameHead.h" class CGameScen ...

  8. HTTP 403详解

    1.什么是Http 403错误Http协议中对403错误定义如下The server understood the request, but is refusing to fulfill it. Au ...

  9. 02、Quick Start for Windows phone

    在使用这个 SDK 提供的功能前,必须先添加类库的引用到你的工程里.参考: Download and add the libraries to the project. 定义你的 XAML 的 UI ...

  10. 彻底征服 Spring AOP 之 理论篇

    基本知识 其实, 接触了这么久的 AOP, 我感觉, AOP 给人难以理解的一个关键点是它的概念比较多, 而且坑爹的是, 这些概念经过了中文翻译后, 变得面目全非, 相同的一个术语, 在不同的翻译下, ...