如何在 Eloquent(laravel 之外)中记录来自多个连接的每个查询
How to log every query from multiple connections in Eloquent (outside laravel)
我在我的应用程序中使用多个数据库连接,一个 SQLServ,另一个 MySQL。我想按顺序调试来自两个服务器的每个查询。因此,我需要使用 Event::listen
而不是使用 Manager::getQueryLog()
。我使用 SlimFramework 和 PHP-DI.
index.php
// Create container & database
$containerBuilder = new DI\ContainerBuilder(App\Lib\Container::class);
$containerBuilder->useAnnotations(false);
$containerBuilder->addDefinitions(__DIR__ . '/../config/settings.php');
$container = $containerBuilder->build();
$app = \DI\Bridge\Slim\Bridge::create($container);
// Register database
$capsule = new \Illuminate\Database\Capsule\Manager();
foreach ($container->get('database') as $con => $config) {
$capsule->addConnection($config, $con);
}
$capsule->setEventDispatcher(new \Illuminate\Events\Dispatcher());
// Throw error A facade root has not been set. pretty sure it
// was because i use it outside laravel
$capsule->setAsGlobal();
$capsule->bootEloquent();
$container->set('connection', $capsule);
// Listen
DB::listen(function($query) {
Log::info(
$query->sql,
$query->bindings,
$query->time
);
});
App\Lib\Container::class
namespace App\Lib;
use DI\Container as DIContainer;
class Container extends DIContainer
{
public function __get($key)
{
if ($this->has($key)) {
return $this->get($key);
}
}
}
如何记录来自多个连接的每个查询,但按顺序,如下所示。
select * from tableInMySQL limit 0,10;
select TOP 10 * from [tableInMSSQL];
update tableInMySQL set field='value';
编辑
就像我之前说的,我使用 SlimFramework 和 PHP-DI。
所以,我不使用 LARAVEL 作为一个整体。 (不使用服务提供商)
DB::listen
抛出错误,$capsule->getConnection('con_name')->getEventDispatcher()
return null
你应该在 app/Providers/AppServiceProvider.php
的 boot()
函数中编写 DB::listen 事件
DB::listen(function ($query) {
$qry = str_replace(['?'], ['\'%s\''], $query->sql);
$qry = vsprintf($qry, $query->bindings);
Log::info('query_log', [
'query' => $qry,
'bindings' => $query->bindings,
]);
});
请将此添加到 Providers/AppServiceProvider.php 文件并在 laravel 日志文件中检查它们
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;
public function register() {
Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
Log::debug($query->sql . ' - ' . serialize($query->bindings));
});
}
要按顺序记录多个数据库连接的查询,我们需要先enableQueryLog
,配置单独的记录器。
$capsule->setAsGlobal();
$capsule->bootEloquent();
$container->set('connection', $capsule);
$capsule->connection('<MySqlConnectionName>')->enableQueryLog();
$capsule->connection('<SqlServerConnectionName>')->enableQueryLog();
//$capsule->connection('<MongoConnectionName>')->enableQueryLog();
// Listen
\Illuminate\Database\Capsule\Manager::listen(function($query) {
if($query->connectionName == 'mysql') {
$mysqlLogger->debug('mysql', [
'query' => $query->sql,
'bindings' => $query->bindings
]);
} elseif($query->connectionName == 'sqlserver') {
$sqlServerLogger->debug('mongodb', [
'query' => $query->sql,
'bindings' => $query->bindings
]);
} /*elseif($query->connectionName == 'mongodb') {
$mongoDbLogger->debug('mongodb', [
'query' => $query->sql,
'bindings' => $query->bindings
]);
}*/
});
我在 AppServiceProvider.php
上将代码放入 boot() 方法中
if (\App::environment('local')) {
\DB::listen(function ($query) {
\Log::info($query->sql);
});
}
因此,日志将只写入开发环境。
对于登陆这里的任何人,我们需要在每个连接上附加监听器
setting.php
return [
'maintenance' => false,
'base_path' => empty($_ENV['SUBDIR']) ? '' : '/' . $_ENV['SUBDIR'],
'database' => [
'default' => [ // sql server
"driver" => env('DB_MSSQL_DRIVER'),
"host" => env('DB_MSSQL_HOST'),
"port" => env('DB_MSSQL_PORT'),
"database" => env('DB_MSSQL_DATABASE'),
"username" => env('DB_MSSQL_USERNAME'),
'password' => env('DB_MSSQL_PASSWORD'),
],
'mysql' => [
"driver" => env('DB_MYSQL_DRIVER'),
"host" => env('DB_MYSQL_HOST'),
"port" => env('DB_MYSQL_PORT'),
"database" => env('DB_MYSQL_DATABASE'),
"username" => env('DB_MYSQL_USERNAME'),
'password' => env('DB_MYSQL_PASSWORD'),
],
],
"template" => [
"view" => __DIR__ . "/../module",
"cache" => __DIR__ . "/../cache",
],
];
index.php
// build PHP-DI container
$container = $containerBuilder->build();
//register database
$capsule = new \Illuminate\Database\Capsule\Manager();
foreach ($container->get('database') as $con => $config) {
$capsule->addConnection($config, $con);
$capsule->getConnection($con)->setEventDispatcher(new \Illuminate\Events\Dispatcher());
$capsule->getConnection($con)->listen(function ($q) {
// or use logger
$d = str_replace('?', "'?'", "[$q->connectionName]\t" . $q->sql);
$d = vsprintf(str_replace('?', '%s', $d), $q->bindings);
file_put_contents(__DIR__ . '/../log/sql.log', $d . PHP_EOL, FILE_APPEND);
});
}
$capsule->setAsGlobal();
$capsule->bootEloquent();
$container->set('connection', $capsule);
我在我的应用程序中使用多个数据库连接,一个 SQLServ,另一个 MySQL。我想按顺序调试来自两个服务器的每个查询。因此,我需要使用 Event::listen
而不是使用 Manager::getQueryLog()
。我使用 SlimFramework 和 PHP-DI.
index.php
// Create container & database
$containerBuilder = new DI\ContainerBuilder(App\Lib\Container::class);
$containerBuilder->useAnnotations(false);
$containerBuilder->addDefinitions(__DIR__ . '/../config/settings.php');
$container = $containerBuilder->build();
$app = \DI\Bridge\Slim\Bridge::create($container);
// Register database
$capsule = new \Illuminate\Database\Capsule\Manager();
foreach ($container->get('database') as $con => $config) {
$capsule->addConnection($config, $con);
}
$capsule->setEventDispatcher(new \Illuminate\Events\Dispatcher());
// Throw error A facade root has not been set. pretty sure it
// was because i use it outside laravel
$capsule->setAsGlobal();
$capsule->bootEloquent();
$container->set('connection', $capsule);
// Listen
DB::listen(function($query) {
Log::info(
$query->sql,
$query->bindings,
$query->time
);
});
App\Lib\Container::class
namespace App\Lib;
use DI\Container as DIContainer;
class Container extends DIContainer
{
public function __get($key)
{
if ($this->has($key)) {
return $this->get($key);
}
}
}
如何记录来自多个连接的每个查询,但按顺序,如下所示。
select * from tableInMySQL limit 0,10;
select TOP 10 * from [tableInMSSQL];
update tableInMySQL set field='value';
编辑
就像我之前说的,我使用 SlimFramework 和 PHP-DI。
所以,我不使用 LARAVEL 作为一个整体。 (不使用服务提供商)
DB::listen
抛出错误,$capsule->getConnection('con_name')->getEventDispatcher()
return null
你应该在 app/Providers/AppServiceProvider.php
boot()
函数中编写 DB::listen 事件
DB::listen(function ($query) {
$qry = str_replace(['?'], ['\'%s\''], $query->sql);
$qry = vsprintf($qry, $query->bindings);
Log::info('query_log', [
'query' => $qry,
'bindings' => $query->bindings,
]);
});
请将此添加到 Providers/AppServiceProvider.php 文件并在 laravel 日志文件中检查它们
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;
public function register() {
Event::listen('Illuminate\Database\Events\QueryExecuted', function ($query) {
Log::debug($query->sql . ' - ' . serialize($query->bindings));
});
}
要按顺序记录多个数据库连接的查询,我们需要先enableQueryLog
,配置单独的记录器。
$capsule->setAsGlobal();
$capsule->bootEloquent();
$container->set('connection', $capsule);
$capsule->connection('<MySqlConnectionName>')->enableQueryLog();
$capsule->connection('<SqlServerConnectionName>')->enableQueryLog();
//$capsule->connection('<MongoConnectionName>')->enableQueryLog();
// Listen
\Illuminate\Database\Capsule\Manager::listen(function($query) {
if($query->connectionName == 'mysql') {
$mysqlLogger->debug('mysql', [
'query' => $query->sql,
'bindings' => $query->bindings
]);
} elseif($query->connectionName == 'sqlserver') {
$sqlServerLogger->debug('mongodb', [
'query' => $query->sql,
'bindings' => $query->bindings
]);
} /*elseif($query->connectionName == 'mongodb') {
$mongoDbLogger->debug('mongodb', [
'query' => $query->sql,
'bindings' => $query->bindings
]);
}*/
});
我在 AppServiceProvider.php
上将代码放入 boot() 方法中 if (\App::environment('local')) {
\DB::listen(function ($query) {
\Log::info($query->sql);
});
}
因此,日志将只写入开发环境。
对于登陆这里的任何人,我们需要在每个连接上附加监听器
setting.php
return [
'maintenance' => false,
'base_path' => empty($_ENV['SUBDIR']) ? '' : '/' . $_ENV['SUBDIR'],
'database' => [
'default' => [ // sql server
"driver" => env('DB_MSSQL_DRIVER'),
"host" => env('DB_MSSQL_HOST'),
"port" => env('DB_MSSQL_PORT'),
"database" => env('DB_MSSQL_DATABASE'),
"username" => env('DB_MSSQL_USERNAME'),
'password' => env('DB_MSSQL_PASSWORD'),
],
'mysql' => [
"driver" => env('DB_MYSQL_DRIVER'),
"host" => env('DB_MYSQL_HOST'),
"port" => env('DB_MYSQL_PORT'),
"database" => env('DB_MYSQL_DATABASE'),
"username" => env('DB_MYSQL_USERNAME'),
'password' => env('DB_MYSQL_PASSWORD'),
],
],
"template" => [
"view" => __DIR__ . "/../module",
"cache" => __DIR__ . "/../cache",
],
];
index.php
// build PHP-DI container
$container = $containerBuilder->build();
//register database
$capsule = new \Illuminate\Database\Capsule\Manager();
foreach ($container->get('database') as $con => $config) {
$capsule->addConnection($config, $con);
$capsule->getConnection($con)->setEventDispatcher(new \Illuminate\Events\Dispatcher());
$capsule->getConnection($con)->listen(function ($q) {
// or use logger
$d = str_replace('?', "'?'", "[$q->connectionName]\t" . $q->sql);
$d = vsprintf(str_replace('?', '%s', $d), $q->bindings);
file_put_contents(__DIR__ . '/../log/sql.log', $d . PHP_EOL, FILE_APPEND);
});
}
$capsule->setAsGlobal();
$capsule->bootEloquent();
$container->set('connection', $capsule);