目次
2. トップページ、コラムナビゲーション、カルーセル画像、広告スペース、コラムコンテンツ表示
1. コンテンツ詳細ページ
プロジェクト紹介
このプロジェクトはフロントエンドとバックエンドに分かれています。フロントの機能には、ユーザーのログインと登録、コンテンツ一覧、コンテンツ詳細ページ、広告表示、コメントや人気コンテンツなどが含まれます。ログインしていない場合は、背景が自動的にログイン ページにジャンプします。ユーザー名「admin」、パスワード「123456」、認証コードを入力後、「ログイン」ボタンをクリックしてログインしてください。ログイン後、ページ上部右側に現在ログインしているユーザー名「admin」と「終了」ボタンが表示されますので、「終了」ボタンをクリックしてバックエンドシステムを終了してください。背景ページの左側にはメニューバーがあり、ユーザーはメニューバー内のメニュー項目を選択して操作することができます。プロジェクトで使用する必要がある技術的なポイントには、ファイルのアップロード、ページング、およびセッション技術が含まれます。プロジェクト全体の開発は、機能を実現するためのステップに基づいて完了し、最初にバックエンドの開発が実装され、データが提供され、次にフロントエンドのデータ表示が完了します。
Laravelをインストールする
まず、Laravel をインストールするファイルを選択し、次にそのファイルを選択して Laravel インストールコマンドを実行します:composer create-project --prefer-dist laravel/laravel ./ 5.8.*
たとえば、 D ドライブの phpstudy_pro->WWW に Laravel をダウンロードしたい場合、 D ドライブのphpstudy_pro->WWWファイルを選択し、そのファイルにcmdと書き込み、Enter キーを押してファイルの終端に入ります。を選択し、コマンドを実行してLaravelをインストールします。動作を下図に示します。
設定ファイル
Laravel をインストールした後、Apache のconf\extra\httpd-vhosts.conf設定ファイルに仮想ホストを作成します。具体的な構成は次のとおりです。
<VirtualHost *:80>
DocumentRoot "C:/web/apache2.4/htdocs/cms/public"
ServerName cms.com
<VirtualHost>
次に、Apache のhostsファイルを編集し、解析レコード「127.0.0.1 cms.com」を追加します。以下に示すように。
MySQL サーバーにログインし、データベースcmsを作成し、コンテンツ管理システムのデータベースとして cms を使用します。
プロジェクトを開き、config\database.phpデータベース構成ファイルでデータベース名をcmsに変更します。
.envファイルに正しいデータベース構成情報を構成します。すべてが完了すると、プロジェクト内でデータベースにアクセスできるようになります。
必要な静的ファイルを導入する
1. バックエンドユーザーのログイン
1. ユーザーテーブルの作成
(1) コマンドラインで以下のコマンドを実行し、マイグレーションファイルを作成します。
php artisan make:migration create_admin_user_table
(2) 上記コマンドを実行すると、database\migrationsディレクトリに時刻プレフィックス_create_admin_user_table.phpが付いたファイルが生成されます。
(3)マイグレーションファイルのup()メソッドにテーブル構造情報を追加します具体的なコードは以下の通りです。
public function up()
{
Schema::create('admin_user', function (Blueprint $table) {
$table->increments('id')->comment('主键');
$table->string('username', 32)->comment('用户名')->unique();
$table->string('password', 32)->comment('密码');
$table->char('salt', 32)->comment('密码salt');
$table->timestamps();
});
}
(4) マイグレーションファイル作成後、以下のコマンドでマイグレーションを実行します。
php artisan migrate
(5) 上記のコマンドにより、移行ファイル内のup()メソッドが実行され、データ テーブルの作成が完了します。
(6) フィルファイルを作成します。具体的なコマンドは次のとおりです。
php artisan make:seeder AdminuserTableSeeder
(7) 上記コマンドを実行すると、database\seedsディレクトリに、対応する移行ファイルが生成されます。ファイル名は、 AdminuserTableSeeder.php になります。
(8)充填ファイルのrun()メソッドに充填コードを記述します。
public function run()
{
$salt = md5(uniqid(microtime(), true));
$password = md5(md5('123456') . $salt);
DB::table('admin_user')->insert([
[
'id' => 1,
'username' => 'admin',
'password' => $password,
'salt' => $salt
],
]);
}
(9) fill file コマンドを実行します。
php artisan db:seed --class=AdminuserTableSeeder
(10) データベースが正常に作成されたら、ユーザー モデルを作成します。
php artisan make:model Admin
(11) app\Admin.phpを開き、モデル内で操作したいテーブル名を指定する 具体的なコードは以下の通りです。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Admin extends Model
{
protected $table = 'admin_user';
public $fillable = ['username', 'password'];
}
2. ログインページを表示する
(1) ユーザー コントローラーを作成します。具体的なコードは次のとおりです。
php artisan make:controller Admin/UserController
(2) 上記コマンドを実行すると、app\Http\Controllers\AdminディレクトリにUserController.phpが作成され、名前空間はApp\Http\Controllers\Adminとなります。
(3) UserController.phpを開き、login()メソッドを作成します。具体的なコードは次のとおりです。
public function login(){
return view('admin/login');
}
(4) Routes\web.php ファイルにルーティング ルールを追加します。具体的なコードは次のとおりです。
Route::get('/admin/login','Admin\UserController@login');
(5) 背景関連のテンプレート ファイルを格納するために使用される admin ディレクトリを resource\views ディレクトリに作成します。admin ディレクトリに login.blade.php ファイルを作成します。具体的なコードは次のとおりです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入静态文件 -->
<title>登录</title>
</head>
<body class="login">
<div class="container">
<!-- 登录表单 -->
</div>
</body>
</html>
(6) 上記 6 行目で静的ファイルを導入します。具体的なコードは次のとおりです。
<link rel="stylesheet" href="{
{asset('admin')}}/common/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/common/font-awesome-4.2.0/css/font-awesome.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/common/toastr.js/2.1.4/toastr.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/css/main.css">
<script src="{
{asset('admin')}}/common/jquery/1.12.4/jquery.min.js"></script>
<script src="{
{asset('admin')}}/common/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script src="{
{asset('admin')}}/common/toastr.js/2.1.4/toastr.min.js"></script>
<script src="{
{asset('admin')}}/js/main.js"></script>
(7) コメントログインフォームの下にログインフォームを定義します 具体的なコードは以下の通りです。
<form action="" method="post" class="j-login">
<h1>后台管理系统</h1>
<div class="form-group">
<input type="text" name="username" class="form-control" placeholder="用户名" required>
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" placeholder="密码" required>
</div>
<div class="form-group">
<input type="text" name="captcha" class="form-control" placeholder="验证码" required>
</div>
<!-- 验证码 -->
<div class="form-group">
{
{csrf_field()}}
<input type="submit" class="btn btn-lg btn-block btn-success" value="登录">
</div>
</form>
(8) Composer を使用して mews/captcha 検証コード ライブラリをロードします。具体的なコードは次のとおりです。
composer require mews/captcha=3.0
(9) 検証コードの設定ファイルを作成します 具体的なコマンドは以下の通りです。
php artisan vendor:publish
(10) 上記コマンド実行後、コマンドラインにシリアル番号「9」を入力して「Enter」キーを押すと、 config\captcha.phpファイルが自動生成されます。
(11) config\captcha.php ファイルを編集し、文字数を 4 に変更します。具体的なコードは次のとおりです。
'default' => [
'length' => 4, //字符个数
'width' => 120, //图片宽度
'height' => 36, //图片高度
'quality' => 90, //图片质量
'math' => false, //数学计算
],
(12) config\app.phpに認証コードサービスをサーバーに登録します。具体的なコードは次のとおりです。
'providers' => [
...(原有代码)
Mews\Captcha\CaptchaServiceProvider::class,
...(原有代码)
]
(13) config\app.phpファイルに認証コードサービスのエイリアスを登録します具体的なコードは以下の通りです。
'aliases' => [
...(原有代码)
'Captcha' =>Mews\Captcha\Facades\Captcha::class,
]
(14) ログインフォームに確認コードを追加します。具体的なコードは次のとおりです。
<div class="form-group">
<div class="login-captcha"><img src="{
{ captcha_src() }}" alt="captcha"></div>
</div>
(15) ブラウザ経由でアクセスすると、ページの効果は次のようになります。
(16) 単体検証コードイメージ以降の検証コードを置き換える機能を実装するには、テンプレートにJavaScriptコードを記述します。具体的なコードは以下のとおりです。
<script>
$('.login-captcha img').click(function() {
$(this).attr('src', '{
{ captcha_src()}}' + '?_=' + Math.random());
});
</script>
3.Ajax インタラクション
(1) public\admin\js\main.jsファイルを開き、次のコードを追加します。
(function (window, $, toastr) {
window.main = {
token: '', // 保存令牌
toastr: toastr,
init: function (opt) {
$.extend(this, opt); // 将传入的opt对象合并到自身对象中
toastr.options.positionClass = 'toast-top-center';
return this;
},
ajax: function (opt, success, error) {
opt = (typeof opt === 'string') ? {url: opt} : opt;
var that = this;
var options = {
success: function (data, status, xhr) {
that.hideLoading();
if (!data) {
toastr.error('请求失败,请重试。');
} else if (data.code === 0) {
toastr.error(data.msg);
error && error(data);
} else {
success && success(data);
}
opt.success && opt.success(data, status, xhr);
},
error: function (xhr, status, err) {
that.hideLoading();
toastr.error('请求失败,请重试。');
opt.error && opt.error(xhr, status, err);
}
};
that.showLoading();
$.ajax($.extend({}, opt, options));
},
showLoading: function() {
$('.main-loading').show();
},
hideLoading: function() {
$('.main-loading').hide();
},
};
})(this, jQuery, toastr);
(2) main オブジェクトにajaxPost()メソッドを記述する具体的なコードは以下のとおりです。
ajaxPost: function(opt, success, error) {
opt = (typeof opt === 'string') ? {url: opt} : opt;
var that = this;
var callback = opt.success;
opt.type = 'POST';
opt.success = function(data, status, xhr) {
if (data && data.code === 1) {
toastr.success(data.msg);
}
callback && callback(data, status, xhr);
};
that.ajax(opt, success, error);
},
(3) main.js にajaxForm()メソッドを記述し、フォームを Ajax 送信メソッドに変更する 具体的なコードは以下のとおりです。
ajaxForm: function (selector, success, error) {
var form = $(selector);
var that = this;
form.submit(function (e) {
e.preventDefault();
that.ajaxPost({
url: form.attr('action'),
data: new FormData(form.get(0)),
contentType: false,
processData: false
}, success, error);
});
},
4. ユーザーのログインを確認する
(1) Routes\web.phpファイルにルーティング ルールを追加します。具体的なコードは次のとおりです。
//登录验证
Route::post('/admin/check','Admin\UserController@check');
(2) UserController.phpにcheck()メソッドを作成します。具体的なコードは次のとおりです。
public function check(Request $request)
{
//声明自动验证规则
$rule = [
'username' => 'required',
'password' => 'required|min:6',
'captcha' => 'required|captcha'
];
// 声明自动验证规则对应的提示信息(验证失败返回信息)
$message = [
'username.required' => '用户名不能为空',
'password.required' => '密码不能为空',
'password.min' => '密码最少为6位',
'captcha.required' => '验证码不能为空',
'captcha.captcha' => '验证码有误'
];
//进行自动验证,验证表单提交数据
$validator = Validator::make($request->all(), $rule, $message);
// 输出验证结果并返回给浏览器
if ($validator->fails()) { //验证失败fails()方法
foreach ($validator->getMessageBag()->toArray() as $v) {
$msg = $v[0];
}
return response()->json(['code' => 0, 'msg' => $msg]);
}
// 获取用户输入的用户名、密码信息,以及数据表中用户名、密码信息
$username = $request->get('username');
$password = $request->get('password');
$theUser = Admin::where('username',$username)->first();
// 对用户输入的密码与数据库中的密码进行比较,如果密码正确则登录成功,并将用户信息保存在session中
// 跳转至后台首页,如果登录失败,则显示“登录失败”
if($theUser->password == md5(md5($password). $theUser->salt))
{
Session::put('user', ['id'=>$theUser->id,'name'=>$username]);
return response()->json(['code' => 1, 'msg' => '登录成功']);
}else{
return response()->json(['code' => 0, 'msg' => '登录失败']);
}
}
(3) 上記のコードで使用されている一部のクラスは、名前空間にインポートする必要があります。具体的なコードは次のとおりです。
use App\Admin;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
(4) login.blade.phpの <script> タグ内にコードを追加します。具体的なコードは次のとおりです。
main.ajaxForm('.j-login', function() {
location.href = '/index.php/admin/index';
});
(5) ブラウザからアクセスし、6桁未満のパスワードを入力するとページ上に「パスワードは6桁以上である必要があります」というエラーメッセージが表示され、認証コードを誤って入力すると「認証が完了しました」というエラーメッセージが表示されます。 「コードが間違っています」というメッセージがページに表示されます。正しいユーザー名 (admin) とパスワード (123456) を送信すると、「ログイン成功」というプロンプトがページに表示されます。
5. ユーザー出口
(1)ユーザーコントローラーにlogout()メソッドを追加します具体的なコードは以下のとおりです。
public function logout(){
if(request()->session()->has('user')){
request()->session()->pull('user',session('user'));
}
return redirect('/admin/login');
}
(2) Routes\web.phpファイルにルーティング ルールを追加します。具体的なコードは次のとおりです。
//用户退出
Route::get('/admin/logout','Admin\UserController@logout');
(3) ブラウザからのアクセス ユーザーがログインしていることを確認した後、http://cms.com/index.php/admin/logout にアクセスすると、ブラウザは自動的にログイン ページにジャンプし、ユーザーが正常にログインしたことを示します。ログアウトしました。
2. バックエンドのホームページ
1.バックエンドページのレイアウト
(1) レイアウトディレクトリに admin.blade.php ファイルを作成します 具体的なコードは次のとおりです。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--引入静态文件-->
<title>@yield('title')</title>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light main-navbar">
<a class="navbar-brand" href="#">后台管理系统</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="nav ml-auto main-nav-right">
<li>
<a href="#" class="j-layout-pwd">
<i class="fa fa-user fa-fw"></i>{
{session()->get('user.name')}}
</a>
</li>
<li>
<a href="{
{url('admin/logout')}}">
<i class="fa fa-power-off fa-fw"></i>退出
</a>
</li>
</ul>
</div>
</nav>
<!-- 后台页面的首页部分 -->
<div class="main-container">
<div class="main-content">
<div>@yield('main')</div>
</div>
</div>
</body>
</html>
(2) ページに静的リソースを導入します。具体的なコードは次のとおりです。
<link rel="stylesheet" href="{
{asset('admin')}}/common/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/common/font-awesome-4.2.0/css/font-awesome.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/common/toastr.js/2.1.4/toastr.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/css/main.css">
<script src="{
{asset('admin')}}/common/jquery/1.12.4/jquery.min.js"></script>
<script src="{
{asset('admin')}}/common/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script src="{
{asset('admin')}}/common/toastr.js/2.1.4/toastr.min.js"></script>
<script src="{
{asset('admin')}}/js/main.js"></script>
(3) ページの左側のナビゲーション バーを定義します。具体的なコードは次のとおりです。
<div class="main-sidebar">
<ul class="nav flex-column main-menu">
</div>
(4) ホームページ メニューを追加します。具体的なコードは次のとおりです。
<li class="">
<a href="{
{url('admin/index')}}" class="active">
<i class="fa fa-home fa-fw"></i>首页
</a>
</li>
(5) 列メニューを追加します。具体的なコードは次のとおりです。
<li class="main-sidebar-collapse"> <!-- 被收起的双层项 -->
<a href="#" class="main-sidebar-collapse-btn"> <!-- 链接用于展开或收起子菜单 -->
<i class="fa fa-list-alt fa-fw"></i>栏目
<span class="fa main-sidebar-arrow"></span> <!-- 双层项的右侧小箭头 -->
</a>
<ul class="nav">
<!-- 设置子菜单 -->
<li>
<a href="#" data-name="addcategory">
<i class="fa fa-list fa-fw"></i>添加</a>
</li>
<li>
<a href="#" data-name="category">
<i class="fa fa-table fa-fw"></i>列表</a>
</li>
</ul>
</li>
(6) コンテンツ フォームを追加します。具体的なコードは次のとおりです。
<li class="main-sidebar-collapse">
<a href="#" class="main-sidebar-collapse-btn">
<i class="fa fa-list-alt fa-fw"></i>内容
<span class="fa main-sidebar-arrow"></span>
</a>
<ul class="nav">
<li>
<a href="#" data-name="addcontent">
<i class="fa fa-list fa-fw"></i>添加</a>
</li>
<li>
<a href="#" data-name="content">
<i class="fa fa-table fa-fw"></i>列表</a>
</li>
</ul>
</li>
(7) 広告フォームを追加します。具体的なコードは次のとおりです。
<li class="main-sidebar-collapse">
<a href="#" class="main-sidebar-collapse-btn">
<i class="fa fa-cog fa-fw"></i>广告
<span class="fa main-sidebar-arrow"></span>
</a>
<ul class="nav">
<li>
<a href="#" data-name="adv">
<i class="fa fa-list fa-fw"></i>广告位</a>
</li>
<li>
<a href="#" data-name="advcontent">
<i class="fa fa-list-alt fa-fw"></i>广告内容</a>
</li>
</ul>
</li>
(8) メッセージフォームを追加します。具体的なコードは次のとおりです。
@if(!empty(session('message')))
<div class="alert alert-success" role="alert"
style="text-align:center;margin:0 auto;width: 400px">
{
{session('message')}}
</div>
@endif
@if(!empty(session('tip')))
<div class="alert alert-warning" role="alert"
style="text-align:center;margin:0 auto;width: 400px">
{
{session('tip')}}
</div>
@endif
(9) <body> タグの末尾の前に <script> タグを追加して、メッセージ テンプレートの表示時間を制御します。具体的なコードは次のとおりです。
<script>
// setInterval(myFunction,myTimeLapse),每隔myTimeLapse(毫秒)执行一次myFunction()函数
setInterval(function(){
$('.alert').remove();
},3000);
</script>
(10) public\admin\js\main.jsファイルを変更し、layout() メソッドを記述します。具体的なコードは次のとおりです。
layout: function() {
$('.main-sidebar-collapse-btn').click(function() {
$(this).parent().find('.nav').slideToggle(200);
$(this).parent().toggleClass('main-sidebar-collapse').siblings().
addClass('main-sidebar-collapse').find('.nav').slideUp(200);
return false;
});
},
(11) main.jsにmenuActive()メソッドを追加して、指定したメニュー項目を選択状態に設定します 具体的なコードは次のとおりです。
menuActive: function(name) {
var menu = $('.main-menu');
menu.find('a').removeClass('active');
menu.find('a[data-name=\'' + name + '\']').addClass('active');
menu.find('a[data-name=\'' + name + '\']').parent().parent().show();
}
(12) <script> タグ内でlayout()メソッドを呼び出す 具体的なコードは以下の通りです。
main.layout();
2. 背景ホームページを表示する
(1) 公開ファイルの作成後、バックエンドホームページ admin\index.blade.php を作成します。具体的なコードは次のとおりです。
@extends('admin/layouts/admin')
@section('title', '后台首页')
@section('main')
<div>
<div class="main-title">
<h2>首页</h2>
</div>
<div class="main-section">
<div class="card">
<div class="card-header">服务器信息</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">系统环境:{
{ $server_version }}</li>
<li class="list-group-item">Laravel版本:{
{ $laravel_version }}</li>
<li class="list-group-item">MySQL版本:{
{ $mysql_version }}</li>
<li class="list-group-item">服务器时间:{
{ $server_time }}</li>
<li class="list-group-item">文件上传限制:{
{ $upload_max_filesize }}</li>
<li class="list-group-item">脚本执行时限:{
{ $max_execution_time }}</li>
</ul>
</div>
</div>
</div>
@endsection
(2) Indexコントローラーを作成します。具体的なコードは次のとおりです。
php artisan make:controller Admin\IndexController
(3) Index コントローラにIndex()メソッドを追加します。具体的なコードは次のとおりです。
public function index(Request $request){
$data = [
'server_version' => $request->server('SERVER_SOFTWARE'),
'laravel_version' => app()::VERSION,
'mysql_version' => $this->getMySQLVer(),
'server_time' => date('Y-m-d H:i:s', time()),
'upload_max_filesize' => ini_get('file_uploads') ?
ini_get('upload_max_filesize') : '已禁用',
'max_execution_time' => ini_get('max_execution_time') . '秒'
];
return view('admin\index', $data);
}
(4) 上記コードの 6 行目で、getMySQLVer()メソッドを呼び出して MySQL のバージョンを取得し、getMySQLVer() メソッドを作成します。具体的なコードは次のとおりです。
private function getMySQLVer()
{
$res = DB::select('SELECT VERSION() AS ver');
return $res[0]->ver ?? '未知';
}
(5) getMySQLVer() メソッドでは、DB クラスを使用して SQL を実行し、MySQL のバージョンを取得し、DB クラスの名前空間をインポートします。具体的なコードは次のとおりです。
use DB;
(6) Routes\web.php ファイルにルーティング ルールを追加します。具体的なコードは次のとおりです。
Route::get('/admin/index', 'Admin\IndexController@index');
(7) ブラウザを通じてバックエンドのホームページにアクセスすると、次のような効果が得られます。
3. ログインステータスの確認
(1)ユーザーがログインしているかどうかを確認するための管理ミドルウェアを作成します。具体的なコードは次のとおりです。
php artisan make:middleware Admin
(2) app\Http\Middleware\Admin.phpを開き、ユーザーのログインを確認するためのコードを追加します。具体的なコードは次のとおりです。
public function handle($request, Closure $next)
{
if (request()->session()->has('user')) {
$user = request()->session()->get('user');
view()->share('user', $user);
} else {
return redirect('/admin/login');
}
return $next($request);
}
(3) app\Http\Kernel.phpファイルにルーティングミドルウェアを登録します。具体的なコードは次のとおりです。
protected $routeMiddleware = [
...(原有代码)
'Admin' => \App\Http\Middleware\Admin::class,
];
(4) ホームページのルーティング ルールを変更し、バックグラウンドのホームページにユーザー認証を追加します。具体的なコードは次のとおりです。
Route::get('/admin/index', 'Admin\IndexController@index')->middleware(['Admin']);
3. カラム管理
1.列テーブルの作成
(1) 列テーブルもコマンド ラインから作成されます。前の手順に従って、移行ファイルとフィル ファイルを作成します。
(2) カラムテーブルの移行ファイルを開き、ファイルのup()メソッドにテーブル構造情報を追加する具体的なコードは以下のとおりです。
public function up()
{
Schema::create('category', function (Blueprint $table) {
$table->increments('id')->comment('主键');
$table->integer('pid')->comment('父类id') ->default('0');
$table->string('name', 32)->comment('分类名称');
$table->integer('sort')->comment('排序值') ->default('0');
$table->timestamps();
});
}
(3) カラムテーブルの作成後、プロジェクト内でカラムテーブルを操作するために、カラムテーブルに対応するモデルファイルを作成します 具体的なコードは以下の通りです。
php artisan make:model Category
(4) app\Category.phpファイルを開きます。具体的なコードは次のとおりです。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = "category";
public $fillable = ['pid', 'name', 'sort'];
}
2. 列を追加する
(1)カテゴリコントローラーを作成します。具体的なコードは次のとおりです。
php artisan make:controller Admin\CategoryController
(2)コントローラにadd()メソッドを追加して列を追加する機能を実装します 具体的なコードは以下の通りです。
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Category;
class CategoryController extends Controller
{
public function add(){
$category = Category::where('pid', 0)->get();
return view('admin.category.add', ['category' => $category] );
}
}
(3) admin\category\add.blade.phpビュー ファイルを作成します。具体的なコードは次のとおりです。
@extends('admin/layouts/admin')
@section('title', ' 添加栏目')
@section('main')
<div class="main-title"><h2>添加栏目</h2></div>
<div class="main-section">
<div style="width:543px">
<!-- 添加栏目表单 -->
<form method="post" action="{
{ url('/category/save') }}">
<div class="form-group row">
<label class="col-sm-2 col-form-label">序号</label>
<div class="col-sm-10">
<input type="number" name="sort" class="form-control" value="0" style="width:80px;">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">上级栏目</label>
<div class="col-sm-10">
<select name="pid" class="form-control" style="width:200px;">
<option value="0">---</option>
@foreach ($category as $v)
<option value="{
{ $v->id }}"> {
{ $v->name }}</option>
@endforeach
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">名称</label>
<div class="col-sm-10">
<input type="text" name="name" class="form-control" style="width:200px;">
</div>
</div>
<div class="form-group row">
<div class="col-sm-10">
{
{csrf_field()}}
<button type="submit" class="btn btn-primary mr-2">提交表单</button>
<a href="{
{url('category')}}" class="btn btn-secondary">返回列表</a>
</div>
</div>
</form>
</div>
</div>
<script>
main.menuActive('addcategory');
</script>
@endsection
(4) Routes\web.phpファイルにルーティング ルールを追加します。具体的なコードは次のとおりです。
// 栏目
Route::prefix('category')->namespace('Admin')->middleware(['Admin'])->group(function () {
Route::get('add', 'CategoryController@add');
});
(5) レイアウト ファイルadmin.blade.phpを変更し、追加した列のナビゲーション用のリンクを追加します。具体的なコードは次のとおりです。
<a href="{
{ url('category/add') }}" data-name="addcategory"><i class="fa fa-list fa-fw"></i>添加</a>
(6)カテゴリコントローラにsave()メソッドを記述し、列を追加するためのフォームデータを受け取る具体的なコードは以下の通りです。
public function save(Request $request){
$data = $request->all();
$this->validate($request,[
'name'=>'required|unique:category'.$rule,
],[
'name.required'=>'栏目名称不能为空',
'name.unique'=>'栏目名称不能重复'
]);
$re = Category::create($data);
if($re){
return redirect('category')->with('message','添加成功');
}else{
return redirect('category/add')->with('tip','添加失败');
}
}
(7) Routes\web.phpファイルの列のルーティング グループにルーティング ルールを追加します。具体的なコードは次のとおりです。
Route::post('save', 'CategoryController@save');
3. カラム一覧表示
(1)カテゴリコントローラにindex()メソッドを作成します具体的なコードは以下の通りです。
public function index(){
$category = $this->getTreeListCheckLeaf($data);
return view('admin.category.index', ['category' => $category]);
}
(2)カテゴリモデルにgetTreeListCheckLeaf()メソッドとTreeList()メソッドを追加します。具体的なコードは次のとおりです。
public function getTreeListCheckLeaf($data, $name = 'isLeaf')
{
$data = $this->treeList($data);
foreach ($data as $k => $v) {
foreach ($data as $vv) {
$data[$k][$name] = true;
if ($v['id'] === $vv['pid']) {
$data[$k][$name] = false;
break;
}
}
}
return $data;
}
public function treeList($data, $pid = 0, $level = 0, &$tree = [])
{
foreach ($data as $v) {
if ($v['pid'] == $pid) {
$v['level'] = $level;
$tree[] = $v;
$this->treeList($data, $v['id'], $level + 1, $tree);
}
}
return $tree;
}
(3) ビューファイルindex.phpを作成します。具体的なコードは次のとおりです。
@extends('admin/layouts/admin')
@section('title', '栏目列表')
@section('main')
<div class="main-title"><h2>栏目管理</h2></div>
<div class="main-section form-inline">
<a href="{
{ url('category/add') }}" class="btn btn-success">+ 新增</a>
</div>
<div class="main-section">
<form method="post" action="" class="j-form">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th width="75">序号</th><th>名称</th><th width="100">操作</th>
</tr>
</thead>
<tbody>
<!-- 栏目列表 -->
@foreach($category)
<tr class="j-pid-{
{ $v['pid'] }}"
@if($v['level'])style="display:none"@endif>
<td><input type="text" class="form-control j-sort" maxlength="5" value="{
{$v['sort']}}" data-name="sort[{
{$v['id']}}]" style="height:25px;font-size:12px;padding:0 5px;"></td>
<td>
@if($v['level'])
<small class="text-muted">├──</small> {
{$v['name']}}
@else
<a href="#" class="j-toggle" data-id="{
{$v['id']}}">
@if(!$v['isLeaf'])
<i class="fa fa-plus-square-o fa-minus-square-o fa-fw"></i>
@endif
{
{$v['name']}}
</a>
@endif
</td>
<td>
<a href="{
{ url('category/edit', ['id' => $v['id']]) }}" style="margin-right:5px;">编辑</a>
<a href="{
{ url('category/delete', ['id' => $v['id']]) }}" class="j-del text-danger">删除</a>
</td>
</tr>
@endforeach
@if(empty($category))
<tr><td colspan="4" class="text-center">还没有添加栏目</td></tr>
@endif
</tbody>
</table>
{
{csrf_field()}}
<input type="submit" value="改变排序" class="btn btn-primary">
</form>
</div>
<script>
main.menuActive('category');
$('.j-toggle').click(function() {
var id = $(this).attr('data-id');
$(this).find('i').toggleClass('fa-plus-square-o');
$('.j-pid-' + id).toggle();
return false;
});
$('.j-sort').change(function() {
$(this).attr('name', $(this).attr('data-name'));
});
$('.j-del').click(function() {
if (confirm('您确定要删除此项?')) {
var data = { _token: '{
{ csrf_token() }}' };
main.ajaxPost({url:$(this).attr('href'), data: data}, function(){
location.reload();
});
}
return false;
});
</script>
@endsection
(4) Routes\web.phpファイル内の列のルーティング グループに列リストのルーティング ルールを追加します。具体的なコードは次のとおりです。
Route::get('', 'CategoryController@index');
(5) admin.blade.phpを変更し、リスト メニュー項目へのリンクを追加します。具体的なコードは次のとおりです。
<a href="{
{ url('category') }}" data-name="category"><i class="fa fa-table fa-fw"></i>列表</a>
(6) ブラウザからアクセスすると、列リストのページ効果は次のようになります。
(7) カラム一覧ページでカラムの並び替えを変更するには、カラム一覧ページでフォームの送信アドレスを設定する必要がありますが、具体的なコードは以下のとおりです。
<form method="post" action="{
{ url('category/sort')}}" class="j-form">
(8)ソートされたルーティング ルールを、 routes\web.phpファイルの列のルーティング グループに追加します。具体的なコードは次のとおりです。
Route::post('sort', 'CategoryController@sort');
(9)カテゴリコントローラにsort()メソッドを追加します具体的なコードは以下の通りです。
public function sort(Request $request){
$sort = $request->input('sort');
foreach ($sort as $k => $v) {
Category::where('id', (int)$k)->update(['sort' => (int)$v]);
}
return redirect('category')->with('message','改变排序成功');
}
(10) ブラウザからアクセスし、カラムの機能が正しく実行されるか観察します。
4. 列の編集
(1) リストページの「編集」ボタンにリンクを追加します 具体的なコードは以下の通りです。
<a href="{
{ url('category/edit', ['id' => $v['id']]) }}" style="margin-right:5px;">编辑</a>
(2) routes\web.phpファイルの列のルーティンググループに編集列のルーティングルールを追加します。具体的なコードは以下のとおりです。
Route::get('edit/{id}', 'CategoryController@edit');
(3)カテゴリコントローラに edit() メソッドを追加します具体的なコードは以下のとおりです。
public function edit($id){
$data = [];
if ($id) {
if (!$data = Category::find($id)) {
return back()->with('tip', '记录不存在。');
}
}
$category = Category::where('pid', 0)->get();
return view('admin.category.edit', ['id'=>$id, 'data'=>$data, 'category' => $category]);
}
(4) ビューファイルedit.blade.phpを作成します。具体的なコードは次のとおりです。
@extends('admin/layouts/admin')
@section('title', '栏目列表')
@section('main')
<div class="main-title"><h2>编辑分类</h2></div>
<div class="main-section">
<div style="width:543px">
<!-- 编辑表单 -->
<form method="post" action="{
{ url('/category/save') }}">
<div class="form-group row">
<label class="col-sm-2 col-form-label">序号</label>
<div class="col-sm-10">
<input type="number" name="sort" class="form-control" value="{
{$data->sort}}" style="width:80px;">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">上级分类</label>
<div class="col-sm-10">
<select name="pid" class="form-control" style="width:200px;">
<option value="0">---</option>
@foreach($category as $v)
<option value="{
{ $v->id }}" @if($data['pid'] == $v['id']) selected @endif> {
{ $v->name }}</option>
@endforeach
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">名称</label>
<div class="col-sm-10">
<input type="text" name="name" class="form-control" value="{
{$data->name}}" style="width:200px;">
</div>
</div>
<div class="form-group row">
<div class="col-sm-10">
{
{csrf_field()}}
<input type="hidden" name="id" value="{
{$id}}">
<button type="submit" class="btn btn-primary mr-2">提交表单</button>
<a href="{
{url('category')}}" class="btn btn-secondary">返回列表</a>
{
{--<a href="{
{url('category')}}">--}}
{
{--<button class="btn btn-secondary">返回列表</button>--}}
{
{--</a>--}}
</div>
</div>
</form>
</div>
</div>
<script>
main.menuActive('category');
</script>
@endsection
(5) save()メソッドを変更して、列 ID に従って列の内容を更新します。具体的なコードは次のとおりです。
public function save(Request $request){
$data = $request->all();
$rule = isset($data['id']) ? ',name,'.$data['id'] : '';
$this->validate($request,[
'name'=>'required|unique:category'.$rule,
],[
'name.required'=>'栏目名称不能为空',
'name.unique'=>'栏目名称不能重复'
]);
if(isset($data['id'])){
$id = $data['id'];
unset($data['id']);
unset($data['_token']);
$res = Category::where('id',$id)->update($data);
$type = $res ? "message" : "tip";
$message = $res ? "修改成功" : "修改失败";
return redirect('category')->with($type, $message);
}
$re = Category::create($data);
if($re){
return redirect('category')->with('message','添加成功');
}else{
return redirect('category/add')->with('tip','添加失败');
}
}
5.列の削除
(1) リストページの「削除」ボタンにリンクを追加します 具体的なコードは以下の通りです。
<a href="{
{ url('category/delete', ['id' => $v['id']]) }}" class="j-del text-danger">删除</a>
(2)カテゴリコントローラーにdelete()メソッドを追加します。具体的なコードは次のとおりです。
public function delete($id){
if (!$category = Category::find($id)) {
return response()->json(['code' => 0, 'msg' => '删除失败,记录不存在。' ]);
}
$category->delete();
return response()->json(['code' => 1, 'msg' => '删除成功' ]);
}
(3) Routes \web.phpファイルの列ルーティング グループに列を削除するためのルーティング ルールを追加します。具体的なコードは次のとおりです。
Route::post('delete/{id}', 'CategoryController@delete');
4. コンテンツ管理
1. 目次を作成する
(1) 上記の手順でコンテンツテーブルに対応する移行ファイルを作成した後、移行ファイルの up() メソッドにテーブル構造情報を追加します。具体的なコードは次のとおりです。
public function up()
{
Schema::create('content', function (Blueprint $table) {
$table->increments('id')->comment('主键');
$table->integer('cid')->comment('栏目id')->default(0);
$table->string('title', 255)->comment('标题');
$table->text('content', 255)->comment('内容');
$table->char('image', 255)->comment('图片');
$table->tinyInteger('status')->comment('状态默认1推荐2')->default(1);
$table->timestamps();
});
}
(2) コンテンツテーブルに対応するモデルファイルを作成します 具体的なコードは以下のとおりです。
php artisan make:model Content
(3) 上記のコマンドを実行すると、 app\Content.phpファイルが自動的に作成されます。具体的なコードは次のとおりです。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Content extends Model
{
protected $table = "content";
public $fillable = ['cid', 'title', 'content', 'image', 'status'];
}
2. コンテンツを追加する
(1)コンテンツコントローラーを作成します。具体的なコードは次のとおりです。
php artisan make:controller Admin\ContentController
(2)コントローラにadd()メソッドを導入してコンテンツを追加する機能を実装し、save()メソッドで追加したコンテンツを保存する 具体的なコードは以下のとおりです。
public function add()
{
$data = Category::orderBy('sort', 'asc')->get()->toArray();
$cate = new CategoryController();
$category = $cate->getTreeListCheckLeaf($data);
return view('admin.content.add', ['category' => $category]);
}
public function save(Request $request)
{
$data = $request->all();
$this->validate($request,[
'cid'=>'required',
'title'=>'required'
],[
'cid.require'=>'分类不能为空',
'title.require'=>'标题不能为空'
]);
if(isset($data['id'])){
$id = $data['id'];
unset($data['id']);
unset($data['_token']);
$res = Content::where('id',$id)->update($data);
$type = $res ? "message" : "tip";
$message = $res ? "修改成功" : "修改失败";
return redirect('content')->with($type, $message);
}
$re = Content::create($data);
if($re){
return redirect('content')->with('message','添加成功');
}else{
return redirect('content/add')->with('tip','添加失败');
}
}
(3)カテゴリモデルの名前空間とコンテンツの名前空間をコントローラにインポートします具体的なコードは以下の通りです。
use App\Category;
use App\Content;
(4) resource\views\admin\content\add.blade.phpビュー ファイルを作成します。具体的なコードは次のとおりです。
@extends('admin/layouts/admin')
@section('title', '添加内容')
@section('main')
<div class="main-title"><h2>添加内容</h2></div>
<div class="main-section">
<div style="width:80%">
<!-- 添加内容表单 -->
<form method="post" action="{
{ url('/content/save') }}" class="j-form">
<div class="form-group row">
<label class="col-sm-2 col-form-label">所属分类</label>
<div class="col-sm-10">
<select name="cid" class="form-control" style="width:200px;">
<!-- 分类下拉列表 -->
@foreach($category as $v)
@if($v['level'])
<option value="{
{$v['id']}}">
<small class="text-muted">├──</small>{
{$v['name']}}
</option>
@else
<option value="{
{$v['id']}}"> {
{$v['name']}}</option>
@endif
@endforeach
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">标题</label>
<div class="col-sm-10">
<input type="text" name="title" class="form-control" style="width:200px;">
</div>
</div>
<!-- 上传图片按钮 -->
<div class="form-group row">
<label class="col-sm-2 col-form-label">图片</label>
<div class="col-sm-10">
<input type="file" id="file1" name="image" value="上传图片" multiple="true">
</div>
<div class="col-sm-10 offset-sm-2">
<div class="upload-img-box" id="uploadImg"></div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">简介</label>
<div class="col-sm-10">
<!-- <textarea class="j-goods-content" name="content" style="height:500px"></textarea> -->
<script type="text/plain" class="j-goods-content" name="content" style="height:500px"></script>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">状态</label>
<div class="col-sm-10">
<div class="form-check form-check-inline" style="height:38px">
<input class="form-check-input" id="inlineRadio1" type="radio" name="status" value="1" checked>
<label class="form-check-label" for="inlineRadio1">默认</label>
</div>
<div class="form-check form-check-inline" style="height:38px">
<input class="form-check-input" id="inlineRadio2" type="radio" name="status" value="2">
<label class="form-check-label" for="inlineRadio2">推荐</label>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-10">
{
{csrf_field()}}
<button type="submit" class="btn btn-primary mr-2">提交表单</button>
<a href="{
{url('content')}}" class="btn btn-secondary">返回列表</a>
</div>
</div>
</form>
</div>
</div>
<link href="{
{asset('admin')}}/common/uploader/uploadifive.css" rel="stylesheet" />
<script src="{
{asset('admin')}}/common/uploader/jquery.uploadifive.js"></script>
<script src="{
{asset('admin')}}/common/editor/ueditor1.4.3.3/ueditor.config.js"></script>
<script src="{
{asset('admin')}}/common/editor/ueditor1.4.3.3/ueditor.all.min.js"></script>
<script src="{
{asset('admin')}}/common/editor/main.editor.js"></script>
<script>
main.menuActive('addcontent');
$(function() {
$('#file1').uploadifive({
'auto' : true,
'fileObjName' : 'image',
'fileType' : 'image',
'buttonText' : '上传图片',
'formData' : { '_token' : "{
{ csrf_token() }}" },
'method' : 'post',
'queueID' : 'uploadImg',
'removeCompleted' : true,
'uploadScript' : '{
{ url('content/upload')}}',
'onUploadComplete': uploadPicture_icon
});
});
function uploadPicture_icon(file, data) {
var obj = $.parseJSON(data);
var src = '';
if (obj.code) {
filename = obj.data.filename;
path = obj.data.path;
$('.upload-img-box').empty();
$('.upload-img-box').html(
'<div class="upload-pre-item" style="max-height:100%;"><img src="' + path + '" style="width:100px;height:100px"/> <input type="hidden" name="image" value="'+filename+'" class="icon_banner"/></div>'
);
} else {
alert(data.info);
}
}
main.editor($('.j-goods-content'), 'goods_edit', function(opt) {
opt.UEDITOR_HOME_URL = '{
{asset('admin')}}/common/editor/ueditor1.4.3.3/';
}, function(editor) {
$('.j-form').submit(function() {
editor.sync();
});
});
</script>
@endsection
(5) Routes\web.phpファイルにコンテンツ管理ルーティング グループを追加します。具体的なコードは次のとおりです。
Route::prefix('content')->namespace('Admin')->middleware(['Admin'])->group(function () {
Route::get('add', 'ContentController@add');
Route::post('save', 'ContentController@save');
});
(6) admin.blade.phpを変更し、コンテンツを追加するためのメニュー項目へのリンクを追加します。具体的なコードは次のとおりです。
<a href="{
{ url('content/add') }}" data-name="addcontent">
<i class="fa fa-list fa-fw"></i>添加</a>
3. 写真をアップロードする
(1) コンテンツ追加画面に写真をアップロードするボタンを追加します 具体的なコードは以下の通りです。
<div class="form-group row">
<label class="col-sm-2 col-form-label">图片</label>
<div class="col-sm-10">
<input type="file" id="file1" name="image" value="上传图片" multiple="true">
</div>
<div class="col-sm-10 offset-sm-2">
<div class="upload-img-box" id="uploadImg"></div>
</div>
</div>
(2) ビューにファイルをアップロードするために必要なスタイルと JavaScript コードを導入します。具体的なコードは次のとおりです。
<link href="{
{asset('admin')}}/common/uploader/uploadifive.css" rel="stylesheet" />
<script src="{
{asset('admin')}}/common/uploader/jquery.uploadifive.js"></script>
<script src="{
{asset('admin')}}/common/uploader/jquery.uploadifive.min.js"></script>
(3) Contentコントローラーにupload()メソッドを記述します具体的なコードは以下の通りです。
public function upload(Request $request)
{
if ($request->hasFile('image')) {
$image = $request->file('image');
if ($image->isValid()) {
$name = md5(microtime(true)) . '.' . $image->extension();
$image->move('static/upload', $name);
$path = '/static/upload/' . $name;
$returndata = array(
'filename' => $name,
'path' => $path
);
$result = [
'code' => 1,
'msg' => '上传成功',
'time' => time(),
'data' => $returndata,
];
return response()->json($result);
}
return $image->getErrorMessage();
}
return '文件上传失败';
}
(4) Routes\web.phpファイル内のコンテンツのルーティング グループに画像をアップロードするためのルーティング ルールを追加します。具体的なコードは次のとおりです。
Route::post('upload', 'ContentController@upload');
4.UFditorを統合する
(1) public\admin\common\editor\main.editor.jsファイルを作成します 具体的なコードは以下のとおりです。
(function($, main) {
var def = {
UEDITOR_HOME_URL: '', // UEditor URL
serverUrl: '', // UEditor内置上传地址设为空
autoHeightEnabled: false, // 关闭自动调整高度
wordCount: false, // 关闭字数统计
toolbars: [['fullscreen', 'source', '|', // 自定义工具栏按钮
'undo', 'redo', '|', 'bold', 'italic', 'underline', 'strikethrough',
'forecolor', 'backcolor', 'fontfamily', 'fontsize', 'paragraph', 'link',
'blockquote', 'insertorderedlist', 'insertunorderedlist', '|',
'inserttable', 'insertrow', 'insertcol', '|', 'drafts']]
};
var instances = {};
main.editor = function(obj, id, before, ready) {
var opt = $.extend(true, {}, def);
before(opt);
if (instances[id]) {
instances[id].destroy();
$('#' + id).removeAttr('id');
}
return instances[id] = createEditor(obj, id, opt, ready);
};
function createEditor(obj, id, opt, ready) {
obj.attr('id', id);
var editor = UE.getEditor(id, opt);
editor.ready(function() {
ready(editor);
});
return editor;
}
}(jQuery, main));
(2) add.blade.phpファイルにエディタ関連のファイルを導入します具体的なコードは以下のとおりです。
<script src="{
{asset('admin')}}/common/editor/ueditor1.4.3.3/ueditor.config.js"></script>
<script src="{
{asset('admin')}}/common/editor/ueditor1.4.3.3/ueditor.all.min.js"></script>
<script src="{
{asset('admin')}}/common/editor/main.editor.js"></script>
5. コンテンツ一覧の表示
(1) Contentコントローラーにindex()メソッドを記述する具体的なコードは以下の通りです。
public function index($id = 0)
{
$data = Category::orderBy('sort', 'asc')->get()->toArray();
$cate = new CategoryController();
$category = $cate->getTreeListCheckLeaf($data);
$content = Content::get();
if ($id) {
$content = Content::where('cid', $id)->get();
}
return view('admin.content.index', ['category' => $category, 'content' => $content, 'cid' => $id]);
}
(2) コンテンツを表示する場合、コンテンツに対応する列を表示する必要があるため、Content モデルに関連付けモデルを追加します。具体的なコードは次のとおりです。
public function category()
{
return $this->belongsTo('App\Category', 'cid', 'id');
}
(3) resource\views\admin\content\index.blade.phpファイルを作成します。具体的なコードは次のとおりです。
@extends('admin/layouts/admin')
@section('title', '内容列表')
@section('main')
<div class="main-title"><h2>内容管理</h2></div>
<div class="main-section form-inline">
<a href="{
{ url('content/add') }}" class="btn btn-success">+ 新增</a>
<!-- 此处编写分类下拉菜单 -->
<select class="j-select form-control" style="min-width:120px;margin-left:8px">
<option value="{
{ url('content', ['id' => 0]) }}">所有分类</option>
@foreach($category as $v)
@if($v['level'])
<option value="{
{ url('content', ['d' => $v['id']]) }}" data-id="{
{$v['id']}}">
<small class="text-muted">--</small> {
{$v['name']}}
</option>
@else
<option value="{
{ url('content', ['id' => $v['id']]) }}" data-id="{
{$v['id']}}">
{
{$v['name']}}
</option>
@endif
@endforeach
</select>
</div>
<div class="main-section">
<form method="post" action="{
{ url('category/sort')}}" class="j-form">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th width="75">序号</th><th>分类</th><th>图片</th><th>标题</th>
<th>状态</th><th>创建时间</th><th width="100">操作</th>
</tr>
</thead>
<tbody>
@foreach($content as $v)
<!-- 此处编写内容列表代码 -->
<tr class="j-pid-{
{ $v->pid }}" @if($v->level)style="display:none"@endif>
<td>{
{ $v->id }}</td>
<td>{
{ $v->category->name}}</td>
<td><img @if($v->image) src="/static/upload/{
{ $v->image}}" @else src="{
{asset('admin')}}/img/noimg.png" @endif width="50" height="50"></td>
<td>{
{ $v->title }}</td>
<td>@if($v->status==1) 默认 @else 推荐 @endif</td>
<td>{
{ $v->created_at }}</td>
<td><a href="{
{ url('content/edit', ['id' => $v->id ]) }}" style="margin-right:5px;">编辑</a>
<a href="{
{ url('content/delete', ['id' => $v->id ]) }}" class="j-del text-danger">删除</a>
</td>
</tr>
@endforeach
@if(empty($content))
<tr><td colspan="7" class="text-center">还没有添加内容</td></tr>
@endif
</tbody>
</table>
{
{csrf_field()}}
</form>
</div>
<script>
main.menuActive('content');
$('.j-select').change(function() {
location.href = $(this).val();
});
$('option[data-id=' + {
{$cid}} + ']').attr('selected', true);
$('.j-del').click(function() {
if (confirm('您确定要删除此项?')) {
var data = { _token: '{
{ csrf_token() }}' };
main.ajaxPost({url:$(this).attr('href'), data: data}, function(){
location.reload();
});
}
return false;
});
</script>
@endsection
(4)コンテンツ一覧ページのルートをroutes\web.phpファイルに追加します。具体的なコードは以下のとおりです。
Route::get('{id?}', 'ContentController@index');
6. コンテンツの編集
(1) コンテンツ一覧ページの「編集」ボタンにリンクを追加します 具体的なコードは以下の通りです。
<a href="{
{ url('content/edit', ['id' => $v->id ]) }}" style="margin-right:5px;">编辑</a>
(2) Contentコントローラーにedit()メソッドを追加します。具体的なコードは次のとおりです。
public function edit(Request $request)
{
$id = $request->id;
$data = Category::orderBy('sort', 'asc')->get()->toArray();
$cate = new CategoryController();
$category = $cate->getTreeListCheckLeaf($data);
$content = Content::find($id);
return view('admin.content.edit', ['category' => $category, 'content' => $content]);
}
(3)コンテンツ一覧ページのルートをroutes\web.phpファイルに追加します 具体的なコードは以下のとおりです。
Route::get('edit/{id}', 'ContentController@edit');
7. コンテンツの削除
(1) コンテンツ一覧ページの「削除」ボタンにリンクを追加します 具体的なコードは以下の通りです。
<a href="{
{ url('content/delete', ['id' => $v->id ]) }}" class="j-del text-danger">删除</a>
(2)コンテンツを削除するためのルートをroutes\web.phpファイルに追加します。具体的なコードは次のとおりです。
Route::post('delete/{id}', 'ContentController@delete');
(3) Contentコントローラーにdelete()メソッドを追加します。具体的なコードは次のとおりです。
public function delete($id)
{
if (!$content = Content::find($id)) {
return response()->json(['code' => 0, 'msg' => '删除失败,记录不存在。' ]);
}
$content->delete();
return response()->json(['code' => 1, 'msg' => '删除成功' ]);
}
5. 広告枠管理
1.広告スロットテーブルを作成する
(1) 広告スロットテーブルに対応するマイグレーションファイルを作成後、マイグレーションファイルのup()メソッドにテーブル構造情報を追加する具体的なコードは以下のとおりです。
public function up()
{
Schema::create('adv', function (Blueprint $table) {
$table->increments('id')->comment('主键');
$table->string('name', 32)->comment('广告位名称');
$table->timestamps();
});
}
(2) 広告枠テーブルに対応するモデルファイルを作成します 具体的なコードは以下の通りです。
php artisan make:model Adv
(3) 上記のコマンドを実行すると、 app\Adv.phpファイルが自動的に作成されます。具体的なコードは次のとおりです。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Adv extends Model
{
protected $table = "adv";
public $fillable = ['name'];
}
2. 広告スペースを追加する
(1) Advコントローラーを作成します。具体的なコードは次のとおりです。
php artisan make:controller Admin\AdvController
(2)コントローラにadd()メソッドを追加して広告スロットを追加する機能を実装し、save ()メソッドを追加して追加した広告スロットを保存します 具体的なコードは次のとおりです。
public function add($id = 0){
$data = [];
if($id > 0){
$data = Adv::find($id);
}
return view('admin.adv.add', ['data' => $data]);
}
public function save(Request $request){
$data = $request->all();
$this->validate($request,[
'name'=>'required'
],[
'name.require'=>'名称不能为空'
]);
if(isset($data['id'])){
$id = $data['id'];
unset($data['id']);
unset($data['_token']);
$res = Adv::where('id',$id)->update($data);
$type = $res ? "message" : "tip";
$message = $res ? "修改成功" : "修改失败";
return redirect('adv')->with($type, $message);
}
$re = Adv::create($data);
if($re){
return redirect('adv')->with('message','添加成功');
}else{
return redirect('adv/add')->with('tip','添加失败');
}
}
(3) Adv 名前空間をコントローラに導入します。具体的なコードは次のとおりです。
use App\Adv;
(4) routes\web.phpに広告スペース管理用のルーティンググループを追加します。具体的なコードは次のとおりです。
//广告
Route::prefix('adv')->namespace('Admin')->middleware(['Admin'])->group(function () {
Route::get('add/{id?}', 'AdvController@add');
Route::post('save', 'AdvController@save');
});
3. 広告スロット一覧の表示・編集・削除
(1) admin.blade.phpを修正し、広告枠のメニュー項目へのリンクを追加します 具体的なコードは以下の通りです。
<a href="{
{url('adv')}}" data-name="adv">
<i class="fa fa-list fa-fw"></i>广告位</a>
(2) Routes\web.phpに広告スロットリストのルートを追加します。具体的なコードは次のとおりです。
Route::get('', 'AdvController@index');
route::post('delete/{id}','AdvController@delete');
(3) Adv コントローラに、index()メソッドとdelete()メソッドを記述します。具体的なコードは次のとおりです。
public function index(){
$adv = Adv::all();
return view('admin.adv.index', ['adv' => $adv]);
}
public function delete($id){
if (!$content = Adv::find($id)) {
return response()->json(['code' => 0, 'msg' => '删除失败,记录不存在。' ]);
}
if(Advcontent::where('advid', '=', $id)->exists()){
return response()->json(['code' => 0, 'msg' => '该广告位下有广告记录,请先删除广告内容。' ]);
}
$content->delete();
return response()->json(['code' => 1, 'msg' => '删除成功' ]);
}
(4) Index.blade.phpファイルを作成します。具体的なコードは次のとおりです。
@extends('admin/layouts/admin')
@section('title', '广告位列表')
@section('main')
<div class="main-title"><h2>广告位管理</h2></div>
<div class="main-section form-inline">
<a href="{
{ url('adv/add') }}" class="btn btn-success">+ 新增</a>
</div>
<div class="main-section">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th width="75">序号</th><th>广告位名称</th><th width="100">操作</th>
</tr>
</thead>
<tbody>
<!-- 广告位列表-->
@foreach($adv as $v)
<tr class="j-pid-{
{ $v['pid'] }}">
<td><input type="text" value="{
{$v->id}}" class="form-control j-sort" maxlength="5" style="height:25px;font-size:12px;padding:0 5px;"></td>
<td>{
{$v->name}}</td>
<td>
<a href="{
{ url('adv/add', ['id' => $v->id]) }}" style="margin-right:5px;">编辑</a>
<a href="{
{ url('adv/delete', ['id' => $v->id]) }}" class="j-del text-danger">删除</a>
</td>
</tr>
@endforeach
@if(empty($adv))
<tr><td colspan="4" class="text-center">还没有添加广告位</td></tr>
@endif
</tbody>
</table>
</div>
<script>
main.menuActive('adv');
$('.j-del').click(function() {
if (confirm('您确定要删除此项?')) {
var data = { _token: '{
{ csrf_token() }}' };
main.ajaxPost({url:$(this).attr('href'), data: data}, function(){
location.reload();
});
}
return false;
});
</script>
@endsection
(5) ブラウザでアクセスすると、次のような効果が得られます。
(6) ブラウザからアクセスし、「削除」ボタンをクリックして広告枠を削除し、広告枠が正常に削除されたか確認してください。
6. 広告コンテンツの管理
1. 広告コンテンツテーブルを作成する
(1) 広告コンテンツテーブルの移行ファイルを作成し、移行ファイルのup()メソッドにテーブル構造情報を追加します具体的なコードは以下の通りです。
public function up()
{
Schema::create('adcontent', function (Blueprint $table) {
$table->increments('id')->comment('主键');
$table->integer('advid')->comment('广告位id');
$table->integer('path')->comment('图片路径');
$table->timestamps();
});
}
(2) 以下の内容表に対応するモデルファイルを作成します 具体的なコードは以下の通りです。
php artisan make:model Advcontent
(3) 上記コマンドを実行すると、 app\Advcontent.phpファイルが自動的に作成され、そのファイル内に次のコードが記述されます。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Advcontent extends Model
{
protected $table = "adcontent";
public $fillable = ['advid','path'];
}
2.広告の追加、表示、編集、削除
(1) Advcontentコントローラーを作成します。具体的なコードは次のとおりです。
php artisan make:controller Admin\AdvcontentController
(2)コントローラにadd()メソッドを追加して広告追加機能を実装し、save ()メソッドを追加して広告コンテンツを保存し、upload()メソッドを追加してアップロードした広告画像を保存し、index( delete()メソッドを追加すると、具体的なコードは次のとおりです。
public function add($id = 0){
$data = [];
if($id > 0){
$data = Advcontent::find($id);
if($data['path']){
$data['path'] = explode("|", $data['path']);
}else{
$data['path'] = [];
}
}
$position = Adv::all();
return view('admin.advcontent.add', ['data' => $data, 'position' => $position]);
}
public function save(Request $request){
$data = $request->all();
$path = '';
foreach($data['path'] as $v){
$path .= $v . "|";
}
$data['path'] = substr($path,0,-1);
if(isset($data['id'])){
$id = $data['id'];
unset($data['id']);
unset($data['_token']);
$res = Advcontent::where('id',$id)->update($data);
$type = $res ? "message" : "tip";
$message = $res ? "修改成功" : "修改失败";
return redirect('advcontent')->with($type, $message);
}
$re = Advcontent::create($data);
if($re){
return redirect('advcontent')->with('message','添加成功');
}else{
return redirect('advcontent/add')->with('tip','添加失败');
}
}
public function upload(Request $request){
if ($request->hasFile('image')) {
$image = $request->file('image');
if ($image->isValid()) {
$name = md5(microtime(true)) . '.' . $image->extension();
$image->move('static/upload', $name);
$path = '/static/upload/' . $name;
$returndata = array(
'filename' => $name,
'path' => $path
);
$result = [
'code' => 1,
'msg' => '上传成功',
'time' => time(),
'data' => $returndata,
];
return response()->json($result);
}
return $image->getErrorMessage();
}
return '文件上传失败';
}
public function index(){
$adv = Advcontent::all();
foreach($adv as $v){
if($v['path']){
$v['path'] = explode("|", $v['path']);
}else{
$v['path'] = [];
}
}
return view('admin.advcontent.index', ['adv' => $adv]);
}
public function delete($id){
if (!$content = Advcontent::find($id)) {
return response()->json(['code' => 0, 'msg' => '删除失败,记录不存在。' ]);
}
$content->delete();
return response()->json(['code' => 1, 'msg' => '删除成功' ]);
}
(3) コントローラに広告スペースの名前空間を導入する 具体的なコードは以下の通りです。
use App\Advcontent;
use App\Adv;
(4) resource\views\admin\advcontent\add.blade.phpビュー ファイルを作成します。具体的なコードは次のとおりです。
@extends('admin/layouts/admin')
@section('title', '添加广告')
@section('main')
<div class="main-title"><h2><div class="main-title"><h2>@if(!empty($data))编辑@else添加@endif广告</h2></div>
<div class="main-section">
<div style="width:543px">
<form method="post" action="{
{ url('/advcontent/save') }}">
<div class="form-group row">
<label class="col-sm-3 col-form-label">选择广告位</label>
<div class="col-sm-9">
<!-- 广告位列表 -->
<select name="advid" class="form-control" style="width:200px;">
@foreach ($position as $v)
<option value="{
{ $v->id }}" @if(isset($data->advposid) && $data->advposid == $v->id) selected @endif>
{
{ $v->name }}
</option>
@endforeach
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">上传图片</label>
<div class="col-sm-9">
<input type="file" id="file1" name="path" value="上传图片">
</div>
<div class="col-sm-9 offset-sm-3">
<div class="upload-img-box" id="uploadImg">
@if(isset($data->path))
<div class="upload-pre-item" style="max-height:100%;">
@foreach ($data->path as $val)
<img src="/static/upload/{
{$val}}"
style="width:100px;height:100px"/>
<input type="hidden" name="path[]" value="{
{$val}}"
class="icon_banner"/>
@endforeach
</div>
@endif
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-9">
{
{csrf_field()}}
@if(isset($data['id'])) <input type="hidden" name="id" value="{
{$data->id}}"> @endif
<button type="submit" class="btn btn-primary mr-2">提交表单</button>
<a href="{
{ url('advcontent') }}" class="btn btn-secondary">返回列表</a>
</div>
</div>
</form>
</div>
</div>
<link href="{
{asset('admin')}}/common/uploader/uploadifive.css" rel="stylesheet" />
<script src="{
{asset('admin')}}/common/uploader/jquery.uploadifive.js"></script>
<script>
main.menuActive('advcontent');
$(function(){
$('#file1').uploadifive({
'auto' : true,
'fileObjName' : 'image',
'fileType' : 'image',
'buttonText' : '上传图片',
'formData' : { '_token' : "{
{ csrf_token() }}" },
'method' : 'post',
'queueID' : 'uploadImg',
'removeCompleted' : true,
'uploadScript' : '{
{ url('advcontent/upload')}}',
'onUploadComplete' : uploadPicture_icon
});
});
function uploadPicture_icon(file, data) {
var obj = $.parseJSON(data);
var src = '';
if (obj.code) {
filename = obj.data.filename;
path = obj.data.path;
if ($('.upload-pre-item').length > 0) {
$('.upload-pre-item').append(
'<img src="' + path + '" style="width:100px;height:100px"/> <input type="hidden" name="path[]" value="'+filename+'" class="icon_banner"/>'
);
} else {
$('.upload-img-box').append(
'<div class="upload-pre-item" style="max-height:100%;"><img src="' + path + '" style="width:100px;height:100px"/> <input type="hidden" name="path[]" value="'+filename+'" class="icon_banner"/></div>'
);
}
} else {
alert(data.info);
}
}
</script>
@endsection
(5) Index.phpファイルを作成します。具体的なコードは次のとおりです。
@extends('admin/layouts/admin')
@section('title', '广告内容管理')
@section('main')
<div class="main-title"><h2>广告内容管理</h2></div>
<div class="main-section form-inline">
<a href="{
{ url('advcontent/add') }}" class="btn btn-success">+ 新增</a>
</div>
<div class="main-section">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th width="75">序号</th><th>广告位名称</th><th>广告图片</th><th width="100">操作</th>
</tr>
</thead>
<tbody>
<!-- 广告位列表 -->
@foreach($adv as $v)
<tr class="j-pid-{
{ $v['pid'] }}">
<td><input type="text" value="{
{$v->id}}" class="form-control j-sort" maxlength="5" style="height:25px;font-size:12px;padding:0 5px;"></td>
<td>{
{$v->position->name}}</td>
<td>
@foreach($v->path as $val)
<img src="/static/upload/{
{$val}}" style="height:40px;width: 50px">
@endforeach
</td>
<td><a href="{
{ url('advcontent/add', ['id' => $v->id]) }}" style="margin-right:5px;">编辑</a>
<a href="{
{ url('advcontent/delete', ['id' => $v->id]) }}" class="j-del text-danger">删除</a>
</td>
</tr>
@endforeach
@if(empty($adv))
<tr><td colspan="4" class="text-center">还没有添加广告内容</td></tr>
@endif
</tbody>
</table>
</div>
<script>
main.menuActive('advcontent');
$('.j-del').click(function() {
if (confirm('您确定要删除此项?')) {
var data = { _token: '{
{ csrf_token() }}' };
main.ajaxPost({url:$(this).attr('href'), data: data}, function(){
location.reload();
});
}
return false;
});
</script>
@endsection
(6) Routes\web.phpに広告スペース管理用のルーティンググループを追加します。具体的なコードは次のとおりです。
//广告列表
Route::prefix('advcontent')->namespace('Admin')->middleware(['Admin'])->group(function () {
Route::get('add/{id?}', 'AdvcontentController@add');
Route::post('save', 'AdvcontentController@save');
Route::post('upload','AdvcontentController@upload');
Route::get('', 'AdvcontentController@index');
route::post('delete/{id}','AdvcontentController@delete');
});
(7) app\Advcontent.phpを修正し、関連付けモデルを設定し、広告枠情報を取得する 具体的なコードは以下の通りです。
public function position()
{
return $this->belongsTo('App\Adv', 'advid', 'id');
}
(8) Adv コントローラーに Advcontent 名前空間を導入します。具体的なコードは次のとおりです。
use App\Content;
(9) ブラウザからアクセスすることで、広告コンテンツの表示、編集、削除が可能です。
結論
要約すると、Laravel フレームワークは、コンテンツ管理システムのバックエンド機能を実装するために使用されます。プロジェクトの表示画像は次のとおりです。
表紙
1. ページレイアウト
(1) resource\viewsディレクトリにパブリック ファイルの保存に使用するパブリック ディレクトリを作成し、このディレクトリに静的ファイルの保存に使用するstatic.blade.phpを作成します。具体的なコードは次のとおりです。
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{
{asset('home')}}/common/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="{
{asset('home')}}/common/font-awesome-4.2.0/css/font-awesome.min.css">
<link rel="stylesheet" href="{
{asset('home')}}/css/main.css">
<script src="{
{asset('home')}}/common/jquery/1.12.4/jquery.min.js"></script>
<script src="{
{asset('home')}}/common/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
(2) header.blade.phpファイルを作成します。具体的なコードは次のとおりです。
<div class="header">
<header>
<div class="container">
<a href="{
{url("/")}}" style="color:#000000">
<div class="header-logo"><span>内容</span>管理系统</div>
</a>
<ul class="header-right">
@if(session()->has('users.name'))
<li>
<a href="#" class="j-layout-pwd">
<i class="fa fa-user fa-fw"></i>{
{ session()->get('users.name') }}
</a>
</li>
<li><a href="{
{ url('logout') }}"><i class="fa fa-power-off fa-fw"></i>退出</a></li>
@else
<li><a href="#" data-toggle="modal" data-target="#loginModal">登录</a></li>
<li><a href="#" data-toggle="modal" data-target="#registerModal">注册</a></li>
@endif
</ul>
</div>
</header>
<!-- 栏目列表 -->
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container">
<div></div>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-expanded="false" aria-controls="navbarSupportedContent" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="/">首页</a>
</li>
@foreach($category as $v)
@if(isset($v['sub']))
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{
{$v['name']}}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
@foreach($v['sub'] as $val)
<a class="dropdown-item" href="{
{url('lists', ['id' => $val['id']] )}}">{
{$val['name']}}</a>
@endforeach
</div>
</li>
@else
<li class="nav-item">
<a class="nav-link" href="{
{url('lists', ['id' => $v['id']] )}}">{
{$v['name']}}</a>
</li>
@endif
@endforeach
</ul>
</div>
</div>
</nav>
</div>
<!-- 登录表单 --->
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">登录</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="username">用户名</label>
<input type="text" name="name" class="form-control" id="username">
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" name="password" class="form-control" id="password">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-primary" id="login">登录
</button>
</div>
</div>
</div>
</div>
<!-- 注册表单 --->
<div class="modal fade" id="registerModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">注册</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="username1">用户名</label>
<input type="text" name="name" class="form-control" id="username1">
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" name="email" class="form-control" id="email">
</div>
<div class="form-group">
<label for="password1">密码</label>
<input type="password" name="password" class="form-control" id="password1">
</div>
<div class="form-group">
<label for="confirm">确认密码</label>
<input type="password" class="form-control" id="confirm">
</div>
</div>
<div class="modal-footer">
{
{csrf_field()}}
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-primary" id="register">立即注册</button>
</div>
</div>
</div>
</div>
<script>
$("#login").bind("click",function(){
var data = {
'name' : $("#username").val(),
'password' : $("#password").val(),
'_token' : "{
{ csrf_token() }}"
};
$.post("{
{ url('login') }}", data, function(result){
if (result.status == 1) {
alert(result.msg);
window.location.reload();
} else {
alert(result.msg);
return;
}
});
});
$("#register").bind("click",function(){
var data = {
'name' : $("#username1").val(),
'email' : $("#email").val(),
'password' : $("#password1").val(),
' password_confirmation' : $("#confirm").val(),
'_token' : "{
{ csrf_token() }}"
};
$.post("{
{ url('register') }}", data, function(result){
if (result.status == 1) {
alert(result.msg);
$('#registerModal').modal('hide');
location.reload();
} else {
alert(result.msg);
return;
}
});
});
</script>
(3)ページ下部のコンテンツを保存するために使用されるresource\views\common\footer.blade.phpファイルを作成します。具体的なコードは次のとおりです。
<div class="footer">
<div class="container">内容管理系统</div>
</div>
2. トップページ、コラムナビゲーション、カルーセル画像、広告スペース、コラムコンテンツ表示
(1) ホームページビューを作成し、resource\viewsディレクトリにindex.blade.phpを作成します。具体的なコードは次のとおりです。
<!DOCTYPE html>
<html>
<head>
@include('public/static')
<title>首页</title>
</head>
<body>
@include('public/header')
<div class="main">
<div class="container">
<div class="row mt-4">
<!-- 轮播图 -->
<div class="col-md-6 main-carousel">
<div id="carouselExampleCaptions" class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
@foreach($recommend as $k=>$con)
<div class="carousel-item @if($k==0) active @endif">
<img src="/static/upload/{
{$con->image}}" class="d-block w-100">
<a href="{
{url('detail', ['id'=> $con->id])}}">
<div class="carousel-caption d-none d-md-block">
<h5>{
{$con->title}}</h5>
<p></p>
</div>
</a>
</div>
@endforeach
</div>
<a class="carousel-control-prev" href="#carouselExampleCaptions" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselExampleCaptions" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div>
<!-- 广告位 -->
<div class="col-md-6">
<div class="row main-imgbox">
@foreach($adv as $adval)
<div class="col-md-6">
<a href="#"><img class="img-fluid" src="/static/upload/{
{$adval}}"></a>
</div>
@endforeach
</div>
</div>
</div>
<div class="row">
<div class="col-md-9">
<div class="row">
<!-- 栏目内容 -->
@foreach($list as $value)
<div class="col-md-6 mb-4">
<div class="card main-card">
<div class="card-header">
<h2>{
{$value->name}}</h2>
<span class="float-right">
<a href="{
{ url('lists', ['id' => $value->id ])}}">[ 查看更多 ]</a>
</span>
</div>
@foreach($value->content as $val)
<div class="card-body">
<div class="main-card-pic">
<a href="{
{url('detail', ['id'=> $val->id])}}">
<img class="img-fluid" src="/static/upload/{
{$val->image}}">
<span><i class="fa fa-search"></i></span>
</a>
</div>
<div class="main-card-info">
<span><i class="fa fa-calendar"></i>
{
{ date('Y-m-d', strtotime($val->created_at)) }}</span>
</div>
<h3><a href="{
{url('detail', ['id'=> $val->id])}}">{
{$val->title}}</a></h3>
<div class="main-card-desc">{!!str_limit($val->content , 100)!!}</div>
</div>
@endforeach
</div>
</div>
@endforeach
</div>
</div>
<div class="col-md-3">
<!-- 侧边栏 -->
@include('public/sidebar')
</div>
</div>
</div>
</div>
@include('public/footer')
</body>
</html>
(2) Index コントローラーを作成します。具体的なコードは次のとおりです。
php artisan make:controller IndexController
(3) コントローラーにメソッドを追加します。具体的なコードは次のとおりです。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Category;
use App\Content;
use App\Adv;
use App\Like;
use App\Comment;
use Illuminate\Support\Facades\DB;
class IndexController extends Controller
{
public function index()
{
$this->navBar();
$this->hotContent();
$recommend = Content::where('status', '2')->get(); // 新增代码
$advcontent = [];
$advlist = Adv::where('name', 'imgbox')->get();
foreach ($advlist as $key => $value) {
foreach ($value->content as $k => $v) {
$advcontent= explode('|', $v->path);
}
}
$list = Category::orderBy('id', 'desc')->get()->take(4);
return view('index', ['recommend' => $recommend, 'adv' => $advcontent, 'list' => $list]);
}
protected function navBar(){
$data = Category::orderBy('sort', 'asc')->get()->toArray();
$category = $sub = [];
foreach($data as $k=>$v){
if ($v['pid'] != 0) {
$sub[$v['id']] = $v;
}
}
foreach($data as $key=>$val){
if ($val['pid'] == 0) {
$category[$key] = $val;
}
foreach($sub as $subv) {
if ($subv['pid'] == $val['id']) {
$category[$key]['sub'][] = $subv;
}
}
}
return view()->share('category', $category);
}
public function lists($id)
{
if(!$id){
return redirect('/')->with('tip','缺少参数');
}
$this->navBar();
$this->hotContent();
$content = Content::where('cid', $id)->paginate(4);
return view('lists', ['id' => $id, 'content' => $content]);
}
public function detail($id)
{
if(!$id){
return redirect('/')->with('tip','缺少参数');
}
$this->navBar();
$this->hotContent();
$content = Content::find($id);
$count = Like::where('cid', $id)->get()->count();
$comments = Comment::where('cid', $id)->get();
return view('detail', ['id' => $content->id, 'cid' => $content->cid,
'content' => $content, 'count' => $count, 'comments' => $comments]);
}
public function like($id)
{
if(!$id){
return response()->json(['status'=>'2','msg'=>'缺少参数']);
}
@session_start();
$data = array(
'uid' => session()->get('users.id'),
'cid' => $id
);
$re = Like::create($data);
if($re){
$count = Like::where('cid', $id)->get()->count();
return response()->json(['status'=>'1', 'msg'=>'点赞成功', 'count'=>$count]);
}else{
return response()->json(['status'=>'2', 'msg'=>'点赞失败']);
}
}
public function comment(Request $request)
{
$cid = $request->input('cid');
$content = $request->input('content');
$uid = session()->get('users.id');
if(!$content){
return response()->json(['status'=>'2', 'msg'=>'缺少参数']);
}
$data = array(
'uid' => $uid,
'cid' => $cid,
'content' => $content,
);
$re = Comment::create($data);
if ($re) {
$theComment = Comment::where('cid', $cid)->where('uid', $uid)->orderBy('id','desc')->first();
$theComment->created_time = date('Y-m-d', strtotime($theComment->created_at));
$count = Comment::where('cid', $cid)->get()->count();
$theComment->count = $count;
$theComment->user = $theComment->user->name;
return response()->json(['status' => '1', 'msg' => '评论成功',
'data' => $theComment]);
} else {
return response()->json(['status' => '2', 'msg' => '评论失败']);
}
}
protected function hotContent(){
$hotContent = Like::select('cid',DB::raw('count(*) as num'))->orderBy('num', 'desc')->groupBy('cid')->get()->take(2);
return view()->share('hotContent', $hotContent);
}
}
(4) Routes\web.phpファイルにルーティング ルールを追加します。具体的なコードは次のとおりです。
// 首页
Route::get('/', 'IndexController@index');
Route::get('/lists/{id}', 'IndexController@lists');
Route::get('/detail/{id}', 'IndexController@detail');
Route::get('/like/{id}', 'IndexController@like');
Route::get('/comment', 'IndexController@comment');
Route::post('/register', 'UserController@register');
Route::post('/login', 'UserController@login');
Route::get('/logout', 'UserController@logout');
(5) app\Adv.phpを修正し、関連付けモデルを設定します 具体的なコードは次のとおりです。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Adv extends Model
{
protected $table = "adv";
public $fillable = ['name'];
public function content()
{
return $this->hasMany('App\Advcontent', 'advid', 'id');
}
}
(6) app\Category.phpを変更し、関連付けモデルを設定します。具体的なコードは次のとおりです。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = "category";
public $fillable = ['pid', 'name', 'sort'];
public function content()
{
return $this->hasMany('App\Content', 'cid', 'id')->orderBy('id', 'desc')->limit(1);
}
}
(7) ブラウザからアクセスし、完全に表示されるか確認します。
フロントデスクのユーザー管理
ユーザー登録、ユーザーログイン、ユーザーログアウト
(1) header.blade.phpビューに登録フォームとログインフォームを追加します具体的なコードは以下の通りです。
<div class="header">
<header>
<div class="container">
<a href="{
{url("/")}}" style="color:#000000">
<div class="header-logo"><span>内容</span>管理系统</div>
</a>
<ul class="header-right">
@if(session()->has('users.name'))
<li>
<a href="#" class="j-layout-pwd">
<i class="fa fa-user fa-fw"></i>{
{ session()->get('users.name') }}
</a>
</li>
<li><a href="{
{ url('logout') }}"><i class="fa fa-power-off fa-fw"></i>退出</a></li>
@else
<li><a href="#" data-toggle="modal" data-target="#loginModal">登录</a></li>
<li><a href="#" data-toggle="modal" data-target="#registerModal">注册</a></li>
@endif
</ul>
</div>
</header>
<!-- 栏目列表 -->
<nav class="navbar navbar-expand-md navbar-dark">
<div class="container">
<div></div>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-expanded="false" aria-controls="navbarSupportedContent" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="/">首页</a>
</li>
@foreach($category as $v)
@if(isset($v['sub']))
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{
{$v['name']}}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
@foreach($v['sub'] as $val)
<a class="dropdown-item" href="{
{url('lists', ['id' => $val['id']] )}}">{
{$val['name']}}</a>
@endforeach
</div>
</li>
@else
<li class="nav-item">
<a class="nav-link" href="{
{url('lists', ['id' => $v['id']] )}}">{
{$v['name']}}</a>
</li>
@endif
@endforeach
</ul>
</div>
</div>
</nav>
</div>
<!-- 登录表单 --->
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">登录</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="username">用户名</label>
<input type="text" name="name" class="form-control" id="username">
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" name="password" class="form-control" id="password">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-primary" id="login">登录
</button>
</div>
</div>
</div>
</div>
<!-- 注册表单 --->
<div class="modal fade" id="registerModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">注册</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="username1">用户名</label>
<input type="text" name="name" class="form-control" id="username1">
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" name="email" class="form-control" id="email">
</div>
<div class="form-group">
<label for="password1">密码</label>
<input type="password" name="password" class="form-control" id="password1">
</div>
<div class="form-group">
<label for="confirm">确认密码</label>
<input type="password" class="form-control" id="confirm">
</div>
</div>
<div class="modal-footer">
{
{csrf_field()}}
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-primary" id="register">立即注册</button>
</div>
</div>
</div>
</div>
<script>
$("#login").bind("click",function(){
var data = {
'name' : $("#username").val(),
'password' : $("#password").val(),
'_token' : "{
{ csrf_token() }}"
};
$.post("{
{ url('login') }}", data, function(result){
if (result.status == 1) {
alert(result.msg);
window.location.reload();
} else {
alert(result.msg);
return;
}
});
});
$("#register").bind("click",function(){
var data = {
'name' : $("#username1").val(),
'email' : $("#email").val(),
'password' : $("#password1").val(),
' password_confirmation' : $("#confirm").val(),
'_token' : "{
{ csrf_token() }}"
};
$.post("{
{ url('register') }}", data, function(result){
if (result.status == 1) {
alert(result.msg);
$('#registerModal').modal('hide');
location.reload();
} else {
alert(result.msg);
return;
}
});
});
</script>
(2)ユーザーコントローラーを作成します。具体的なコードは次のとおりです。
php artisan make:controller UserController
(3) ユーザー コントローラーにメソッドを追加します。具体的なコードは次のとおりです。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\User;
use Illuminate\Support\Facades\Session;
class UserController extends Controller
{
public function register(Request $request)
{
$rule = [
'name' => 'required|unique:users',
'email' => 'required|email',
'password' => 'required|min:6',
'password_confirmation' => 'required'
];
$message = [
'name.require' => '用户名不能为空',
'name.unique' => '用户名不能重复',
'email.require' => '邮箱不能为空',
'email.email' => '邮箱格式不符合规范',
'password.require' => '密码不能为空',
'password.min' => '密码最少为6位',
'password.confirmed' => '密码和确认密码不一致'
];
$validator = Validator::make($request->all(), $rule, $message);
if ($validator->fails()) {
foreach ($validator->getMessageBag()->toArray() as $v) {
$msg = $v[0];
}
return response()->json(['status' => '2', 'msg' => $msg]);
}
$re = User::create($request->all());
if ($re) {
Session::put('users', ['id' => $re->id, 'name' => $re->name]); // 注册成功后保存登录状态
return response()->json(['status' => '1', 'msg' => '注册成功']);
} else {
return response()->json(['status' => '2', 'msg' => '注册失败']);
}
}
public function login(Request $request)
{
$rule = [
'name' => 'required|bail',
'password' => 'required|min:6'
];
$message = [
'name.required' => '用户名不能为空',
'password.required' => '密码不能为空',
'password.min' => '密码最少为6位'
];
$validator = Validator::make($request->all(), $rule, $message);
if ($validator->fails()) {
foreach ($validator->getMessageBag()->toArray() as $v) {
$msg = $v[0];
}
return response()->json(['status'=>'2', 'msg'=>$msg]);
}
$name = $request->get('name');
$password = $request->get('password');
$theUser = User::where('name', $name)->first();
if ($theUser) {
if ($password == $theUser->password) {
Session::put('users', ['id' => $theUser->id,'name' => $name]);
return response()->json(['status' => '1', 'msg' => '登录成功']);
} else {
return response()->json(['status' => '2', 'msg' => '密码错误']);
}
} else {
return response()->json(['status' => '2', 'msg' => '用户不存在']);
}
}
public function logout()
{
if (request()->session()->has('users')) {
request()->session()->pull('users', session('users'));
}
return redirect('/');
}
}
コンテンツ一覧ページ
1. コンテンツ一覧
(1)リソース\viewsディレクトリにlists.blade.phpを作成します。具体的なコードは次のとおりです。
<!DOCTYPE html>
<html>
<head>
@include('public/static')
<title>列表页</title>
</head>
<body>
@include('public/header')
<div class="main">
<div class="main-crumb">
<div class="container">
<!-- 面包屑导航 -->
<nav aria-label="breadcrumb">
{!! Breadcrumbs::render('category', $id); !!}
</nav>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-9">
<div class="row">
<!-- 内容列表 -->
@foreach($content as $con)
<div class="col-md-6 mb-4">
<div class="card main-card">
<div class="main-card-pic">
<a href="{
{ url('detail', ['id' => $con->id ])}}">
<img class="img-fluid" src="@if($con->image)/static/upload/{
{$con->image}}@else {
{asset('admin')}}/img/noimg.png @endif">
<span><i class="fa fa-search"></i></span>
</a>
</div>
<div class="card-body">
<div class="main-card-info">
<span><i class="fa fa-calendar"></i>{
{ date('Y-m-d', strtotime($con->created_at)) }}</span>
<span><i class="fa fa-comments"></i>{
{$con->comments->count()}}</span>
</div>
<h3><a href="{
{ url('detail', ['id' => $con->id ])}}">{
{$con->title}}</a></h3>
<div class="main-card-desc">{
{str_limit(strip_tags($con->content),100)}}</div>
</div>
<a href="{
{ url('detail', ['id' => $con->id ])}}" class="main-card-btn">阅读更多</a>
</div>
</div>
@endforeach
</div>
{
{ $content->links()}}
</div>
<div class="col-md-3">
<!-- 侧边栏 -->
@include('public/sidebar')
</div>
</div>
</div>
</div>
@include('public/footer')
</body>
</html>
(2) ブラウザからコンテンツ一覧ページにアクセスし、効果を確認します。
2. ブレッドクラムナビゲーション
1.インストール
(1) Composerを使用して、 laravel-breadcrumbsライブラリをロードします。具体的なコードは次のとおりです。
composer require davejamesmiller/laravel-breadcrumbs
(2) config\app.phpファイルでこのサービスプロバイダを Laravel に登録します。具体的なコードは次のとおりです。
'providers' => [
...(原有代码)
DaveJamesMiller\Breadcrumbs\BreadcrumbsServiceProvider::class,
],
(3)使いやすいように、 config\app.phpファイルにエイリアスを登録します。具体的なコードは次のとおりです。
'aliases' => [
...(原有代码)
'Breadcrumbs' => DaveJamesMiller\Breadcrumbs\Facades\Breadcrumbs::class,
],
2.ナビゲーションを設定する
(1) ホームページにナビゲーション リンクを設定し、routes\breadcrumbs.phpファイルを作成します。具体的なコードは次のとおりです。
<?php
use DaveJamesMiller\Breadcrumbs\Facades\Breadcrumbs;
use App\Category;
use App\Content;
Breadcrumbs::register('home', function($breadcrumbs){
$breadcrumbs->push('首页', route('home'));
});
Breadcrumbs::register('category', function ($breadcrumbs, $id) {
$category = Category::find($id);
$breadcrumbs->parent('home');
$breadcrumbs->push($category->name, route('category', $id));
});
Breadcrumbs::register('detail', function ($breadcrumbs, $posts) {
$content = Content::find($posts['id']);
$breadcrumbs->parent('category', $posts['cid']);
$breadcrumbs->push($content->title, route('detail', $posts['id']));
});
(2) ブラウザからコンテンツ一覧ページにアクセスすると、パンくずリストのナビゲーション効果が表示されます。
コンテンツ表示
1. コンテンツ詳細ページ
resource\viewsディレクトリにdetail.blade.phpを作成します。具体的なコードは次のとおりです。
<!DOCTYPE html>
<html>
<head>
@include('public/static')
<title>详细页</title>
</head>
<body>
@include('public/header')
<div class="main">
<div class="main-crumb">
<div class="container">
<!-- 面包屑导航 -->
<nav aria-label="breadcrumb">
{!! Breadcrumbs::render('detail', ['id'=>$id,'cid'=>$cid]); !!}
</nav>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-9">
<!-- 内容区域 -->
<article class="main-article">
<header>
<h1>{
{$content->title}}</h1>
<div>发表于{
{ date('Y-m-d', strtotime($content->create_time)) }}</div>
</header>
<div class="main-article-content">
<p><img class="img-fluid" src="/static/upload/{
{$content->image}}"></p>
<p>{!! $content->content !!}</p>
</div>
<!-- 点赞模块 -->
@if(session()->has('users'))
<div class="main-article-like">
<span>
<i class="fa fa-thumbs-up" aria-hidden="true">{
{$count}}</i>
</span>
</div>
@endif
</article>
<div class="main-comment">
<!-- 评论列表 -->
@if(!$comments->isEmpty())
<div class="main-comment-header">
<span id="count">{
{$comments->count()}}</span> 条评论
</div>
@foreach($comments as $val)
<div class="main-comment-item">
<div class="main-comment-name">{
{$val->user->name}}</div>
<div class="main-comment-date">
{
{ date('Y-m-d', strtotime($val->created_at)) }}</div>
<div class="main-comment-content">{
{$val->content}}</div>
</div>
@endforeach
@endif
</div>
<!-- 发表评论模块 -->
<div class="main-reply">
@if(session()->has('users'))
<div class="main-reply-header">发表评论</div>
<div class="main-reply-title">评论内容</div>
<div><textarea name="content" rows="8" id="content"></textarea></div>
<div>
<input type="hidden" id='c_id' value="{
{$id}}">
<input type="button" value="提交评论" id="publish">
</div>
@endif
</div>
</div>
<div class="col-md-3">
<!-- 侧边栏 -->
@include('public/sidebar')
</div>
</div>
</div>
</div>
@include('public/footer')
</body>
<script>
$(document).ready(function() {
$(".fa-thumbs-up").bind("click", function () {
$.get("{
{ url('like', $id) }}", {}, function (result) {
var count = result.count;
$(".fa-thumbs-up").html();
$(".fa-thumbs-up").html(count);
});
});
$('#publish').bind("click",function(){
var data = {
'cid' : $("#c_id").val(),
'content' : $("#content").val()
};
$.get("{
{ url('comment') }}",data, function(result){
var data = result.data;
var user = data.user;
var html = '<div class="main-comment-item">';
html += '<div class="main-comment-name">' + user['name'] + '</div>';
html += '<div class="main-comment-date">';
html += data['created_time'];
html += '</div>';
html += '<div class="main-comment-content">';
html += data['content'] + '</div>';
html += '</div>';
$(".main-comment").append(html);
$("#count").html();
$("#count").html(data['count']);
});
});
});
</script>
</html>