常见问题
1. 执行 php artisan migration:make 报 Command "migrate:make" is not defined?
因为 php artisan migrate:make 是 Laravel 4 的语法,而 Laravel5 已经换成了 php artisan make:migration
执行 php artisan make:migration table_name 会为每个表在工程的 database 目录下的 migrations 目录下生成一个 php 文件。
如果要将这些文件添加到库中生成对应的表则需要执行 php artisan migrate
2. 更新依赖时出问题了如何解决?
先 composer clearcache 清理包、仓库缓存,再用 composer update,如果不起效,就删掉 vendor 目录重新安装。
3. Laravel 源码的结构
- app:网站的业务逻辑代码,例如:控制器/模型/路由等
- bootstrap:框架启动与自动加载设置相关的文件
- config:网站的各种配置文件
- database:数据库操作相关的文件
- public:网站的对外文件夹,入口文件和静态资源(CSS,JS,图片等)
- resources:前端视图文件和原始资源(CSS,JS,图片等)
- storage:编译后的视图、基于会话、文件缓存和其它框架生成的文件
- tests:自动化测试文件
- vendor:Composer 依赖文件
- app/Http/Controllers:存放控制器
- app/Http/Middleware:存放中间件
- resources/views:视图路径 blade 视图
4. laravel 配置文件
- .env: 环境配置文件
- .env.example:.env 文件的一个示例
- .gitignore: git 的设置文件,制定哪些文件会被 git 忽略,不纳入文件管理
- composer.json: 网站所需的 composer 扩展包
- composer.lock: 扩展包列表,确保这个网站的副本使用相同版本的扩展包
- gulpfile.js:GULP 配置文件( GULP 后边会学到)
- package.json: 网站所需的 npm 包
- readme.md: 网站代码说明文件
- app/Http/routes.php:网站的大多数路由都定义在该文件中,该文件将会被 AppProvidersRouteServiceProvider 类加载。
5. phpstorm 中使用 laravel 的方法
- 安装 Laravel Plugin 插件
- 安装 Laravel IDE Helper 代码提示
5.1. 使用 composer 安装插件
代码语言:javascript复制composer require barryvdh/laravel-ide-helper
在 config 目录里的 app.php 文件中的'providers'添加如下内容
代码语言:javascript复制BarryvdhLaravelIdeHelperIdeHelperServiceProvider::class,
5.2. 在 app 目录里的 Providers 目录里的 AppServiceProvider.php 文件中的
代码语言:javascript复制public function register()里输入如下内容来注册
if ($this->app->environment() !== 'production') { $this->app->register(BarryvdhLaravelIdeHelperIdeHelperServiceProvider::class); }
5.3. 生成代码跟踪支持
代码语言:javascript复制php artisan ide-helper:generate
5.4. php artisan serve 启动服务
artisan 的 serve 命令还支持两个参数:
- host 设置主机地址
- port 设置 web server 监听的端口号 例如:php artisan serve --port=8888
5.5. 如果添加了 debugbar 拓展
代码语言:javascript复制composer require barryvdh/laravel-debugbar
页面下方会出现:
如何查看 phpinfo
创建一个简单的文本文档并命名为 phpinfo.php
代码如下:
代码语言:javascript复制<?php
phpinfo();
?>
放入 nginx 或 apache 中之后,通过浏览器访问这个文件即可显示 PHP 信息 如:http://192.168.1.100/phpinfo.php
配置 phpstorm xdebug laravel 环境来 debug 源码
1. 安装
安装 phpstorm 和 laravel 的部分这里不再多说,之前都有提到。
安装 xdebug:
- E:softwarenginx-1.10.3>php -v
PHP 7.1.32 (cli) (built: Aug 28 2019 09:08:22) ( NTS MSVC14 (Visual C 2015) x64 )Copyright (c) 1997-2018 The PHP GroupZend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
- 下载 Xdebug
- 地址:https://xdebug.org/download.php 下载对应 php 版本的即可。
- 将下载下来的 dll 文件放置 php 安装目录的 ext 目录中并重命名为 php_xdebug.dll
- 配置 php.ini,添加以下配置:
[xdebug]zend_extension="E:softwarephp-7.1.32-nts-Win32-VC14-x64extphp_xdebug.dll"xdebug.remote_enable=1xdebug.remote_port=9000xdebug.remote_host=localhostxdebug.profiler_enable=1xdebug.remote_mode = "req"xdebug.trace_output_dir="./xdebug"xdebug.profiler_output_dir="./xdebug"xdebug.remote_handler="dbgp"xdebug.idekey = "phpstorm" //必填
- 扫行php -m查看安装情况:
C:Usersadmin>php -m[PHP Modules]bcmathbz2calendarCorectypecurldatedomexiffileinfofilterftpgdgettextgmphashiconvimapintljsonldaplibxmlmbstringmcryptmysqlimysqlndodbcopensslpcrePDOpdo_mysqlPDO_ODBCpdo_pgsqlpdo_sqlitepgsqlPharreadlineReflectionsessionshmopSimpleXMLsoapsocketsSPLsqlite3standardtidytokenizerwddxxdebugxmlxmlreaderxmlrpcxmlwriterxslzipzlib
[Zend Modules]Xdebug
可以看到Xdebug已经安装成功。
- 配置phpstorm,主要参考下面两张图片
- laravel在phpstorm中的配置主要参考:https://www.jetbrains.com/help/phpstorm/laravel.html,这里只是列出Debug Artisan commands的phpstorm的配置:
图中arguments配置的是artisan的命令。
源码跟踪
代码语言:javascript复制Auth::attempt($username, $request->isRemember))
对于Auth的attempt方法,表面上来看我们无从找起,但是进入Auth类会发现,Auth 是通过 Facade 动态绑定的,绑定到哪里呢,进一步寻找我们发现 在 vendor/laravel/framework/src/Illuminate/AuthServiceProvider 中:
代码语言:javascript复制 class AuthServiceProvider extends ServiceProvider{ /** * Register the authenticator services. * * @return void */ protected function registerAuthenticator() { $this->app->singleton('auth', function ($app) { $app['auth.loaded'] = true; return new AuthManager($app); });
$this->app->singleton('auth.driver', function ($app) { return $app['auth']->guard(); }); }}
默认Auth是绑定了AuthManager:
代码语言:javascript复制 <?phpnamespace IlluminateAuth;
use Closure;use InvalidArgumentException;use IlluminateContractsAuthFactory as FactoryContract;class AuthManager implements FactoryContract{ use CreatesUserProviders;
protected $app;
protected $guards = [];
public function guard($name = null) { $name = $name ?: $this->getDefaultDriver();
return isset($this->guards[$name]) ? $this->guards[$name] : $this->guards[$name] = $this->resolve($name); }
public function getDefaultDriver() { return $this->app['config']['auth.defaults.guard']; }
public function __call($method, $parameters) {
return $this->guard()->{$method}(...$parameters); }}
并没有找到 attempt 方法,不过有一个__call 的魔术方法,那肯定是他里面没错了,为了快速找到他究竟是何方神圣,直接用
代码语言:javascript复制dd(get_class($this->guard()));
输出为:
代码语言:javascript复制IlluminateAuthSessionGuard
再往下的方法调用都可以通过debug的方式确定实现类了。这里就不再赘述,详情见:https://learnku.com/articles/5963/toggle-laravel-login-default-bcrypt-encryption-validation
初始化laravel程序时通过修改库的方式添加了一个用户,校验不通过的问题
Auth.attempt调用了:
代码语言:javascript复制IlluminateAuthSessionGuard::attempt: 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; } /** * Determine if the user matches the credentials. * * @param mixed $user * @param array $credentials * @return bool */ protected function hasValidCredentials($user, $credentials) { return ! is_null($user) && $this->provider->validateCredentials($user, $credentials); }
然后$this->provider->validateCredentials调用了:
代码语言:javascript复制IlluminateAuthEloquentUserProvider::validateCredentials: public function validateCredentials(UserContract $user, array $credentials) { $plain = $credentials['password']; return $this->hasher->check($plain, $user->getAuthPassword()); }
这里会发现是通过hasher去check库里的密码和登录端传入的密码的,通过debug查看这个hasher为BcryptHasher的一个实例,于是对往库中添加的密码123456做如下处理:
代码语言:javascript复制 $hasher = new BcryptHasher(); $hashPass = $hasher ->make("123456"); printf($hashPass);
将打印出来的结果添加到库中的密码栏即可用该用户名与密码登录。