Laravel5.1 搭建博客 --文章的增删改查
教程源于: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 搭建博客 --文章的增删改查的更多相关文章
- 夺命雷公狗---Thinkphp----12之文章的增删改查(图片上传和关联查询)
我们由于表分析的不够完善,所以我们来加多一个tid的字段,到时候主要目的是为了更好的遍历出文章是属于那个分类下的,表如下所示: 那么下一步我们就开始创建一个ArticleController.clas ...
- Laravel5.1 搭建博客 --编译前端文件
上篇文章写了Gulp编译前端文件,这篇记录下在搭建博客中使用Gulp 1 引入bootstrap和js 1.1 首先先在项目本地安装Bower sudo npm install bower 1.2 创 ...
- Laravel5.1 搭建博客 --展示简单的首页
今天起开始搭建博客,把之前学的东西运用下. 1 创建 配置项目 1.1 创建项目 composer create-project laravel/laravel blog 5.1.1 1.2 配置数据 ...
- .net core项目搭建swagger接口实现简单增删改查
.net core搭建swagger 1,新建立.net core项目(这里不再细说) 2,引入NuGet程序包 3,建立项目之后在Startup类中配置swagger 这里我直接把代码贴出来: 在C ...
- Laravel5.1 搭建博客 --构建标签
博客的每篇文章都是需要有标签的,它与文章也是多对多的关系 这篇笔记也是记录了实现标签的步骤逻辑. 在我们之前的笔记中创建了Tag的控制器和路由了 所以这篇笔记不在重复 1 创建模型与迁移文件 迁移文件 ...
- Django搭建博客文章---模型层
页面展示所需字段 1.文章标题---文本类型 2.文章摘要---文本类型 3.文章内容--文本类型 4.唯一的ID标记---int数字类型(自增.主键) 5.发布日期--日期类型 模型层定义字段 1. ...
- Laravel5.1 搭建博客 --后台登录
今天咱来实现后台的登录. 首先我们的后台需要三个控制器: PostController:管理文章. TagController:管理文章标签. UploadController:上传文件. 当我们访问 ...
- Laravel5.1 搭建博客 --上传文件及文件管理
教程源自:Laravel学院 这一节 咱来说说上传文件的功能实现,我们会把上传的文件保存到项目本地,不仅上传 还有删除和预览功能. 1 配置 我们先从配置开始做起,先修改我们自己创建的 blog.ph ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 自定义仓储之增删改查
上一篇文章(https://www.cnblogs.com/meowv/p/12913676.html)我们用Code-First的方式创建了博客所需的实体类,生成了数据库表,完成了对EF Core的 ...
随机推荐
- linux命令:tail 命令
tail 命令从指定点开始将文件写到标准输出.使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不但刷新, ...
- Axure 蚂蚁设计团队组件库 让交互稿美美"搭"
Github资源:https://github.com/ant-design/ant-design-pro English | 简体中文 技术实践篇 https://pro.ant.design/do ...
- IE提示console未定义问题解决
在页面加入如下代码: if (!window.console || !console.firebug){ var names = ["log", "debug&qu ...
- 如何用nodejs 开发一个命令行交互工具
参考地址1 参考地址2 一.npm package.json bin 1.package.json { "name": "test", "versio ...
- struts2实现简单文件上传
struts2 在内部已经帮我们做了很多封装的工作,我们只需要简单的写一些配置即可. 1 表单页面 <form action="${pageContext.request.contex ...
- Redis(十五):哨兵Sentinel
Redis哨兵 Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务: 监控(Monitoring): Sentinel 会不断地检查你 ...
- CLoadScene类
#ifndef __LOADSCENE_H__ #define __LOADSCENE_H__ #include "GameFrameHead.h" class CGameScen ...
- HTTP 403详解
1.什么是Http 403错误Http协议中对403错误定义如下The server understood the request, but is refusing to fulfill it. Au ...
- 02、Quick Start for Windows phone
在使用这个 SDK 提供的功能前,必须先添加类库的引用到你的工程里.参考: Download and add the libraries to the project. 定义你的 XAML 的 UI ...
- 彻底征服 Spring AOP 之 理论篇
基本知识 其实, 接触了这么久的 AOP, 我感觉, AOP 给人难以理解的一个关键点是它的概念比较多, 而且坑爹的是, 这些概念经过了中文翻译后, 变得面目全非, 相同的一个术语, 在不同的翻译下, ...