Codeigniter dynamically change to undefined Database - codeigniter

I need to connect to a DB that has not been defined in the database.php config file.
It has not been defined because there are over 200 possible databases.
I will loop through my clients table to get their client code that will determine which database will be in use at the moment.
I generate the db name with a string inside the loop like this:
$db_name = "db_".$row['code'];
From this, I need to connect to a new DB which will loop through the tables of the DB to check if this DB and the master DB are synchronized.
I tried the following code, but it does not seem to work:
$this -> db -> database = $db_name;
and I also tried to define a blank connection in the config like this:
$db['temp'] = $db['default'];
$db['temp']['database'] = "";
and then change to the generated DB name with the
$this -> db -> database = $db_name;
function, but did not work.
I am not sure if this is at all possibe, but this was all I could find on how to switch DB connections.
If you have any alternative suggestions, please let me know.
Thanx is advance

The switching of Databases you may have found in the CodeIgniter Documentation is probably the only, sensible way of obtaining the information without heavily bloating the config files. So hypothetically speaking:
$db_config = array(
//Shared values
'hostname' => '...',
'dbdriver' => '...';
);
$all_results = array();
$getDatabases = $this->database_model->get_databases();
foreach( $getDatabases as $key => $row )
{
$client_db = null;
$db_forge = null;
$db_name = "db_". $row['code'];
//Use copy of shared DB Values.
$active_config = $db_config;
$active_config['database'] = $db_name;
$client_db = $this->load->database( $active_config, TRUE );
$db_forge = $this->load->dbforge( $client_db, TRUE );
$result =
$client_db->select( "*" )
->get_where( "TB_EXAMPLE", array( "client_id" => '...' ))->row();
//Example of reason to drop the table
if ( !empty( $result ) && $result->INACTIVE == TRUE )
{
$db_forge->drop_table( "TB_EXAMPLE" );
}
//Now finished with this connection to this particular Database.
$client_db->close();
$all_results[] = $result;
}
However this is pretty ill-advised. It'll obviously connect to 200 different databases, intensive and expensive. If they are all on the same server; it would be better to SELECT by different databases, than instead connecting to them.

Related

$_SESSION variables use in queries

I have spent nearly two days going in circles on this one.
I seem to have difficulty using $_SESSION or $_POST as strings in any query or converting them to strings to use.
I am using a simple hash approach to login to a site.
Extract from script is
<?php
session_start();
echo "******Running Authenticate<br>";
echo "data submitted<br>".$_POST['site_login']."<br>".$_POST['site_password']."<br><br>";
$SiteLogin = $_POST['site_login']
$_SESSION['site_login'] = $_POST['site_login'];
$_SESSION['site_password'] = $_POST['site_password'];
$_SESSION['session_id'] = session_id();
$_SESSION['Now_val'] = date('Y-m-d H:i:s');
//include 'showallvars.php';
include 'dbconfig.php';
// Prepare our SQL
if ($stmt = $con->prepare('SELECT site_index, site_password FROM web_sites WHERE site_login = ?')) {
// Bind parameters (s = string, i = int, b = blob, etc), hash the password using the PHP password_hash function.
$stmt->bind_param('s', $_POST['site_login']);
$stmt->execute();
$stmt->store_result();
// Store the result so we can check if the account exists in the database.
if ($stmt->num_rows > 0) {
$stmt->bind_result($id, $password);
$stmt->fetch();
echo "account exists";
}
else
{
header('Location: badindex.php');
}
if (password_verify($_POST['site_password'], $password)) {
// Verification success! User has loggedin!
echo "password good";
}
else
{
header('Location: badindex.php');
}
}
$_SESSION['loggedin'] = TRUE;
?>
that works fine
BUT there is another field ( 'site_name') in the record which i want to carry forward.
This should be easy !!
and there is a dozen ways of doing it
for example the "standard" example is something like
$name = $mysqli->query("SELECT site_name FROM web_sites WHERE site_login = 'fred'")->fetch_object()->site_name;
That works fine
but no matter how i try - concatenating or or ... I cannot get $_SESSION['site_login'] or $_POST['site_login'] to replace 'fred'.
There seems to be white space added in.
Assistance or guidance ?
It should be possible to as easy as doing the following:
So:
if ($stmt = $con->prepare('SELECT site_index, site_password
FROM web_sites WHERE site_login = ?')) {
becomes:
if ($stmt = $con->prepare('SELECT site_index, site_password, site_login
FROM web_sites WHERE site_login = ' . $SiteLogin)) {
Do note, it is bad practice to do directly parse $SiteLogin to a query, because now someone can SQL Inject this and hack your website. All they need to do is use your form and figure out that which field is responsible for $SiteLogin. You would need to escape your $SiteLogin. Assuming Mysqli, it would become:
if ($stmt = $con->prepare('SELECT site_index, site_password, site_login
FROM web_sites WHERE site_login = ' . $con->real_escape_string($SiteLogin))) {
Thank you for that BUT the instant I saw the curly brackets in your answer - it all came flooding back to me. I had forgotten that PHP has problems with the square brackets
$sql = ("SELECT site_name FROM web_sites WHERE site_login = '". $_SESSION{'site_login'} ."' LIMIT 1");
I KNEW it was easy !
Your comments on injection are of course correct but this was an edited code excerpt and $SiteLogin was just added in as a "temporary working variable if needed"

jquery datatable with ajax based pagination

I have javascript function that populates datatable using Ajax. My javascript code looks like :
$('#results').dataTable({
// Ajax load data
"ajax": {
"url": "get_intl_tickets",
"type": "POST",
"data": {
"user_id": 451,
"csrfmiddlewaretoken" : csrftoken,
}
}
})
My server side script in django has a function that loads around 500 data rows. Now the problem is that I don't want to load whole data at a time. Instead I want to have first 10 data rows. Then with pagination, another 10 rows like that.
I read the page server side processing documentation of datatables. I tried with "serverSide": true option as well. I am not understanding server side script. There is given an example of PHP. It seems that they are not using any parameters like draw, recordsFiltered, recordsTotal there. There they have used php SSP class. And it is unknown what does it do. I am trying to implement it in django.
But I am not finding proper good documentation to implement. Any help will be appreciated.
Old question but one I also had a surprisingly difficult time finding an answer to, so in case anyone else ends up here... :P
I found this 2020 article very helpful, specifically part 6 showing the "complete code" that includes getting the correct variables, building the SQL query, and how to build/structure the data object that it responds with:
https://makitweb.com/datatables-ajax-pagination-with-search-and-sort-php/
Their example posted below:
<?php
## Database configuration
include 'config.php';
## Read value
$draw = $_POST['draw'];
$row = $_POST['start'];
$rowperpage = $_POST['length']; // Rows display per page
$columnIndex = $_POST['order'][0]['column']; // Column index
$columnName = $_POST['columns'][$columnIndex]['data']; // Column name
$columnSortOrder = $_POST['order'][0]['dir']; // asc or desc
$searchValue = mysqli_real_escape_string($con,$_POST['search']['value']); // Search value
## Search
$searchQuery = " ";
if($searchValue != ''){
$searchQuery = " and (emp_name like '%".$searchValue."%' or
email like '%".$searchValue."%' or
city like'%".$searchValue."%' ) ";
}
## Total number of records without filtering
$sel = mysqli_query($con,"select count(*) as allcount from employee");
$records = mysqli_fetch_assoc($sel);
$totalRecords = $records['allcount'];
## Total number of record with filtering
$sel = mysqli_query($con,"select count(*) as allcount from employee WHERE 1 ".$searchQuery);
$records = mysqli_fetch_assoc($sel);
$totalRecordwithFilter = $records['allcount'];
## Fetch records
$empQuery = "select * from employee WHERE 1 ".$searchQuery." order by ".$columnName." ".$columnSortOrder." limit ".$row.",".$rowperpage;
$empRecords = mysqli_query($con, $empQuery);
$data = array();
while ($row = mysqli_fetch_assoc($empRecords)) {
$data[] = array(
"emp_name"=>$row['emp_name'],
"email"=>$row['email'],
"gender"=>$row['gender'],
"salary"=>$row['salary'],
"city"=>$row['city']
);
}
## Response
$response = array(
"draw" => intval($draw),
"iTotalRecords" => $totalRecords,
"iTotalDisplayRecords" => $totalRecordwithFilter,
"aaData" => $data
);
echo json_encode($response);
Nice exemple:
https://datatables.net/examples/server_side/defer_loading.html
But you need edit server side.
Response demo
{
draw:2,
recordsFiltered:57,
recordsTotal:57
}

Active Record Delete works false

I try to delete entries in the database with the active records of Yii. But I think it works really weird.
I want to delete all records of my table where vehicle_id = the given id and plug_id NOT IN (given string)
I tried a lot of ways and nothing worked but this
$query = "delete from `vehicle_details` where `vehicle_id`= ".$vehicle->id." AND `plug_id` NOT IN (".implode(',', array_map(function($item) {
return $item->type;
}, $vehicleDetails->plug)).")";
$command = Yii::app()->db->createCommand($query);
$command->execute();
But why isn't this working???
VehicleDetail::model()->DeleteAllByAttributes(
array('vehicle_id' => $vehicle->id),
array('condition' => 'plug_id NOT IN (:ids)',
'params' => array('ids' => implode(',', array_map(function($item) {
return $item->type;
}, $vehicleDetails->plug)))));
Or this:
VehicleDetail::model()->deleteAll(' vehicle_id = :vehicleId AND plug_id NOT IN (:ids)', array('vehicleId' => $vehicle->id, 'ids' => implode(',', array_map(function($item) {
return $item->type;
}, $vehicleDetails->plug))));
But if I make and Find by attributes out of this query it works well and returns the correct data.
I hope you can explain it to me.
Your code does not work because of wrong arguments passed in the methods. Problems occur when YII tries to build CDbCriteria object using your array arguments. Fortunetly, you can build a CDbCriteria by yourself and pass it into methods directly. Guess in this particular case it will be easier to use a CDbCriteria object to solve the issue.
$dbc = new CDbcriteria();
$dbc->condition = 'vehicle_id = :vehicleId';
$dbc->params = array(':vehicleId'=>$vehicle->id);
$dbc->addNotInCondition(
'plug_id',
array_map(
function($item) {
return $item->type;
},
$vehicleDetails->plug)
);
VehicleDetail::model()->deleteAll($dbc);
That is all you need.

executeQueryLocally does not work well when using withParameters

I'm trying to use executeQueryLocally in a query that has 'withParamters', but it seems that I get locally cached data even when using new values in the 'withParameters'. It is as if 'executeQueryLocally' ignores values in 'withParameters'.
here is the code in the client side:
var query = EntityQuery.from('ProductsFilteredByCategory')
.withParameters({ categoryId: categoryId })
.select("productId,name,desc,shopPrice,webPrice")
.orderBy('name');
var p = manager.executeQueryLocally(query);
if (p.length > 5) {
productsObservable(p);
return Q.resolve();
}
here is the code for 'ProductsFilteredByCategory' on the server side:
[HttpGet]
public IQueryable<Product> ProductsFilteredByCategory(int categoryId)
{
Category category = _contextProvider.Context.Categories.Include("Products").Include("SubCategories").First(c => c.CategoryId == categoryId);
var prods = from p in category.Products select p;
category.SubCategories.ForEach(sc => prods = prods.Concat(_contextProvider.Context.Categories.Include("Products").First(c => c.CategoryId == sc.CategoryId).Products));
return prods.AsQueryable();
}
what happens is that after I retrieve the data once with 'p.length > 5' being true, in every subsequent call 'p.length > 5' is still true even when 'categoryId' is different, so the data that is bound to the observable is loaded once and never changes.
Thanks for your help !
Elior
The EntityQuery.withParameters method is NOT intended for local query use. (We should probably document this better).
WithParameters sends application domain specific parameters that can only be interpreted on the server. Unlike with 'where', 'orderBy', 'take' etc, there is no global interpretation that can be determined for a withParameters call. It can only be understood within the context of the server side method that accepts the parameters.

How to set Component parameters in J2.5?

I've created a J2.5 component with some config fields using config.xml in the admin folder of the component.
How can I set parameters in the config programatically?
I've tried the code bellow, but it obviously doesn't save the result to the DB:
$params = & JComponentHelper::getParams('com_mycomponent');
$params->set('myvar', $the_value);
Could anyone please show some examples of how to achieve this?
The safest way to do this would be to include com_config/models/component.php and use it to validate and save the params. However, if you can somehow validate the data params yourself I would stick with the following (much more simple solution):
// Get the params and set the new values
$params = JComponentHelper::getParams('com_mycomponent');
$params->set('myvar', $the_value);
// Get a new database query instance
$db = JFactory::getDBO();
$query = $db->getQuery(true);
// Build the query
$query->update('#__extensions AS a');
$query->set('a.params = ' . $db->quote((string)$params));
$query->where('a.element = "com_mycomponent"');
// Execute the query
$db->setQuery($query);
$db->query();
Notice how I cast the params to a string (when building the query), it will convert the JRegistry object to a JSON formatted string.
If you get any caching problems, you might want to run the following after editing the params:
From a model:
$this->cleanCache('_system');
Or, else where:
$conf = JFactory::getConfig();
$options = array(
'defaultgroup' => '_system',
'cachebase' => $conf->get('cache_path', JPATH_SITE . '/cache')
);
$cache = JCache::getInstance('callback', $options);
$cache->clean();
The solution is here...
http://www.webtechriser.com/tutorials/82-joomla-3-0/86-how-to-save-component-parameters-to-database-programmatically
You can replace in Joomla 2.5+ the
// check for error
if (!$table->check()) {
$this->setError('lastcreatedate: check: ' . $table->getError());
return false;
}
if (!$table->store()) {
$this->setError('lastcreatedate: store: ' . $table->getError());
return false;
}
with
if (!$table->save()) {
$this->setError('Save Error: ' . $table->getError());
return false;
}

Resources