Module specific database - zend framework 2 - zend-framework2

Using Zend Framework version 2, how to configure different databases for different modules. Each module will have access to different database.
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=test;host=localhost',
'driver_options' => array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''),
'username' => 'root',
'password' => '',
),
placed above code in module.config.php for each module with different DB name
Thanks in advance

The concept of a module configuration is actually more that the module is providing some configuration for the application. The supplied configuration is merged into a single configuration and therefore using the same configuration key names will cause this data to be overwritten.
So instead use descriptive names - db_user or db_logging etc.
Also it's probably a good idea to look at ServiceManager factories, as you can pull out some common database credentials and then use a different database name depending on which factory is being used.
I've only lightly touched on databases in ZF2 so maybe someone else will offer a better approach.

Related

ZF2 - How to pass config array to base test case class

When using AbstractControllerTestCase (or it's subclasses) you get a convenient method setApplicationConfig() that let's you pass an array similar to config/application.config.php, so that you include only the modules you need in order to test.
How do you pass the array that goes into config/autoload/global.php to AbstractControllerTestCase?
PS: if it helps, I'm trying to pass a custom ORM connection that uses SQLite
You can simply make separate config files to be used when testing and load those inside your test controller.
for example;
copy config/application.config.php to config/application.config.test.php
Make a small change to allow us to load separate test config files without touching the global config files used by the production application.
'config_glob_paths' => array(realpath(__DIR__) . '/autoload/{,*.}{global,test}.php'),
This will allow us to override any config values we need as the test config files are loaded after the usual global config files. We can now please any test specific configureation inside test.php, anything.test.php etc.
now you can copy
autoload/global.php to autoload/test.php
You can now change config items and these will override those inside global.php
autoload/test.php
<?php
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'sqlite:' . __DIR__ .'/../../data/testing.sqlite',
//'dsn' => 'mysql:dbname=somedatabase;host=localhost',
'username' => 'dbuser',
'password' => 'passwordgoeshere',
),
You could also change the driver to use SQL lite or what ever your require to run your tests.
Now you just need to make your test controllers load our new application config file:
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class ExampleTest extends AbstractHttpControllerTestCase
{
public function setUp()
{
$this->setApplicationConfig(
include __DIR__ . '/../../config/application.config.test.php'
);
}
This allows you to keep all your test configuration separate to your main application config settings.

zend 2: Override 'db' configuration in config\autoload\global.php, local.php for a specific module

I want to make sure this works the way I think it does.
I have setup DB info inside of myapp/config/autoload/global.php like this:
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2tutorial;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
...
Now I'm messing around with a new module and would like to configure that specific module with a different db. If I add a 'db' config array to NewModule/config/module.config.php will it overwrite the global config? I'm not sure if the application wide global.php file is the same as a module specific config file or if it has a special specification- like accepting a db configuration while module specific config files do not.
edit: Well I tried this and it appears the db entry I added in module.config is being completely ignored. How can I override the db config per module? It would be very convenient for testing purposes.
If I add a 'db' config array to NewModule/config/module.config.php will it overwrite the global config?
Yes. All configs are merged together in to one monster array.
ZF support multiple adapters, you'll just have to refer to them by name in code so it knows which one you want. See this blog post for details on how to set it up: http://samsonasik.wordpress.com/2013/07/27/zend-framework-2-multiple-named-db-adapter-instances-using-adapters-subkey/

How do I reference a tiny_tds connection in ruby/sinatra via database.yml (or other)?

I'm trying to figure out how to pull data from a database without the need to place a connection string at the top of each ruby file.
I'm learning the basics of ruby via a little Sinatra app I'm putting together which pulls data from a MSSQL database.
So far I've managed to create various simple erb pages that display data from the MSSQL database by using the following code structure at the top of each file:-
<% client = TinyTds::Client.new(:username => 'name', :password => 'password', :dataserver => 'hostname', :database => 'database') %>
<% data = client.execute("SELECT * from tablename") %>
From the books, guides and online tutorials I've found based on lots of configs to do with PostgreSQL or MySQL databases it seems to me I need to be creating a central file to store my connection data (such as a database.yml file) and then referencing that somewhere/somehow in my app.
Would that be correct, and should I be doing that in my main.rb file so that each of my .erb files do not require the connection string or do I have to still refer to the database in each .erb file also?
I've noted references to creating database config variables such as:-
db_config = YAML.load(File.Open("/path_to_file/database.yml")) [ENV['RAILS_ENV']]
but that clearly seems suited to Rails apps.
Could I do something similar for my sinatra driven 'app'?
Thanks.
This should work:
require "sinatra"
require "sinatra/config_file"
config_file 'path/to/config.yml'
DB = TinyTds::Client.new(
:username => settings.name,
:password => settings.password,
:dataserver => settings.hostname,
:database => settings.database
)
get '/' do
#result = DB.do_stuff
haml :index
end
What I would suggest though, is that you look for an ORM that supports TinyTDS and use that to set up the database connection and run queries. I use Sequel a lot and I know it supports TinyTDS, but I'm sure others do too.
I'd also suggest not putting things like database settings in a file that gets checked in to source control, as it's sensitive information. I prefer to put this kind of thing into environment variables for production, and use a config file to load the environment variables in development (for convenience). Using the above example:
DB = TinyTds::Client.new(
:username => ENV["name"],
:password => ENV["password"],
:dataserver => ENV["hostname"],
:database => ENV["database"]
)
Those env variables are loaded into the production server's memory, which makes them a little bit more secure. For development, I load YAML files before starting up Sinatra, adding each value to an ENV var. I'm not suggesting this is a standard way, but it's how I do it.

Dynamically defining the database name in a Ruby Rails application

Is there a way of setting the database name dynamically (coming originally from database.yml), ideally using part of the application pathname?
Background of the question is, I have a single source code that shall run on one and the same server multiple times but each instance of the application should have a different database.
Example, I have an auction site which works with the currency USD. Now I want to run the same auction site again (one the same server) for a second currency. For valid reasons I don't want to make the application multi-currency capable, I'ld like to keep the source code as is.
Setting up the application on the same server using sub-URL I will follow this approach:
http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rack_to_sub_uri
The question left is, how does each instance of the application get its own DB name, e.g. the one instance uses the database name production_USD and the otherone uses production_CAD
Edit: The solution works like a charm, thanks to the feedback received:
My folder structure on the server is
/var/www/auction/USD-US Dollar
/var/www/auction/CAD-Canadian Dollar
/var/www/auction/source
/var/www/logs
With the source folder containing the original source code and the USD and CAD being links to the source (no actual need for copying any code anywhere other than placing it into source.
Next to set the DB dynamically. The currency is determined automatically by looking
at the folder name. I put it into the application.rb as I need it to
in an early stage because I also want different log files for the different currencies.
I am storing the log files outside of the source folder to make sure I don't loose them
when the source folder gets refreshed from the QA system
Here the code changes:
application.rb:
fname = File.basename(File.expand_path('../../', __FILE__))
curr = fname.split("-")
if curr[1].nil?
CURR_SHORT = "XXX"
CURR_LONG = "XXX"
else
CURR_SHORT = curr[0]
CURR_LONG = curr[1]
end
dbname = "myapp_#{CURR_SHORT}_#{Rails.env[0..2]}"
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3",
:host => "localhost",
:username => "myuser",
:password => "mypass",
:database => dbname
)
module Virex
class Application < Rails::Application
config.logger = ActiveSupport::BufferedLogger.new("../logs/#{Rails.env}.#{CURR_SHORT}.log")
....
Of course, have a look at ActiveRecord::Base.establish_connection :
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "myuser",
:password => "mypass",
:database => "somedatabase"
)
You can put this piece of code in an initializer, with the database name you want, depending on your pathname.
Complete doc here

How do I store keys for API's in Rails?

I have several api's that I am integrating with and need to call in various parts of my application.
What is the way to store the keys, the user/password, or token information, say, a configuration file and then how do I call them for use in other parts of the application?
Thanks.
Just to keep this question up-to-date, there is a new way to do this in Rails 4.1:
From the Rails guides:
Rails 4.1 generates a new secrets.yml file in the config folder. By default, this file contains the application's secret_key_base, but it could also be used to store other secrets such as access keys for external APIs.
You can store usernames/passwords and similar configuration information in mechanisms that rails already uses; you can either stuff the configuration data right into your environment configuration files (where production, testing, and development are configured), or you could use your own mechanism and:
require "yaml"
config_hash = YAML::load_file("/path/to/your/config.yaml")
Easiest is to store the info as constants in your various environment files. That way you can use different accounts for development, production, etc.
# Eg
# development/environment.rb
....
API_1_USER = "user101"
API_1_PW = "secret!"
Alternative is to create a yaml file, then read it when your app signs in to an api. This is the style used by rails itself with the config/databse.yml file
ADDED
You can also store as a constant using a hash or nested hash.
# Eg
# development/environment.rb
....
API_1 = {"user" => "user101", "pw" => "secret!"}
API_2 = {"user" => "user102", "pw" => "double_secret"}
# or nested hashes
API_KEYS = {
"api_1" => {"user" => "user101", "pw" => "secret!"},
"api_2" => {"user" => "user102", "pw" => "double_secret"}}
# using them in another file:
foo.signin(API_1['user'], API_1['pw'])
# or
foo.signin(API_KEYS["api_1"]['user'], API_KEYS["api_1"]['pw'])
# note, I use string constants instead of symbols to save vm (since the hash is
# not referenced more than once or twice). You could also use
# symbols as the keys, especially if the hash will be referenced often:
API_1 = {:user => "user101", :pw => "secret!"}
Check out Configatron, it's pretty awesome and can be used exactly for this purpose.

Resources