How to handle config files (or db creditentials) in git branches? - php

I have a simple web app. I have a production database for the live version, and a test database for development. I store the database credentials in a config file, like so:
<?php
return array(
'hostname' => 'myhostname',
'username' => 'myuser',
'password' => 'mypassword',
'dbname' => 'myLiveDB',
);
?>
This file is tracked by git. On the development branch I want to have file with the same name, just with different credentials. I do my work in this branch, test things out and then merge into master when I want to deploy a newer version.
I never want to see this file change during a merge/rebase operation. Each branch should always keep its own version and it should only be updated by committing directly onto the branch.
What I have considered so far:
.gitattributes files with merge=ours for the config file + git config --global merge.ours.driver true. I don't think this works for rebase, which is a problem. I'm also not sure if every other developer working on this would need to update their config manually, or is there a way to change that setting on a repository level?
ditch the config file, rewrite everything to use environment variables. set them manually for the server and for each dev.
have a config_test.php and a config_prod.php in the repository. When deploying, have the script take a look at what branch we are deploying from and copy the the correct file while renaming it to config.php

I guess the third point might be good and a right method. In spring-boot (java) we used to have different profiles in yamal file (application.yml) with names like dev, test, prod etc and spring itself will take the exact file when it is running in that specific environment. Check something like is there or not.
But in your case, just think whether you need a file which is under git or not.
Think that you have a file under your home directory (say /home/myname/testfile/development.properties). And change the code so that, if this properties file exists then take it otherwise take the other one.

Related

Symfony 5 global dynamic configuration file

I'm a long time Zend Framework user (now renamed Laminas). But I decided to give a try to last Symfony version. So I just installed it in 5.1.2.
I'm facing a question regarding the multiple environments deployments. In my compay, we have :
Local environment which is developer pc.
Development.
Staging.
Production.
In ZF-Laminas, we have a global.php file which is located in config directory.
For those of you who are not familiar with this framework, you can override key set in global.php file by creating local.php file.
In this global file, I use to put standard configuration for my application.
For example (prod) :
'open_id' => [
'client_id' => 1234
]
Then, I have development and staging files which car override those values for every environmenet. During the deployment, the file corresponding to the environment is copied to local.php.
Let's say staging.local.php.dist becomes local.php with :
'open_id' => [
'client_id' => 5678
]
Which is fine because value is overriding the one from global file.
I would like the same behavior in Symfony but I don't see something similar in Symfony 5.
So far, I only found two possibilities
Create a bundle which will allow me to have a <bundle_name>.yaml file in config/packages directory. According to the documentation (https://symfony.com/doc/current/configuration.html#configuration-files), I will be able to have dev, prod and staging overrides. But it forces me to create a bundle to handle just some standard configurations, which is huge.
Use .env files. But .env files only allow string data, not complex data like arrays.
What do I miss ? Or is it my "zend" way of doing things that is wrong ?
Thanks.
You can also create services_%env%.yaml (services_dev.yaml, services_test.yaml) files for each environment. It will allow you to define different parameters and override/define services for each environment.
Example:
config/services_dev.yaml
parameters:
hello: 'world'
From what I understand from your post, your goal is to have different config values based on the server you are on. If this is the case, you can use environment variables (in the .env file or .env.local for server specific config). You can then use these values in your applications by binding the env var to a parameter. This parameter will then be available within the configuration by using %parameter_name% as value or within the container. You can also pas parameters to services (service definitions are handled the same way as any other config). For more information you can checkout these sources:
https://symfony.com/doc/current/configuration/env_var_processors.html
https://symfony.com/doc/current/configuration.html

How to change different configuration settings between environments in PHP?

I have a a few php files which I call via AJAX calls. They all have a URL to my config.php. Now I've the problem that I always have to change the URLs to that config file by hand when I deploy a new version on my server.
Local Path:
define('__ROOT__', $_SERVER["DOCUMENT_ROOT"].'/mywebsite');
Server Path:
define('__ROOT__', $_SERVER["DOCUMENT_ROOT"].'/../dev.my-website.tld/Modules/');
I want to track changes in all of these PHP files. I'm searching for a solution to automatically change this path.
E.g.
This is my current workflow:
Local Environment:
(path version A)
do changes in the code
git add, git commit, git merge, git push to my server
Server:
git reset --hard
change path to version B
You are trying to run different code bases between development and live, which is not recommended -- they should be identical. The way I tackle this is to use an environment variable to specify which of several config files should be loaded.
In my Apache vhost I do something like this:
SetEnv ENVIRONMENT_NAME local
And then I use a function to read the environment name:
function getEnvironmentName()
{
$envKeyName = 'ENVIRONMENT_NAME';
$envName = isset($_SERVER[$envKeyName]) ? $_SERVER[$envKeyName] : null;
if (!$envName)
{
throw new \Exception('No environment name found, cannot proceed');
}
return $envName;
}
That environment name can then be used in a config file to include, or to retrieve values from a single array keyed on environment.
I often keep environment-specific settings in a folder called configs/, but you can store them anywhere it makes sense in your app. So for example you could have this file:
// This is /configs/local.php
return array(
'path' => '/mywebsite',
// As many key-values as you want
);
You can then do this (assuming your front controller is one level deep in your project, e.g. in /web/index.php):
$root = dirname(__DIR__);
$config = include($root . '/configs/' . getEnvironmentName() . '.php');
You'll then have access to the appropriate per-environment settings in $config.
A pure git way to achieve this would be filters. Filters are quite cool but often overlooked. Think of filters as a git way of keyword expansion that you could fully control.
The checked in version of your file would for example look like this:
define('__ROOT__', 'MUST_BE_REPLACED_BY_SMUDGE');
Then set up two filters:
on your local machine, you'd set up a smudge filter that replaces
'MUST_BE_REPLACED_BY_SMUDGE'
with
$_SERVER["DOCUMENT_ROOT"].'/mywebsite'
on your server, you'd set up a smudge filter that replaces
'MUST_BE_REPLACED_BY_SMUDGE'
with
$_SERVER["DOCUMENT_ROOT"].'/../dev.my-website.tld/Modules/'
on both machines, the clean filter would restore the line to be
define('__ROOT__', 'MUST_BE_REPLACED_BY_SMUDGE');
Further information about filters could be found in this answer and in the Git Book.

Laravel and Github - Workflow and Problems

I have a Laravel project right now and I'm using Github for my project.
I have two branches, master and develop.
The problem right now is,...
I have all the files in one folder /dev I'm using Sublime Text 2 and the official Github Client. When I switch branches, I see that in ST2 in the status bar, that's fine.
I put sftp-config.json in my gitignore BUT I have different FTP data for master and develop. I always have to edit the data in ST2 tu upload correctly onto my FTP to test my changes. Sometimes I even forget that, and accidentally upload develop to my master/live page.
Same problem for the routes.php, I need to disable SSL in my routes.php for the DEV because I do not have a wildcard certificate and my dev branches/ftp runs on dev.domain.tld and my main site at www.domain.tld .
I created a environment for my Laravel configs, one main config and "development" config.
Is it possible to use Config::get('app.ssl') in my routes.php in my filter? Like that:
Route::group(['before' => ['csrf',Config::get('app.ssl')]], function () {
Route::get('page', array('as' => 'page','uses' => 'PageController#getIndex'));
});
?
My workflow right now is very annoying and confusing sometimes. I always have to check that I do not upload stuff on my live server or changes the master files.
Any suggestions are highly appreciated!
Of course! Laravel supports environmental configuration out of the box. You can find pretty much everything you need in the official docs. However here's an example:
app/config/app.php - "main config"
array(
// other config entries
'ssl' => true
)
app/config/local/app.php - config for the environment local (you can call it whatever you want)
array(
'ssl' => false // here we override the value from our main config
)
Now the last thing we have to do is make sure our environments get detected correctly.
Laravel uses the host name to detect an environment. So you need to figure out how your machine(s) is called.
An easy way to do that is with the PHP function gethostname()
In bootstrap/start.php you can define your environments:
$env = $app->detectEnvironment(array(
'local' => array('your-machine-name'),
'other-environment' => array('other-machine-name')
));

How to make ZF2 db credentials environment specific

I am starting a new project.
I am using ZF2. I have just installed it and have the Skeleton application up and running.
This is my deployment process:
I develop on my local machine
I then push to my public github repository
I then use deployhq.com to deploy those to my production
server which is where the user would see the changes made.
I have tried to look around stack, zend site, and google at blogs etc but still dont have any real understanding or solution to my problem.
I want the application to use different database credentials based on its environment. E.g. if on 'dev', my local machine, then use credentials A, but if on live server, then use credentials B.
I have read a lot about global and local autoload config files etc, but baring in mind my github repo is public, any where I commit any config files with my db details would be visible.
I was wondering if there was a way to have, the same theory, global and local files with the DB connections in, i upload the production details manually, not via git for security reason, and tell git to ignore the local config file somehow? I would also need to know how I tell the application to use those config files based on the environment and there location.
In Zend 2 There are
Global configuration file &
Module level configuration file
IF you want to know there use you can refer the link below
How does configuration works in ZF2
When I had a same scenario I used the above link to understand and exploit Zend Config module which is really good to handle the situation like this .
create two files
production.php
local.php
in both these files
return this array based on the environment
return array(
"dbname" => "yourdbname"
"dbhostname" => "dbhostname"
"dbusername" => "yourdbusername",
"dbpassword" => "yourdbpassword"
);
in config/autoload/ directory of your zend framewrok application
later edit your config/application.config.php file as per below instructions
// get the application env from Apache vhost file ( here you can set in your apache vhost file as production or local )
$applicationEnv = getenv('APPLICATION_ENV');
$environmentSpecificConfigPath = "config/autoload/{,*.}{".$applicationEnv.",local}.php";
// Next with in the config array pass the environment specific configuration path
'config_glob_paths' => array($environmentSpecificConfigPath)
in any controller or action
you can just use the below code
$configArray = $this->getGlobalConfig();
Now $configarray has all your DB credentials to create a connection
$adapter = new Zend\Db\Adapter\Adapter(array(
'driver' => 'Mysqli',
'database' => $configArray['dbname'],
'username' => $configArray['dbusername'],
'password' => $configArray['dbpassword']
));
If you use config array to connect the DB in your entire application
you dont need to worry about environment changes just make sure you have an Apache APPLICATION_ENV entry in your vhost file
you can do that by adding below line in your apache vhost file
SetEnv APPLICATION_ENV "production" // in your production server
SetEnv APPLICATION_ENV "local" // in your local
Also Last but not least you can use the Zend Experts module ZeDB
https://github.com/ZendExperts/ZeDb
To manage your CRUD applications
Hope the above steps may help you in creating the environment

What is the right way to maintain a "version for the server" - with only config files changed, in Git?

I sometimes work with Codeigniter, and after I'm done developing on the local site, I need to migrate the files to the server. All the files in the /config/ folder need to be changed to match the Server settings. It's not right to make an entire commit for these changes, do I simply make Git ignore these files altogether, or is there a way to track these changes and apply them with Git at the right moment?
You could keep versioned:
two "value config files", with the right values for each environment
a template config file, with value placeholder in it (for instance, ##PORT_NUMBER##)
a script able to generate the actual config file depending on the current environment
a content filter driver which, on checkout, will trigger the script in order to generate the right config file.
Note: that supposes your template config file has a recognizable content (the filter doesn't have a name or path of the file). See "Git equivalent of subversion's $URL$ keyword expansion" for more on the limitation of git content filter driver).
It depends on Your needs. In my company we use other approach.
We've created several environments (where the asterix is internal project name):
devel - site runs on domain **.local.com*
test - site run on domain test.*.company.com
beta - beta.*.company.com
production - every other domain.
Based on the domain name we switch automatically configurations.
Basicly config file looks like:
<?php
return array(
'_env' => array(
'devel' => array(
// config for devel
),
'production' => array(
// config for production
)
)
);
?>
Some frameworks (AFAIR Zend) set the environment name in Virtual Host config (or .htaccess). You should look at: zend framework auto switch production staging test .. etc
Have You looked at CI documentation? There's a section about it.
Create two folders in the config folder. One is called development and the other is production. Now copy config.php, database.php etc to each of these folders. Now when you are on production server, CodeIgniter will first check the production folder for the files. If it is not there, then it uses the default file in the config folder. And if you are on development environment, CodeIgniter will first check the development folder.
If you want to keep any config file identical to the production and development environment, keep it in config folder.
If you want to set the environment then add the following code in .htaccess file:
#This code for Development Environment
SetEnv CI_ENV development
and
#This code for Production Environment
SetEnv CI_ENV production

Categories