Yii2 How to Execute two Statement using PDO? or other way - php

I want to CREATE DATABASE and in same database want to import data. But what i tried since getting no luck.
Action
public function actionRestore($id = null)
{
$list = $this->getFileList();
$file = $list[$id];
if(isset($file))
{
$transaction = Yii::$app->db->beginTransaction();
try{
$sql = 'DROP DATABASE IF EXISTS '.$this->getDbName().';CREATE DATABASE '.$this->getDbName();
$sqlFile = $this->path . basename($file);
Yii::$app->db->pdo->prepare($sql,$this->execSqlFile($sqlFile));
if(Yii::$app->db->pdo->exec())
{
$transaction->commit();
Yii::$app->session->setFlash('success', 'Backup Restored Successfully');
return $this->redirect(['index']);
}
$transaction->rollback();
}
catch(\Exception $e) {
$transaction->rollBack();
Yii::$app->session->setFlash('error', "Backup not Restored. <br>".$e->getMessage());
return $this->redirect(['index']);
}
}
}
I am not sure about execSqlFile() method :
public function execSqlFile($sqlFile)
{
$flag = false;
if (file_exists($sqlFile))
{
$sqlArray = file_get_contents($sqlFile);
$cmd = Yii::$app->db->createCommand($sqlArray);
try {
$cmd->execute();
$flag = true;
}
catch(Exception $e)
{
$flag = false;
throw new \yii\db\Exception($e->getMessage());
}
}
return $flag;
}
1) getDbName() gets database name.
1) getFileList() gets file to be executed in execSqlFile().
I am not getting any error or message of success or failure.
I want to combine both into one preparedStatement, but don't know what i am missing here.

I found the solution i need to use shell_exec:
public function execSqlFile($sqlFile)
{
if (file_exists($sqlFile))
{
$database=array();
$db=Yii::$app->db;
$database=explode(";",$db->dsn);
$dbname=explode("=",$database['1']);
$output = shell_exec('mysql -u '.$db->username.' -p'.$db->password.' '. $dbname['1'] .'< '.$sqlFile);
}
return $output;
}

Don't use PDO object directly. You loose abstractions. I would just execute two commands like this:
public function actionRestore($id = null)
{
if($id !== null && $this->restoreDatabase($id)) {
Yii::$app->session->setFlash('success', 'Backup Restored Successfully');
} else {
Yii::$app->session->setFlash('error', "Backup not Restored. <br>" . $e->getMessage());
}
return $this->redirect(['index']);
}
private function restoreDatabase($id)
{
$list = $this->getFileList();
$file = $list[$id];
if (isset($file)) {
$transaction = Yii::$app->db->beginTransaction();
try {
Yii::$app->db->createCommand('DROP DATABASE IF EXISTS ' . $this->getDbName() . '; CREATE DATABASE ' . $this->getDbName())->execute();
$sqlFile = $this->path . basename($file);
$this->execSqlFile($sqlFile);
$transaction->commit();
return true;
} catch (\Exception $e) {
$transaction->rollBack();
Yii::error($e->getMessage()); //Probably throw exception?
return false;
}
}
}
private function execSqlFile($sqlFile)
{
if (!file_exists($sqlFile)) {
return false;
}
$sql = file_get_contents($sqlFile);
$command = Yii::$app->db->createCommand($sql);
try {
$command->execute();
return true;
} catch (Exception $e) {
throw new \yii\db\Exception($e->getMessage());
}
}

Related

i have sql custom execution method, but there are found error unbuffered query

i have a class which has custom query execution. Then it shown some error if after i execute that.
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
I have search out my problem answer but, almost of them recommend me to put $stmt->closeCursor() in my code, but i have done with it and still get error. The error shown is same with error above. Below is my DBClassification class. Please help me. Thanks :)
<?php
class DBClassification
{
public $db = null;
public $host = "localhost";
public $user = "root";
private $pass = "";
public $path = __DIR__ . "\\";
public $prefixFilename = "klasifikasi_";
public $dbexception = [];
public $stmt;
public function setHost($host){
$this->host = $host;
}
public function setUser($user){
$this->user = $user;
}
public function setPass($pass){
$this->pass = $pass;
}
public function setPath($path)
{
if (!is_dir($path)) die ("Directory \$path is not correct!\n$path");
$lastchar = substr($path, -1);
if ($lastchar != "/" && $lastchar != "\\") $path = $path . "/";
if (strpos($path, '/') !== false) $path = str_replace("/","\\",$path);
$this->path = $path . $this->host . "\\"; // setting path to the generated output file
}
public function setPrefixFilename($prefixFilename){
$this->prefixFilename = $prefixFilename;
}
public function setDBException($dbexception=[]){
$this->dbexception = $dbexception;
}
public function init($host,$user,$pass,$path,$prefixFilename,$dbexception=[])
{
if (!$dbexception) $dbexception = ["information_schema","mysql","performance_schema","phpmyadmin","sys"];
$this->setHost($host);
$this->setUser($user);
$this->setPass($pass);
$this->setPath($path);
$this->setPrefixFilename($prefixFilename);
$this->setDBException($dbexception);
$this->openConnection();
}
// Establishing Connection to mysql database on specified host
public function openConnection(){
try {
$db = new PDO("mysql:host=".$this->host, $this->user, $this->pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->db = $db;
return true;
} catch (PDOException $e) {
die("Error!: " . $e->getMessage());
}
return false;
}
public function run(){
try {
$databases = $this->stmtExec("SHOW DATABASES",true);
foreach($databases as $database): // execute each database
$dbname = $database['Database']; // database name
if(!in_array($dbname,$this->dbexception)): // prevent clasifying dbname which contain in dbexception
echo "USE $dbname\n";
$this->stmtExec("USE $dbname");
$tables = $this->stmtExec("SHOW TABLES",true);
endif; // if(!in_array($dbname,$dbexception)):
endforeach; // foreach($databases as $database):
} catch (Exception $e) {
echo "Something wrong, failed to clasify each database in host " . $this->host . "\n";
die("Error!: ".$e->getMessage());
}
}
public function stmtExec($sql,$fetch=false)
{
try {
$this->stmt = $this->db->prepare($sql);
if ($fetch) {
if ($this->stmt->execute()) $return = $this->stmt->fetchAll(PDO::FETCH_ASSOC);
} else {
$return = $this->stmt->execute();
}
$this->stmt->closeCursor();
} catch (PDOException $e) {
$errormsg = "db Error: ". $this->stmt->queryString . PHP_EOL . $e->getMessage();
$queryFilename = $this->path . "error.txt";
file_put_contents($queryFilename, $errormsg);
print_r($errormsg);die();
}
return $return;
}
}
[ANSWERED]
I have found the solution from that, i have to delete false status in pdo attribute "PDO::ATTR_EMULATE_PREPARES". I think it become error because it will check query in prepare method. And query "use $dbname" is one which has no output and will give error if prepare check is on. Thats all my opinion.

Mysqli query function insert duplicate lines

I have been trying to insert a new line to mysql db but insert(){...} function has inserted duplicate lines.
I also have tried several methods to insert but it doesn't works. All of the methods have inserted duplicate rows .
How can I fix the problem? Do you have any idea?
Thank you for your help & advice.
protected $db;
public function __construct() {
try {
$this->db = new mysqli('localhost', 'root', '', 'trigger');
$this->db->set_charset("utf8");
} catch (mysqli_sql_exception $e) {
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
}
}
public function select($table, $rows = "", $where = "", $return_type = "") {
if (empty($rows)) {
$rows = "*";
}
if (empty($where)) {
$where = "";
} else {
$where = "where " . $where;
}
try {
$query = $this->db->query("SELECT $rows FROM $table $where");
if ($return_type == "json") {
return json_encode($query);
} else {
return $query;
}
} catch (mysqli_sql_exception $exc) {
return $exc->getMessage();
}
}
public function insert($table, $params) {
$_keyArr = array();
$_valueArr = array();
foreach ($params as $key => $value) {
$_keyArr[] .= $key;
$_valueArr[] .= $value;
}
$keys = implode("`,`", $_keyArr);
$values = implode("','", $_valueArr);
$query = $this->db->query("INSERT INTO `$table` (`$keys`) VALUES('$values')");
try {
return $query;
} catch (mysqli_sql_exception $ex) {
return $ex->getMessage();
}
}
-------------Answer to matt-------------
I call with following code:
if ($this->db->insert("table_name", array("path" => "test", "flow_name" => "test"))) {
echo 'ok';
} else {
echo 'not ok';
}
-------------Answer to Pavel-------------
"REPLACE INTO" didn't work. The problem occured again.
Just use REPLACE INTO instead INSERT INTO
$query = $this->db->query("REPLACE INTO `$table` (`$keys`) VALUES('$values')");

laravel decimal increment or + getting weird result

i'm trying to do when a user deposit, there is a deposit record, once admin approve, there is a transaction inserted, deposit record status update and increase user credit, but all the amount field is store as decimal(12,2)
here come the weird thing
user_credit = 1001.00
deposit_amount = 500.00
when user_credit + deposit_amount, the results is 501, what the ????
here is the transaction model approveDeposit() method
/**
*
* #param int $depositId
* #return boolean|array
*/
public function addDepositTransaction($depositId) {
$dp = null;
$user = null;
$t = null;
\DB::beginTransaction();
$errors = array();
//Select the deposit id
try {
$dp = new \Deposit();
$dp = $dp::find($depositId);
if (!$dp || !$dp->exists()) {
$errors[] = 'Deposit Id Not Found.';
\DB::rollback();
return $errors;
} else {
// if ($dp->status != 0) {
// $errors[] = 'This Deposit is already ' . $dp->getStatusText();
// \DB::rollback();
// return $errors;
// }
}
} catch(\Exception $ex) {
$errors[] = $ex->getMessage();
\DB::rollback();
return $errors;
}
//Select the user which taken from deposit
try {
$user = \User::find($dp->user_id);
} catch (\Exception $ex) {
$errors[] = $ex->getMessage();
\DB::rollback();
return $errors;
}
//Insert new transaction
try {
$t = new \Transactions();
$t->user_id = $dp->user_id;
$t->action = \Transactions::ACTION_DEPOSIT;
$t->credit = \Transactions::CREDIT_POINTS;
$t->credit_tag = \Transactions::CREDIT_TAG_POINTS;
$t->amount = $dp->deposit_amount;
$t->description_tag = 'deposit';
$t->description = 'User Deposit Accepted';
$t->related_one = $dp->id;
if ($t->save()) {
} else {
$errors = $t->errors()->all();
\DB::rollback();
return $errors;
}
} catch (\Exception $ex) {
$errors[] = $ex->getMessage();
\DB::rollback();
return $errors;
}
//Update the deposit status to 1(complete)
try {
$dp->status = 1;
if ($dp->save(\Deposit::getStatusRules())) {
} else {
$errors = $dp->errors()->all();
\DB::rollback();
return $errors;
}
} catch (\Exception $ex) {
$errors[] = $ex->getMessage();
\DB::rollback();
return $errors;
}
//Finally, update the user credits
try {
// $user->increment('points', (int)$dp->deposit_amount);
// (float)$user->points = (float)($user->points) + (float)($dp->deposit_amount);
dd($user->points + $dp->deposit_amount);
if ($user->save(\User::getPointsRules())) {
} else {
$errors = $user->errors()->all();
\DB::rollback();
return $errors;
}
} catch (\Exception $ex) {
$errors[] = $ex->getMessage();
\DB::rollback();
return $errors;
}
\DB::commit();
return true;
}
i try setting the variable type to both (int) (float) (string), also the result is wrong, i also tried the $model->increment('field', number), but the result become 2.00

insert elements into query php and mysql

i'm working on admin panel form and i have a problem in connect form page to mysql .. i made table name : main_settigns and i'm working with MVC .. this is the form controller :-
enter code here
<?php
if(isset($_POST['submit']) && $_POST['submit'] == "Update")
{
$mainsettings['site_name'] = $_POST['site_name'];
$mainsettings['site_url'] = $_POST['site_url'];
$mainsettings['site_desc'] = $_POST['site_desc'];
$mainsettings['site_email'] = $_POST['site_email'];
$mainsettings['site_tags'] = $_POST['site_tags'];
$mainsettings['site_homapanel'] = $_POST['site_homapanel'];
$mainsettings['fb'] = $_POST['fb'];
$mainsettings['tw'] = $_POST['tw'];
$mainsettings['yt'] = $_POST['yt'];
$mainsettings['username'] = $_POST['username'];
try {
include 'models/Arageek.php';
include 'models/Add.php';
$addmMainSettings = new Add($mainsettings, "main_settigns");
if($addmMainSettings == TRUE)
{
echo 'successfully Added';
}
}
catch (Exception $exc)
{
echo $exc->getMessage();
}
}
else
{
try {
include 'models/Arageek.php';
include 'models/Display.php';
$data = new Display("main_settigns");
$displayData = $data->getData();
} catch (Exception $exc)
{
echo $exc->getMessage();
}
include 'views/v_mainSettings.php';
}
?>
this is the model page :-
enter code here
<?php
/* add class
* insert the data into mysql database
* #author Dev.Yasser
*/
class Add extends Arageek
{
private $data;
private $tablename;
private $cxn;
public function __construct($data, $tablename)
{
if(is_array($data))
{
$this->data = $data;
$this->tablename = $tablename;
}
else
{
throw new Exception("Error: the data must be in an array .");
}
$this->connectToDB();
$this->AddData($this->data);
$this->close();
}
// insert the data into the table
function AddData($data)
{
foreach ($data as $key=> $value)
{
$keys[] = $key;
$values[] = $value;
}
$tblKeys = implode($keys, ",");
$dataValues = '"'. implode($values, '","') .'"';
$query = "INSERT INTO $this->tablename ($tblKeys) VALUES ($dataValues)";
if($sql = mysql_query($query))
{
return TRUE;
}
else {
throw new Exception("Error: Can not excute the query");
return FALSE;
}
}
}
?>
and the parent class :-
enter code here
<?php
class Arageek {
private $cxn;
function connectToDB()
{
include 'models/Database.php';
$vars = "include/vars.php";
$this->cxn=new Database($vars);
}
function close()
{
$this->cxn->close();
}
}
?>
the result after submit the form is : "Error: Can not excute the query"

I'm using Unit Of Work Design Pattern with PHP for my project

I'm working on a project which is using Unit of work design pattern. It includes Storage,EntityCollection,..... Code of unit of work includes PDO Adapter code file. But the adapter is not complete for running queries. I have found the files from somewhere.
I can't build queries what I want. Every time I'm writing code I faces to many problems related query. So can you please help me to make it more flexible... For example i want to run like : $db->select()->where('id>:id')->andWhere('')->orWHere()->orderBy()->groupBy()->having()->fetch()/fetchOne(); or similar to it.
<?php
namespace D\Adapter;
class PdoAdapter implements \D\DB\DatabaseInterface {
protected $config = array();
protected $database;
protected $connection;
protected $statement;
protected $fetchMode = \PDO::FETCH_ASSOC;
public function __construct($dsn, $username = null, $password = null, array $driverOptions = array()) {
$this->config = compact("dsn", "username", "password", "driverOptions");
$this->database = $driverOptions['db_name'];
}
public function getStatement() {
if ($this->statement === null) {
throw new \PDOException(
"There is no PDOStatement object for use.");
}
return $this->statement;
}
public function connect() {
// if there is a PDO object already, return early
if ($this->connection) {
return;
}
try {
$this->connection = new \PDO(
$this->config["dsn"], $this->config["username"], $this->config["password"], $this->config["driverOptions"]);
$this->connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$this->connection->setAttribute(
\PDO::ATTR_EMULATE_PREPARES, false);
} catch (\PDOException $e) {
throw new \RunTimeException($e->getMessage());
}
}
public function disconnect() {
$this->connection = null;
}
public function prepare($sql, array $options = array()) {
$this->connect();
try {
$this->statement = $this->connection->prepare($sql, $options);
return $this;
} catch (\PDOException $e) {
throw new \RunTimeException($e->getMessage());
}
}
public function execute(array $parameters = array()) {
try {
$this->getStatement()->execute($parameters);
return $this;
} catch (\PDOException $e) {
throw new \RunTimeException($e->getMessage());
}
}
public function countAffectedRows() {
try {
return $this->getStatement()->rowCount();
} catch (\PDOException $e) {
throw new \RunTimeException($e->getMessage());
}
}
/**
* countAffectedRows iin Alias
*/
public function count() {
try {
return $this->getStatement()->rowCount();
} catch (\PDOException $e) {
throw new \RunTimeException($e->getMessage());
}
}
public function getLastInsertId($name = null) {
$this->connect();
return $this->connection->lastInsertId($name);
}
public function fetch($fetchStyle = null, $cursorOrientation = null, $cursorOffset = null) {
if ($fetchStyle === null) {
$fetchStyle = $this->fetchMode;
}
try {
return $this->getStatement()->fetch($fetchStyle, $cursorOrientation, $cursorOffset);
} catch (\PDOException $e) {
throw new \RunTimeException($e->getMessage());
}
}
public function fetchAll($fetchStyle = null, $column = 0) {
if ($fetchStyle === null) {
$fetchStyle = $this->fetchMode;
}
try {
return $fetchStyle === \PDO::FETCH_COLUMN ? $this->getStatement()->fetchAll($fetchStyle, $column) : $this->getStatement()->fetchAll($fetchStyle);
} catch (\PDOException $e) {
throw new \RunTimeException($e->getMessage());
}
}
public function select($table, $bind = array(), $where = "", $options = array()) {
if (count($bind) > 0) {
foreach ($bind as $col => $value) {
unset($bind[$col]);
$bind[":" . $col] = $value;
}
}
if (isset($options['fields'])) {
$fields = $options['fields'];
} else {
$fields = '*';
}
$sql = "SELECT " . $fields . " FROM " . $table . " ";
if (strlen($where) > 2) {
$sql .= "WHERE " . $where;
}
// set_flash($sql);
$this->prepare($sql)
->execute($bind);
return $this;
}
public function query($sql, array $bind = array()) {
if (is_array($bind)) {
foreach ($bind as $col => $value) {
unset($bind[$col]);
$bind[":" . $col] = $value;
}
}
$this->prepare($sql)
->execute($bind);
return $this;
}
public function insert($table, array $bind) {
$cols = implode(", ", array_keys($bind));
$values = implode(", :", array_keys($bind));
foreach ($bind as $col => $value) {
unset($bind[$col]);
$bind[":" . $col] = $value;
}
$sql = "INSERT INTO " . $table
. " (" . $cols . ") VALUES (:" . $values . ")";
return (int) $this->prepare($sql)
->execute($bind)
->getLastInsertId();
}
public function update($table, array $bind, $where = "") {
$set = array();
foreach ($bind as $col => $value) {
unset($bind[$col]);
$bind[":" . $col] = $value;
$set[] = $col . " = :" . $col;
}
$sql = "UPDATE " . $table . " SET " . implode(", ", $set)
. (($where) ? " WHERE " . $where : " ");
return $this->prepare($sql)
->execute($bind)
->countAffectedRows();
}
public function delete($table, $where = "") {
$sql = "DELETE FROM " . $table . (($where) ? " WHERE " . $where : " ");
return $this->prepare($sql)
->execute()
->countAffectedRows();
}
public function fetchAllTables() {
$sql = "SHOW TABLES FROM " . $this->database;
$this->prepare($sql)
->execute();
return $this;
}
public function fetchAllFields($table) {
$sql = "SHOW FIELDS FROM " . $table;
$this->prepare($sql)
->execute();
return $this;
}
}
---FULL code is here---
https://github.com/batmunkhcom/mbm/tree/master/src/D
First of all the concern of an UnitOfWork Pattern is to track everything you do during a business transaction that can affect the database. After transactions, it figures out everything that needs to be done to alter the database as a result of your work. Your class has other concerns.
It looks like a godclass (antipattern). It has more than one responsibility: Connection, PeparedStatement, Execution, and other helpers. Its quite difficult to scale and maintain. Try to split all responsibilities to different classes in SOLID way with corresponding design pattern.
Your idea faced in your code is already done by other frameworks. Its very hard work to implement it again. For example you can try Doctrine ORM/DBAL Framework.

Categories