SaaS application structure in YII using separate database - yii

I need create a SaaS application structure in YII Framework using separate database, but the examples in the web are using a single database. Any information or handbook will be welcome.
Thanks

You can use a second DB by adding it to your main.php ex:
'db'=>array(
'connectionString' => 'mysql:host=localhost;dbname=database',
'emulatePrepare' => true,
'username' => 'username',
'password' => 'password',
'charset' => 'utf8',
'schemaCachingDuration' => 3600,
'enableProfiling' => true,
),
'db2'=>array(
'connectionString' => 'mysql:host=localhost;dbname=database2',
'class'=>'CDbConnection',
'emulatePrepare' => true,
'username' => 'username',
'password' => 'password',
'charset' => 'utf8',
'schemaCachingDuration' => 3600,
'enableProfiling' => true,
),
Then you can set the getDbConnection() method inside the active records that are to use this second db. I would suggest making a parent class extending from CActiveRecord with this code and then extending that.
It should contain:
public static $db2;
public function getDbConnection()
{
if(self::$db2!==null)
return self::$db2;
else
{
self::$db2=Yii::app()->db2;
if(self::$db2 instanceof CDbConnection)
{
self::$db2->setActive(true);
return self::$db2;
}
else
throw new CDbException(Yii::t('yii','Active Record requires a "db" CDbConnection application component.'));
}
}

Related

zfcuser + doctrine custom user entity

I'm working on a project with zf2, and the zfcuser module with doctrine. I have created a custom user module that extends zfcuser, also a custom entity for the user table, and make all the necessary changes for the integration. But my problem is when trying to authenticate myself, I get this error:
An alias "Zend\Db\Adapter\Adapter" was requested but no service could be found.
This happens when zfcuser_user_mapper attempts to change the adapter.
Note: I am not very clear why I need to use the Zend \ Db \ Adapter \ Adapter, since I am working with doctrine.
This is the code in the module.php of the custom user module.
public function getServiceConfig() {
return [
'aliases' => array(
'zfcuser_zend_db_adapter' => 'Zend\Db\Adapter\Adapter',
),
'factories' => [
'usuario_login_form' => 'Usuario\Factory\Form\Login',
'usuario_registro_form' => 'Usuario\Factory\Form\Register',
'usuario_user_service' => 'Usuario\Factory\Service\UserFactory',
//'usuario_user_mapper' => 'Usuario\Factory\Mapper\User',
'usuario_auth_service' => 'Usuario\Factory\AuthenticationService',
'Usuario\Authentication\Adapter\Db' => 'Usuario\Factory\Authentication\Adapter\DbFactory',
'Usuario\Authentication\Storage\Db' => 'Usuario\Factory\Authentication\Storage\DbFactory',
//'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\Adapter',
'usuario_user_mapper' => function ($sm) {
$mapper = new Mapper\User();
$mapper->setDbAdapter($sm->get('zfcuser_zend_db_adapter'));
$mapper->setEntityPrototype(new ORM\Entity\Usuarios());
$mapper->setHydrator(new \ZfcUser\Mapper\UserHydrator());
return $mapper;
},
]
];
}
This is my global.php file
return array(
'doctrine' => array(
'connection' => array(
'orm_default' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => array(
'host' => 'localhost',
'port' => '3306',
'user' => 'root',
'password' => 'toor',
'dbname' => 'deporte',
)
)
)
),
);
This is my module.config.php file:
'controllers' => array(
),
'doctrine' => array(
'driver' => array(
// overriding zfc-user-doctrine-orm's config
'usuario_entity' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'paths' => __DIR__ . '/../src/Usuario/ORM/Entity',
),
'orm_default' => array(
'drivers' => array(
'Usuario\ORM\Entity' => 'usuario_entity',
),
),
),
),
'zfcuser' => array(
'auth_adapters' => array(100 => 'Usuario\Authentication\Adapter\Db'),
// telling ZfcUser to use our own class
'user_entity_class' => 'Usuario\ORM\Entity\Usuarios',
// telling ZfcUserDoctrineORM to skip the entities it defines
'enable_default_entities' => false,
),
I thank you for the help, I have already been with this error for days. Thank you very much, and excuse my English.
If you want to change the Entity and want to use your then use following steps:
if the zfcuser.global.php file which is placed in config/autoload folder (if not then you can copy if from zfcuser module.
In this global file search for "user_entity_class" key and define your own entity class.By default it uses
'user_entity_class' => 'ZfcUser\Entity\User',
Like I am using it for Employee entity
'user_entity_class' => 'Employee\Entity\Employee',
In this entity you need to implement UserInterface.
use ZfcUser\Entity\UserInterface;
/**
* Employee
*
* #ORM\Table(name="employee")
* #ORM\Entity(repositoryClass="Employee\Repository\EmployeeRepository")
*/
class Employee implements UserInterface {
}
If you want to override db adapter then you need to do following steps:
'service_manager' => array(
'invokables' => array(
'ZfcUser\Authentication\Adapter\Db' => 'Employee\Authentication\Adapter\Db',
),
),
In this file you need to extend and implements.
namespace Employee\Authentication\Adapter;
use InvalidArgumentException;
use Zend\Authentication\Result as AuthenticationResult;
use Zend\Crypt\Password\Bcrypt;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\Session\Container as SessionContainer;
use ZfcUser\Authentication\Adapter\AdapterChainEvent as AuthenticationEvent;
use ZfcUser\Entity\UserInterface as UserEntity;
use ZfcUser\Mapper\HydratorInterface as Hydrator;
use ZfcUser\Mapper\UserInterface as UserMapper;
use ZfcUser\Authentication\Adapter\AbstractAdapter;
use ZfcUser\Options\AuthenticationOptionsInterface as AuthenticationOptions;
class Db extends AbstractAdapter implements ServiceManagerAwareInterface
{
}
For more information you can follow zfcuser wiki here:
https://github.com/ZF-Commons/ZfcUser/wiki

YII2 API Model Database Connection

I'm developing a API in YII2 with multiple databases. I want to choose the database in real time. The idea is to read one variable available in controler (API key) to identify the correct connection database in model.
For example in webapplication like a portal i have (it works):
in db default connection i have
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=dbcompany_0',
'username' => 'root',
'password' => 'XXXXXXXXXXXXXXXXXXXX',
'charset' => 'utf8',
],
In model I have
public function tableName()
{
$schema = '';
$user = User::find(Yii::app()->user->id);
$schema = "dbcompany_". $user->CompanyId;
return $schema . '.' . 'customer';
}
With this approach I just have a single db connection for all database companies.
How I can apply the same\similiar approach in API. I don't have sessions.
Any idea is well welcome.
Create a new component under db as:
'db1' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=dbcompany_0',
'username' => 'root',
'password' => 'XXXXXXXXXXXXXXXXXXXX',
'charset' => 'utf8',
],
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=dbcompany_0',
'username' => 'root',
'password' => 'XXXXXXXXXXXXXXXXXXXX',
'charset' => 'utf8',
],
And use it as:
Yii::$app->db1
Yii::$app->db2;
All requests are authenticate using a token and this is associated to the user. When the authentication is done YII Framework assigns the userid to \Yii::$app->user->identity->id. So from anywhere I can identify the company owner in model.
public static function tableName(){
$moreinfo= account\Userextra::findOne(\Yii::$app->user->identity->id);
$schema = \Yii::$app->params['table.prefix'] . $moreinfo->CompanyId;
return $schema . '.country';
}

Slim Framework with ORM (Eloquent) connect multiple db

I am using Slim Framework with Eloquent 4.1.x as ORM for a project and need to connect to multiple databases.
I followed this link to setup the ORM. But how can I connect to multiple databases by following the given tutorial?
In my models I have different files that are used for different tables in different databases.
Like the User.php file has the following,
<?php
namespace Service\Framework\Model;
use Illuminate\Database\Eloquent\Model;
class Users extends Model {
protected $table = 'users';
}
This class uses the users table in db_2 database. I want to switch from the default database db_1 in a method in this Class. Like,
<?php
namespace Service\Framework\Model;
use Illuminate\Database\Eloquent\Model;
class Users extends Model {
protected $table = 'users';
public function getUsers() {
// Switch the database to db_2
$users = self::all();
// Again switch back to default database db_1
return $users;
}
}
How can I do that? Please help me with some suggestions.
P.S: I am not using Capsule here.
EDIT #1
So the code I am using to setup a single connection is as follows,
$settings = array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'db_1',
'username' => 'dbuser',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => ''
);
// Bootstrap Eloquent ORM
$container = new Container();
$connFactory = new ConnectionFactory($container);
$conn = $connFactory->make($settings);
$resolver = new ConnectionResolver();
$resolver->addConnection('default', $conn);
$resolver->setDefaultConnection('default');
Model::setConnectionResolver($resolver);
You can connect to multiple databases with this simplified code:
$app = new \Slim\App([
'db' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'products',
'username' => 'user',
'password' => 'pass',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
],
'db_second' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'second',
'username' => 'user',
'password' => 'pass',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
],
]);
$container = $app->getContainer();
// connect to db with Illuminate larvel
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection($container['settings']['db']);
$capsule->addConnection($container['settings']['db_second'], 'db_second');
$capsule->setAsGlobal();
$capsule->bootEloquent();
/// END connect to db
// to accsess the $capsule with our container from our controllers
$container['db'] = function($container) use ($capsule){
return $capsule;
};
and in the Model file put:
protected $connection = 'db_second';
First you should setup multiple connections. After connections are set up you can instruct model to use specific connection with $connection propery.
namespace Service\Framework\Model;
use Illuminate\Database\Eloquent\Model;
class Users extends Model {
protected $connection = 'mysql2';
protected $table = 'users';
}
In routes or controllers you can user setConnection() method.
$user = new User;
$user->setConnection('mysql2');
print_r($user->find(1));

Cakephp - [Oracle] make query to another users table

I need que make a select query from a table outside my user. I can make the select query from toad for example but in cakephp i get this error:
Missing Database Table Error: Table cursos for model Curso was not
found in datasource ot.
I understand the error occurs because the table doesn't exists directly in my user.
The question is: is there any way to get the data in this situation??
look what I understand the problem you have 2 databases and users want to use one for work:
Multiple Database connection issue CakePHP
in your database.php You can configure 2 connections
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'test',
'password' => 'test1',
'database' => 'test_portal',
'prefix' => ''
//'encoding' => 'utf8',
);
public $test = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'dfffd_23',
'password' => 'dsfsd324',
'database' => 'testdbuser',
'prefix' => ''
//'encoding' => 'utf8',
);
}
now in your model you have to specify which of the settings or connections want used for so you can select the users that you want.
class Example extends AppModel {
public $useDbConfig = 'test';
}
you can see this in the documentation

configuring database config for live site in codeigniter keep getting 500 internal server error

Im pretty done new to actually setting up sites as a live version, I've only done websites using local host. Im using codeigniter for this one, and i've traced my problem to the model where it loads the database. This makes me think that my database config isn't set up correctly.
The model's function is as follows:
public function register($email, $password, $first_name, $last_name, $gender, $birthday){
$salt = $this->generateSalt();
$password = $this->hash($password, $salt);
$data = array('email' => $email, 'password' => $password, 'salt' => $salt, 'first_name' => $first_name,
"last_name" => $last_name, 'gender' => $gender, "birthday" => $birthday);
$this->load->database();
if($this->db->insert('users', $data)){
$this->loginById($this->db->insert_id());
return true;
}else{
return false;
}
}
And the database config looks like this though I removed the password and username for privacy the username and pass I used are the same as I used to get into phpmyadmin though:
$db['default'] = array(
'dsn' => '',
'hostname' => 'http://130.184.99.114/',
'username' => '',
'password' => '',
'database' => 'meetings',
'dbdriver' => 'mysqli',
'dbprefix' => '',
'pconnect' => TRUE,
'db_debug' => TRUE,
'cache_on' => FALSE,
'cachedir' => '',
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
'autoinit' => TRUE,
'encrypt' => FALSE,
'compress' => FALSE,
'stricton' => FALSE,
'failover' => array()
);
So, how do I need to set this up? I think Im on the right track, but im really new to this, so please explain it in a way I can learn please! :D IF you need any more information please let me know.
The hostname you have listed is incorrect.
It should either be:
'hostname' => '130.184.99.114',
or
'hostname' => 'localhost',
depending on how the server has been set up.
Have you set this up in the /application/config/database.php file, or are you doing it differently? I ask as I see failover => array() in there, which isn't in the default configuration file.