- In
LaravelS
,Swoole
isHttp Server
started incli
mode, replacingFPM
. - Delivering a task, triggering an asynchronous event will call
app('swoole')
and get theSwoole\http\server
instance from theLaravel container
. This instance is injected into the container only whenLaravelS
is started. - So, once you leave the
LaravelS
, due to the cross-process, you will beunable
to successfully callapp('swoole')
:- The code that runs in various
command line
modes, such as the Artisan command line and the PHP script command line. - Run the code under
FPM
/Apache PHP Module
, view SAPILog::info('PHP SAPI', [php_sapi_name()]);
.
- The code that runs in various
Use package encore/laravel-admin
Modify
config/laravels.php
and addLaravelAdminCleaner
incleaners
.
'cleaners' => [
Hhxsv5\LaravelS\Illuminate\Cleaners\LaravelAdminCleaner::class,
],
Use package jenssegers/agent
// Reset Agent
\Event::listen('laravels.received_request', function (\Illuminate\Http\Request $req, $app) {
$app->agent->setHttpHeaders($req->server->all());
$app->agent->setUserAgent();
});
Use package barryvdh/laravel-debugbar
Not support
cli
mode officially, you need to add the environment variableAPP_RUNNING_IN_CONSOLE
to be non-cli`, but there may be some other issues.
Add environment variable APP_RUNNING_IN_CONSOLE=false
to .env
.
Use package the-control-group/voyager
voyager
dependencies arrilot/laravel-widgets, whereWidgetGroupCollection
is a singleton, appending widget will cause them to repeat the display, you need to reset the singleton by re-registering the ServiceProvider.
// config/laravels.php
'register_providers' => [
Arrilot\Widgets\ServiceProvider::class,
],
Use package overtrue/wechat
The asynchronous notification callback will be failing, because
$app['request']->getContent()
is empty, give it a value.
public function notify(Request $request)
{
$app = $this->getPayment();//Get payment instance
$app['request'] = $request;//Add this line to the original code and assign the current request instance to $app['request']
$response = $app->handlePaidNotify(function ($message, $fail) use($id) {
//...
});
return $response;
}
Use package laracasts/flash
Flash messages are held in memory all the time. Appending to
$messages
when call flash() every time, leads to the multiple messages. There are two solutions.
1.Reset $messages
by middleware app('flash')->clear();
.
2.Re-register FlashServiceProvider
after handling request, Refer register_providers.
Use package laravel/telescope
Because Swoole is running in
cli
mode,RequestWatcher
does not recognize the ignored route properly.
Solution:
1.Add environment variable APP_RUNNING_IN_CONSOLE=false
to .env
;
2.Modify code.
// Edit file `app/Providers/EventServiceProvider.php`, add the following code into method `boot`
// use Laravel\Telescope\Telescope;
// use Illuminate\Support\Facades\Event;
Event::listen('laravels.received_request', function ($request, $app) {
$reflection = new \ReflectionClass(Telescope::class);
$handlingApprovedRequest = $reflection->getMethod('handlingApprovedRequest');
$handlingApprovedRequest->setAccessible(true);
$handlingApprovedRequest->invoke(null, $app) ? Telescope::startRecording() : Telescope::stopRecording();
});
- Laravel 5.3+ controller is bound to
Route
underRouter
, andRouter
is a singleton, controller will only be constructedonce
, so you cannot initializerequest-level data
in the constructor, the following shows you thewrong
usage.
namespace App\Http\Controllers;
class TestController extends Controller
{
protected $userId;
public function __construct()
{
// Wrong usage: Since the controller is only constructed once and then resident in memory, $userId will only be assigned once, and subsequent requests will be misread before requesting $userId
$this->userId = session('userId');
}
public function testAction()
{
// read $this->userId;
}
}
- Two solutions (choose one)
1.Avoid initializing request-level
data in the constructor, which should be read in the concrete Action
. This coding style is more reasonable, it is recommended to do so.
# List all properties of all controllers related your routes.
php artisan laravels:list-properties
namespace App\Http\Controllers;
class TestController extends Controller
{
protected function getUserId()
{
return session('userId');
}
public function testAction()
{
// call $this->getUserId() to read $userId
}
}
2.Use the automatic destruction controller
mechanism provided by LaravelS
.
// config/laravels.php
// Set enable to true and exclude_list to [], which means that all controllers are automatically destroyed.
'destroy_controllers' => [
'enable' => true, // Enable automatic destruction controller
'excluded_list' => [
//\App\Http\Controllers\TestController::class, // The excluded list of destroyed controller classes
],
],
-
flush
/ob_flush
/ob_end_flush
/ob_implicit_flush
:swoole_http_response
does not supportflush
. -
dd()
/exit()
/die()
: will lead to Worker/Task/Process quit right now, suggest jump out function call stack by throwing exception. -
header()
/setcookie()
/http_response_code()
: Make HTTP response by Laravel/LumenResponse
only in LaravelS underlying.
- $_GET/$_POST/$_FILES/$_COOKIE/$_REQUEST/$_SESSION/$GLOBALS, $_ENV is
readable
, $_SERVER ispartial readable
.
-
The max size of
GET
request's header is8KB
, limited bySwoole
, the bigCookie
will lead to parse Cookie fail. -
The max size of
POST
data/file is limited bySwoole
package_max_length, default2M
. -
The max size of the file upload is limited by memory_limit, default
128M
.
Warning: inotify_add_watch(): The user limit on the total number of inotify watches was reached
-
Inotify limit is default
8192
for mostLinux
, but the amount of actual project may be more than it, then lead to watch fail. -
Increase the amount of inotify watchers to
524288
:echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
, note: you need to enableprivileged
forDocker
.
See Laruence's blog Do NOT USE (include/require)_once
-
To include the files about
class
/interface
/trait
/function
, sugguest to use (include/require)_once. In other cases, use include/require. -
In the multi-process mode, the child process inherits the parent process resource. Once the parent process includes a file that needs to be executed, the child process will directly return true when it uses require_once(), causing the file to fail to execute. Now, you need to use include/require.
After enabling
handle_static
, static resource files will be handled byLaravelS
. Due to the PHP environment,MimeTypeGuesser
may not correctly recognizeMimeType
. For example, Javascript and CSS files will be recognized astext/plain
.
Solutions:
1.Upgrade Swoole to 1.9.17+
.
2.Register a custom MIME guesser.
// MyGuessMimeType.php
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
class MyGuessMimeType implements MimeTypeGuesserInterface
{
protected static $map = [
'js' => 'application/javascript',
'css' => 'text/css',
];
public function guess($path)
{
$ext = pathinfo($path, PATHINFO_EXTENSION);
if (strlen($ext) > 0) {
return Arr::get(self::$map, $ext);
} else {
return null;
}
}
}
// AppServiceProvider.php
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
public function boot()
{
MimeTypeGuesser::getInstance()->register(new MyGuessMimeType());
}