Following is my cake console code to generate database schema. I have to manage multiple database schema migration. When I am calling generateDb function it creates a master schema after that i am switching database connection to client database, but client schema is not generating. its again generating master schema.
class HelloShell extends AppShell {
public $uses = array('ClientDbdetail');
public function generateDb() {
$runCommand = shell_exec(APP.'Console/cake schema generate -f master');
if ($runCommand) {
$sessionArray = $this->ClientDbdetail->find('first', array('recursive' => -1));
$this->__switchDb($sessionArray['ClientDbdetail']);
shell_exec(APP.'Console/cake schema generate -f client');
$this->out('Schema generated');
} else {
$this->out('Schema not generated');
}
}
private function __switchDb(array $userDetail) {
$username = 'default';
$settings = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'port' => 3306,
'login' => $userDetail['user_dbuser'],
'password' => $userDetail['user_dbpwd'],
'database' => $userDetail['user_dbname'],
'prefix' => ''
);
ConnectionManager::drop($username);
ConnectionManager::create($username, $settings);
ConnectionManager::getDataSource($username);
}
}
From CakePHP book there is an example.
public $connection = 'default';
public function before($event = array()) {
$db = ConnectionManager::getDataSource($this->connection);
$db->cacheSources = false;
return true;
}
and after :
public function before($event = array()) {
$articles = ClassRegistry::init('Articles', array(
'ds' => $this->connection
));
// Do things with articles.
}
see this : http://book.cakephp.org/2.0/en/console-and-shells/schema-management-and-migrations.html
Related
I have too many function for database inside one model file
See my example :
<?php
namespace App\Models;
use CodeIgniter\Model;
use Medoo\Medoo;
class DBMedoo extends Model {
public $database;
public $maxfolder;
protected $session;
function __construct()
{
include APPPATH . 'ThirdParty/vendor/autoload.php';
$this->session = \Config\Services::session();
$this->session->start();
$this->database = new Medoo([
// [required]
'type' => 'mysql',
'host' => 'localhost',
'database' => 'db_testing',
'username' => 'root',
'password' => '',
// [optional]
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'port' => 3306,
// [optional] Table prefix, all table names will be prefixed as PREFIX_table.
'prefix' => '',
// [optional] Enable logging, it is disabled by default for better performance.
'logging' => true,
// [optional]
// Error mode
// Error handling strategies when error is occurred.
// PDO::ERRMODE_SILENT (default) | PDO::ERRMODE_WARNING | PDO::ERRMODE_EXCEPTION
// Read more from https://www.php.net/manual/en/pdo.error-handling.php.
'error' => \PDO::ERRMODE_SILENT,
// [optional]
// The driver_option for connection.
// Read more from http://www.php.net/manual/en/pdo.setattribute.php.
'option' => [
\PDO::ATTR_CASE => \PDO::CASE_NATURAL
],
// [optional] Medoo will execute those commands after connected to the database.
'command' => [
'SET SQL_MODE=ANSI_QUOTES'
]
]);
}
public function FDatabase() {
return $this->database;
}
public function UpdatePriceAlertPush($idx) {
$this->FDatabase()->update('tb_apppricealert', [
'triggered' => 1,
'ispush' => 1,
'ipaddress' => $_SERVER['REMOTE_ADDR'],
'datetime' => date('Y-m-d H:i:s')
], [
'idx' => $idx
]);
}
include 'Ticker.php'; // Here error
include 'CheckUpdateVersion.php'; // Here error
// and 50 more.....
}
?>
How to separate each public function into every part of file and include in the main model ?
In my example above both :
include 'Ticker.php'; // Here error
include 'CheckUpdateVersion.php'; // Here error
Got error.
This is "Ticker.php"
<?php
// ================================== TICKER
function InsertTicker($array) {
$this->FDatabase()->action(function($database) use (&$array) {
$this->FDatabase()->insert('tb_ticker', [
'ticker' => $array['ticker'],
'company' => $array['company'],
'ipaddress' => $_SERVER['REMOTE_ADDR'],
'datetime' => date('Y-m-d H:i:s')
]);
// If you found something wrong, just return false value to rollback the whole transaction.
if ($this->FDatabase()->error) {
return false;
}
});
}
function SelectAllTicker() {
$Data = $this->FDatabase()->select('tb_ticker', '*');
return $Data;
}
function GetTicker($ticker) {
$Data = $this->FDatabase()->get('tb_ticker', '*', [
'ticker' => $ticker
]);
return $Data;
}
?>
and this is "CheckUpdateVersion.php"
<?php
// ================================== CHECK UPDATE VERSION
function GetUpdateVersion() {
$Data = $this->FDatabase()->get('tb_version', '*', [
'ORDER' => [
'idx' => 'DESC'
]
]);
return $Data;
}
?>
I want to separate every category function to each file. So in my model it is easy to read and find the function. Also the model will look more tidy.
Is there anyway to achieve it ? I don't want to put all public function into one file. It is too long to read and when try to use the function I need to search the name.
If I separate it into some of file base on category. Then it is easy to find and structure data may look tidy.
Remember this is codeigniter 4
I'm using LDAP in my User data fixtures and I don't want to hardcode the LDAP login options. Initially, I tried this:
$options = array(
'host' => '%ldap_host%',
'port' => '%ldap_port%',
'useSsl' => true,
'username' => '%ldap_username%',
'password' => '%ldap_password%',
'baseDn' => '%ldap_baseDn_users%'
);
But that didn't work. I did some research and realized I needed to include the container in my fixtures. However, it's at this point I'm unsure what my next step is.
As I understand it I need to use the container and it's get method to get the service containing the parameters, but I don't know what that is:
$this->container->get('parameters');
Doesn't work, so I'm wondering what I should use.
My full datafixture is as follows:
class LoadFOSUsers extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
{
/**
* #var ContainerInterface
*/
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function load(ObjectManager $manager)
{
$this->container->get('parameters');
// Not sure how to access param values.
$options = array(
'host' => '%ldap_host%',
'port' => '%ldap_port%',
'useSsl' => true,
'username' => '%ldap_username%',
'password' => '%ldap_password%',
'baseDn' => '%ldap_baseDn_users%'
);
$ldap = new Ldap($options);
$ldap->bind();
$baseDn = '%ldap_baseDn_users%';
$filter = '(&(&(ObjectClass=user))(samaccountname=*))';
$attributes=['samaccountname', 'dn', 'mail','memberof'];
$result = $ldap->searchEntries($filter, $baseDn, Ldap::SEARCH_SCOPE_SUB, $attributes);
foreach ($result as $item) {
echo $item["dn"] . ': ' . $item['samaccountname'][0] . PHP_EOL;
}
}
public function getOrder()
{
// the order in which fixtures will be loaded
// the lower the number, the sooner that this fixture is loaded
return 8;
}
}
You just have to fetch them from container via getParameter('name') or get them all in a bag via getParameterBag().
So:
$options = array(
'host' => $this->container->getParameter('ldap_host'),
'port' => $this->container->getParameter('ldap_port'),
'useSsl' => true,
'username' => $this->container->getParameter('ldap_username'),
'password' => $this->container->getParameter('ldap_password'),
'baseDn' => $this->container->getParameter('ldap_baseDn_users')
);
etc.
I'm using doctrine to fetch data from my MySQL database. This is all done in Silex. These are the lines of code that enable Doctrine for me.
$config = new \Doctrine\DBAL\Configuration();
$connParams = array(
'driver' => 'pdo_mysql',
'dbname' => 'webshop',
'host' => 'localhost',
'user' => 'root',
'password' => '',
'charset' => 'utf8'
);
$conn = \Doctrine\DBAL\DriverManager::getConnection($connParams, $config);
$app['dbcon'] = $conn;
$app->get('/', function () use ($app){
$user = new User($app['dbcon']);
return $app['twig']->render('home.twig', [
'content' => 'Home',
]);
})->bind('home');
And I'm trying to create a user class for login stuff etc. The user class looks like this:
<?php
namespace Models;
class User
{
private $db;
public function __construct($db)
{
$this->db = $db;
$query = $this->db->prepare("SELECT * FROM users");
$query->execute();
$query = $query->fetchAll();
foreach($query as $user){
print_r($user);
}
}
}
Though, the following is the result:
Array ( [id] => 1 [username] => araguera [password] => password [salt] => ksjdfiwe98ru2w98h )
Why does it return as an array and not as an object? Because I want to be able to do something like "$query->username".
To add to u_mulder's comment, you can use PDO style to fetch results as object:
$res = $query->fetchAll(\PDO::FETCH_OBJ);
And in case you want to use fetch (to get one row) you can use:
$res = $query->fetchObject();
I am developing an application in CakePHP. I need two databases in same function in same controller. In Invoice I need to to add data in invoices table but need students list to show from another database having students table.
public function add() {
if ($this->request->is('post')) {
$this->Invoice->create();
$this->request->data['Invoice']['created_by'] = $this->Auth->user('id');
if ($this->Invoice->save($this->request->data)) {
$this->Session->setFlash(__('The Invoice has been saved.'), 'default', array('class' => 'alert alert-success'));
}
return $this->redirect(array('action' => 'view',$Invoice_id));
}
// fetch students from different database.
$this->loadModel('Student');
$users = $this->Student->find('list',array('fields'=>array('Student.id','Student.name')));
}
I am using the public $useDbConfig = 'fees'; as second DB configuration but unable to get the data in same function. Please help.
<?php
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'root',
'password' => 'admin',
'database' => 'inventory',
'prefix' => '',
//'encoding' => 'utf8',
);
// fetch students from fees controller.
public $fees = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'root',
'password' => 'admin',
'database' => 'fees',
'prefix' => '',
//'encoding' => 'utf8',
);
}
You need to declare that your Students model will use a different database source. You are saying that you used the public $useDbConfig = 'fees'; with out mentioning in which model you used this property.
Check this link
We can then configure the datasource in our app/Config/database.php
file by adding something like this:
public $faraway = array(
'datasource' => 'FarAwaySource',
'apiKey' => '1234abcd', );
Then use the database config in our models like this:
class MyModel extends AppModel {
public $useDbConfig = 'faraway';
}
So fees looks like some database that should be used on the Invoice model:
class Invoice extends AppModel {
public $useDbConfig = 'fees';
}
and Students models should most probably stay on the default database
class Students extends AppModel {
public $useDbConfig = 'default'; // This line is optional. Even if you don't write this line your model will load data from the default database.
}
Maybe the databases are the other way around but I think you got the point.
You can still configure the database source of your models from inside your Controller by doing the following:
public function add() {
...
$this->Student->useDbConfig = 'fees'
...
}
or most preferable
public function add() {
...
$this->Student->setDataSource('default')
...
}
I have a simple form which after submitting redirects to processAction inside AuthController and in this action I want to create a simple table bar.
EDITED:
Referring to Zend framerwork DB DDL update, I made a little modification in below code
AuthController.php
<?php
namespace Blog\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Debug\Debug;
use Blog\Form\LoginForm;
use Zend\Authentication\AuthenticationService;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\Sql\Sql;
use Zend\Db\Sql\Ddl;
use Zend\Db\Sql\Ddl\Column;
use Zend\Db\Sql\Insert;
use Zend\Authentication\Adapter\DbTable as DbTableAuthAdapter;
class AuthController extends AbstractActionController
{
protected $adapter;
public function getAdapter()
{
if (!$this->adapter) {
$sm = $this->getServiceLocator();
$this->adapter = $sm->get('Zend\Db\Adapter\Adapter');
}
return $this->adapter;
}
public function indexAction()
{
return new ViewModel();
}
public function processAction()
{
$DB = new \Zend\Db\Adapter\Adapter(array(
'driver' => 'Pdo',
'database' => 'blog',
'username' => 'root',
'password' => 'mysql'
));
$this->adapter = $this->getAdapter();
$sql = new Sql($this->adapter);
$table = new Ddl\CreateTable('bar');
$table->addColumn(new Column\Integer('id'));
$table->addColumn(new Column\Varchar('name', 255));
$table->setTable('bar');
$results = $this->adapter->query($sql->getSqlStringForSqlObject($table), $this->adapter ::QUERY_MODE_EXECUTE);
return new ViewModel();
}
}
global.php:
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=blog;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter'
=> 'Zend\Db\Adapter\AdapterServiceFactory',
),
),
);
Module.php
<?php
namespace Blog;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
class Module implements AutoloaderProviderInterface,ConfigProviderInterface
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getServiceConfig()
{
return array(
'factories' =>array(
'Zend\Db\Adapter\Adapter' => function ($sm) {
$config = $sm->get('Config');
return new \Zend\Db\Adapter\Adapter($config['db']);
}
)
);
}
}
Problem:(Updated)
table bar is not created and shows error like
Fatal error: Class 'Blog\Controller\Zend\Db\Adapter\Adapter' not found
in /var/www/zend2/module/Blog/src/Blog/Controller/AuthController.php
on line 110
if I print
echo $sql->getSqlStringForSqlObject($table);
The query prints like this
CREATE TABLE `bar` ( `id` INTEGER NOT NULL, `name` VARCHAR(255) NOT NULL )
but table was not there.
Error occurs in below line of code as it is not able to identify adapter :
$results = $this->adapter->query($sql->getSqlStringForSqlObject($table), $this->adapter ::QUERY_MODE_EXECUTE);
But works in this way:
$results = $this->adapter->query($sql->getSqlStringForSqlObject($table), $DB ::QUERY_MODE_EXECUTE);
I am using Zend 2.4
I think you are trying to access non existing service. You can try to create a service factory:
config.php
<?php
return [
'db' => [
'driver' => 'Pdo',
'database' => 'blog',
'username' => 'root',
'password' => 'mysql'
]
];
Module.php
<?php
class Module
{
public function getServiceConfig()
{
return [
'factories' => [
'Zend\Db\Adapter\Adapter' => => function ($sm) {
$config = $sm->get('Config');
return new \Zend\Db\Adapter\Adapter($config['db']);
},
],
];
}
}
Then, you can access the service with the service manager:
AuthController.php
class AuthController extends AbstractActionController
{
public function getAdapter()
{
if (!$this->adapter) {
$sm = $this->getServiceLocator();
$this->adapter = $sm->get('Zend\Db\Adapter\Adapter');
}
return $this->adapter;
}
public function processAction()
{
$this->adapter = $this->getAdapter();
$sql = new Sql($this->adapter);
// other stuff here
}
}
You can find more examples here and here.
For beginners in ZF2 ,the query execute won't work if you don't instantiate class Zend\Db\Adapter\Adapter correctly.
I corrected like
$DB = new \Zend\Db\Adapter\Adapter(array(
'driver' => 'Pdo',
'database' => 'blog',
'username' => 'root',
'password' => 'mysql'
));
Also below line of code :
$results = $this->adapter->query($sql->getSqlStringForSqlObject($table), $DB ::QUERY_MODE_EXECUTE);
Ref Fatal error : class not found in Zend framework 2
Note: I still fail to understand why $this->adapter = $this->getAdapter(); not working instead of $DB.Any hint will be appreciated.