Yii get all databases - yii

I'm trying to get all databases in my Yii application.
My very first solution is as follows:
$dsn = "mysql:host = localhost; dbname=myDBname";
$username = "myUsername";
$password = "myPassword";
$command = "show databases";
$db = new PDO($dsn, $username, $password);
$db->query($command);
var_dump($db->query($command)->fetchAll()) ;
However, I understand that this solution doesn't take advantage of the framework. So I try looking for a better way, and that may look like this:
$sql = "show databases";
$command = Yii::app()->db->createCommand($sql);
$result = $command->query();
var_dump($result);
With this way, however, the result is not as I expected. It actually returns an object instance of CDbDataReader class. and the property to access the real PDO object is kept private (its name is "_statement") so I cann't access it to fetch all databases.
So, could you help me find a more elegant way that can get more from the Yii framework that the first solution?
Thank you.

Oh I got answer, I just have to change "query" method to "queryAll" so it looks something like that:
var_dump(Yii::app()->db->createCommand('SHOW DATABASES')->queryAll());

Related

Create an exact copy of Analysis Services database with AMO

I'm trying to automate the creation of an exact copy of an Analysis Services database using Microsoft.AnalysisServices namespace. My code is:
using (var server = new Server())
{
server.Connect(connString);
var newDb = server.Databases.GetByName(dbName).Clone();
newDb.Name = newDbName;
newDb.ID = server.Databases.GetNewID();
server.Databases.Add(newDb);
newDb.Update(UpdateOptions.ExpandFull);
server.Disconnect();
}
However it seems it creates an empty database instead because from SSMS i'm not able to see any tables, datasources and similar (check my screenshot here).
Is there a way to fix this? Thanks.
#gmarchi
You need to clone the child Model object using Model.clone() method as well to make to make it work. You can add Model using code like below -
var connString = "Provider=MSOLAP;Data Source=asazure://westus2.asazure.windows.net/xxxxxxxxxxxx:rw";
var dbName = "AW Internet Sales";
var newDbName = "CloneDb";
using (var server = new Server())
{
server.Connect(connString);
var newDb = server.Databases.GetByName(dbName).Clone();
var newModel = server.Databases.GetByName(dbName).Model.Clone();
newDb.Name = newDbName;
newDb.ID = server.Databases.GetNewID();
newDb.Model = newModel;
server.Databases.Add(newDb);
newDb.Update(UpdateOptions.ExpandFull);
server.Disconnect();
}
Please find below the screenshot after the code run.
Please let me know if you have any questions.
Thanks.

How in codeception to make rollback a database if the test failed?

I need to test the feature in account. But for this need register an account. If the feature does not work correctly and the test fails, how do I can automatically delete an account from a database (account created during testing)?
I think you have a few options.
You can do clean-up in your Cest class's _before or _after methods (if you use a framework you could use an ORM to delete all accounts for example).
Codeception's Db module (see https://codeception.com/docs/modules/Db) also has a cleanup flag which, when true, will load a user-defined database dump before each test (you could create a dump with no accounts).
There might be other options too. If you use Yii2 for example, the Yii2 module for Codeception has a cleanup flag that will wrap tests in a transaction if true (see https://codeception.com/for/yii).
We are facing problems like this, too. If you insert the account with the DB module of codception you can use the cleanup flag and it will automaticly clean up the database after each run.
If you create the account by a test and you want to go sure that the account isn't existing before you start the test you can extend the DB module by a delete function (that has to used with care, we only allow that in testing environments).
<?php
namespace Helper\Shared;
class DbHelper extends \Codeception\Module {
public function deleteFromDatabase($table, $criteria)
{
$dbh = $this->getModule('Db')->_getDbh();
$query = "delete from `%s` where %s";
$params = [];
foreach ($criteria as $x => $y) {
$params[] = "`$x` = '$y'";
}
$params = implode(' AND ', $params);
$query = sprintf($query, $table, $params);
codecept_debug($query);
$this->debugSection('Query', $query, json_encode($criteria));
$sth = $dbh->prepare($query);
return $sth->execute(array_values($criteria));
}
}
This can be used in the test code with ...
$I->deleteFromDatabase('account', ['id' => '123456']);
If it's possible the DB Module should be used to create the account and clean it up again. This method above is pretty dangerous dependend on the systems you are using it.

zend_db standalone

i want to use zend_db standalone cos zend framework is too much for my project but i'm new with it,
is it correct to do this:
$pdoParams = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES
UTF8;');
$params = array(
'host' => 'localhost',
'username' => 'ss_fraat',
'password' => 'jos10',
'dbname' => '_a2hDB',
'driver_options' => $pdoParams
);
try {
$db = Zend_Db::factory('PDO_MYSQL', $params);
//set default adapter
Zend_Db_Table_Abstract::setDefaultAdapter($db);
} catch (Exception $e) {
exit($e->getMessage());
}
//save Db in registry for later use
Zend_Registry::set('dbAdapter', $db);
then in any class do this:
$db = Zend_Registry::get('db');
/** quote to avoid sql injection */
$date = $db->quote('1980-01-01');
$sql = 'SELECT * FROM product WHERE name = ' . $date;
$result = $db->query($sql);
$db->query(); //run a query
i really need to do this
Zend_Db_Table_Abstract::setDefaultAdapter($db);
i get this code from a website,
is it necessary to use Zend_Db_Table_Abstract if i'm not using the full zend framework,
or it is better for example to use this:
$db = Zend_Db::factory( ...options... );
$select = new Zend_Db_Select($db);
what i want is to setup a pdo/mysql connexion in my bootstrap php page and be able to get that db instance in any class without starting a new connexion to execute queries but i'm not sure how to do that use Zend_Db_Table_Abstract or Zend_Db_Select use the registry Zend_Registry::set('dbAdapter', $db) or not
thanks a lot
The purpose of Zend_Db_Table_Abstract is so you can create your own model classes based around the Table Data Gateway design pattern. The idea of that pattern is that you have a class that encapsulates all the sql you would need for interfacing with a table. So the assumption is that you will be creating model classes that extend Zend_Db_Table_Abstract for each table. If you are going to do that, then you will want to call Zend_Db_Table_Abstract::setDefaultAdapter($db) in your setup/bootstrap. Recent versions of ZF provide as an alternative a quick way of getting basic functionality without having to create a custom class definition by just instantiating Zend_Db_Table:
$userTable = new Zend_Db_Table('users');
In summary, none of this particularly has to do with the MVC part of the framework, although some people choose to use Zend_db as the basis for db connections and models, instead of using a more fully featured ORM like Doctrine or Propel.
The other code you provided simply illustrates that you do not need to use Zend_Db_Table_Abstract either -- you can simply setup an instance of a Zend_Db_Adapter and use that instance to call query() or its other methods.

Doctrine adding a many-to-many relation for transient records

two models Site and Language share a many-to-many relationship (they are bi-directional)
How do I add a relationship between them?
Ideally I want to do this : (add an existing language to a new Site)
$site = new Site();
$site->name = "Google"
$site->url = "www.google.com";
---- code to add language----
$site->save();
Or should I only add the language after calling save() and if so how is that done?
Thanks in advance
I really cannot offer much better explanation than that:
http://www.doctrine-project.org/projects/orm/1.2/docs/manual/working-with-models/en#many-to-many-relations
Found the problem : The primary key of the association table is not set to "Auto-Increment"
this code works
$site = new Site();
$site->name = "Google";
$site->url = "www.google.com";
// now add languages
$langIds = array(1, 2,3);
foreach ($langIds as $id) {
$site->SiteLanguage[]->languageId = $id;
}
// now call save --- this creates a new site along with associations
$site->save();

CakePHP: get user info in models

I'm moving some of my find code inside models.
Previously in my controller I had
$this->Book->Review->find('first', array(
'conditions' => array(
'Review.book_id' => $id,
'Review.user_id' => $this->Auth->user('id')
)
));
so in my Review model I put something like
function own($id) {
$this->contain();
$review = $this->find('first', array(
'conditions' => array(
'Review.book_id' => $id,
'Review.user_id' => AuthComponent::user('id')
)
));
return $review;
}
So I'm calling AuthComponent statically from the Model. I know I can do this for the method AuthComponent::password(), which is useful for validation. But I'm getting errors using the method AuthComponent::user(), in particular
Fatal error: Call to a member function
check() on a non-object in
/var/www/MathOnline/cake/libs/controller/components/auth.php
on line 663
Is there a way to get the info about the currently logged user from a model?
Create a new function in the "app_model.php" ("AppModel.php" in CakePHP 2.x), so it will be available at all models within our application:
function getCurrentUser() {
// for CakePHP 1.x:
App::import('Component','Session');
$Session = new SessionComponent();
// for CakePHP 2.x:
App::uses('CakeSession', 'Model/Datasource');
$Session = new CakeSession();
$user = $Session->read('Auth.User');
return $user;
}
in the model:
$user = $this->getCurrentUser();
$user_id = $user['id'];
$username = $user['username'];
The way that I use is this:
App::import('component', 'CakeSession');
$thisUserID = CakeSession::read('Auth.User.id');
It seems to work quite nicely :-)
I think the code is fine as it is and belongs in the Controller, or at the very least it needs to receive the ids from the Controller and not try to get them itself. The Model should only be concerned with fetching data from a data store and returning it. It must not be concerned with how the data is handled in the rest of the application or where the parameters to its request are coming from. Otherwise you paint yourself into a corner where the ReviewModel can only retrieve data for logged in users, which might not always be what you want.
As such, I'd use a function signature like this:
function findByBookAndUserId($book_id, $user_id) {
…
}
$this->Review->findByBookAndUserId($id, $this->Auth->user('id'));
There is a nice solution by Matt Curry. You store the data of the current logged user in the app_controller using the beforeFilter callback and access it later using static calls. A description can be found here:
http://www.pseudocoder.com/archives/2008/10/06/accessing-user-sessions-from-models-or-anywhere-in-cakephp-revealed/
EDIT: the above link is outdated: https://github.com/mcurry/cakephp_static_user
I think this is not good idea to get value from Session. Better solution to get logged user id inside any model simply try this:
AuthComponent::user('id');
This will work almost every where. View, Model and Controller
Dirtiest way would be to just access the user information in the Session. Least amount of overhead associated with that.
The "proper" way would probably be to instantiate the AuthComponent object, so that it does all the stuff it needs to be fully operational. Much like a death star, the AuthComponent doesn't really work well when not fully setup.
To get a new AC object, in the model:
App::import( 'Component', 'Auth' );
$this->Auth = new AuthComponent();
Now you can use $this->Auth in the model, same as you would in the controller.
For CakePHP 3.x this easy component is available: http://cakemanager.org/docs/utils/1.0/components/globalauth/. Direct accessing the Session is not possible because of different SessionKeys.
With the GlobalAuthComponent you can access your user-data everywhere with: Configure::read('GlobalAuth');.
Greetz
Bob
I use cake 2.2 and these both work great:
$this->Session->read('Auth.User');
//or
$this->Auth->user();
You can also get a field of currently logged in user:
$this->Session->read('Auth.User.email');
//or
$this->Auth->user()['email'];
None of these solutions work in CakePHP version 3. Anyone know of a way to do this? Right now, I'm completely stepping around the framework by accessing the $_SESSION variable directly from my model.