Magento 1.9 and mongoDB - php

I'm trying to research how to integrate between magento and mongodb. At first, how to connect? and execute CRUD?
P/s: My system is using mysql, and I want to use mongodb too.

I based my work with mongo next to magento with this functionality github.com/colinmollenhour/magento-mongo
If you will have problems with connection change _newConnection metod in Mage_Core_Model_Resource to this:
protected function _newConnection($type, $config)
{
if ($config instanceof Mage_Core_Model_Config_Element) {
$config = $config->asArray();
}
if (!is_array($config)) {
return false;
}
$connection = false;
// try to get adapter and create connection
$className = $this->_getConnectionAdapterClassName($type);
if ($className) {
// define profiler settings
$config['profiler'] = isset($config['profiler']) && $config['profiler'] != 'false';
$connection = new $className($config);
if ($connection instanceof Varien_Db_Adapter_Interface) {
// run after initialization statements
if (!empty($config['initStatements'])) {
$connection->query($config['initStatements']);
}
} else {
$connection = false;
}
}
// try to get connection from type
if (!$connection) {
$typeInstance = $this->getConnectionTypeInstance($type);
$connection = $typeInstance->getConnection($config);
// if (!$connection instanceof Varien_Db_Adapter_Interface) {
// $connection = false;
// }
}
return $connection;
}
Regards,

Simply changing the connection layer won't work. You will need a full MongoDB abstraction layer to replace the MySQL abstraction layer plus underlying database.
Take a look at https://github.com/colinmollenhour/magento-mongo, which should get you started. I haven't used it myself so I cannot vouch for its quality or completeness.
PS: Why do you even want to replace MySQL? Unless you have very good reasons, I'd stay with the default as it be much better battle tested.

Related

Is this right way to use php oop and mysqli?

I am not very experienced in php oop. Moreover, when mysqli comes with php oop, it make me more confused about using it in best efficient way. Anyway, first look at my connection class:
<?php
//connectionclass.php
class connection{
public $conn;
public $warn;
public $err;
function __construct(){
$this->connect();
}
private function connect(){
$this->conn = # new mysqli('localhost', 'sever_user', 'user_password');
if ($this->conn->connect_error) {
$this->conn = FALSE;
$this->warn = '<br />Failed to connect database! Please try again later';
}
}
public function get_data($qry){
$result = $this->conn->query($qry);
if($result->num_rows>=1){
return $result;
}else{
$this->err = $this->conn->error;
return FALSE;
}
$result->free();
}
public function post_data($qry){
$this->conn->query($qry);
if($this->conn->affected_rows>=1){
return TRUE;
}else{
$this->err = $this->conn->error;
return FALSE;
}
}
}
?>
Now please structure of a php page which uses mysql database to store and get data:
<?php
//login.php
include('/include/connectionclass.php');
$db = new connection();
$query = "SELECT * FROM USERS WHERE user_country='India'";
$data = $db->get_data($query);
if($data){
while($row=$data->fetch_assoc()){
echo 'User Name: ':.$row["user_name"].' Age: '.$row["age"];
}
}
?>
So my login.php uses connection class to get data about users. All the things are running well. But one things made me confused. In connectionclass.php $this->conn is itself an object as it calls new mysqli. So this is an object inside another object $db. Moreover, When I am using $data = $db->get_data($query);, a result set is created inside object $db by method get_data, then this result set is copied into a variable $data inside login.php page.
So according to me, actually two result sets/data sets are creating here, one inside db object and one inside login page. Is it right way to use mysqli and php to get dataset from mysql database? Will it use more memory and server resources when the dataset is larger (when have to get large amount of data for many users)?
If it is not right way, please explain your points and please give me code which can be used efficiently for php oop and mysqli.

PHP Database Advice

I'm sorry for the lack of information on this question I just need some advice on some code. I think only a programmer can answer this because my code is unique and I couldn't find any answers that help me.
Index.php
<?php
include ( 'Blue/BlueDatabase.php' );
include ( 'Blue/BlueUsers.php' );
use Blue\BlueDatabase;
use Blue\BlueLoader;
$database = new BlueDatabase();
$database->Connect('localhost', 'root', '', 'database');
?>
And now I have my "BlueLoader" class and I have this code in the class aswell
$database = new BlueDatabase();
$database->Connect('localhost', 'root', '', 'database');
What I want to know is. Is it worth adding that code to every class? It makes it look untidy and I think there will be a more stabler way of doing it. Do i need to do the connect function once ive done it before? does it need to be done for every class? I'm just new to php and unsure about some things. Is this script stable? / Secure
Any advice or answers will be helpful
Just incase you need my connect function (All my mysql commands are in an array like
//Example:
$commands['mysql_query'] = mysql_query;
final public function connect($sHost, $sUser, $sPass, $sName, $sPort = false, $sType = 'mysql_connect')
{
if(!$this->connected)
{
if ($sPort)
{
$sHost = $sHost . ':' . $sPort;
}
$this->connection = $this->_aCmd[$sType]($sHost, $sUser, $sPass);
if($this->connection)
{
$mydatabase = $this->_aCmd['mysql_select_db']($sName, $this->connection);
if($mydatabase)
{
$this->connected = true;
}
else
{
die('could not connect to database');
}
}
else
{
die('could not connect to host');
}
}
}
Advice:
Stop using the deprecated ext/mysql extension. Don't bother trying to wrap it in an OO framework.
Use PDO, because it already has a good OO usage, and has several other features that ext/mysql doesn't have. Mysqli is a runner-up, but I find PDO is easier to use.
Don't open a new connection in each class that uses a database. Create one connection and pass the connection object to each such class, probably as a constructor argument.
An alternative is to use a Registry class to store "global" objects like database connections.
Globals are great! They are perfect for indicating that you're taking a sub-optimal approach and you need to step back and re-evaluate.
Here are a few different ways you can address the issue.
$dbh = new DatabaseObject($connection_info);
$foo = new Object1($dbh);
$bar = new Object2();
$bar->GiveDbh($dbh);
$baz = new RegistryObject();
$baz->register('dbh', $dbh);
$bom = new Object3($baz);
I'd also include a Singleton method, but SO yells at me every time I do. :/
Also, you should probably re-jigger your database class to stop using mysql_* functions. Yadda yadda PDO MySQLi, you know the drill.

Singleton holding multiple ADODB connections

A legacy website is exhibiting unexpected behavior with it's database connections. The application connects to several MySQL databases on the same server and the original developer created a "singleton" class that holds connection objects for each of them.
Lately we have been encountering a strange behavior with the class: when a connection to www is created after creating extra, getting the instance of extra returns a connection that has the correct parameters when viewed with var_dump() but is actually connected to the www database.
What could cause this? The code has worked before at some stage. Creating a new connection on each call to getInstance() fixes the problem but I'd like to solve this the right way if possible.
<?php
class DBConnection
{
private static $default;
private static $extra;
private static $intra;
private static $www;
public static function getInstance($dbname = "default")
{
global $db; // This is an array containing database connection parameters
if(!($dbname == "default" || $dbname == "extra" || $dbname == "www" || $dbname == "intra"))
{
$dbname = "default";
}
if (empty(self::$$dbname)) // Making this pass every time fixes the problem
{
try
{
self::$$dbname = ADONewConnection('mysqlt');
if(isset($db[$dbname]))
{
self::$$dbname->connect(DBHOSTNAME, $db[$dbname]["dbusername"], $db[$dbname]["dbpassword"], $db[$dbname]["dbname"]);
}
else
{
// fallback
self::$$dbname->connect(DBHOSTNAME, DBUSERNAME, DBPASSWORD, DBNAME);
}
self::$$dbname->SetFetchMode(ADODB_FETCH_ASSOC);
self::$$dbname->execute("SET NAMES utf8");
return self::$$dbname;
}
catch(Exception $e)
{
exit("DB connection failed");
}
}
else
{
return self::$$dbname;
}
}
}
Here's a simplified example of the class misbehaving:
$cn = DBConnection::getInstance("extra");
$cn->debug = true;
$rs = $cn->execute("SELECT * FROM messages WHERE id = ".$this->id);
The last line fails with the error message "Table www.messages does not exist".
1: You don't need to establish connection in getInstance().
getInstance must not do anything, but return instance of DB class.
2: when you do self::$$dbname->connect(, if (empty(self::$$dbname)) will return you false next time you call it.
Singleton is described here: http://en.wikipedia.org/wiki/Singleton_pattern
What you have - it's just a static method.

Calling MySQL stored routines more than once in PHP

I want to call multiple MySQL stored routines sequentially with PHP, but I can only call a single one successfully---after that I get the error Commands out of sync; you can't run this command now. Researching the problem I found it's a common headache (caused by not "finishing up" the previous call before the next one is made), but I didn't find a solution I could apply to my code:
for ($i=0; $i<10; $i+=1)
{
if (!($conn=getconn() && ($result=mysql_query("call MyStoredRoutine();", $conn))))
{
$errorMessage = mysql_error($conn); // Error 2nd time here...
}
else {
while ($row=mysql_fetch_array($result)) {
// Retrieve data here...
}
}
}
And the implementation of getconn() (I don't think it's relevant but you never know):
function getconn() {
global $custdb, $custdb_connection, $dbuser, $dbpass;
if (! $custdb_connection) {
if (! ($custdb_connection = mysql_connect("localhost", $dbuser, $dbpass, true))) return false;
if (! (# mysql_select_db($custdb, $custdb_connection))) return false;
}
return $custdb_connection;
}
PHP version is 5.3.8-1~dotdeb.1, MySQL is 5.1.54-1ubuntu4.
Anybody knows what I should do to my code to make it work?
Maybe switch to MySQLi and use multi-query()
MySQLi gives you the added benefit of prepared statements and is build to support OOP.

Is this wrapper for PDO 'good code' ? Are there any potential problems?

I built this class to work with PDO, to make SQL queries 'easier' and less to worry about.
Here are my thoughts
Should it be more like class DB extends PDO?
Is the query method too big? Should it be split into private methods which are called.. is this what is known as loose coupling?
Is my way for detecting a SELECT query too ugly for it's own good?
What other problems are evident? As I am sort of learning-as-I-go, I'm sure I could have overlooked a lot of potential problems.
Thank you
`
class Db
{
private static $_instance = NULL;
private function __construct() {
// can not call me
}
private function __clone() {
// no!
}
public static function getInstance() {
if (!self::$_instance)
{
try {
self::$_instance = new PDO('mysql:host=' . CONFIG_MYSQL_SERVER . ';dbname=' . CONFIG_MYSQL_DATABASE, CONFIG_MYSQL_USERNAME, CONFIG_MYSQL_PASSWORD);;
self::$_instance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
trigger_error($e->getMessage());
}
}
return self::$_instance;
}
public static function query($query /*string*/, $bindings = NULL)
{
$queryPortion = substr($query,0, 6);
try {
if ($bindings) {
$prepared = self::getInstance()->prepare($query);
foreach($bindings as $binding=>$data) { // defaults to string
if (!is_array($data)) {
$prepared->bindParam($binding, $data);
} else {
switch(count($data)) {
case 1:
$prepared->bindParam($binding, $data['value']);
break;
case 2:
$prepared->bindParam($binding, $data['value'], $data['dataType']);
break;
case 3:
$prepared->bindParam($binding, $data['value'], $data['dataType'], (int)$data['length']);
break;
default:
trigger_error('An error has occured with the prepared statement bindings.');
return false;
break;
}
}
}
$prepared->execute();
return $prepared->fetchAll(PDO::FETCH_ASSOC);
} else if (String::match($queryPortion, 'select')) { // if this is a select query
$rows = self::getInstance()->query($query);
return $rows->fetchAll(PDO::FETCH_ASSOC);
} else {
return self::getInstance()->exec($query);
}
}
catch(PDOException $e)
{
trigger_error($e->getMessage());
}
}
public static function getLastInsertId()
{
try {
self::getInstance()->lastInsertId();
}
catch(PDOException $e)
{
trigger_error($e->getMessage());
}
}
public static function disconnect()
{
// kill PDO object
self::$_instance = NULL;
}
}
It's not bad and as it's been said it might help for small applications although it's mostly a very thin abstraction on another abstraction. It's not bringing a lot of others functionalities.
Something you might want to consider, amongst other things:
As this is PHP5 code, use exceptions instead of trigger_error and set_exception_handler if necessary until exceptions are more widespread, but it's definitely cleaner and more future-proof.
You are using a singleton, it's not a bad thing necessarily but in this case, for example, one shortcoming will be that you'll only be able to handle one connection to one database.
I don't know if you make use of stored procedures, but a stored procedure might return a result set through the query() method too.
You have two semi-colons (;;) at the end of your new PDO line.
That being said, I don't think your query method is too big and there's not much that could be recalled from elsewhere in there at the moment. Though as soon as you see two or three lines that could be called from another function, split it. That's a good way to DRY.
Yes and No.
It is good code for a simple quick and dirty application.
The problem comes when you use this in a more complex structured application.
Where the error handling will vary depending on which sql you are executing.
Also any severe errors will show up as "problem at line 999" type errors
where 999 is in your super duper routine and you will have difficulty tracing it back
to a particular sql request.
Having said that I do this sort of thing myself all the time on small projects.
Here's what I've used (just replace the references to Zzz_Config with $GLOBALS['db_conf'] or something):
/**
* Extended PDO with databse connection (instance) storage by name.
*/
class Zzz_Db extends PDO
{
/**
* Named connection instances.
*
* #var array
*/
static private $_instances;
/**
* Retrieves (or instantiates) a connection by name.
*
* #param string $name Connection name (config item key).
* #return Zzz_Db Named connection.
*/
static public function getInstance($name = null)
{
$name = $name === null ? 'db' : "db.$name";
if (!isset(self::$_instances[$name])) {
if (!$config = Zzz_Config::get($name)) {
throw new RuntimeException("No such database config item: $name");
}
if (!isset($config['dsn'])) {
if (!isset($config['database'])) {
throw new RuntimeException('Invalid db config');
}
$config['dsn'] = sprintf('%s:host=%s;dbname=%s',
isset($config['adapter']) ? $config['adapter'] : 'mysql',
isset($config['host']) ? $config['host'] : 'localhost',
$config['database']);
}
$db = self::$_instances[$name] = new self(
$config['dsn'],
isset($config['username']) ? $config['username'] : null,
isset($config['password']) ? $config['password'] : null);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'Zzz_Db_Statement');
if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') {
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$db->exec('SET CHARACTER SET utf8');
}
}
return self::$_instances[$name];
}
}
Usage whould be:
$db = Zzz_Db::getInstance(); // or Zzz_Db::getInstance('some_named_db')
$stmt = $db->prepare('SELECT ...
The goal is to keep the db configuration in an *.ini file (editable by a non-coder).
I went the other way and made a class that extends PDO with a bunch of wrapper functions around prepare()/execute(), and it's much nicer than the built in functions (though that's a bit subjective...).
One other thing: you should set PDO::ATTR_EMULATE_PREPARES to false unless you're using a really old version of mysql (<=4.0). It defaults to true, which is a huge headache and causes things to break in obscure ways... which I'm guessing is the reason you've got a huge wrapper around bindParam() in the first place.
To answer your question, if it is a good code or not, ask yourself:
What is the added value of my code compared to using PDO directly?
If you find a good answer, go for using your code. If not, I would stick with PDO.
Also try considering implementing Zend Framework's DB class which works on its own and supports PDO.

Categories