Yii2: How to log SQL query? - sql

I want to log every SQL query executed so I can debug it and then copy, paste and test it in my database tool.
I tried this solution (Yii - echo the last query) (and other similar solutions) but it is not working because I think it is for Yii1. I need it for Yii2.
I think the solution is independent of the database (I use PostgreSQL).
Maybe I have to configure it in the common/config/main-local file.

If you need in Yii (1), please update your components array in main.php like this
'components'=>array(
#/*
'fixture'=>array(
'class'=>'system.test.CDbFixtureManager',
),
#*/
'db'=>array(
'connectionString' => 'mysql:host=localhost;dbname=intakes_manager_test',
'emulatePrepare' => true,
'username' => 'root',
'password' => 'root',
'charset' => 'utf8',
'enableProfiling'=>true,
'enableParamLogging'=>true,
),
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CFileLogRoute',
'levels'=>'error,trace,info,warning',
//'filter'=>'CLogFilter',
'categories'=>'system.db.*',
'logFile'=>'sql.log'
)
)
),
),
For the same in Yii 2, do like below
'components' => [
'log' => [
'targets' => [
'file' => [
'class' => 'yii\log\FileTarget',
],
'db' => [
'class' => 'yii\log\DbTarget',
],
],
],
to know more about yii 2 logging see doc here

postgresql.conf
log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements
log_min_duration_statement = 0
You would need to restart the Postgresql service

Related

Setting unknown property: yii\log\Logger::targets

After Installed the Yii in my system when I try to run it getting this error.
Unknown Property – yii\base\UnknownPropertyException
Setting unknown property: yii\log\Logger::targets
Here is some of the documentation I created while implementing logging in Yii, it might be of your help:
========================= Configure xampp to send the emails from localhost code ==========================================
Changes for C:\xampp\php\php.ini file:
search for [mail function]:
[mail function]
SMTP=localhost to SMTP=smtp.gmail.com
smtp_port=587
sendmail_from=me#example.com to sendmail_from=your email address
sendmail_path = "\"C:\xampp\sendmail\sendmail.exe\" -t"
mail.add_x_header=Off
mail.log = syslog
Changes for C:\xampp\sendmail\sendmail.ini:
search for [sendmail]:
smtp_server=smtp.gmail.com
smtp_port=587
smtp_ssl=auto
error_logfile=error.log
debug_logfile=debug.log
auth_username=same as "sendmail_from" in php.ini file
auth_password=generated password for the email account
force_sender= same as "auth_username" in this file
================================================ Restart Xampp Server =====================================================
=================================================== Add table in DB =======================================================
drop table if exists "log";
create table "log"
(
"id" number(20) NOT NULL PRIMARY KEY,
"level" integer,
"category" varchar(255),
"log_time" number,
"prefix" text,
"message" text,
key "idx_log_level" ("level"),
key "idx_log_category" ("category")
);
============================================ Configuration in Yii2 project ================================================
add in "components" array in app\config\console.php and app\config\web.php both files:
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => false,
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'smtp.gmail.com',
'username' => 'your email address (for testing on localhost use same as in ini files)',
'password' => 'generated password',
'port' => 587,
'encryption' => 'tls',
],
], //end of mailer
'log' => [
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning','info'],
],
[
'class' => 'yii\log\DbTarget',
'levels' => ['error', 'warning','info'],
],
[
'class' => 'yii\log\EmailTarget',
'mailer' => 'mailer',
'levels' => ['error', 'warning','info'],
//'categories' => ['yii\db\*'],
'message' => [
'from' => ['your email address(for testing on localhost use same as in ini files)'],
'to' => ['receiptent email address'],
],
],
], // end of targets
'flushInterval' => 1,
], //end of logs
//------------------------ web.php (log configuration setup) -------------------------//
//categories name would be later assgined to messages:
Yii::info($message, 'userNotification');

INSERT data from database into another database, running on different hosts

I'm facing the following problem:
I have two MariaDB databases, running on two different hosts. Both of them are used to run two different websites, each of them having Drupal and CiviCRM installed and running.
Some of the data stored in the contacts table of CiviCRM from website 1 needs to be kept in sync with these same contacts on website 2.
Keeping in sync means : inserting new contacts, and updating existing contacts.
I was wondering if this coud be done via trigger?
I know I can activate remote sql on my cPanel, as I use this to work with Mysql Workbench or similar software.
Any ideas? Would a trigger work? Do I rather need to write some code in another language than SQL?
You can add multiple databases at the same time for your Drupal to connect to in your settings.php:
$databases = [
'HOST1.DATABASE' => [
'default' => [
'driver' => 'mysql',
'username' => '',
'password' => '',
'host' => '127.0.0.1',
'port' => '3306',
'prefix' => '',
'database' => 'contacts',
'collation' => 'utf8mb4_general_ci',
],
],
'HOST2.DATABASE' => [
'default' => [
'driver' => 'mysql',
'username' => '',
'password' => '',
'host' => '127.0.0.1',
'port' => '3306',
'prefix' => '',
'database' => 'contacts_audit',
'collation' => 'utf8mb4_general_ci',
],
],
];
After this you can define in the getConnection() method, which key of the $database array you want to connect.
\Drupal\Core\Database\Database::getConnection('HOST1.DATABASE')
->query('CREATE TRIGGER contacts_after_update AFTER UPDATE ON contacts FOR EACH ROW BEGIN')
->execute();
and
\Drupal\Core\Database\Database::getConnection('HOST2.DATABASE')
->query('INSERT INTO contacts_audit ( contact_id, updated_date, updated_by) VALUES ( NEW.contact_id, SYSDATE(), ); END;')
->execute();
(If you leave the parameter of getConnection() empty, it would connect to the database on $databases['default'] key. Also, you can use setActiveConnection() if you want to work more with the database, which as its name says, sets the active connection to the desired key of $databases)
Hope this helps some way.

Laravel SQL Server connection with ENCRYPT=yes trustServerCertificate=true

I got a ubuntu docker container which runs php 5.5.9, laraverl 5.2 which can connect successfully to SQL Server and get results back.
The docker image I am using is https://hub.docker.com/r/h2labs/laravel-mssql/
The problem I got is that the server uses encryption and I cant find how to pass the following parameters to the laravel connection string for mssql
ENCRYPT=yes;trustServerCertificate=true
My SQL Server connection string at present looks like this
DB_CONNECTION=sqlsrv
DB_HOST=sql.mydomain.com
DB_PORT=1433
DB_DATABASE=mydbname
DB_USERNAME=mysusername
DB_PASSWORD=mypass
My laravel database config looks like this
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
],
The SQL Server error log entry is
Encryption is required to connect to this server but the client library does not support encryption; the connection has been closed. Please upgrade your client library. [CLIENT: 103.31.114.56]
Support for either option was not introduced until Laravel 5.4; Specifically, v5.4.11
So you would first need to upgrade to laravel/framework:>=5.4.11,<5.5
Then, to configure your application, you will need to modify your config/database.php file as follows:
// ...
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'encrypt' => 'yes', // alternatively, defer to an env variable
'trust_server_certificate' => 'true', // alternatively, defer to an env variable
],
// ...
DatabaseServiceProvider, via ConnectionFactory and SqlServerConnector will use this to build the underlying PDO connection with those options set in the DSN.

NOAUTH Authentication required. Laravel + Redis

I am getting error NOAUTH Authentication required.
My laravel version is 5.3 and I am using predis 1.1.1 to connect redis.
in etc/redis/redis.conf I have:
bind 127.0.0.1
requirepass somepassword
in .env file I have
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=somepassword
REDIS_PORT=6379
in config/database.php I have:
'redis' => [
'cluster' => false,
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],
I am connecting redis via:
self::$_db = \Redis::connection('default');
and using it like:
self::$_db->pipeline(function ($pipe) use ($profile, $time,$type, $id) {
$pipe->zadd(self::getProfileKey($profile, $type), $time, $id);
$pipe->zadd(self::getProfileKey($profile), $time, $type . ':' . $id);
$pipe->zadd(self::getModelKey($type,$id) . '::favoritedBy', $time, $profile->profile_id);
});
So, when I comment out requirepass and send password as null it works but it does not work and throw error NOAUTH Authentication required. when the password is in place. I need to have password in place as per my project requirement. Please help. Thanks in advance.
So after some research, I got a solution for this issue:
We need to add:
'options' => [
'parameters' => ['password' => env('REDIS_PASSWORD', null)],
],
In config array. See complete example below: database.php
'redis' => [
'cluster' => false,
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 3,
],
'options' => [
'parameters' => ['password' => env('REDIS_PASSWORD', null)],
],
],
In .env file:
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=mmdgreat
REDIS_PORT=6379
I solve it downgrading the predis! :D
composer require predis/predis:0.8.4
I'm using the Laravel 5.3 too! :)

Don't use prepared statements in Laravel Eloquent ORM?

Can I have Eloquent ORM run a query without using prepared statements? Or do I have to use whereRaw()?
I need to use a raw query because I'm trying to interact with InfiniDB, which lacks support for prepared statements from PHP. At any rate, all queries will be using internally generated data, not user input so it should not be a security issue.
For anything other than SELECT you can use unprepared()
DB::unprepared($sql);
For an unprepared SELECT you can use plain PDO query() by getting access to active PDO connection through getPdo()
$pdo = DB::getPdo();
$query = $pdo->query($sql);
$result = $query->fetchAll();
There's an easy way to do it. In the file config/database.php you can specify options for php PDO like so:
'mysql_unprepared' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PROXY_PORT', '6033'),
'username' => env('DB_CACHED_USERNAME', 'forge'),
'password' => env('DB_CACHED_PASSWORD', ''),
'database' => env('DB_DATABASE', 'forge'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? [
PDO::ATTR_EMULATE_PREPARES => true,
] : [],
'modes' => [
'ONLY_FULL_GROUP_BY',
'STRICT_TRANS_TABLES',
'NO_ZERO_IN_DATE',
'NO_ZERO_DATE',
'ERROR_FOR_DIVISION_BY_ZERO',
'NO_ENGINE_SUBSTITUTION',
],
],
As you can see, there is an option PDO::ATTR_EMULATE_PREPARES which, when set to true, will do a prepare-like action on application level and send the query unprepared instead. I didn't figure PDO had this option until I had already created an extension for Laravel's mysql driver just to intercept select queries and do unprepared mysqli queries instead so that ProxySql could cache them.
So this answer could have been a lot more complicated. Cheers.