Codeigniter mysql db connection with Amazon RDS failing - php

I am having the worst time with this after searching for hours and hours.
My connection to Amazon RDS credentials are correct, however, I cannot pull any data and I get a 500 error from the following.
I've made this in the most raw of coding to avoid any CI mistakes, On my model I have:
class Foreclosure_model extends CI_Model {
public function __construct() {
parent::__construct();
$this->db = $this->load->database('aws');
}
function get_sql_results($state,$county){
return $this->db->query("select State, County from foreclosure_properties where State = 'CA' AND County = 'del norte'");
}
}
Then on my controller I have:
$this->data['listings'] = $this->foreclosure_model->get_sql_results($state,$county);
on my aws connection information I have:
$db['aws']['hostname'] = 'XXXXXXXXXXXXX.us-west-2.rds.amazonaws.com';
$db['aws']['username'] = 'XXXXXXXX';
$db['aws']['password'] = 'XXXXXXXX';
$db['aws']['database'] = 'xxxxxx_xxxxxx';
$db['aws']['dbdriver'] = 'mysql';
$db['aws']['dbprefix'] = '';
$db['aws']['pconnect'] = TRUE;
$db['aws']['db_debug'] = TRUE;
$db['aws']['cache_on'] = FALSE;
$db['aws']['cachedir'] = '';
$db['aws']['char_set'] = 'utf8';
$db['aws']['dbcollat'] = 'utf8_general_ci';
$db['aws']['swap_pre'] = '';
$db['aws']['autoinit'] = TRUE;
$db['aws']['port'] = 3306;
I have tried doing this exact same connection directly with Navicat to test the sql connection and query, it works successfully. I cannot seem to get this to run in Codeigniter.
The result when run on Codeigniter is a 500 error.
Any assistance is greatly appreciated.

As you're using more than one connection, you'll want to pass in a second parameter of 'TRUE' to return the database object.
$this->db = $this->load->database('aws', TRUE);
If you don't pass this, then the database object is not returned and therefor you can't call any of the functions (such as get(), query() etc).
You can read more about multiple connections here:
https://ellislab.com/codeigniter/user-guide/database/connecting.html
Hope this helps - let me know how you get on!
Note: It may be worth mentioning it may make things easier if instead of assigning the database to $this->db, you chose another name such as $this->aws_db as then you're not overwriting the $this->db object for your default database. Probably not a big issue, but may make it easier to troubleshoot as your project grows.

Related

Slow performance MySql

I'm trying out performance of a system I'm building, and it's really slow, and I don't know why or if it should be this slow. What I'm testing is how many single INSERT I can do to the database and I get around 22 per second. That sounds really slow and when I tried to do the inserts i a singel big SQL-query I can insert 30000 records in about 0.5 seconds. In real life the inserts is made by different users in the system so the overhead of connecting, sending the query, parsing the query etc. will always be there. What I have tried so far:
mysqli with as little code as possible. = 22 INSERT per second
PDO with as little code as possible. = 22 INSERT per second
Changing the connection host from localhost to 127.0.0.1 = 22 INSERT per second
mysqli without statement object and check for SQL-injection = 22 INSERT per second
So something seams to be wrong here.
System specs:
Intel i5
16 gig ram
7200 rpm diskdrive
Software:
Windows 10
XAMPP, fairly new with MariaDB
DB engine innoDB.
The code I used to do the tests:
$amountToInsert = 1000;
//$fakeData is an array with randomly generated emails
$fakeData = getFakeData($amountToInsert);
$db = new DatabaseHandler();
for ($i = 0; $i < $amountToInsert; $i++) {
$db->insertUser($fakeUsers[$i]);
}
$db->closeConnection();
The class that calls the database:
class DatabaseHandler {
private $DBHOST = 'localhost';
private $DBUSERNAME = 'username';
private $DBPASSWORD = 'password';
private $DBNAME = 'dbname';
private $DBPORT = 3306;
private $mDb;
private $isConnected = false;
public function __construct() {
$this->mDb = new mysqli($this->DBHOST, $this->DBUSERNAME
, $this->DBPASSWORD, $this->DBNAME
, $this->DBPORT);
$this->isConnected = true;
}
public function closeConnection() {
if ($this->isConnected) {
$threadId = $this->mDb->thread_id;
$this->mDb->kill($threadId);
$this->mDb->close();
$this->isConnected = false;
}
}
public function insertUser($user) {
$this->mDb->autocommit(true);
$queryString = 'INSERT INTO `users`(`email`, `company_id`) '
.'VALUES (?, 1)';
$stmt = $this->mDb->prepare($queryString);
$stmt->bind_param('s', $user);
if ($stmt->execute()) {
$stmt->close();
return 1;
} else {
$stmt->close();
return 0;
}
}
}
The "user" table has 4 columns with the following structure:
id INT unsigned primary key
email VARCHAR(60)
company_id INT unsigned INDEX
guid TEXT
I'm at a loss here and don't really know where to look next. Any help in the right direction would be very much appreciated.
Like it's explained in the comments, it's InnoDB to blame. By default this engine is too cautious and doesn't utilize the disk cache, to make sure that data indeed has been written on disk, before returning you a success message. So you basically have two options.
Most of time you just don't care for the confirmed write. So you can configure mysql by setting this mysql option to zero:
innodb_flush_log_at_trx_commit = 0
as long as it's set this way, your InnoDB writes will be almost as fast as MyISAM.
Another option is wrapping all your writes in a single transaction. As it will require only single confirmation from all the writes, it will be reasonable fast too.
Of course, it's just sane to prepare your query only once with multiple inserts but the speed gain is negligible compared to the issue above. So it doesn't count neither as an explanation nor as a remedy for such an issue.
Your test isn't a very good way of judging performance. Why because you are preparing a statement 1000 times. That's not the way prepared statements are supposed to be used. The statement is prepared once and different parameters bound multiple times. Try this:
public function __construct() {
$this->mDb = new mysqli($this->DBHOST, $this->DBUSERNAME
, $this->DBPASSWORD, $this->DBNAME
, $this->DBPORT);
$this->isConnected = true;
$queryString = 'INSERT INTO `users`(`email`, `company_id`) '
.'VALUES (?, 1)';
$this->stmt_insert = $this->mDb->prepare($queryString);
}
and
public function insertUser($user) {
$this->stmt_insert->bind_param('s', $user);
if ($this->stmt_insert->execute()) {
return 1;
} else {
return 0;
}
}
And, you will be seeing a huge boost in performance. So to recap, there's nothing wrong with your system, it's just the test that was bad.
Update:
Your Common Sense has a point about preparing in advance and reusing the prepared statement not giving a big boost. I tested and found it to be about 5-10%
however, There is something that does give a big boost. Turning Autocommit to off!. Inserting 100 records which previously took about 4.7 seconds on average dropped to < 0.5s on average!
$con->autocommit(false);
/loop/
$con->commit();

PHP OOP Help - Work In Progress

I am right now trying to write a PHP class that executes database information. Yet I feel like I am doing something majorly wrong! It seems like what you would have to type in to get it to work is too much. Here is a example of what it looks like:
<?php
class database {
public $query_type = "";
public $database_name = "";
public $database_items_query = array();
public $database_where = "";
public function __construct($query_type, $database_name, $database_items_query, $database_where) {
$this->query_type = $query_type;
$this->query_name = $query_name;
$this->query_items_query = $query_items_query;
$this->query_where = $query_where;
}
public function database_query($query_type, $database_name, $database_items_query, $database_where) {
if ($query_type == "select") {
return $sqlquery = "SELECT ($database_items_query) FROM $database_name WHERE $database_where";
}
elseif ($query_type == "update") {
return $sqlquery = "UPDATE $databasename ";
}
}
}
$username = new database("");
?>
So for the beginning you would have to type in just this to get it to work the first function?
$username = new database("select","users","username","id");
So basically with what I have so far, what am I doing wrong? Sorry if this does not make sense :(
Ok I can see what you are trying to do, A constructor is normally used to "Create" a object. When the object is created then you have the opportunity to store values inside it so you dont have to
re-enter them, You only have to call a constructor once in a objects lifetime, and you can reuse all the methods multiple times.
soo... if you change your method declaration for database_query to something along these lines:
public function database_query($database_items_query = $this->database_items_query, $database_where = $this->query_where) {
$query_type = $this->query_type;
$database_name = $this->database_name;
Then you would be using the class variables as default values so your code would be something along the lines of
$columns = array("Name","Description");
$db = new database("SELECT","my_db",$columns,"1=1");
$db->database_query(); // returns name and description from all rows
$db->database_query(array("*") ); // returns all columns and rows
$db->database_query(array("*"),"id=7"); // returns all columns where id = 7
$other_db = new database("SELECT","my_other_db",$columns,"1=1");
$db->database_query(array("id") ); // calling database_query on first object instance
$other_db->database_query(array("*") ); // calling database_query on second object instance
When using objects/classes you have to remember that you can declare variables which belong to a given instance of the object so you can re
Dunno about you but when I was your age I was writing a fair bit of C, and to get introduced to OO I was described classes as being structs with function pointers inside.
If trying to learn OO I would reccomend taking a look at java since there is a lot of first principals OO stuff out there, then once comfortable with that style of code
taking what you have learned across to the language which you know a bit better (in your case PHP.)

duplicate return value php

$amnt = "1.00";
$from = "USD";
$to = "GBP";
/* Set up new DB object with the from/to currency */
$DBob = new database($from, $to);
$locFrom = $DBob->readLocation($from);
$locTo = $DBob->readLocation($to);
echo $locFrom . $locTo;
The echo return for both objects return the same value, for the $to variable... rather than returning two seperate queries in SQL. The queries are the same however one uses the $from currency code and the other uses the $to currency code
sql code:
public function readLocation($toFrom)
{
//establish a connection to the mysql database
$dbcon = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) OR DIE ('Could not connect to Mysql database: '. mysqli_connect_error());
if ($toFrom == 'from')
{
//$substring1 = substr($this->fromcurr,0,2);//
$query2 = ("SELECT location AS loc FROM currency WHERE countrycode ="."'$this->fromcurr'");
}
elseif ($toFrom == 'to');
{
//$substring1 = substr($this->tocurr,0,2);//
$query2 = ("SELECT location AS loc FROM currency WHERE countrycode ="."'$this->tocurr'");
}
$result = mysqli_query($dbcon,$query2);
$resultR = mysqli_fetch_array($result);
mysqli_close($dbcon);
$queryResult = $resultR['loc'];
return $queryResult;
}
You have messed up the code of the function so it does not work. I highlight some points how you can improve it which will help you to not only remove the errors but to prevent similar errors in the future by changing how you write your code.
In this discussion, I leave the topic of proper value encoding aside which can result into flaws and defects (SQL inection). Just saying, you should add those on your own.
The main business of the function is to build a conditional SQL query and execute it. So first of all move the query building out of the function into a function of it's own:
private function buildReadLocationSQL($countrycode)
{
$SQLPattern = "SELECT location AS loc FROM currency WHERE countrycode = '%s'";
return sprintf($SQLPattern, $countrycode);
}
Then you need to find out what $countrycode should be. You are using two string values here to describe what you need. Why not name the functions instead?
public function readLocationFrom()
{
...
}
public function readLocationTo()
{
...
}
Having two functions here it's clear what they do and you can not make any mistakes when you invoke (call) them.
The missing part is to encapsulate the database connection and query. This makes sense anyway because you only want to connect to the database once your application runs and not on every query. Connecting to a database is expensive. Also this helps to extend your class later on by making the code more modular.
So let's change the database class a bit to make it store the connection (you don't need to explicitly close it either, PHP will do this for you when the script ends) and to offer a function to query the database:
class Database
{
private $connection;
private function connect()
{
$connection = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if ($connection === FALSE)
{
throw new RuntimeException(sprintf('Could not connect to Mysql database: %s', mysqli_connect_error()));
}
$this->connection = $connection;
}
private function query($sql)
{
if (!$this->connection) $this->connect(); // lazy connect to the DB
$result = mysqli_query($this->connection, $sql);
if (!$result)
{
throw new RuntimeException(sprintf('Could not query the Mysql database: %s', mysqli_error($this->connection)));
}
return $result;
}
...
}
These two new private functions take care about the database specific connection and query jobs. As you add more and more functions to your database class over time, you can easily re-use them. Also those two are private (as the $connection member), because you want to hide the details from the rest of your application.
This now needs to be brought together with the readLocationFrom and readLocationTo functions to get it to work. As both functions do similar things, we create another private function that encapsulates both and which is similar to your original function logic.
However, this time, we take care that passed arguments contain only values that make sense (pre-condition checks). Also the function is private, so that it can not be called by other code which reduces the possibility of calling it wrong from outside of the class (it can't be called from the outside):
private function readLocationConditional($what)
{
switch($what)
{
case 'from':
$countrycode = $this->fromcurr;
break;
case 'to':
$countrycode = $this->tocurr;
break;
default:
throw new InvalidArgumentException(sprintf('Invalid value for $what ("%s").', $what));
}
$sql = $this->buildReadLocationSQL($countrycode);
$result = $this->query($sql);
$array = mysqli_fetch_array($result);
$field = 'loc';
if (!isset($array[$field]))
{
throw new UnexpectedValueException(sprintf('Row does not contain %s (contains %s)', $field, implode(',', array_keys($array))));
}
$location = $array[$field];
return $location;
}
So let's take a closer look what's done differently to the original function: The input values are validated and the conditional variable is assigned to $countrycode. This helps to keep things apart. In case some "undefined" value for $what is given, an exception is thrown. This will immediately notify you if you used this function wrongly.
Then the new buildReadLocationSQL function is used to create the SQL, the new query function is used to run the query. At the end, the data returned from the database is validated again and an exception is thrown if the needed field is missing. This will immediately notify you if something is wrong with the returned data.
This is now easy to bring together with the two new public functions which are actual wrappers for the new private function readLocationConditional. So let's put this all together:
public function readLocationFrom()
{
return $this->readLocationConditional('from');
}
public function readLocationTo()
{
return $this->readLocationConditional('to');
}
So now, you've rewritten the database class to make it more flexible and better functioning. Put it together and that's it.
The first key point here is that you check error conditions properly. I've used exceptions instead of die because I think it's more developer friendly. You can do this with die statements as well or with error values etc.. But Exceptions do not only tell you a message, but also where something happened, can be caught (you can't catch die) and can have a different type, so they carry much more helpful information if something goes wrong.
The second key point is that you simplify your code. The more simple your code flow is, the easier it is to code. Putting things that cover the same into functions of it's own is very productive. You can write them as you go on while you keep things separated. And another tip: The less parameters a function have (ideally: zero which is not always possible), the less you can do wrong and the less input values you need to verify.
Just to say: You originally did this somehow as well, but not completely. You had only one place where you checked for an error (the connection to the mysql database), but not for the query itself, not for the return value from the query and not for the function parameter. Putting everything into small functions of it's own, it's easier to see what to check for and handle the details.
Last but not least, the new usage, I made the names more speaking (nstd o abbr evrthng):
$amount = "1.00";
$currencyFrom = "USD";
$currencyTo = "GBP";
$db = new Database($currencyFrom, $currencyTo);
echo $db->readLocationFrom(), $db->readLocationTo();
Hope this helps. And don't fear to write some lines of code more as long as it helps to prevent errors (it's your code, use it as a tool for you) and with modularity in mind. In the end you will see that this is less code and less hassles. Looking for the actual part you made an error in is also a good place to start.
Discussion of errors; I've seen the following:
elseif ($toFrom == 'to');
^
If-blocks can be daunting, restructuring your code helps here. Reduce the use of if and especially elseif. Moving parts into functions of it's own helps to reduce complexity. Less complexity, less errors (we are humans).
$query2 = ("...");
^ ^
This parenthesis is superfluous, might be a sign for just copied over code from a previous function call. Take more care.
Just putting the finger on these errors doesn't show the whole picture and just fixing those won't get you a step further. So it's better to recognize the errors and to understand why they have been made and then to think about how to prevent them.
It looks like whatever this code is supposed to do (which isn't entirely clear), it's not being used correctly. Take a look at some important parts:
$from = "USD";
$to = "GBP";
later...
$locFrom = $DBob->readLocation($from);
$locTo = $DBob->readLocation($to);
and inside that function...
if($toFrom == 'from') {
//...
}
else if($toFrom == 'to'); {
//...
}
That conditional is never satisfied. The $toFrom function parameter (which is not a particularly intuitive variable name) is being set to "USD" and "GBP" with the two calls to the function. It's never equal to "from" or "to" as the conditional assumes.
So $query2 never even gets set to anything. This would lead me to believe that the behavior of this line is an error or undefined:
$result = mysqli_query($dbcon,$query2);
Better variable/function names may help lead you to the logical use of whatever this code is supposed to be doing. But as it stands right now, the function is assuming values that the calling code isn't supplying. If the function is going to assume those values, the very first thing it should do is check its input:
if (($toFrom != 'to') &&
($toFrom != 'from')) {
// Incorrect argument(s) supplied.
// Throw an error and do not proceed with the function
}

FlashBuilder 4.5 + PHP + mssql list output

I've created a web service with the following code:
class WebUser {
public $USERID;
}
class UseridService
{
public $username = "my_user";
public $password = "my_pw";
public $server = "my_remote_server";
public $databasename = "my_database";
public $tablename = "my_table";
function __construct ()
{
$this->con = mssql_connect($this->server, $this->username, $this->password) or die('Connection failed!');
mssql_select_db($this->databasename);
}
public function getUserid ()
{
$sql = "Select top 10 USERID FROM my_table";
$result = mssql_query($sql);
$rows = array();
while ($row = mssql_fetch_assoc($result))
{
$storage = new WebUser();
$storage->USERID = $row['USERID'];
$rows[] = $row;
}
mssql_close($this->con);
return $rows;
}
}
For now in flash builder 4.5, I want to output the top 10 userids into a List component in my canvas. I can assure everyone that the PHP webservice code I wrote works and returns an array of WebUser() objects with just the USERID string inside.
There is a lot of documentation online for MySQL and how they simply "drag and drop" the webservice into a list and it "magically" works. Despite trying to follow their conventions using MSSQL instead, I simply cannot get it working.
I was hoping if anyone can offer a piece of advice on what to do? Even if it's not an answer itself, does anyone know any online documentation that works specifically with Flashbuilder/PHP/MSSQL?
Go to the source! Adobe Documentation on setting this up:
http://www.adobe.com/devnet/flash-builder/articles/flashbuilder-php-part1.html
They walk you through hooking up a service in Flashbuilder, connecting your data objects, and displaying them.
I know what you're asking asks for MSSQL, but the database you use on the back-end doesn't matter. What matters is serializing your object from the server-side to the client-side (i.e. PHP to AS3) which means matching the objects on both ends or finding a way to convert them (i.e. JSON-encoded objects in a REST-based web service can be de-serialized quite smoothly using the as3core library as an example).

Using sqlite efficiently with php

I'm porting over a small php app to use sqlite, and this is the first time that I use sqlite with php and its been a while since i last coded something with php(it was php4 by the time).
The trouble i'm having right now is that apparently with sqlite you need to call the sqlite3 object several times since it apparently doesnt establish a permanent connection with the database, so my code right now is filled with
$db = new SQLite3('test.db');
in every single function in the code. is this efficient? is there a better and cleaner way of doing this?
the other issue that i'm having is if i use sqlite inside say include/functions.php it tries to look for test.db inside this include/ dir when it should be using the app root. how could i fix this efficiently?
You only have to establish a connection again if your $db variable goes out of scope or is otherwise destroyed. If you create the variable inside a function, it will go out of scope as soon as the function exits, forcing you to recreate the variable/connection in the next function.
As such, in some form or another, you will need to create the variable in a scope that is accessible everywhere a database connection is required. The easiest but ugliest is to create it in the global scope. A better way would be to create a static class that holds the connection and can return the connection handler on request. Another way would be to use dependency injection, basically meaning you pass the connection handle into every function or object where it is needed.
The right answer depends on your existing architecture.
Code
<?php
class SQL {
private $db;
function __construct() {
try {
/*** connect to SQLite database ***/
$db = new PDO("sqlite::memory:");
$db->exec("CREATE TABLE blog (Id INTEGER PRIMARY KEY, text TEXT)");
$this->db = $db;
/*** a little message to say we did it ***/
echo 'database created in memory';
} catch(PDOException $e) {
echo $e->getMessage();
}
}
function add($text) {
$this->db->exec("INSERT INTO blog(text) VALUES ('$text')");
}
function get() {
$res = array();
$result = $this->db->query('SELECT text FROM blog');
foreach ($result as $row) {
$res[] = $row['text'];
}
return $res;
}
}
?>
<?php
$sql = new SQL();
$sql->add('hello');
print_r($sql->get());
?>
<?php
$sql = new SQL();
$sql->add('hello');
$sql->add('world');
print_r($sql->get());
?>
Output:
php sql.inc
database created in memoryArray
(
[0] => hello
)
database created in memoryArray
(
[0] => hello
[1] => world
)
As you can see no sprinkling off $db =.
P.S: You should use PDO because it is superior to just calling new SQLite3

Categories