CodeIgniter active records' problems calling multiple stored procedures - mysql

class Registration_model extends CI_Model {
function __construct() {
parent::__construct();
}
function check_email_availability($email)
{
$sql = "CALL proc_1301('$email');";
$query = $this->db->query($sql) or die(mysql_error());
return $query->row_array();
}
function check_username_availability($username)
{
$sqlt = "CALL proc_1303('$username');";
$query = $this->db->query($sqlt) or die(mysql_error());
return $query->row_array();
}
function process_registration($username, $email, $password)
{
$sql = "CALL `proc_1302`('$username', '$email', '$password');";
$query = $this->db->query($sql) or die(mysql_error());
return $query->result_array();
}
this is my controller code which calls three functions from model one by one:
$emailCheckRes = $this->Registration_model->check_email_availability($email);
$usernameCheckRes = $this->Registration_model->check_username_availability($username);
$this->data['regRes'] = $this->Registration_model->process_registration($username, $email, $password);
my problem is when i run only one function it runs successfully but when i run two of them or all three it shows blank page... any idea why ???
SOLUTION
So finally the only solution we got for my own problem is :
/* ADD THIS FUNCTION IN SYSTEM/DATABASE/DB_ACTIVE_REC */
/* USAGE $this->db->freeDBResource($this->db->conn_id); */
function freeDBResource($dbh){
while(mysqli_next_result($dbh)){
if($l_result = mysqli_store_result($dbh)){
mysqli_free_result($l_result);
}
}
}

The problem is related to CodeIgniter's active recors and multiple database stored procedure calling.
First of all check that dbdriver parameter (application/config/database.php) is set to mysqli.
Then, as described in "Calling a stored procedure from CodeIgniter's Active Record class" question on StackOverflow, adding to system/database/DB_active_rec.php the following function:
function freeDBResource($dbh){
while(mysqli_next_result($dbh)){
if($l_result = mysqli_store_result($dbh)){
mysqli_free_result($l_result);
}
}
}
..And in your controller use:
$this->db->freeDBResource($this->db->conn_id);
after any stored procedure calling.

Model and Controller seems to be ok.
If you try a model like:
class Test_model extends CI_Model
{
function __construct()
{
parent::__construct();
}
function a($a_input)
{
return($a_input.': a');
}
function b($b_input)
{
return($b_input.': b');
}
}
...And call it functions from a controller like this:
$this->load->model('Test_model');
$a_result = $this->Test_model->a('aaa');
$b_result = $this->Test_model->b('bbb');
echo($a_result.'<br />'.$b_result);
You can see multiple function calling working fine.
Are you sure you can execute any of three function in model correctly, if you call only one?
If yes, maybe the problem can be find in your stored procedures... Can you try to execute a normal query instead of stored procedures, in model functions? For debug your problem, check also in your /application/config/database.php if db_debug is set to TRUE.

Related

Doctrine - delete all entities

I have problem with deleting all rows in database. I can't find out how to do it. I'm using Symfony and Doctrine. Somewhere I read, that it isn't possible "normal" way, but I can do it by DQL (createQuery), but I don't know syntax.
public function resetDatabase(EntityManagerInterface $em)
{
$query = $em->createQuery('DELETE ???');
$query->execute();
return new Response('', Response::HTTP_OK);
}
public function resetDatabase(EntityManagerInterface $em)
{
$query = $em->createQuery(
'DELETE FROM App\Entity\YourEntity e WHERE e.age > :ageparameter'
)->setParameter('ageparameter', 10)->execute();
return new Response('', Response::HTTP_OK);
}
Ou... I have find out, how to do it.
/**
* #Route("/resetdatabase")
*/
public function resetDatabase(EntityManagerInterface $em)
{
$repository = $em->getRepository(MoneyDatabase::class);
$entities = $repository->findAll();
foreach ($entities as $entity) {
$em->remove($entity);
}
$em->flush();
return new Response('', Response::HTTP_OK);
}
But sometimes it must run twice, because somehow after 30 seconds entities return (but there are only compulsory columns, others are null). And after second run it disappear completely. It's strange, that it does only sometimes. Why it does at all?

Show usage of dynamic generated callable function name

Is there any posibility in PhpStorm to map usage of dynamic generated fucntion between it declaration an usage?
Assume I have next code:
<?php
class TestExample {
public function __construct($component) {
$component_parts = $this->get_dynamic_component_part_list($component);
$this->load_component_parts($component, $component_parts);
}
private function get_dynamic_component_part_list($component){
//Complex logic to get attached parts by $component
$component_parts = array('part1', 'part2');
return $component_parts;
}
private function load_component_parts(&$component, $component_parts) {
foreach ($component_parts as $component_part) {
$component[$component_part] = $this->{'load_' . $component_part}($component['id']);
}
}
private function load_part1($id) {
//Loading and prepare condition from one source
$part1 = new Part1($id);
// Complex algorithm
return $part1;
}
private function load_part2($id) {
//Loading and prepare condition from another source
$part2 = new Part2($id);
// Complex algorithm
return $part2;
}
}
class Part1 {
}
class Part2 {
}
I want to see usage of load_part1 and load_part2.
Is there any way to do it by usage phpDoc or in some other way?
At this moment PhpStorm notice me that this function doesn't have usage but realy it used in load_component_parts method.
You can use the phpDoc annotation #see.
For example:
$className = 'SomeClass';
$method = 'methodToCall';
$anArgument = 'bar';
/** #see SomeClass::someMethod() */
$foo = call_user_func([$className, $method], $anArgument);
This annotation will create at least a reference to this code, so that you know to come back here when you review SomeClass::someMethod() before throwing the "unused" method away.

Yii2 pass query result to a action in another controller

I'm trying to insert record into my audit table upon update of record in any other table. For example, if a user update his profile I want to store the old record and the newly updated record in my audit table. For this in my user model I'm trying to use beforeSave() and pass the value to my audit controller
public function beforeSave($insert)
{
if((parent::beforeSave($insert))){
// Place your custom code here
$query = DepCustomer::findOne($this->customer_id);
Yii::$app->runAction('audit-trial/createaudit', ['query' => $query]);
return true;
}
}
And the action code in audit controller for now
public function actionCreateaudit($query)
{
$model = new Audit();
$model->old = '';
foreach($query as $name => $value){
//$temp = $name .': '. $value.', ';
//$contentBefore[] = $temp;
$audit->old = $audit->old.$name .': '. $value. ', ';
}
// I've not yet any other code for now I'm trying to get the old value
$model->save();
}
I'm getting 404 not found error. What do I need to change in my code to make it work? Thank you!
instead of runAction() . If you want to perform operation on another model, prefer to create a static function in that model (in your case Audit model) to save the data
public function beforeSave($insert)
{
if((parent::beforeSave($insert))){
// Place your custom code here
$query = DepCustomer::findOne($this->customer_id);
Audit::saveOldDetails($query);
return true;
}
}
and write saveOldDetails function in Audit Model
public static saveOldDetails($query){
// your business logic here
}
Refer this link
http://www.yiiframework.com/doc-2.0/yii-base-controller.html#runAction()-detail

Method chainning for join table with pagination on CI 3

I create a core class named MY_Model that extends CI_Model. In this class, I create a method chaining to get all record with pagination like this :
// Take record with paging.
public function get_all_paged()
{
// get argument that passed
$args = func_get_args();
// get_all_paged($offset)
if (count($args) < 2) {
$this->get_real_offset($args[0]);
$this->db->limit($this->_per_page, $this->_offset);
}
// get_all_paged(array('status' => '1'), $offset)
else {
$this->get_real_offset($args[1]);
$this->db->where($args[0])->limit($this->_per_page, $this->_offset);
}
// return all record
return $this->db->get($this->_tabel)->result();
}
So , I just used like this on my controller,
for example
public function index($offset = NULL) {
$karyawan = $this->karyawan->get_all_paged($offset); //get all
}
I am realy confuse to get all record using join, I know join in CI like this :
public function get_all_karyawan() {
$this->db->select('tb_1 , tb_2');
$this->db->from('tb_1');
$this->db->join('tb_2', "where");
$query = $this->db->get();
return $query->result();
}
How to make it into chain in MY_Model?
Any help it so appreciated ...
The good thing in query builder, you can chain your db methods, till get(). So you can define, selects, where queries, limits in different ways.
For example:
public function category($category)
{
$this->db->where('category_id', $category);
return $this;
}
public function get_posts()
{
return $this->db->get('posts')->result();
}
And you can get all posts:
$this->model->get_posts();
Or by category:
$this->model->category(2)->get_posts();
So upon this, in your model:
public function get_all_karyawan() {
$this->db->select('tb_1 , tb_2');
$this->db->join('tb_1', "where");
// Here you make able to chain the method with this
return $this;
}
In your controller:
public function index($offset = NULL) {
$karyawan = $this->karyawan->get_all_karyawan()->get_all_paged($offset);
}

Foeign Key Locking Transaction timeout when a second database connection is opened

I'm having a problem involving a database transaction in one class that is timing out due to a secondary database connection being opened within the transaction; the problem started occurring when I added a foreign key constraint. And, testing using:
SET foreign_key_checks = 0;
I've been able to confirm this.
My database class looks like this (I've left off all of the methods):
class Db {
function __construct($config) {
$this->config = $config;
}
private function connect($config) {$dsn = 'mysql:host=' . $config['host'] . ';dbname=' . $config['dbname'] . ';charset=utf8';
$options = array(
// PDO::ATTR_PERSISTENT => true,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
$dbh = new PDO($dsn, $config['username'], $config['password'], $options);
$dbh->exec("SET NAMES utf8;");
return $dbh;
}
}
My model looks like this:
class Model {
function __construct() {
$this->db = new Db(array('host'=>DB_HOST,'dbname'=>DB_NAME,'username'=>DB_USERNAME,'password'=>DB_PASSWORD));
}
}
The code below then performs a little bit of logic, then an insert into the question_orders table: question_orders has a column question_id, with a foreign key index, which references the parent table questions; I think that the problem is that Assessment_Question_Orders extends the Model and creates a new database connection? Any thoughts on how to maintain both the transaction and foreign key aspects would be appreciated.
class This_Is_A_Problem extends Model() {
public function __construct() {
parent::construct();
}
public function problemFunction() {
/*variable init code left out*/
$this->db->beginTransaction();
$db_result = false;
try {
$db_result = $this->db->insert('questions', $questions_data);
$new_insert_id = $this->db->lastInsertId();
$assessment_question_orders = new Assessment_Question_Orders();
$question_number = $assessment_question_orders->insertSingleQuestionOrder($module_id, $new_insert_id);
$db_result = $this->db->commit();
}
} catch (PDOException $e) {
$this->db->rollBack();
}}}
One thread should (usually) have only one connection to the database. So I recommend one of these patterns:
Plan A: a single $db passed into all classes:
$db = new PDO(...);
$my_obj = new My_Class($db); -- $db is saved in $this->db for use within the methods of My_Class.
Plan B: a singleton Db class with a getter method:
// Singleton (of sorts)
class Db
{
private static $db;
function __construct()
{
self::$db = new PDO(...);
// A variant would include "lazy" instantiation of self::$Db.
}
function Get_Db() { return self::$db; } // All calls get the same `db`
}
class My_class
{
function My_Method()
{
$db = Db::Get_Db();
$db->...
}
}
new Db(); // one time call at start of program
There is only rarely a need to have two db connections in a single program. Plan A easily allows for such. (But see if you can avoid it -- you are in trouble now because of it.)