Defining configuration values under specific namespaces? - php

I'm writing a framework, and have just added namespaces. I've had no trouble converting everything, save for configuration values.
I can define constants easily, so single values are not a problem...but what about an array of values?
Take this array, for instance, which is the configuration array to add a connection to Capsule...
[
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'DB_NAME',
'username' => 'USERNAME',
'password' => 'PASSWORD',
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => ''
]
I have been using a file that looks like this for database configuration...
<?php
namespace BareBones;
use Illuminate\Database\Capsule\Manager as Capsule;
$BareBonesCapsule = new Capsule;
$BareBonesCapsule->addConnection([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'DB_NAME',
'username' => 'USERNAME',
'password' => 'PASSWORD',
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => ''
]);
$BareBonesCapsule->setAsGlobal();
$BareBonesCapsule->bootEloquent();
use Illuminate\Database\Schema\Blueprint as Blueprint;
use Illuminate\Database\Eloquent\Model as Eloquent;
I'm going to start booting Eloquent from my main App class. This will prevent a global variable from doing it. While it is unlikely that $BareBonesCapsule is going to be used, I would still like to keep my framework clean and keep everything in it's namespace.
I could declare a bunch of constants in the configurations file...
<?php
namesapce BareBones;
define("driver", "mysql");
define("host", "localhost");
define("database", "DB_NAME");
/* etc... */
This doesn't seem very clean, and I'm assuming there is a better way to do this. How do other frameworks handle this issue, and what alternative means of configuration do I have while maintaining a separation from the global namespace?

You can use .ini files and break them into sections like so:
; This is a sample configuration file
; Comments start with ';', as in php.ini
[first_section]
one = 1
five = 5
animal = BIRD
[second_section]
path = "/usr/local/bin"
URL = "http://www.example.com/~username"
[third_section]
phpversion[] = "5.0"
phpversion[] = "5.1"
phpversion[] = "5.2"
phpversion[] = "5.3"
urls[svn] = "http://svn.php.net"
urls[git] = "http://git.php.net"
From: http://php.net/manual/en/function.parse-ini-file.php
Symfony supports XML, PHP and YML and allows you to write your own config decoder.

Related

Escaping a PHP function as an Array value

I'm working on a Drupal 8 starter kit with Composer, similar to drupal-composer/drupal-project.
In my post-install script, I want to re-generate a settings.php file with my custom values.
I've seen that can be done with the drupal_rewrite_settings function.
For example, I'm rewriting the config_sync_directory value like that :
require_once $drupalRoot . '/core/includes/bootstrap.inc';
require_once $drupalRoot . '/core/includes/install.inc';
new Settings([]);
$settings['settings']['config_sync_directory'] = (object) [
'value' => '../config/sync',
'required' => TRUE,
];
drupal_rewrite_settings($settings, $drupalRoot . '/sites/default/settings.php');
Problem is I want my Drupal 8 project to have a Dotenv so the maintainers don't have to modify the settings.php but only a .env file in the root folder of the project. To make it work, my settings.php must look like this :
$databases['default']['default'] = [
'database' => getenv('MYSQL_DATABASE'),
'driver' => 'mysql',
'host' => getenv('MYSQL_HOSTNAME'),
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'password' => getenv('MYSQL_PASSWORD'),
'port' => '',
'prefix' => '',
'username' => getenv('MYSQL_USER'),
];
$settings['trusted_host_patterns'] = explode(',', '^'.getenv('SITE_URL').'$');
As you can see, the values are replaced by PHP functions, and I can't see a good way to print those values, to the point I'm not even sure that's possible.
So my question is : is it possible to escape a PHP function as an Array value when declaring this variable ?
Looks like it's not possible because of the way the Drupal function works.
Solution 1 by #misorude
Using the drupal_rewrite_settings function, we can add the value of settings as a String, like this :
$settings['settings']['trusted_host_patterns'] = (object) [
'value' => "FUNC[explode(',', '^'.getenv('SITE_URL').'$')]",
'required' => TRUE,
];
And after that, we can replace all occurrences of "FUNC[***]" by *** directly in the settings.php file.
Solution 2
Put all your settings in a separate file. Example here, a custom.settings.php file :
if (getenv('DEBUG') == 'true') {
$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/dev.services.yml';
$config['system.performance']['css']['preprocess'] = FALSE;
$config['system.performance']['js']['preprocess'] = FALSE;
}
$databases['default']['default'] = [
'database' => getenv('MYSQL_DATABASE'),
'driver' => 'mysql',
'host' => getenv('MYSQL_HOSTNAME'),
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'password' => getenv('MYSQL_PASSWORD'),
'port' => '',
'prefix' => '',
'username' => getenv('MYSQL_USER'),
];
$settings['trusted_host_patterns'] = explode(',', '^'.getenv('SITE_URL').'$');
$settings['file_private_path'] = 'sites/default/files/private';
$settings['config_sync_directory'] = '../config/sync';
Then we can copy the default.settings.php and add our custom settings.
$fs = new Filesystem();
$settings_generated = $drupalRoot . '/sites/default/settings.php';
$settings_default = $drupalRoot . '/sites/default/default.settings.php';
$settings_custom = $drupalRoot . '/../includes/custom.settings.php';
$fs->remove($settings_generated);
$fs->dumpFile($settings_generated, file_get_contents($settings_default) . file_get_contents($settings_custom));
There's also a appendToFile method that seems way better than dumping a new file with dumpFile, but it was not working unfortunatly.

PDO Exception:SQLSTATE[HY000] [2006] MySQL server has gone away with xampp

I'm trying to connect to the database and fetching some records but I'm getting error:
Error i'm getting
I'm using Slim PHP framework and slim-twig to render views so my code for the connection file is:
<?php
use Payment\App;
use Illuminate\Database\Capsule\Manager as Capsule;
session_start();
require __DIR__ . '/../vendor/autoload.php';
$app = new App;
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => 'localhost:8080',
'database' => 'payment',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => ''
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();
require __DIR__ . '/../app/routes.php';
?>
I had also configured my php.ini file properties like max_execution_time & max_allowed_packets but it didn't work and i had also checked that no loop is causing this problem because it takes approx 3 min to show me this error,in this 3 min the it loads.so please anyone can tell me where i'm doing in my code?
Probably caused by your packets. The following settings should help:
Run this in your MySQL terminal.
set global max_allowed_packet=104857600

Use Illuminate database

I want to use Illuminate database(https://github.com/illuminate/database). Not with Laravel, use only in my php file.
I do
use Illuminate\Database\Capsule\Manager as Capsule;
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
But it seems not working, and don't show any error message. Do I need to require any file? The illuminate directory is in the same directory with my php file.
EDIT:
I can use query now. Like this
$users = Capsule::table('users')->where('votes', '>', 100)->get();
I don't know how to use model.
User.php
class User extends Illuminate\Database\Eloquent\Model {
}
My php file
require 'vendor/autoload.php';
require 'User.php';
$users = User::where('status', '=', 1)->get();
Got error
Fatal error: Call to a member function connection() on a non-object in /Users/someone/repos/test/vendor/illuminate/database/Illuminate/Database/Eloquent/Model.php on line 2472
SOLVED:
Everything works fine. Use #majid8911 example https://github.com/mattstauffer/IlluminateNonLaravel
Thank you everyone.
take a look at here I successfully did the same with this tutorial:
https://github.com/mattstauffer/IlluminateNonLaravel

Using different databases based on user request

I've installed Laravel-4 and jenssegers / Laravel-MongoDB which has the same interface to Eloquent model as Laravel, so everything is pretty transparent and 1 database connection works OK.
what I'm trying to do, is switch to another database based on user request (Consider it as API that decided where to go and grab data).
This is what I did:
App::before(function($request)
{
$dbPrefix = $request->segment(1);
if (!is_null($dbPrefix)) {
$dbName = strtolower($dbPrefix);
$newDb = DB::connection('mongodb_'.$dbName);
}
});
From here.. I don't know what to do.. Is it connected to new database that way? how do I tell my Laravel to use $newDb when I refer to DB constant in Models?
But I want it to happen before application starts, so specifying "$connection" variable in model or using explicit call to other database like DB::connection('mongodb2')->query(...) is no good for me.
Thanks
The solution to this would be:
/app/filters.php:
App::before(function($request)
{
$dbPrefix = $request->segment(1);
if (!is_null($dbPrefix)) {
$connectionName = 'mongodb_'.strtolower($dbPrefix);
Config::set('database.default', $connectionName);
}
});
/config/database.php:
'mongodb_soccer' => array(
'driver' => 'mongodb',
'host' => 'localhost',
'port' => 27017,
'username' => 'user',
'password' => 'password',
'database' => 'SoccerData'
),
'mongodb_tennis' => array(
'driver' => 'mongodb',
'host' => 'localhost',
'port' => 27017,
'username' => 'user',
'password' => 'password',
'database' => 'TennisData'
)
Requests:
site.com/soccer
will get connection mongodb_soccer
site.com/tennis
will get connection mongodb_tennis
You can pre-authorize it in default "admin" database where your users are stored, and then switch to any database connection per user request to get the actual data.
I needed it this way for API development.
Good luck

CakePHP - Setup database with a form

I would like to setup the database in CakePHP providing host, login and password with a form (so without writing the database.php file myself). The purpose is some kind of automatic setup of CakePHP (I would use this to provide salt and cypherSeed too).
Is this possible? What's the best way to do go? I read something about writing file via PHP...
If you create/load your database connection from your controller you can have this data variable. I don't think it's a good idea to write database.php file with a form.
So I would do something like this:
//Controller
$this->Formdatabase = ClassRegistry::init('Formdatabase');
$db_host = '';//load from file or DB
$db_user = '';//load from file or DB
$db_pass = '';//load from file or DB
$db_database = '';//load from file or DB
ConnectionManager::create("form_database", array(
'datasource' => 'Database/Mysql',
'driver' => 'mysql',
'persistent' => false,
'host' => $db_host,
'login' => $db_user,
'password' => $db_pass,
'database' => $db_database,
'prefix' => '',
'encoding' => 'UTF8',
'port' => '',
));
$this->Formdatabase->useTable = ''; //table you want to use. (in Model or controller)
//Model
<?php
class Formdatabase extends Model {
public $useDbConfig = 'form_database';
}
?>
//Now you can use $this->Formdatabase->find('...'); ...
Hope I could help, good luck!

Categories