laravel5 框架常用功能

全局安裝

composer global require "laravel/installer"
安装后执行
export PATH=PATH:HOME/.composer/vendor/bin
将laravel 加入全局路径

新建project
laravel new common-system
composer create-project --prefer-dist laravel/laravel common-system 
添加 auth support
php artisan make:auth
添加 model 并生成数据迁移文件
php artisan make:model Models/PasswordHistory -m

执行迁移

php artisan migrate

针对某个表执行,--table 和 --create 选项可用来指定数据表的名称,或是该迁移被执行时会创建的新数据表。这些选项需在预生成迁移文件时填入指定的数据表:

php artisan make:migration create_users_table
php artisan make:migration create_users_table --create=users

migrate:refresh命令首先回滚所有的数据据迁移, 然后运行migrate 命令, 这个命令有效地重建了整个数据库。

php artisan migrate:refresh
// 刷新数据库结构并执行数据填充
php artisan migrate:refresh --seed

修改字段需要安装第三方库
composer require doctrine/dbal

如果装了这个库之后,手动修改了db 结构,会报错~~,将它删除掉重新安装就可以了

创建 seeder 类
php artisan make:seeder UsersTableSeeder

运行seed

php artisan db:seed
php artisan db:seed --class=UsersTableSeeder
路由不区分大小写

在入口 index.php 中添加:

// uri 全部转成小写
$GLOBALS['_SERVER']['REQUEST_URI'] = strtolower($GLOBALS['_SERVER']['REQUEST_URI']);

参考:https://laracasts.com/discuss/channels/laravel/how-do-i-make-routes-case-insensitive?page=1

自定义事件

生成自定义事件

php artisan make:event UpdateUserStatusEvent

创建自定义事件监听器

php artisan make:listener UpdateUserStatusListener --event UpdateUserStatusEvent

./app/Providers/EventServiceProvider.php 中添加监听器和事件的关联

'App\Events\UpdateUserStatusEvent' => [
        'App\Listeners\UpdateUserStatusListener',
 ],

fire 事件
event(new UpdateUserStatusEvent($event->user, "lock"));

auth 的 failed 事件是怎么触发的?
SessionGuard.phpattempt

 /**
     * Attempt to authenticate a user using the given credentials.
     *
     * @param  array  $credentials
     * @param  bool   $remember
     * @return bool
     */
    public function attempt(array $credentials = [], $remember = false)
    {
        $this->fireAttemptEvent($credentials, $remember);

        $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

        // If an implementation of UserInterface was returned, we'll ask the provider
        // to validate the user against the given credentials, and if they are in
        // fact valid we'll log the users into the application and return true.
        if ($this->hasValidCredentials($user, $credentials)) {
            $this->login($user, $remember);

            return true;
        }

        // If the authentication attempt fails we will fire an event so that the user
        // may be notified of any suspicious attempts to access their account from
        // an unrecognized user. A developer may listen to this event as needed.
        $this->fireFailedEvent($user, $credentials);

        return false;
    }

登入失败触发 fireFailedEvent 事件。如果我们要监听 failed 事件,可以添加 listener,并在 EventServiceProvider 绑定 listerevent 的关系

protected $listen = [
        'App\Events\SomeEvent' => [
            'App\Listeners\EventListener',
        ],
        'App\Events\UpdateUserStatusEvent' => [
            'App\Listeners\UpdateUserStatusListener',
        ],
        'Illuminate\Auth\Events\Login' => [
            'App\Listeners\LoginListener',
        ],
        'Illuminate\Auth\Events\Failed' => [
            'App\Listeners\LoginFailedListener',
        ],
    ];

listener:

<?php

namespace App\Listeners;

use Illuminate\Auth\Events\Failed;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use App\Repositories\LoginLogRepository;
use App\Models\LoginLog;
use App\Libs\nmg\account\AccountFactory;
use App\Events\UpdateUserStatusEvent;

class LoginFailedListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  AuthLoginEvent  $event
     * @return void
     */
    public function handle(Failed $event)
    {
        if (!$event->user) return false;
        
        $userID = $event->user->id;
        $log = new LoginLogRepository();
        $log->addLoginLog($userID, false, 'login failed');
        
        $count = $log->getLoginFailedTime($userID);
        
        // 如果密码错误超过次数,发送email提醒
        $accountFactory = new AccountFactory();
        $maxTimes = $accountFactory->getPolicyByName("incorrectTimes");
        if ($count >= $maxTimes) {
            event(new UpdateUserStatusEvent($event->user, "lock"));
        }
        
        return false;
    }
}

添加 login 事件

login 后将登入状态记录到 DB 。新建 2 个 Event Listener, 并在 EventServiceProvider 中添加

protected $listen = [
        'App\Events\SomeEvent' => [
            'App\Listeners\EventListener',
        ],
        'Illuminate\Auth\Events\Login' => [
            'App\Listeners\LoginListener',
        ],
        'Illuminate\Auth\Events\Failed' => [
            'App\Listeners\LoginFailedListener',
        ],
    ];

Auth 默认带了 login 和 failed 事件,在

vendor\laravel\framework\src\Illuminate\Auth\Events

在 Listener 的 handle 中添加事件处理

public function handle(Login $event)
{
        //
        Log::info("email:" . $event->user->email);
        return false; // 停止事件传播
}
自定义验证规则

https://github.com/golaravel/laravel4.1docs/blob/master/cn/validation.md#custom-validation-rules

获取最近一次执行的sql

DB::enableQueryLog();

$users = $this->user->search("david");
var_dump($users->toArray());

$queries = DB::getQueryLog();
var_dump($queries);
$last_query = end($queries);
var_dump($last_query);
echo $last_query['query'];
array (size=3)
  'query' => string 'select * from `users` where `user_id` like ? order by `user_id` desc' (length=68)
  'bindings' => 
    array (size=1)
      0 => string '%david%' (length=7)
  'time' => float 13

使用DebugBar
install:
composer require barryvdh/laravel-debugbar

https://github.com/barryvdh/laravel-debugbar
但是,如果是ajax请求,debugbar不会输出ajax的sql

use Barryvdh\Debugbar\Facade as Debugbar;
Debugbar::error('my test!', 'my_label');
发送邮件

基于 API 的驱动,例如 Mailgun 和 SparkPost 通常比 SMTP 服务器更简单快速。如果可能,你应该尽可能使用这些驱动。所有的 API 驱动都需要 Guzzle HTTP 函数库,你可以使用 Composer 包管理器安装它:

composer require guzzlehttp/guzzle

生成 mailables#
在 Laravel 中,每种类型的邮件都代表一个「mailables」对象。这些对象存储在 app/Mail
目录中。如果在你的应用中没有看见这个目录,别担心,在首次使用 make:mail
命令创建 mailables 类时这个目录会被创建,例如:

php artisan make:mail LockAccount

修改Build

public function build()
{
    return $this->view('view.lock_account');
}

修改email 模板文件

如何禁用csrf token?
laravel 默认是开启 csrf token 的,但是有时我们会通过第三方工具测试 url ,例如发送post 请求,如果开启 csrf token 会导致请求失败。
我们可以在全局关闭csrf token。
打开文件:app\Http\Kernel.php
把这行注释掉:
'App\Http\Middleware\VerifyCsrfToken'

如果只想关闭某个url 页面的csrf token 。可以在.\app\Http\Middleware\VerifyCsrfToken.php
添加例外路由规则

/**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        //
        'admin/*',
    ];

参考文档

API 授权

composer require laravel/passport
在./config/app.php 添加 providers

Laravel\Passport\PassportServiceProvider::class,
Model添加访问器

laravel可以为 model 默认属性添加访问器,使数据按照自定义的格式输出。也可以生成一个不存在的属性,但是在 对象或 toArray 输出时不会显示,但是直接访问该属性名是可以输出的。

public function getDisplayNameAttribute()
{
    return  $this->last_name . ',' . $this->first_name . ($this->nick_name ? " ($this->nick_name)" : '');
}
artisan 命令参考

显示 debug 信息,可以在命令行最后加上 -vvv
生成带资源控制器

php artisan make:controller PhotoController --resource
php artisan make:controller PhotoController --resource --model=Photo
Route::resource('photos', 'PhotoController');

生成新的app key

php artisan key:generate

查看路由

 php artisan route:list

生成model 和migrate

php artisan make:model User -m

执行数据库迁移,请注意:不能针对某个表执行迁移

php artisan migrate
php artisan list
php artisan help migrate
php artisan migrate refresh # 重置数据库,rollback后再执行migrate,会删除所有表和数据

生成 data seed

php artisan make:seeder GroupsTableSeeder

可以针对某个seeder 执行,但是不能rollback。

php artisan db:seed 
php artisan db:seed --class=UsersTableSeeder

如何在 seed 中批量插入数据?
若使用以下方式, 不会自动加入 create_at,update_at 等默认值。

DB::table('users')->insert([
            'name' => str_random(10),
            'email' => str_random(10).'@gmail.com',
            'password' => bcrypt('secret'),
        ]);

改成UserModel::insert($users); 也一样。不会加入自动的 timestamp 字段,要手动加上这2个字段
参考下:
http://stackoverflow.com/questions/12702812/bulk-insertion-in-laravel-using-eloquent-orm/26569967#26569967
因为 timestamp 是eloquent 才有的。可以改成用 create 生成 timestamp

public function run()
    {
        $websites = [
            [
                'title' => '1',
                'atom_link' => 'http://www.xx.com/feed/',
            ],
            [
                'title' => '新22',
                'atom_link' => 'http://www.xxxx.hk/feed/',
            ]             
        ];
        foreach($websites as $website){
            Website::create($website);
        }
    }

清除缓存等

php artisan config:clear
php artisan view:clear // 清除 storage\framework\views 下的cache 文件
php artisan route:clear
php artisan clear-compiled
cache 设置和获取
Cache::put('test', true, 30);
dump(Cache::getDefaultDriver());
$this->assertTrue(Cache::get('test'));

使用 put 设置 cache 要注意的是,不能省略第三个参数minutes。否则默认是null,实际上不会存储cache。在phpunit中若不设置第三个参数,则assertTrue是false。

另外,如果是在laravel中设置的cache,在phpunit中是获取不到的,因为两者的驱动方式不一样,phpunitphpunit.xml中设置了cache的存储驱动,laravel默认是 file 驱动

<php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
</php>
日志记录
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);
Log::info('User failed to login.', ['id' => $user->id]);

查看最近 一條sql

DB::enableQueryLog();// 全局使用可以放入AppServiceProvider的 boot 中
DB::getQueryLog()

将每次sql操作都写入log文件。在AppServiceProvider.php的boot中添加

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        DB::enableQueryLog();
        DB::listen(function ($query) {
            Log::debug("SQL: ", [
                $query->sql,
                $query->bindings,
                $query->time
            ]);
        });
    }
Eloquent 添加自定义访问器 (Defining An Accessor)

可以在model中添加自定义属性访问器,获取后可以直接像访问原生字段一样访问。但是如果返回成json或array,这些自定义属性是不会添加上去的。
因为默认laravel是不会加上去的,要在model上添加需要append的自定义属性,参考
https://laravel.io/forum/02-26-2014-model-attribute-accessor-not-working-with-object-get-helper-function

protected $appends = array('displayName');
phpunit

执行所有测试用例

phpunit

只执行指定test function
phpunit --filter 'testMembers'
参考
https://phpunit.de/manual/current/zh_cn/textui.html#textui.clioptions
https://phpunit.de/

如果phpunit执行以下错误

PHP Fatal error:  Uncaught Error: Call to undefined method PHPUnit_Util_Configuration::getTestdoxGroupConfiguration() in /home/laravel5/common-system/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:1066
Stack trace:
#0 /home/laravel5/common-system/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(163): PHPUnit_TextUI_TestRunner->handleConfiguration(Array)
#1 /usr/share/php/PHPUnit/TextUI/Command.php(155): PHPUnit_TextUI_TestRunner->doRun(Object(PHPUnit_Framework_TestSuite), Array)
#2 /usr/share/php/PHPUnit/TextUI/Command.php(106): PHPUnit_TextUI_Command->run(Array, true)
#3 /usr/bin/phpunit(29): PHPUnit_TextUI_Command::main()
#4 {main}
  thrown in /home/laravel5/common-system/vendor/phpunit/phpunit/src/TextUI/TestRunner.php on line 1066
root@linuxtest:/home/laravel5/common-system# phpunit --version
PHPUnit 5.1.3 by Sebastian Bergmann and contributors.

表示phpunit的版本太低,在 composer.json 中要求 "phpunit/phpunit": "~5.7"。请升级phpunit 至最低要求版本!

$ wget https://phar.phpunit.de/phpunit-6.1.phar
$ chmod +x phpunit-6.1.phar
$ sudo mv phpunit-6.1.phar /usr/local/bin/phpunit
$ phpunit --version

测试controllers
有个方法调用了route的action。由于在phpunit中无法获取到route,因此会测试失败。这种情况,可以测试controller的方法,通过

public function testRemoveGroups()
{
    $response = $this->call('POST', 'Admin\GroupController@removeGroups', ['ids'=>'7,8']);
}

请注意,laravel5.1用的是$this->action(); laravel 5.4 没有action这个方法了。

获取 表的所有字段
模板

模板渲染时报错

ErrorException
 in helpers.php line 532:htmlspecialchars() expects parameter 1 to be string, array given (View: /home/laravel5/common-system/resources/views/cms/user/privileges.blade.php)

如果赋值的数据是数据类型,不应该用var members = {{ $members }};
而应该用var members = {!! $members !!};

自定义辅助函数

-- 1. 在 app 目录下新建一个文件 helpers.php**
-- 2. 在 composer.json 文件的 autoload 字典中添加 "files":["app/helpers.php"][图片上传失败...(image-ed170d-1532662234986)]
-- 3. 执行命令:composer dumpautoload
OK搞定
-- 4. 这其实是与composer中的自动加载有关 -> **链接

为数组或 collect 添加分页

注意 array_slice 最后一个参数如果改成 true 会导致重新排序。默认 false
$data 是数组

use Illuminate\Pagination\LengthAwarePaginator;

/**
     * 根据热度,时间等因素排序
     * @param int $perPage 
     * @param array $pagesize
     * @return mixed
     */
    public function smart_paginate($page=1, $page_size = 10)
    {
        $data = $this->getAllFeeds();     
    
        // Start displaying items from this number;
        $offSet = ($page * $page_size) - $page_size; 
        return new LengthAwarePaginator(array_slice($data, $offSet, $page_size), 
            count($data), 
            $page_size, 
            $page, 
            ['path' => request()->url(), 
            'query' =>  request()->query()]);
    }
为数据库查询添加 cache

Laravel4 的 ->remember(60) 的写法已经被抛弃了。

use Illuminate\Support\Facades\Cache;

$value = Cache::remember('users', $minutes, function () {
    return DB::table('users')->get();
});
cronjob 日志权限变成root 导致 website 无法打开

设置了cronjob 来执行console command,用的是root用户执行的,且日志是按日期生成的,导致生成的日期文件都是root用户创建的,而website使用的是www-data,因此没有权限写入这些root创建的日志文件。
解决办法:将cronjob 放入www-data的crontab 中执行。

model 查询重置查询

同一个model执行多次查询,会使用上一次查询的条件。为了重置查询,需要加上 newQuery()
newQueryWithoutScopes

newQueryWithoutScope

API 文檔:
https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Model.html#method_newQuery

$model->newQuery()->where($data)->get();
Session 后直接执行exist();不会保存session

例如

public function testSession()
{
     session(['key' => 'abc']);
     exit();
}

//  无输出
 public function getSession()
 {
        echo session('key');
 }

不要exit(),就有输出

public function testSession()
{
     session(['key' => 'abc']);
}

//  有输出
 public function getSession()
 {
        echo session('key');
 }

换成

 $request->session()->put('key', 'abcd');

也是一样的结果。别人有提出过这个问题:

https://github.com/laravel/framework/issues/3267
https://stackoverflow.com/questions/46403996/sessionput-not-working-when-i-put-die-or-exit-after-declaration-in-laravel
https://stackoverflow.com/questions/26206021/laravel-session-storage-is-empty-on-refresh
标准答案:

 Laravel's session data is written as part of the response shutdown process. This is for efficiency reasons - if you're making dozens of Session::put
 calls in a request, it's better to make them all at once in bulk.
As a result, if you don't cause a response with something like View::make
 or Response::json
 or what have you and instead exit
 or die
, session data won't be written as you've short circuited the response lifecycle.
request 如何区分有无input这个field以及这个field的内容为空的区别?

如果form中无某个input和有input但是内容为空,通过$request获取到的都是null。如何区别这两者情况呢?

<input type="text" name="password" value="">

有input且value=‘’的情况

        $input = $request->all();
        var_dump($input);
        var_dump($request->has('password'));// 有input 返回true,无则返回false
        var_dump($request->input('password'));//有input且value='' 也返回null
        var_dump($request->password);//有input且value='' 也返回null
        var_dump($_POST['password']);//有input且value='' 也返回“”
        exit();

无input,就都返回null。这个是一样的。
因此,可以通过$request->has()方法区别input是否存在和输入值为空的情况

5.5 取消了整数类型字段的第二个参数
$table->unsignedTinyInteger('width', 4)->default(1);

会报错



  [Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default val
  ue for 'width' (SQL: create table `sys_grid_files` (`id` int unsigned not n
  ull auto_increment primary key, `file_name` varchar(255) not null, `origina
  l_name` varchar(255) null, `file_path` varchar(255) not null, `file_size` i
  nt unsigned not null default '0', `file_type` varchar(50) not null, `width`
   tinyint unsigned not null default '0' auto_increment primary key, `height`
   tinyint unsigned not null default '0' auto_increment primary key, `storage
  _engine` varchar(50) not null comment 'local or s3', `upload_user` varchar(
  50) null, `status` tinyint unsigned not null default '1' auto_increment pri
  mary key, `created_at` timestamp null, `updated_at` timestamp null) default
   character set utf8mb4 collate utf8mb4_unicode_ci engine = InnoDB)



  [Doctrine\DBAL\Driver\PDOException]
  SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default val
  ue for 'width'



  [PDOException]
  SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default val
  ue for 'width'

要改成

$table->unsignedTinyInteger('width')->default(1);
laravel migration 找不到db的问题

执行php artisan migrate出现

 [Illuminate\Database\QueryException]
  SQLSTATE[HY000] [1049] Unknown database 'instagram_auto_post_cms' (SQL: sel
  ect * from information_schema.tables where table_schema = instagram_auto_po
  st_cms and table_name = migrations)

的错误,这个sqlphpmyadmin中执行,确实是没有记录的。

select * from information_schema.tables where table_schema = instagram_auto_post_cms and table_name = migrations

这个db是手动通过phpmyadmin添加的,删除掉,再用create database instagram_auto_post_cms创建,就可以在information_schema.tables表中见到这个db了。再次执行php artisan migrate,正确执行。

leftJoin 多条件查询

使用闭包函数,传$join参数进行处理。如果是查询不要用on,改用where。因为用on会将1转换成string,导致查询类型错误。

$now = datetime();
        $posts = $this->model->select('ig_post.id', 'ig_post.message', 'ig_post.publish_time', 
                                      'ig_post.post_type', 'ig_post.page_id', 
                                      'sys_grid_files.file_path', 'sys_grid_files.file_name')
                    ->leftJoin('sys_grid_files_mapping', function ($join) {
                         $join->on('sys_grid_files_mapping.pk_value', '=', 'ig_post.id');
                         $join->on('sys_grid_files_mapping.field_name', '=', 'ig_post.post_type');
                         $join->where('sys_grid_files_mapping.status', '=', 1);
                    })
                    ->leftJoin('sys_grid_files', 'sys_grid_files.id', '=', 'sys_grid_files_mapping.file_id')
                    ->where('page_id', $page_id)
                    ->where('sync_status', 0)
                    ->where('publish_time', '<', $now)
                    ->get();
.env 的配置内容包含空格必须用引号包含起来,否则会报错

执行代码报以下错误

Fatal error: Uncaught ReflectionException: Class config does not exist in /home/laravel5/ig_cms/vendor/laravel/framework/src/Illuminate/Container/Container.php:752 Stack trace: #0 /home/laravel5/ig_cms/vendor/laravel/framework/src/Illuminate/Container/Container.php(752): ReflectionClass->__construct('config') #1 /home/laravel5/ig_cms/vendor/laravel/framework/src/Illuminate/Container/Container.php(631): Illuminate\Container\Container->build('config') #2 /home/laravel5/ig_cms/vendor/laravel/framework/src/Illuminate/Container/Container.php(586): Illuminate\Container\Container->resolve('config', Array) #3 /home/laravel5/ig_cms/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(732): Illuminate\Container\Container->make('config', Array) #4 /home/laravel5/ig_cms/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php(110): Illuminate\Foundation\Application->make('config', Array) #5 /home/laravel5/ig_cms/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php(272): app('config') #6 /home/laravel5/ig in /home/laravel5/ig_cms/vendor/laravel/framework/src/Illuminate/Container/Container.php on line 752

执行composer dump-autload报错:

Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover


  [Dotenv\Exception\InvalidFileException]
  Dotenv values containing spaces must be surrounded by quotes.


Script @php artisan package:discover handling the post-autoload-dump event returned with error code 1

env 配置文件

如果使用了config:cache 则只有config文件才能读取到env('xxx')。其它地方都读取不到。必须建议env 变量对应的config文件'env.php'通过config('env.xxx')来读取。参考:https://icewing.cc/post/laravel-5-env.html

参考资料

laravel5.4 中文文档
laravel up and running
laravel5.1 LTS 速查表
laravel5.4 API
PIPE 模式
PIPE

php artisan list
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值