laravel 学习记录

学习目的

  • 熟悉Linux系统
  • 学习MySQL
  • 学习laravel框架
  • 练习vim
  • 练习Markdown
  • 练习git

开发环境

开发过程

功能介绍

  • 用户管理
    – 增加用户
    – 管理员删除用户
    – 查看用户
    – 编辑用户
  • (取消)关注用户
  • 发布微博
  • 查看微博
  • 评论

数据库设计

  • object:基础字段
  • person:人员信息
  • users:用户表,一个人员一个用户
  • Follower: 粉丝表
    用户关系
  • blogbody:发布的博客
  • BlogFollow:关注的博客
  • comment:评论
    博客与评论
创建项目

发目录

$ sudo mkdir /home/xx/www/laravel -p
$ chmod -R 777 laravel
$ cd /home/xx/www/laravel

创建laravel项目

$ composer create-project laravel/laravel blog --prefer-dist "5.6.*"

目录结构

目录说明
app应用程序的业务逻辑代码存放文件夹
app/Console存放自定义 Artisian 命令文件
app/Http/Controllers存放控制器文件
app/Http/Middleware存放「中间件」文件
bootstrap框架启动与自动加载设置相关的文件
composer.json应用依赖的扩展包
composer.lock扩展包列表,确保这个应用的副本使用相同版本的扩展包
config应用程序的配置文件
database数据库操作相关文件(数据库迁移和数据填充)
node_modules存放 NPM 依赖模块
package.json应用所需的 NPM 包配置文件
phpunit.xml测试工具 PHPUnit 的配置文件
public前端控制器和资源相关文件(图片、JavaScript、CSS)
readme.md项目介绍说明文件
resources应用资源
resources/assets未编译的应用资源文件(图片、JavaScript、CSS)
resources/lang多语言文件
resources/views视图文件
routes/api.php用于定义 API 类型的路由
routes/channels.php事件转播注册信息
routes/console.php用于定义 Artisan 命令
routes/web.php用于定义 Web 类型的路由(重点,大部分情况下本书会用到)
server.php使用 PHP 内置服务器时的 URL 重写(类似于 Apache 的 “mod_rewrite” )
storage编译后的视图、基于会话、文件缓存和其它框架生成的文件
storage/app目录可用于存储应用程序使用的任何文件
storage/framework目录被用于保存框架生成的文件及缓存
storage/logs应用程序的日志文件
tests应用测试相关文件
vendorComposer 依赖模块
webpack.mix.jsLaravel 的前端工作流配置文件
yarn.lockYarn 依赖版本锁定文件
.gitignore被 Git 所忽略的文件
.env环境变量配置文件

Bootstrap


Bootstrap 是以 NPM 扩展包的形式集成到 Laravel 项目中的。NPM 是 Node.js(一个基于 Google V8 引擎的 JavaScript 运行环境)的包管理和分发工具。Composer 的一些概念也是从 NPM 中借鉴过来的,因此 NPM 也有个类似 composer.json 文件的 package.json 文件,Laravel 默认会为每个新建的项目自动生成该文件,并会在文件里面默认集成一些较为常用的扩展包。

{
  "private": true,
  "scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },
  "devDependencies": {
    "axios": "^0.16.2",
    "bootstrap-sass": "^3.3.7",
    "cross-env": "^5.0.1",
    "jquery": "^3.1.1",
    "laravel-mix": "^1.0",
    "lodash": "^4.17.4",
    "vue": "^2.1.10"
  }
}

安装

yarn install --no-bin-links

安装完成之后,让我们对 Laravel 默认生成的 app.scss 文件进行编辑,删除此文件里的所有内容,只留下面一行,导入 Bootstrap:resources/assets/sass/app.scss

@import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap";

将 Bootstrap 导入成功之后,我们需要使用以下命令来将 .scss 文件编译为 .css 才能正常使用,编译命令:$ npm run dev。也可以通过下面的命令,在每次检测到 .scss 文件发生更改时,自动将其编译为 .css 文件:

$ npm run watch-poll

所有编译后的资源文件都被存放在 public 文件夹中。
注意:Linux环境下面需要将package.json中的cross-env删除

创建model
$ php artisan make:model Models\Users\Person
  • table 对应数据库中的表
  • fillable 过滤用户提交的字段,只有包含在该属性中的字段才能够被正常更新
  • hidden 对用户密码或其它敏感信息在用户实例通过数组或 JSON 显示时进行隐藏

Eloquent 表命名约定


在该文件中,Eloquent Article 模型默认情况下会使用类的「下划线命名法」与「复数形式名称」来作为数据表的名称生成规则。如:

  • Article 数据模型类对应 articles 表;
  • User 数据模型类对应 users 表;
  • BlogPost 数据模型类对应 blog_posts 表;

路由
routes 目录包含了应用的所有路由定义,Laravel 默认包含了几个路由文件:
web.phpapi.phpconsole.phpchannels.php
web.php 文件包含 RouteServiceProvider 放置在 web 中间件组中的路由,它提供会话状态、CSRF 防护和 cookie 加密。如果你的应用不提供无状态的、RESTful 风格的 API,则所有的路由都应该在 web.php 文件中定义。.
api.php件包含 RouteServiceProvider 放置在 api 中间件组中的路由,它提供了频率限制。这些路由都是无状态的,所以通过这些路由进入应用请求旨在通过令牌进行身份认证,并且不能访问会话状态。
console.php件是定义所有基于控制台命令闭包函数的地方。每个闭包函数都被绑定到一个命令实例并且允许和命令行 IO 方法进行简单的交互。尽管这些文件没有定义 HTTP 路由,但它也将基于控制台的入口点(路由)定义到应用程序中。
channels.php来注册你的应用支持的所有的事件广播渠道的地方。
路由配置
Laravel 遵从 RESTful 架构的设计原则,将数据看做一个资源,由 URI 来指定资源。对资源进行的获取、创建、修改和删除操作,分别对应 HTTP 协议提供的 GET、POST、PATCH 和 DELETE 方法。

Route::resource('users', 'UsersController');

等同于

Route::get('/users', 'UsersController@index')->name('users.index');
Route::get('/users/{user}', 'UsersController@show')->name('users.show');
Route::get('/users/create', 'UsersController@create')->name('users.create');
Route::post('/users', 'UsersController@store')->name('users.store');
Route::get('/users/{user}/edit', 'UsersController@edit')->name('users.edit');
Route::patch('/users/{user}', 'UsersController@update')->name('users.update');
Route::delete('/users/{user}', 'UsersController@destroy')->name('users.destroy');

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

Route::prefix('sp')->group(function () {
    Route::namespace('Api\Select') -> prefix('select') -> group(function (){
        Route::get('edu','SelectController@selectYnEdu');   //学校下拉选择
        Route::get('nation','SelectController@selectNation');   //民族选择器
        Route::get('province','SelectController@provinceSelect');   //省下拉选择器
        Route::get('city/{id}','SelectController@citySelect');   //城市下拉选择器
    });
    ...
Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // // 使用 first 和 second 中间件
    });

    Route::get('user/profile', function () {
        // // 使用 first 和 second 中间件
    });
});

...

prefix 创建前缀;namespace命名空间,app/Http/Controller/Api/Select目录下面的控制器;group为分组。name为别名。middleware为中间件。

$php artisan route:list可以查看所有的路由信息。


控制器
$ php artisan make:controller 命名空间/XXController

默认路径在App\Http\Controllers 目录下面。如果完整的控制器类名为App\Http\Controllers\Photos\AdminController ,你在路由中应当采用如下的形式注册:

Route::get('foo', 'Photos\AdminController@method');

控制器中间件
一种在路由当中:

Route::get('profile', 'UserController@show')->middleware('auth');

另外一种是在控制器的构造方法中:

class UserController extends Controller
{
    /**
     * 实例化一个控制器实例
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');

        $this->middleware('log')->only('index');

        $this->middleware('subscribed')->except('store');
    }
}

视图

视图文件存放于 resources/views 目录下。视图文件也可以嵌套在 resources/views 目录的子目录中。「点」符号可以用来引用嵌套视图。例如,如果你的视图存储在 resources/views/admin/profile.blade.php,则可以这样引用它:

return view('admin.profile', $data);

判断视图文件是否存在的方法:View::exists('emails.customer')


权限系统
  • 必须先登录
    当我们使用 Auth 中间件来验证用户的身份时,如果用户未通过身份验证,则 Auth 中间件会把用户重定向到登录页面。如果用户通过了身份验证,则 Auth 中间件会通过此请求并接着往下执行。Laravel 框架默认为我们内置了一些中间件,例如身份验证、CSRF 保护等。所有的中间件文件都被放在项目的 app/Http/Middleware 文件夹中。
    except 方法来设定 指定动作 不使用 Auth 中间件进行过滤,意为 —— 除了此处指定的动作以外,所有其他动作都必须登录用户才能访问,类似于黑名单的过滤机制。相反的还有 only 白名单方法,将只过滤指定动作。
namespace App\Http\Controllers;
...
class UsersController extends Controller
{
    public function __construct()
    {
        //当前controller中,除了下面的方法,其他的都需要认证后才能执行
        //auth属性针对的是已登录的用户
        //guest属性针对未登录的用户
        $this->middleware('auth', [
            'except' => ['show', 'create', 'store']
        ]);
    }
...
}
  • 只能操作属于自己的信息
    比如能编辑自己的个人信息,但是不能编辑其他人的。如果强制编辑,返回403错误。使用授权策略(Policy)来进行权限验证。
  1. 创建授权策略文件:
$ php artisan make:policy UserPolicy
namespace App\Policies;
use Illuminate\Auth\Access\HandlesAuthorization;
use App\Models\User;
class UserPolicy
{
    use HandlesAuthorization;
    public function update(User $currentUser, User $user)
    {
        return $currentUser->id === $user->id;
    }
    public function destroy(User $currentUser, User $user)
    {
        return $currentUser->is_admin && $currentUser->id !== $user->id;
    }
}
  1. 接下来我们还需要在 AuthServiceProvider 类中对授权策略进行设置。AuthServiceProvider 包含了一个 policies 属性,该属性用于将各种模型对应到管理它们的授权策略上。
# app/Providers/AuthServiceProvider.php
protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
        \App\Models\User::class  => \App\Policies\UserPolicy::class,
    ];
  1. 授权策略定义完成之后,便可以通过在用户控制器中使用 authorize 方法来验证用户授权策略。默认的 App\Http\Controllers\Controller 类包含了 Laravel 的 AuthorizesRequests trait。此 trait 提供了 authorize 方法,它可以被用于快速授权一个指定的行为,当无权限运行该行为时会抛出 HttpException。authorize 方法接收两个参数,第一个为授权策略的名称,第二个为进行授权验证的数据。为 edit 方法加上这行:
# app/Http/Controllers/Users/UserController.php
public function edit(User $user)
{
    $this->authorize('update', $user);
    return view('users.edit', compact('user'));
}

update 是指授权类里的 update 授权方法,$user 对应传参 update 授权方法的第二个参数。正如上面定义 update 授权方法时候提起的,调用时,默认情况下,我们 不需要 传递第一个参数,也就是当前登录用户至该方法内,因为框架会自动加载当前登录用户。

  • Blade 命令
    允许在 Blade 模板中做授权判断。接下来让我们利用 @can 指令,例如在用户列表页加上只有管理员才能看到的删除用户按钮。
@can('destroy', $user)
      <form action="{{ route('users.destroy', $user->id) }}" method="post">
        {{ csrf_field() }}
        {{ method_field('DELETE') }}
        <button type="submit" class="btn btn-sm btn-danger delete-btn">删除</button>
      </form>
@endcan

测试数据

假数据的生成分为两个阶段:

  1. 对要生成假数据的模型指定字段进行赋值 - 『模型工厂』;
  2. 批量生成假数据模型 - 『数据填充』;

模型工厂

$ php artisan make:factory UserFactory
# database/factories/UserFactory.php
use Faker\Generator as Faker;
$factory->define(App\Models\User::class, function (Faker $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

define 定义了一个指定数据模型(如此例子 User)的模型工厂。define 方法接收两个参数,第一个参数为指定的 Eloquent 模型类,第二个参数为一个闭包函数,该闭包函数接收一个 Faker PHP 函数库的实例,可以在函数内部使用 Faker 方法来生成假数据并为模型的指定字段赋值。

数据填充

  1. 使用 Seeder 类来给数据库填充测试数据。所有的 Seeder 类文件都放在 database/seeds 目录下,文件名需要按照『驼峰式』来命名,且严格遵守大小写规范。
$ php artisan make:seeder UsersTableSeeder
  1. 修改Seeder类
# database/seeds/UsersTableSeeder.php
use Illuminate\Database\Seeder;
use App\Models\User;
class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
    	/**
    	times 和 make 方法是由 FactoryBuilder 类 提供的 API。times 接受一
    	个参数用于指定要创建的模型数量,make 方法调用后将为模型创建一个 集合。
    	makeVisible 方法临时显示 User 模型里指定的隐藏属性 $hidden,接着
    	使用了 insert 方法来将生成假用户列表数据批量插入到数据库中。
    	*/
        $users = factory(User::class)->times(50)->make();
        User::insert($users->makeVisible(['password', 'remember_token'])->toArray());
        $user = User::find(1);
        $user->name = 'Aufree';
        $user->email = 'aufree@yousails.com';
        $user->password = bcrypt('password');
        $user->save();
    }
}
  1. 在 DatabaseSeeder 中调用 call 方法来指定我们要运行假数据填充的文件。
# database/seeds/DatabaseSeeder.php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Model::unguard();
        $this->call(UsersTableSeeder::class);
        Model::reguard();
    }
}
  1. 使用 migrate:refresh 命令来重置数据库,之后再使用 db:seed 执行数据填充。
$ php artisan migrate:refresh
$ php artisan db:seed

如果指定执行 UserTableSeeder 数据库填充文件,则可以这么做:

$ php artisan migrate:refresh
$ php artisan db:seed --class=UsersTableSeeder

也可以使用下面一条命令来同时完成数据库的重置和填充操作:

$ php artisan migrate:refresh --seed
分页
    public function index()
    {
        $users = User::paginate(10);
        return view('users.index', compact('users'));
    }

默认状况下,页面的当前页数由 HTTP 请求所带的 page 参数决定,当你访问 http://xxxx?page=2 链接时,获取的是第二页的用户列表信息,Laravel 会自动检测到 page 的值并插入由分页器生成的链接中。在上面使用 paginate 方法来指定每页生成的数据数量为 10 条,即当我们有 50 个用户时,用户列表将被分为五页进行展示。在view中调用render方法会自动渲染分页

{!! $users->render() !!}

分页

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值