php系列二之phpstorm Xdebug和laravel常見問題整理
- 2019 年 11 月 23 日
- 筆記
常見問題
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 安裝插件
composer require barryvdh/laravel-ide-helper
在 config 目錄里的 app.php 文件中的'providers'添加如下內容
BarryvdhLaravelIdeHelperIdeHelperServiceProvider::class,
5.2. 在 app 目錄里的 Providers 目錄里的 AppServiceProvider.php 文件中的
public function register()里輸入如下內容來註冊 if ($this->app->environment() !== 'production') { $this->app->register(BarryvdhLaravelIdeHelperIdeHelperServiceProvider::class); }
5.3. 生成程式碼跟蹤支援
php artisan ide-helper:generate
5.4. php artisan serve 啟動服務
artisan 的 serve 命令還支援兩個參數:
- host 設置主機地址
- port 設置 web server 監聽的埠號 例如:php artisan serve –port=8888
5.5. 如果添加了 debugbar 拓展
composer require barryvdh/laravel-debugbar
頁面下方會出現:

如何查看 phpinfo
創建一個簡單的文本文檔並命名為 phpinfo.php
程式碼如下:
<?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的命令。
源碼跟蹤
Auth::attempt($username, $request->isRemember))
對於Auth的attempt方法,表面上來看我們無從找起,但是進入Auth類會發現,Auth 是通過 Facade 動態綁定的,綁定到哪裡呢,進一步尋找我們發現 在 vendor/laravel/framework/src/Illuminate/AuthServiceProvider 中:
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:
<?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 的魔術方法,那肯定是他裡面沒錯了,為了快速找到他究竟是何方神聖,直接用
dd(get_class($this->guard()));
輸出為:
IlluminateAuthSessionGuard
再往下的方法調用都可以通過debug的方式確定實現類了。這裡就不再贅述,詳情見:https://learnku.com/articles/5963/toggle-laravel-login-default-bcrypt-encryption-validation
初始化laravel程式時通過修改庫的方式添加了一個用戶,校驗不通過的問題
Auth.attempt調用了:
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調用了:
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做如下處理:
$hasher = new BcryptHasher(); $hashPass = $hasher ->make("123456"); printf($hashPass);
將列印出來的結果添加到庫中的密碼欄即可用該用戶名與密碼登錄。