不做伸手党,分享快乐,Laravel5 入门小项目详细教程

来源:https://phphub.org/topics/804

仅献给刚入门的同学,又找不到好的项目练习的同学,社区里面的大牛请绕道 “^_^”

这里感谢论坛,社区那些无私的大牛们

github地址

可能会有改动,可以关注github

StuGradeWithLaravel5

一个简易的学生成绩管理,查询系统,仅供新手学习参考。QQ:215672398 有什么好的想法,或是建议,不明白的都可以来找我讨论。

下面,我们开始,我也是从一个新手(伸手党)走过来的,这次自己写一个教程给刚学习laravel,或者感到困惑的同学,我会尽量详细每一个重要的步骤。感谢社区,论坛前仆后继的前辈,本教程仅献给像我一样热爱laravel的新手参考学习,谢谢!

  • 系统的功能简介
  • 需要的一些组件,库
  • 一些源文件位置说明
  • 运行环境
  • 安装
  • 详细学习过程

功能

  • 学生端
    • 登录完善修改个人信息,查看成绩
    • 修改密码,验证邮件(待完善)
  • 管理员
    • 登录能查看所有学生信息,包括新增学生,删除学生
    • 能更新学生成绩,没有修改学生信息的权限
    • 下载学生信息Excel,学生成绩Excel
    • 上传学生名单Excel,更新数据库(待完善)
    • 上传学生成绩Excel,更新数据库(待完善)

组件链接和文档

  • Laravel 5.0(这个大家都懂,最基本的)
  • Bootstrap 3.3.4
  • gulp,前端自动化工具,(官网被墙了),推荐laravel文档中的安装gulp. link
  • TableSorter 表格排序插件
  • Laravel Excel Excel的导出导入组件

说明

  • TableSorter ----- resources/js/jquery.tablesorter.min.js
  • Bootstarp ----- 需要引入bootstarp的font文件(不引入会出现一些问题,见下文)
  • resources/js/main.js ----- 系统功能完善js脚本(意思就是自己写的)
  • resources/css/main/css ----- 同上

环境需要

PHP >= 5.5.0
MCrypt PHP Extension
SQL server(for example MySQL)

安装步骤

  • 1: 获取源代码
  • 2: Composer管理依赖关系的工具
  • 3: 配置文件
  • 4: 安装gulp工具和Laravel Elixir
  • 5: 转移数据表,填充数据
  • 6: 开始

1: 下载源代码

https://github.com/qq215672398/StuGradeWithLaravel5/archive/master.zip

2: Composer Install

安装Composer 来管理PHP依赖关系的工具,详细安装参考官网,不过大部分同学这步肯定Ok了。

安装好之后,在项目根目录下执行命令:

composer update

3: 修改配置文件

将.env.example重命名为.env文件中并且修改

DB_HOST=localhost
DB_DATABASE=dbname
DB_USERNAME=username
DB_PASSWORD=password

在config/app.php 下修改:

'url' => 'http://localhost/项目文件夹名/public',
'timezone' => 'PRC',

4: 安装gulp和Elixir (安装阶段可以跳过)

执行以下命令:

npm install

5: 得到表,和默认用户数据

依次执行一下命令:

php artisan migrate
php artisan db:seed(要是失败的话,可能需要 composer dump-autoload)

现在执行:

php artisan serve

打开浏览器,输入http://localhost:8000/就可以看到首页呢!


6: 登录开始

数据库有3个默认用户(当然你可以在数据库里删除,自己添加,这里只是测试) 这里的相关信息可以在 /database/seeds/UserTableSeeder.php 找到

管理员:

username: 1234567890
pasword: root

同学:

username: 1210311232
pasword: 1210311232

username: 1210311233
pasword: 1210311233

开始学习(至少要阅读过一遍官方文档,熟悉基本用法)

首先,讲讲的我自己的学习思路,拿到一个应用的源代码,我会先看路由,每一个路由对应着什么功能,其中有什么细节,怎么去实现,这是我最希望能学到的。在编码的时候,我个人是路由-功能去完成的,可能这是新手的方法,有大牛能指导一下能更好。所以,我从逐步从路由开始说起,一步一步的编码过程。

你可能会遇到的问题

  • Class App\Http\Controllers\Admin\ExcelController does not exist
  • Class 'App\Http\Controllers\Admin\User' not found
  • 类似的问题

你需要:

  • 检查文件名,看是否一致
  • 检查命名空间
  • 检查类名
  • 检查是否在类外 use User 或者 use Auth 等等

建议,开两个编辑器,一个用来看前面安装好的源代码,一个用来进行下面的学习,学习过程中,请随便参考官方文档,另外,我的教程里面可能不小心会有些小错误,请耐心查看,有些你已经明白了,但是实际操作出现错误无法解决的,你可以按照我下面说的循序,复制原项目的文件,也可以找我交流,谢谢!

安装好laravel,配置好环境之后,我执行了

php artisan fresh

只留下了laravel自带的主页路由 Route::get('/', 'WelcomeController@index');

然后导入我们的数据表,填充默认数据进行测试。

打开 /database/migrations/._create_users_table.php,修改up方法

public function up()
{
    Schema::create('users', function(Blueprint $table)
    {
        $table->integer('id')->unique()->unsigned();  #学号,唯一,取正数
        $table->string('name');                       #姓名
        $table->string('password');                   #密码
        $table->string('phone')->default('');  #手机 默认为空(不是可以为空,值为'')
        $table->string('sex')->default('');    #性别 同上
        $table->string('email')->default('');  #邮箱 同上
        $table->string('pro_class')->default(''); #班级 同上
        $table->boolean('is_admin')->default(0);  #是否为管理员 默认为学生
        $table->rememberToken();
        $table->timestamps();
    });
}

这里为什么这么写,首先我觉的老师新增学生时候是没有填写他信息的权限的,只能生成学号,姓名。密码,所以其他都默认为空,需要学生登录后自己去填写。

然后在User.php中修改$fillable数组

protected $fillable = ['name', 'email', 'is_admin', 'password', 'sex', 'phone', 'pro_class'];

什么意思,我也不是很清楚,这样写了储存user到数据库,输出user属性就不会出问题,至于具体为啥,怪我没有深入,下面继续。

我们先先数据库里面填充一些数据,以方便我们下面测试.

在/database/seeds下新建 UserTableSeeder.php

delete();

        User::create([
        'id' => 1210311232,
        'name' => '李锐',
        'password' => Hash::make('1210311232')
        ]);

        User::create([
        'id' => 1210311233,
        'name' => '陈曦',
        'password' => Hash::make('1210311233')
        ]);

        User::create([
        'id' => 1234567890,
        'name' => '管理员',
        'password' => Hash::make('root'),
        'is_admin' => 1
        ]);

    }

}

然后讲DatabaseSeeder.php中 $this->call('UserTableSeeder')前面的注释取消.

执行

composer dump-autoload
php artisan db:seed

数据就被填充到数据库里面了

下面开始有任何不确定的都可以去看源代码对比

找到WelcomeController.php,可以看到两段代码:

public function __construct()
{
    $this->middleware('guest');
}

public function index()
{
    return view('welcome');
}

上面的构造函数,有什么作用?里面的中间件guest,在Kernel.php 中的routeMiddleware数组里面有注册,它的功能在App\Http\Middleware\RedirectIfAuthenticated.php里面可以看到。

可以理解为登录之后要是还想访问主页,就会自动跳转,跳转细节后面在说。

index方法返回的是welcome页面.

这时候,我们先构建一个基础页面模版,因为后面的每个页面都是需要继承它的.创建 master.blade.php文件.




    
    
    
     @yield('title') 
    


    

    

    @yield('content')





@include('flash')先注释掉,这里暂时还不需要.(记得注释,你可以先删除,最好)

创建我们的welcome.blade.php,随便修饰一下(前端不行 :) )

@extends('master')   {{-- 继承master模版 --}}

@section('title')   {{-- 对应@yield('title') --}}
    学生成绩管理系统
@stop

@section('content')   {{-- 对应@yield('content') --}}
    

{{ Inspiring::quote() }}

同学们登录后先修改相关资料

查询分数,有疑问咨询管理员

点击登录

@stop

好了,首页已经完成了,来看这三个路由

Route::get('login', [
'middleware' => 'guest', 'as' => 'login', 'uses' => 'loginController@loginGet']);
Route::post('login', [
'middleware' => 'guest', 'uses' => 'loginController@loginPost']);
Route::get('logout', [
'middleware' => 'auth', 'as' => 'logout', 'uses' => 'loginController@logout']);

完成登录登出的功能, 在路由中设置中间件, 过滤一些非法请求,关于中间件,参考官方文档

guest 只允许游客(没登陆的情况下)访问get路由login和post路由login,要是已经登录,就会跳转到相应页面,注意关键词响应。我们登录用户有两种,学生,和管理员,当他们在登录的情况下要想访问这两个路由,肯定会做出不同的响应。即,学生,跳转到学生主页,管理员,跳转到管理员主页.现在来看看RedirectIfAuthenticated.php

public function handle($request, Closure $next)
{
    if ($this->auth->check())     
    {
        if (!Auth::user()->is_admin) {
            return new RedirectResponse(url('/stu/home'));  
        } else {
            return new RedirectResponse(url('/admin'));   
        }

    }

    return $next($request);
}

auth 只有登录用户才能访问(这个不知道怎么表达,我就不误人子弟),看下源码 Authenticate.php

public function handle($request, Closure $next)
{
    if ($this->auth->guest())    
    {
        if ($request->ajax())           
        {
            return response('Unauthorized.', 401);
        }
        else       
        {
            return redirect()->guest('login');
        }
    }

    return $next($request);
}

也就是说只有登录了才能登出,就是这个意思。

说完了中间件,创建控制器。loginControlle.php

php artisan make:controller loginController --plain

在里面写上以下内容:

/**
 * 返回login视图,登录页面
 */
public function loginGet()
{
    return view('login');
}

/**
 * 登录响应
 */
public function loginPost(Request $request)
{
    $this->validate($request, User::rules());
    $id = $request->get('id');
    $password = $request->get('password');
    if (Auth::attempt(['id' => $id, 'password' => $password], $request->get('remember'))) {
        if (!Auth::user()->is_admin) {
            return Redirect::route('stu_home');
        } else {
            return Redirect::action('Admin\AdminController@index');
        }

    } else {
        return Redirect::route('login')
            ->withInput()
            ->withErrors('学号或者密码不正确,请重试!');
    }
}

/**
 * 用户登出
 */
public function logout()
{
    if (Auth::check()) {
        Auth::logout();
    }
    return Redirect::route('login');
}

可以使用validate验证用户输入,在laravel5中使用validate非常方便,注意第二个参数,User::rules(), 这是在User模型中一个静态方法,接着在User.php中加入静态方法。

protected static function rules()
{
    return [
        'id' => 'required|digits:10',   
        'password' => 'required'        
        ];
}

验证用户登录使用了Auth::attempt(),这是laravel中自带的验证方法,非常好用,如果验证通过,接着判断是否是管理员,然后分别跳转到不同的url.

return Redirect::route('stu_home') -- 对应路由名为stu_home的路由
return Redirect::action('Admin\AdminController@index') -- 对于这个index方法

登出使用的是Auth::logout().

这时候点击登录,laravel会告诉你view(login)不存在,创建login.blade.php文件

@extends('master')

@section('title')
    欢迎登录
@stop

@section('content')
登录
@include('errors.list') {!! Form::open(['url' => '/login', 'class' => 'form-horizontal', 'role' => 'form']) !!}
{!! Form::label('id', '学号', ['class' => 'col-md-4 control-label']) !!}
{!! Form::text('id', old('id'), ['class' => 'form-control', 'required']) !!}
{!! Form::label('password', '密码', ['class' => 'col-md-4 control-label']) !!}
{!! Form::password('password', ['class' => 'form-control', 'required']) !!}
{!! Form::submit('Login', ['class' => 'btn btn-primary form-control']) !!}
{!! Form::close() !!}
@stop

这时候要是点击登录,还是会报错,因为在laravel5中Illuminate/Html组件被移了,我们可以在composer.json的required数组中加入

"illuminate/html": "5.0"

在config/app.php中的provider数组中添加

'Illuminate\Html\HtmlServiceProvider',

aliases数组中添加

'Html'      => 'Illuminate\Html\HtmlFacade',
'Form'      => 'Illuminate\Html\FormFacade',

接着执行:

composer update

等待安装完成之后,就能看到我们的登录页面了

这时候你随便输入学号密码,页面会刷新一下,不会跳转,错误已经被存在了Session中,现在把他显示出来. 在login.blade.php中有这样一行

@include('errors.list')

我们创建errors/list.blade.php

@if (count($errors) > 0)
    
    @foreach ($errors->all() as $error)
  • {{ $error }}
  • @endforeach
@endif

这时候要是输入不符合前面的规则,你会看到提示英文提示信息,要是输入密码或者帐号错误,你会看到 学号或者密码不正确,请重试, 这是loginPost中返回的自定义错误信息.

现在,我们有两个问题需要解决,第一,英文提示信息,对我们中国用户可能不太友好,你可以更换.第二,错误提示会一直留着页面.下面,我们一一解决.

关于表单验证的自定义错误信息,可以查看官方链接, 现在我们找到/resources/lang/en/validation.php,在custom数组中添加:

'id' => [
        'required' => '学号不能为空',
        "digits"   => "学号必须是 10 位数字",
        "unique"   => "该同学已经存在",
    ],
'password' => [
        'required' => '密码不能为空',
    ],

重新随便输入学号密码,你就可以看到中文提示信息了

关于提示信息的隐藏,这里有两种简单的解决方案,参考bootstrap中的警告框,修改/errors/list.blade.php

@if (count($errors) > 0)
    
@endif

这个时候错误信息的右边就会有一个关闭按钮,点击就可隐藏错误信息

还有一种使用jQuery的一个小方法.在master.blade.php引入脚本main.js

...




...

在public文件夹下新建文件 js/main.js

$(function () {
    $('div.alert').delay(2500).slideUp(300);
});

这是时候再产生错误信息,就会自动隐藏了

下面就是登录后的操作了,学生端的功能比较少,我们先来完成.

选择一组学号密码登录,你会看到url跳转到 http://localhost:8000/stu/home, 在前面loginController中loginPost方法中可以看到关于学生成功登录后的跳转,这时候去创建我们的路由.

Route::get('stu/home', [
    'as' => 'stu_home', 'uses' => 'Stu\StudentController@home']);
Route::get('stu/edit', [
    'as' => 'stu_edit', 'uses' => 'Stu\StudentController@edit']);
Route::post('stu/update', [
    'as' => 'stu_update', 'uses' => 'Stu\StudentController@update']);

接着创建我们的控制器(注意路径, 在Stu下):

php artisan make:controller Stu/StudentController --plain

里面包括以上三个方法,我们一个一个来解决

/**
 * 只允许登录用户访问
 */
public function __construct()
{
    $this->middleware('auth');
}

/**
 * 返回学生主页
 */
public function home()
{
    return view('stu.home');
}

接下来去创建我们的视图文件stu/home.blade.php

@extends('master')

@section('title')
    欢迎 -- {{ Auth::user()->name }}
@stop

@section('content')

学号: {{ Auth::user()->id }}
姓名: {{ Auth::user()->name }}
性别: {{ Auth::user()->sex }}
手机: {{ Auth::user()->phone }}
班级: {{ Auth::user()->pro_class }}
邮箱: {{ Auth::user()->email }}
@stop

刷新,你能看到自己的home页, 留意上面的代码,有一片空白,用来后面完成查分功能

接着我们完成修改资料功能,在StudentController.php中添加:

/**
 * 返回修改资料页面
 */
public function edit()
{
    return view('stu.edit');
}

创建 stu/edit.blade.php

@extends('master')

@section('title')
    修改个人信息
@stop

@section('content')
@include('errors.list')
{!! Form::open(['url' => '/stu/update', 'class' => 'form-horizontal', 'role' => 'form']) !!}
{!! Form::label('id', '学号: ', ['class' => 'col-md-2 control-label']) !!}
{!! Form::text('id', Auth::user()->id, ['class' => 'form-control', 'readonly'])!!}
{!! Form::label('name', '姓名: ', ['class' => 'col-md-2 control-label']) !!}
{!! Form::text('name', Auth::user()->name, ['class' => 'form-control', 'readonly'])!!}
{!! Form::label('sex', '性别: ', ['class' => 'col-md-2 control-label']) !!}
{!! Form::select('sex', ['男' => '男', '女' => '女'], Auth::user()->sex, ['class' => 'form-control']) !!}
{!! Form::label('phone', '手机: ', ['class' => 'col-md-2 control-label']) !!}
{!! Form::text('phone', Auth::user()->phone, ['class' => 'form-control']) !!}
{!! Form::label('pro_class', '班级: ', ['class' => 'col-md-2 control-label']) !!}
{!! Form::text('pro_class', Auth::user()->pro_class, ['class' => 'form-control']) !!}
{!! Form::label('email', '邮箱: ', ['class' => 'col-md-2 control-label']) !!}
{!! Form::email('email', Auth::user()->email, ['class' => 'form-control']) !!}
{!! Form::submit('确认修改', ['class' => 'btn btn-success form-control']) !!}
{!! Form::close() !!}
@stop

点击修改资料:

我们可以看到表单提交到 localhost:8000/stu/update,我们的post路由update对应方法如下:

public function update(Request $request)
{
    $this->validate($request, [
        'phone' => 'required|digits:11',
        'pro_class' => 'required',
        'email' => 'required|email'
        ]);

    Auth::user()->update($request->all());

    return Redirect::route('stu_home');
}

这个时候,我们也可以选择使用自己的Request,首先我们使用如下命令建立Request:

php artisan make:request StudentMesRequest

修改我们的StudentMesRequest.php:

/**
* Determine if the user is authorized to make this request.
* 这里先设置为true,表示有权限去使用这个Request,不然请求会被拒绝
* @return bool
*/
public function authorize()
{
    return true;
}

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules()
{
    return [
        'phone' => 'required|digits:11',
        'pro_class' => 'required',
        'email' => 'required|email'
    ];
}

然后修改update方法(别忘了在类外引入StudentMesRequest, 即use App\Http\Requests\StudentMesRequest;):

public function update(StudentMesRequest $request)
{
    Auth::user()->update($request->all());

    return Redirect::route('stu_home');
}

以上两种方法都可以完成验证功能(看自己喜好吧,使用后者代码比较简洁,模块化,前面的登录也可以这样来写,你可以跳转回去试试),如果现在乱填表单,我们依旧可以看到错误提示,而且错误提示会自动消失,因为我们在edit.blade.php中添加了 @include('errors.list')

如果填写规范,提交后返回到stu_home页.这个时候我们可以添加一个成功信息,来增强用户体验

在 Auth::user()->update($request->all()) 添加:

session()->flash('message', '个人信息修改成功');

接着我们去让session信息读取出来,在master.blade.php中添加

@include('flash')

前面有提到,相信你知道放在哪儿比较合适.接着创建我们的flash.blade.php

@if (Session::has('message'))
    
{{ session('message') }}
@endif

再次修改资料,成功后会看到提示信息,而且信息也会自动隐藏.

做了这么多,我还是提醒大家,随时随地查阅官方文档,或者对比我的代码,以免留下隐患

最后,我们来完成学生端的查分功能,首先,我们知道,users表里面是没有成绩字段的,所以我们这个时候需要建立第二个模型,Grade模型. let's do that

php artisan make:model Grade

找到Grade.php,添加:

protected $table = 'grades';

protected $fillable = [
    'math',     #高数
    'english',  #英语
    'c',        #c语言
    'sport',    #体育
    'think',    #思修
    'soft',     #软件工程
];

protected static function rules(){
    return [
        'math' => 'digits_between:0,2',
        'english' => 'digits_between:0,2',
        'c' => 'digits_between:01,2',
        'sport' => 'digits_between:1,2',
        'think' => 'digits_between:1,2',
        'soft' => 'digits_between:1,2',
        ];
}

有了前面User模型的基础,相信不难理解以上代码.接着在 /database/migrations/ 下找到 .._create_grades_table.php,修改文件:

public function up()
{
    Schema::create('grades', function(Blueprint $table)
    {
        $table->increments('id');
        $table->integer('user_id')->unsigned()->unique()->index();
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->integer('math')->nullable();
        $table->integer('english')->nullable();
        $table->integer('c')->nullable();
        $table->integer('sport')->nullable();
        $table->integer('think')->nullable();
        $table->integer('soft')->nullable();
        $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('grades');
}

这里有一点要说的,关于外键,我很多时候创建外键都不是一次成功的,我感觉我每次在这里都会出点问题,所以,大家要是创建成功,一定要有耐心,后面在phpMyAdmin里查看数据表会有惊喜,留给你去发现(我就不多说了),总之,这里不能跳过,对照源码,查阅资料,花点时间.

因为我们现在还没有完成后台的模块,所以不能进入后台上传分数,这里我们选择在seed里面填充数据 ,打开UserTableSeeder.php,偷个懒,就不再创建一个seeder了,加入:

Grade::create([
    'user_id' => 1210311232,
    'math'    => 99,
    'english'    => 80,
    'c'    => 96,
    'sport'    => 95,
    'think'    => 99,
    'soft'    => 98,
    ]);

Grade::create([
    'user_id' => 1210311233,
    ]);

因为成绩是能为空的,所以像下面那样创建也是可以的,接着运行:

php artisan db:seed

这里我们需要在User.php里面建立和Grade一对一的模型关系,官方文档链接,link,想要更深入的理解Laravel Eloquent,请参考岁寒的三篇关于Eloquent的博文.

在User.php中添加:

public function grade()
{
    return $this->hasOne('App\Grade');
}

接着在试图里面去得到成绩,在前面所说的那个完成查询成绩的地方加上:

@include('stu.grade')

接着创建stu/grade.blade.php:

那么,这个$grade从何而来,我们回到StudentController,修改home方法:

$grade = Auth::user()->grade;

return view('stu.home', compact('grade'));

然后需要在我们的main.js里面添加这样一行:

$('[data-toggle="popover"]').popover();

这里可以参考bootstrap文档,弹出框

接着刷新我们的浏览器,点击查询分数,可以看到

下面,我们开始后台的模块

还是老样子,我们先退出当先登录用户,回到登录页面,登录管理员帐号

1234567890
root

看看我们的url跳转到 http://localhost:8000/admin

接着来添加我们的后台路由:

#查看成绩排名
Route::get('admin/grade', [
    'as' => 'grade_list', 'uses' => 'Admin\GradeController@index']);
#上传分数
Route::post('admin/upload_grade', [
    'as' => 'upload_grade', 'uses' => 'Admin\AdminController@upload_grade']);
#资源控制器,学生的增删改查
Route::resource('admin', 'Admin\AdminController');

首先来看看我们的资源控制器, 官方文档, 运行(注意路径):

php artisan make:controller Admin/AdminController

我们当前的url对应着index方法,进入AdminController.php:

public function __construct()
{
    $this->middleware('admin');
}

这是什么意思?先查看Kernel.php,我们向 $routeMiddleware 数组里面添加:

'admin' => 'App\Http\Middleware\isAdmin'

代表注册中间件 admin,接着运行如下命令新建isAdmin.php:

php artisan make:middleware isAdmin

进入到isAdmin.php:

public function handle($request, Closure $next)
{
    if (!Auth::check()) {
        return Redirect::route('login');
    } else {
        if (!Auth::user()->is_admin) {
            session()->flash('message_warning', '您不是管理员!无法进入相关区域');
            return Redirect::route('stu_home');
        }
    }
    return $next($request);
}

过滤没有登录的用户,重定向到登录页,过滤普通登录用户,重定向到学生登录首页,而且,返回一条警告信息,提示那是管理员区域.打开我们的flash.blade.php,增加:

@if (Session::has('message_warning'))
    
{{ session('message_warning') }}
@endif

现在来测试我们的中间件工作如何

  • 在url中输入http://localhost:8000/login,会发现无法跳转,现在你可以回过头看看之前路由中添加的中间件, 点击跳转

  • 在url中输入http://localhost:8000/logout,退出登录回到登录页

  • 输入一组学生帐号,然后在url中输入http://localhost:8000/admin,你会看到页面刷新,并且弹出警告信息.

下面,继续查看AdminController中的index方法:

public function index()
{
    $result = User::where('is_admin', 0);
    $count = $result->count();
    $users = $result->paginate(10);
    return view('Admin.index', compact('users', 'count'));
}

$count,是学生数量,先传入,后面要使用,$users,这里我不知道怎么说,就是可以实现分页功能,参考官方文档,Link,代表我后面的视图文件中需要分页,每页显示10个user信息.接下来新建我们的视图文件 Admin/index.blade.php

@extends('master')

@section('title')
    管理员
@stop

@section('content')
    
@include('errors.list')

学生信息表

@if (count($users)) @foreach ($users as $user) read1 @endforeach @else

没有学生名单,请管理员添加

@endif
学号 姓名 性别 手机 班级 邮箱 操作
{{ $user->id }} {{ $user->name }} {{ $user->sex }} {{ $user->phone }} {{ $user->pro_class }} {{ $user->email }}
render(); ?>
read2
@stop

注意两个 read 区域,后面用来填充其他功能,这个时候登录管理员帐号密码,你应该能看到下面的效果

render(); ?> 输出分页列表,现在我们只有两组数据,所以暂时看不到,待会完成添加学生的功能之后再来测试这个效果.我们先做删除功能,可以看到删除按钮提交到 http://localhost:8000/admin/1210311232, form表单里面有个值为DELETE的隐藏输入域,告诉路由,这个请求对应这资源控制器的 destory 方法,我们来完成

public function destroy(User $user)
{
    $name = $user->name;
    $user->delete();
    session()->flash('message', $name."同学已经被移除");
    return Redirect::back();
}

看到参数 User $user, 为什么不是id,你一定会这样想.我们打开 App/Http/Provider/RouteServiceProvider.php,修改boot方法,这里我们可以查阅官方文档,路由模型绑定

public function boot(Router $router)
{
    parent::boot($router);

    $router->bind('admin', function($id){
        return \App\User::findOrFail($id);
    });

    //$router->model('admin', 'App/User');
}

上面两种写法都行,看个人喜好.上面写法比较直观,相信你现在也知道了destory方法参数为什么可以那样写了,你可以在destory中dd($user);在浏览器中点击删除,确定删除,就可以看到页面中输出对应的user信息,下面,去掉destory中dd($user),刷新,可以看到对应同学消失,并且出现提示信息,还是贴个图片,我觉得这样能反馈一些信息.

可能看到上面图片中的右侧栏吧,我们先把它完成,然后一一实现它的功能.将index视图文件中的read2替换成:

@include('Admin.right_bar')

接着新建Admin/right_bar.blade.php:

学生列表 -- 返回学生列表,即 http://localhost:8000/admin

添加学生 -- 添加学生页面,即 http://localhost:8000/admin/create

成绩排名 -- 查看成绩列表,即 http://localhost:8000/admin/grade

下载名单 -- 下载学生信息Excel

导出成绩 -- 下载学生成绩Excel

添加学生,对应AdminController中的create方法:

public function create(){
    $result = User::where('is_admin', 0);
    $count = $result->count();
    return view('Admin.create', compact('count'));
}

接着去创建Admin/create.blade.php:

@extends('master')

@section('title')
    添加学生
@stop

@section('content')
    

添加学生


@include('errors.list')
{!! Form::model($user = new \App\User, ['url' => 'admin/', 'class' => 'form-horizontal']) !!}
{!! Form::label('id', '学号: ', ['class' => 'control-label col-md-1']) !!}
{!! Form::text('id', old('id'), ['class' => 'form-control']) !!}
{!! Form::label('name', '姓名: ', ['class' => 'control-label col-md-1']) !!}
{!! Form::text('name', old('name'), ['class' => 'form-control', 'required']) !!}
{!! Form::submit('完成,创建', ['class' => 'btn btn-success form-control']) !!}
{!! Form::close() !!}
@include('Admin.right_bar')
@stop

点击添加学生:

这里我们Form::model(obj, [options]),传入一个新的对象$user, 这里可以查看 /vendor/illuminate/html/FormBuilder.php中的model方法,Form自动帮你填好表单,这里因为是新建,表单为空,后面你就明白了. 接着看我们的url地址, http://localhost:8000/admin,对应控制器中的store方法,

public function store(Request $request)
{
    $this->validate($request, [
        'id' => 'required|digits:10|unique:users',
        ]);
    $user = new User;
    $user->id = $request->id;
    $user->name = $request->name;
    $user->password = Hash::make($user->id);
    $user->save();
    session()->flash('message', $user->name."同学添加成功");
    DB::insert('insert into grades (user_id, math, english, c, sport, think,soft)
        values (?,?,?,?,?,?,?)', [$request->id,null,null,null,null,null,null]);
    return Redirect::to('admin');
}

我解释一下,这里,也就是我的思路,管理员只能添加学生初始化它的学号,姓名,密码(默认为学号),同时在grades表中添加对应的一条记录,至于写法为什么这么不优雅!因为我尝试其他的都不行,你有兴趣可以试试,有好的方法也可以提交给我,创建成功后返回admin并提示信息.

现在我们开始添加学生吧,超过10条就可以了,以便于我们后面的效果测试

接下来完成我们更新成绩功能.

#上传分数
Route::post('admin/upload_grade', [
    'as' => 'upload_grade', 'uses' => 'Admin\AdminController@upload_grade']);

这是一个post路由(响应post http请求), 现在完成更新分数的form表达,讲前面的redd1替换成

@include('Admin.upload_grade')

创建Admin/upload_grade.blade.php:

现在刷新浏览器,点击更新分数

接下来就可以完成分数的上传功能,打开AdminController,添加:

public function upload_grade(Request $request)
{
    $this->validate($request, Grade::rules());
    $grade = Grade::where('user_id', $request->user_id)->first();
    $grade->math = $request->math;
    $grade->english = $request->english;
    $grade->c = $request->c;
    $grade->sport = $request->sport;
    $grade->think = $request->think;
    $grade->soft = $request->soft;
    $grade->save();
    session()->flash('message', '成绩提交成功');
    return Redirect::back();
}

这里有个地方有点问题,分数应该是0-100,参考前面Grade.php中的静态方法

digits_between:1,2   #代表是数字1位到2位,也就是0-99

本来应该使用 min:0|max:100 但是这里实际会把分数当作字符串处理,而不是数字,这样写,会判断成0-100长度的字符串,算是一个小bug吧,就先这样,我还没见过我们学校有考试100的人,哈哈!

下面,我们给每个人上传一下分数.你现在能随便登录一个学生帐号密码,能查询到自己的成绩

对了,别忘了在validation.php里面设置你的提示信息,这里就不再赘述.

接着,我们来完成成绩排名,看我们的路由,先新建Grade控制器:

php artisan make:controller Admin/GradeController --plain

两个方法:

public function __construct()
{
    $this->middleware('admin');
}

public function index()
{
    $result = User::where('is_admin', 0);
    $users = $result->get();
    $count = $result->count();
    return view('Admin.list', compact('count', 'users'));
}

$users是我们的学生信息资源,传递到Admin/list.blade.php视图.

@extends('master')

@section('title')
    学生成绩列表
@stop

@section('content')
    

学生成绩表

@foreach ($users as $user) @endforeach
学号 姓名 高数 英语 C语言 体育 思修 软件
{{$user->id}} {{$user->name}} {{$user->grade->math}} {{$user->grade->english}} {{$user->grade->c}} {{$user->grade->sport}} {{$user->grade->think}} {{$user->grade->soft}}
@include('Admin.right_bar')
@stop

在浏览其中点击成绩排名,你能看到所有人的成绩表吧

那么,问题来了,首先,分数太多,不能突出重点(我认为是不及格的分数),第二不能将科目分数进行排序,我们来一个一个解决.

分数的问题,我觉得讲不及格分数显示为红色比较好,js有点基础的同学应该很中意就办到了.

我们先给tr设置一个class属性

...
@foreach ($users as $user)
    
...

打开我们的main.js,添加:

$('.myGrade').each(function(){
    $(this).children().each(function(){
        if ($(this).html() < 60){
            $(this).addClass("notPass");
        }
    });
});

然后新建一个mian.css文件,放在public/css目录下

.notPass{
    color: red;
}

这个时候你再次刷新浏览器,你可以看到这样的效果了(有点夸张,大学挂科人数不多的)

接着完成表单的排序,官网打开速度很慢,可自行百度下载,或者去项目源文件找到 /resource/js/jquery.tablesorter.min.js ,拷贝到public/js/目录下, 在master.blade.php下引入

然后在main.js里面添加这样一行:

$("#sortTable").tablesorter();

回到list视图文件,给table添加一个id 为 sortTable

刷新浏览器,你就能点击表头进行排序了.更多用法你也可以去参考官方文档

现在我们可以使用前端自动化工具来处理我们的css和js脚本文件了

安装node,安装gulp,在根目录下执行:

npm install

如果你实在安装不成功,可以去googel各种安装方法,或者跳过此节,这样只讲述了基础用法, 我们接着继续resources目录下创建css和js文件夹,接着将以下文件复制到:

js/
  bootstrap.min.js
  jquery.min.js
  jquery.tablesorter.min.js
  main.js

css/
  bootstrap.min.js
  main.js

然后打开gulpfile.js,修改:

var elixir = require('laravel-elixir');

elixir(function(mix) {
    mix.styles([
        "bootstrap.min.css",
        "main.css"
        ]);

    mix.scripts([
        "jquery.min.js",
        "bootstrap.min.js",
        "jquery.tablesorter.min.js",
        "main.js"
        ]);
});

接着执行:

gulp

你就可以找到 public/css/all.css 和 public/js/all.js文件了

接着你可以删除master.blade.php里所有引入的css和js脚本,现在只需要引入两个文件:



刷新浏览器,查看各个功能,正常使用(确保public文件夹下引入bootstrap的fonts文件)

最后,我们完成名单表和成绩表的导出功能,这里我们使用laravel Excel

在composer.json require中加入:

"maatwebsite/excel": "~2.0.0"

执行:

composer update

安装成功后在config/app.php中加入

'Maatwebsite\Excel\ExcelServiceProvider',

'Excel'     => 'Maatwebsite\Excel\Facades\Excel',

然后我们先测试一下是否能成功运行,参考官方文档,Laravel Excel,测试各种功能

这里我只是演示一下,新建一个TestController,在route.php中添加

Route::get('/test', 'TestController@index');

在TestController的index方法中添加:

Excel::create('测试', function($excel) {

$excel->sheet('Sheetname', function($sheet) {

    $sheet->fromArray(array(
        array('data1', 'data2'),
        array('data3', 'data4')
    ));

});

})->export('xls');

然后你可以修改right_bar.blade.php中一个超链接地址为 href="/test",接着点击,你会发现浏览器提示下载文件 测试.xls,就是这么简单.

后面的内容可以在github上查看,(哈哈,貌页面布局被我毁了,我不敢发在这里了,:rabbit: )

 本帖已被设为精华帖!
回复数量:  29
  • nidesky  •  2015-05-10 17:50:32  •  #4325  • 

    兄弟真给力:+1:

  • qq215672398  •  2015-05-10 17:55:28  •  #4326  • 

    @nidesky 哈哈,举手之劳

  • Johnhacker  •  2015-05-10 21:02:14  •  #4327  • 

    到现在尼玛 composer还没安装OK 国内镜像还连不上

  • qq215672398  •  2015-05-10 21:14:14  •  #4328  • 

    @Johnhacker 我直连的,之前连不上,直接安装的.exe

    后来手动安装

    就OK了

  • qq215672398  •  2015-05-10 21:16:13  •  #4329  • 

    @Johnhacker 那些包可以去github上下载源代码,感觉不用composer也是可以使用的

  • Qfix  •  2015-05-11 15:46:51  •  #4349  • 

    直接跟到你的脚步走,果断成功了,很不错,学到了。特别是中间件的应用,干的漂亮!!

  • qq215672398  •  2015-05-11 18:52:07  •  #4353  • 

    @Qfix 谢谢

  • caibirdme  •  2015-05-11 22:19:10  •  #4360  • 

    fillable是设置针对这个模型哪些字段可以被批量修改和插入。如果你不加上,你可以一个字段一个字段地修改,但是不能一起改。楼主很用心啊,赞一个建议可以看看laracast上的部分视频,虽然没字幕但语速其实不快,那上面的内容对laravel剖析得非常透彻

  • qq215672398  •  2015-05-11 22:32:12  •  #4361  • 

    @caibirdme 是的,那个刷了好几遍了,就是有些概念性的东西听不懂,不过能体会到是什么意思

  • jmychou  •  2015-05-12 18:31:21  •  #4394  • 

    支持 :thumbsup::thumbsup:

  • fzhui  •  2015-05-12 21:04:35  •  #4395  • 

    谢了,入门正好需要。

  • hvsy  •  2015-05-12 21:04:50  •  #4396  • 

    虽然已经不算新手了,但是还是感觉楼主写的很棒.

  • Yikmings  •  2015-05-13 19:50:09  •  #4417  • 

    真的非常感謝 !

  • MiYogurt  •  2015-05-14 14:33:49  •  #4456  • 

    Nice. Very Good ,正好拿来练练手。

  • zhouyanyan  •  2015-05-14 15:02:59  •  #4461  • 

    很适合新手,多谢了

  • qq215672398  •  2015-05-14 15:38:49  •  #4463  • 

    @zhouyanyan @MiYogurt

    有想法github上更新和修改

  • kslr  •  2015-05-15 17:52:58  •  #4504  • 

    有点基础的同学应该很中意就办到了. => 有点基础的同学应该很容易就办到了.

  • qq215672398  •  2015-05-15 18:01:37  •  #4505  • 

    @kslr 所以是给入门用的啊,熟悉下基本用法

  • 至尊宝  •  2015-05-27 21:56:41  •  #4779  • 

    @qq215672398 问个小问题哈,在配置'url' => 'http://localhost/项目文件夹名/public',时,比如我的'url' => 'http://localhost/laravel/public',但访问'http://localhost/laravel是laravel文件目录,并没有起作用。

  • qq215672398  •  2015-05-28 01:05:15  •  #4781  • 

    @至尊宝 你直接

    php artisan serve
  • hye  •  2015-05-28 10:08:56  •  #4782  • 

    timezone 设为PRC真的没问题么?Asia/Shanghai

  • qq215672398  •  2015-05-28 11:49:04  •  #4785  • 

    @hye ,貌似没什么问题,PRC不就是中国时区吗

  • hye  •  2015-05-28 12:31:45  •  #4789  • 

    还真没注意timezones.others 哈哈

  • hye  •  2015-05-28 12:33:11  •  #4790  • 

    里面有个warning

    Warning

    Please do not use any of the timezones listed here (besides UTC), they only exist for backward compatible reasons.

  • qq215672398  •  2015-05-28 12:58:09  •  #4792  • 

    @hye 这是啥,重来没见过这个警告

  • hye  •  2015-05-28 13:01:31  •  #4793  • 

    @qq215672398 文档里的,你看看那个文档就知道了 http://php.net/manual/en/timezones.others.php

  • king123321123  •  2015-05-30 14:18:05  •  #4832  • 

    更新成绩功能. 这是一个post路由(响应post http请求), 现在完成更新分数的form表达,讲前面的redd1替换成 @include('Admin.upload_grade')

    这里没看懂。。。

  • king123321123  •  2015-05-30 14:21:00  •  #4833  • 

    @king123321123 这一块总是实现不了功能。。是不是代码问题

  • qq215672398  •  2015-05-30 14:37:45  •  #4835  • 

    @king123321123 你去看下源代码,很简单的,就是给每个人插入一个form表,form表中隐藏id到数据库中保存

你可能感兴趣的:(lavarel)