How to generate SqlDataProvider for 2 db connection - yii2

I have a 2 DB connection, db and db2. I want to get all data from table claim in db2 connection. Below is my sql and it did not read from db2 connection. How to solved this?
$sql = "SELECT * FROM claim where provider_id = xx ";
$sql_count = "SELECT COUNT FROM ( $sql ) AS count ";
$totalCount = Yii::$app->db2->createCommand($sql_count)->queryScalar();
$dataProvider = new SqlDataProvider([
'sql' => $sql,
'totalCount' => $totalCount,
'sort' =>false,
'pagination' => [
'pageSize' => 10,
],
]);
return $dataProvider;

First you need to configure your databases like below:
return [
'components' => [
'db1' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=db1name', //maybe other dbms such as psql,...
'username' => 'db1username',
'password' => 'db1password',
],
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=db2name', //maybe other dbms such as psql,...
'username' => 'db2username',
'password' => 'db2password',
],
],
];
Then you can simply :
//to get from db1
Yii::$app->db1->createCommand((new \yii\db\Query)->select('*')->from('tbl_name'))->queryAll()
//to get from db2
Yii::$app->db2->createCommand((new \yii\db\Query)->select('*')->from('tbl_name'))->queryAll()
If you are using an active record model, in your model you can define:
public function getDb() {
return Yii::$app->db1;
}
//Or db2
public function getDb() {
return Yii::$app->db2;
}
Then:
if you have set db1 in getDb() method, result will be fetched from db1 and so on.
ModelName::find()->select('*')->all();

Related

Error select SQL using expression DBQuery Yii2

iam using this to union 3 unrelated table. in table B and C works fine. but table A is getting error
$tableA = (new \yii\db\Query())
->select([new Expression('sm_wp.no_agenda,"Wajib Pajak" as kategori,mfwp.nama_wp,
user.nama,sm_wp.jenis_surat'),
"sm_wp.nomor_surat, sm_wp.tgl_surat, sm_wp.perihal",])
->from('sm_wp')
->leftjoin('mfwp', 'sm_wp.id_mfwp = mfwp.id')
->leftjoin('user', 'user.id = sm_wp.id_user')
;
error :
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.perihal FROM sm_wp LEFT JOIN mfwp ON sm_wp.id_mfwp = mfwp.id LEFT JOIN `u' at line 2
if i correct to be like this, its work..
$tableA = (new \yii\db\Query())
->select([new Expression('sm_wp.no_agenda,"Wajib Pajak" as kategori,mfwp.nama_wp,
user.nama,sm_wp.jenis_surat, sm_wp.nomor_surat, sm_wp.tgl_surat, sm_wp.perihal'),])
->from('sm_wp')
->leftjoin('mfwp', 'sm_wp.id_mfwp = mfwp.id')
->leftjoin('user', 'user.id = sm_wp.id_user')
;
its work(data appears in gridview as integer). but when i want to use if statement to define sm_wp.jenis_surat to be a string in gridview , no data appears (value not set).
whats wrong with my code..thanks for advice
update:here is my modelsearch
<?php
namespace app\models;
use yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Smwp;
use app\models\Mfwp;
use app\models\Pejabat;
use yii\db\Expression;
class RekapsmSearch extends Rekapsm
{
/**
* {#inheritdoc}
*/
public $nama_wp;
public $kategori;
public $nama;
public function rules()
{
return [
[['no_agenda', 'jenis_surat'], 'integer'],
[['perihal', 'nama_wp', 'nama', 'kategori', 'nomor_surat', 'tgl_surat'], 'safe'],
];
}
/**
* {#inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$tableA = (new \yii\db\Query())
->select([new Expression('sm_wp.no_agenda,"Wajib Pajak" as kategori,mfwp.nama_wp,
user.nama, sm_wp.jenis_surat,
sm_wp.nomor_surat, sm_wp.tgl_surat, sm_wp.perihal'),])
->from('sm_wp')
->leftjoin('mfwp', 'sm_wp.id_mfwp = mfwp.id')
->leftjoin('user', 'user.id = sm_wp.id_user')
;
$tableB = (new \yii\db\Query())
->select([new Expression('sm_seksi.no_agenda, "Seksi" as kategori,
mfseksi.nama_seksi,user.nama, if(sm_seksi.jenis_surat=1,"Permintaan Laporan",
if(sm_seksi.jenis_surat=2,"Permintaan Data",
if(sm_seksi.jenis_surat=3,"Permintaan Profile",
"Lain - Lain")))
'),"concat('ND-',sm_seksi.nomor_surat,'',mfseksi.kode_surat,
date_format(sm_seksi.tgl_surat,'%Y')),
sm_seksi.tgl_surat,sm_seksi.perihal",])
->from('sm_seksi')
->leftjoin('mfseksi', 'sm_seksi.id_pejabat = mfseksi.id')
->leftjoin('user', 'user.id = sm_seksi.id_user')
;
//echo $tableA->createCommand()->getRawSql();
//echo $tableB->createCommand()->getRawSql();
$tableC = (new \yii\db\Query())
->select([new Expression('sm_kpp.no_agenda,"KPP" as kategori, mfkpp.nama_kantor,
user.nama, if(sm_kpp.jenis_surat=1,"Pemberitahuan",
if(sm_kpp.jenis_surat=2,"Permintaan Data",
if(sm_kpp.jenis_surat=3,"Permintaan Profile",
"Lain - Lain"))),
sm_kpp.nomor_surat, sm_kpp.tgl_surat,sm_kpp.perihal'),])
->from('sm_kpp')
->leftjoin('mfkpp', 'sm_kpp.id_kpp = mfkpp.id')
->leftjoin('user', 'user.id = sm_kpp.id_user')
;
$unionQuery = (new \yii\db\Query())
->from(['dummy_name' => $tableA->union($tableB)->union($tableC)]);
$query = $unionQuery;
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->sort->attributes['nama_wp'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['nama_wp' => SORT_ASC],
'desc' => ['nama_wp' => SORT_DESC],
];
$dataProvider->sort->attributes['no_agenda'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['no_agenda' => SORT_ASC],
'desc' => ['no_agenda' => SORT_DESC],
];
$dataProvider->sort->attributes['jenis_surat'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['jenis_surat' => SORT_ASC],
'desc' => ['jenis_surat' => SORT_DESC],
];
$dataProvider->sort->attributes['nomor_surat'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['nomor_surat' => SORT_ASC],
'desc' => ['nomor_surat' => SORT_DESC],
];
$dataProvider->sort->attributes['tgl_surat'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['tgl_surat' => SORT_ASC],
'desc' => ['tgl_surat' => SORT_DESC],
];
$dataProvider->sort->attributes['perihal'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['perihal' => SORT_ASC],
'desc' => ['perihal' => SORT_DESC],
];
$dataProvider->sort->attributes['kategori'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['kategori' => SORT_ASC],
'desc' => ['kategori' => SORT_DESC],
];
$dataProvider->sort->attributes['nama'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['nama' => SORT_ASC],
'desc' => ['nama' => SORT_DESC],
];
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'no_agenda' => $this->no_agenda,
'jenis_surat' => $this->jenis_surat,
'tgl_surat' => $this->tgl_surat,
]);
$query
->andFilterWhere(['like', 'nama_wp', $this->nama_wp])
->andFilterWhere(['like', 'perihal', $this->perihal])
->andFilterWhere(['like', 'nomor_surat', $this->nomor_surat])
->andFilterWhere(['like', 'kategori', $this->kategori])
->andFilterWhere(['like', 'nama', $this->nama])
;
return $dataProvider;
}
}
on jenis surat wont change to be a string(table A), but work fine on table B and C

Yii2 save Log into Database

i have some problem with Log with Yii2.
I set Log Targets in this way:
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'flushInterval' => 1,//test
'targets' => [
[
'class' => 'common\components\SaDbTarget',
'levels' => ['error', 'warning','trace','info'],
'exportInterval' => 1,//test
//'categories' => ['application'],
/*'except' => [
'yii\db\*',
],*/
],
],
],
I create my SaDbTarget extending DbTarget Class, and this is working fine because i found in my table some log.
After that, in a controller i tried to set a log like this way
public function actionIndex(){
$searchModel = new CategorySearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
Yii::trace('trace log', __METHOD__);
Yii::warning('warning log');
// here is the rest of the code
}
I can see this 2 logs into the debug toolbar, but not in my db table.
According to the Docs
To make each log message appear immediately in the log targets, you
should set both flushInterval and exportInterval to be 1
I tried to set this values but still doesn't work.
I don't know what am I doing wrong.
UPDATE
This is my SaDbTarget
namespace common\components;
use Yii;
use yii\log\DbTarget;
use yii\log\Logger;
class SaDbTarget extends DbTarget{
//set custom table db for saving log
public $logTable = 'authlog';
//overwrite export();
public function export(){
$tableName = $this->db->quoteTableName($this->logTable);
$sql = "INSERT INTO $tableName ([[authlog_login]], [[authlog_ip]], [[authlog_area]], [[authlog_act]], [[authlog_time]], [[authlog_data]])
VALUES (:login, :ip, :area, :act, :time, :data )";
$command = $this->db->createCommand($sql);
//Get username
$user=Yii::$app->user->getId();
//Get user ip address
$ip = Yii::$app->request->getUserIP();
//Get area/controller
$controller=Yii::$app->controller->uniqueId;
//Get action
$event= Yii::$app->controller->module->requestedAction->id;
//Set timezone
$time = Yii::$app->formatter->asDate('now', 'php:Y-m-d H:i:s');
//Set Data
$data = $this->messages[0];
$command->bindValues([
':login' => $user,
':ip' => $ip,
':area' => $controller,
':act' => $event,
':time' => $time,
':data' => $data,
])->execute();
}
Could you check wether the 'log' component is set on bootstrap?
I think this could be the issue that the dispatcher is not setup and does not pickup the target.
So the bootstrap should look like
[
'bootstrap' => ['log'],
'components' => [
'log' => [
...
],
....
]
Another way would be to check in the debugger if the dispatcher on the logger is configured correctly.

How i can force an yii2 module to use a specific connection for all his models?

on a module I have add a component named db where i put, like the main Yii component, the data for database connection, I need in my module use everytime the db specified in his configuration for all models and not the main database connection, how I can do this?
You have several way eg. using a separated configuration in app/config/main.php
eg adding a specific dbMyMod to component config
return [
// ...
'components' => [
// ...
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=example',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
'dbMyMod ' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=hostForMudle;dbname=module_db_name',
'username' => 'user_module_name',
'password' => 'password',
'charset' => 'utf8',
],
],
or one way that not require a static configuration in app/confing
could be based on a module function that return a proper db connection
public function myModuleDbCon()
{
$myDbCon = new yii\db\Connection([
'dsn' => 'mysql:host=localhost;dbname=example',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
]);
return myDbConn;
}
then in you module you can retrive the module db connection
aDbConn = Yii::$app->getModule('my_module_name')->myModuleClass->myModuleDbCon();
.
$command = $aDbConn->createCommand('SELECT * FROM myTable');
$result= $command->queryAll();

Could not send email: unknown Cake\Network\Exception\SocketException in cakephp3

Okay I have been to almost all threads but I couldn't find the answer what I want.
Controller: RegistersController
namespace App\Controller;
use App\Controller\AppController;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Event\Event;
use Cake\Mailer\Email;
use Cake\Routing\Router;
class RegistersController extends AppController
{
public function add()
{
$this->loadModel('Tbusers');
$tbusers = $this->Tbusers->newEntity();
if ($this->request->is('post'))
{
$tbusers = $this->Tbusers->patchEntity($tbusers, $this->request->data);
if ($this->Tbusers->save($tbusers)) {
$this->Flash->success(__('Yayie! You have been registered.'));
$baseurl = Router::url('/', true);
$email = base64_encode($this->request->data['email']);
$first_name = $this->request->data['fname'];
$last_name = $this->request->data['lname'];
$username = $first_name.' '.$last_name;
//$confirmation_link = $baseurl.'users/confirm/'.$email;
$email = new Email();
$email->template('email')
->subject('Student Portal - Signup')
->emailFormat('html')
->to($this->request->data['email'])
//->viewVars(['confirmation_link' => $confirmation_link,'username'=>$username])
->viewVars(['username'=>$username])
->from('dotnetdev555#gmail.com')
->send();
if ($email->send())
{
// Success
echo "mail sent";
}
else
{
echo "Mail not sent";
// Failure
}
return $this->redirect(['action' => 'add']);
}
}
Inside Template->Email->html I have file called
email.ctp
Hello <?php echo $username; ?>,<br/>
Thanks,<br/>
Jaymin Sejpal Founder at Student Portal
app.php
'EmailTransport' => [
'default' => [
'className' => 'Mail',
// The following keys are used in SMTP transports
'host' => 'smtp.elasticemail.com',
'port' => 2525,
'timeout' => 30,
'username' => 'dotnetdev555#gmail.com',
'password' => 'secret',
'client' => null,
'tls' => null,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],
I don't know what I am missing to it. I am refferring this
http://book.cakephp.org/3.0/en/core-libraries/email.html for now.
The email host that you are using might be using smtp protocol , so in your app.php . Try editing you className parameter to 'Smtp'
'EmailTransport' => [
'default' => [
'className' => 'Smtp',
// The following keys are used in SMTP transports
'host' => 'smtp.elasticemail.com',
'port' => 2525,
'timeout' => 30,
'username' => 'dotnetdev555#gmail.com',
'password' => 'secret',
'client' => null,
'tls' => null,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],

Phalcon PDO transaction is not working correct

It nearly took me a whole day to resolve the problems about transactions, but I failed.
My requirement is INSERT a new record both in table topic and table topic_data in one transaction.
I have my code like this :
// database connection
$di->set( 'db', function() use( $conf ) {
return new \Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter( [
'host' => $conf->db->host,
'username' => $conf->db->username,
'password' => $conf->db->password,
'dbname' => $conf->db->dbname,
'options' => [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_PERSISTENT => true,
\PDO::ATTR_AUTOCOMMIT => false
]
] );
} );
// transaction code
public function create( $params ) {
$this->db->begin();
$id = \Idalloc::next();
$topic = new Topic();
$topic->id = $id;
$topic->ctime = $_SERVER[ 'REQUEST_TIME' ];
$tags = $params[ 'tags' ];
$params[ 'tags' ] = implode( ',', $tags );
$topic->assign( $params );
if( $topic->save() === false ) {
$this->db->rollback();
return false;
}
for( $i = 0, $l = count( $tags ); $i < $l; ++$i ) {
$topicTag = new TopicTag();
$topicTag->tag_id = $tags[ $i ];
$topicTag->topic_id = $id;
$topicTag->type = $params[ 'type' ];
if( $topicTag->save() === false ) {
$this->db->rollback();
return false;
}
}
var_dump( $this->db->isUnderTransaction() );
$this->db->commit();
return $id;
}
The fails with :
If I don't set \PDO::ATTR_PERSISTENT => true, method "create" with return $id and var_dump( $this->db->isUnderTransaction() ) is TRUE but NO DATA been inserted into both table topic and table topic_tag
If I set \PDO::ATTR_PERSISTENT => true, I will get Exception with :
[Tue, 21 Jun 16 02:16:21 +0800][ERROR] PDOException: There is no active transaction
And still failed to insert data into table topic, but new record appearing in table topic_tag.
If I only keep one of the two parts, it will be working well.
How can I resolve this problem and is there a simple way to create Manual Transactions ?
I found out the solution for this question. The 'db' set in DI must be shared. So there need another parameter "TRUE" :
// database connection
$di->set( 'db', function() use( $conf ) {
return new \Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter( [
'host' => $conf->db->host,
'username' => $conf->db->username,
'password' => $conf->db->password,
'dbname' => $conf->db->dbname,
'options' => [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_PERSISTENT => true,
\PDO::ATTR_AUTOCOMMIT => false
]
] );
}, true );