How to preserve application.ini paths using Zend_Config_Writer_Ini
Asked Answered
M

4

3

I'm currently working on a build system in Phing that takes a Zend Framework project template and configures it according to Phing parameters. One problem that I've come across is when using Zend_Config_Writer_Ini.

My Phing task takes a pre-populated file from the repo called application.default.ini and modifies this using Zend_Config_Ini to add parameters from the build file (db details, etc). It then writes it to application.ini ready for the project to use. A simplified version of the related task code looks something like this:

$appConfig = new Zend_Config_Ini(
    $appDefaultConfigPath, 
    null, 
    array(
        'skipExtends' => true,
        'allowModifications' => true
    )
);

$appConfig->production->resources->db->params->host = $buildProperties->db->host;
$appConfig->production->resources->db->params->username = $buildProperties->db->username;
$appConfig->production->resources->db->params->password = $buildProperties->db->password;
$appConfig->production->resources->db->params->dbname = $buildProperties->db->dbname;

$writer = new Zend_Config_Writer_Ini();
$writer->setConfig($appConfig)
       ->setFilename($appConfigPath)
       ->write();

This works fine as far as the database credentials go but when it comes to pre-populated paths that include defined constants something goes wrong. For example:

bootstrap.path = APPLICATION_PATH "/Bootstrap.php"

becomes:

bootstrap.path = "APPLICATION_PATH/Bootstrap.php"

Is there any way to preserve these config lines when reading/writing to different ini files or should I restructure my build file to copy the file before running the task and only modify the ini lines that I need to change?

Mcclelland answered 12/7, 2011 at 21:21 Comment(2)
You say your DB works fine. How about showing us the code for the data that doesn't work instead of the code that seems to work? Where is the code for the bootstrap config which is not working for you?Rift
Never mind, I got it. My bad!Rift
R
1

When you load the existing config all constants are already translated, i.e. if you look at the object with print_r you won't find your constants anymore. Hence, with the writer the full path is printed instead of the constants.

In your case I guess that the constants don't exist in your environment and therefore are printed as is.

Update: To be more specific. Zend_Config_Ini::_parseIniFile() uses parse_ini_file() to read the ini file which loads the constants as real paths. See php.net doc Example #2

Rift answered 12/7, 2011 at 22:49 Comment(2)
Thanks Adrian, you're spot on. I forgot to bootstrap my phing tasks properly to contain the ZF application constants. While on the same subject, is it best practice for Zend Framework to include PHP constants in a configuration file? It seems kind of messy to me.Mcclelland
The use of php constants in the configuration is very common. Even the ZF Quick Start Guide use them.Diluent
D
1

Straight from this php.net comment:

Constants in ini files are not expanded if they are concatenated with strings quoted with single quotes, they must be in double quotes only to make constants expanded.

Example:

define ('APP_PATH', '/some/path');

mypath = APP_PATH '/config' // Constant won't be expanded: [mypath] => APP_PATH '/config'

mypath = APP_PATH "/config" // Constant will be expanded: [mypath] => /some/path/config

So you could rewrite your pathes with single quotes ... bootstrap.path = APPLICATION_PATH '/Bootstrap.php'

... and later replace all occurrences of APPLICATION_PATH '*' with double quotes (a simple Regex should do).

Diluent answered 13/7, 2011 at 7:25 Comment(0)
D
1

As an alternative you could use Phing's Filter to replace tokens in your configuration template.

A example task:

<target name="setup-config" description="setup configuration">
    <copy file="application/configs/application.ini.dist" tofile="application/configs/application.ini" overwrite="true">
        <filterchain>
            <replacetokens begintoken="##" endtoken="##">
                <token key="DB_HOSTNAME" value="${db.host}"/>
                <token key="DB_USERNAME" value="${db.user}"/>
                <token key="DB_PASSWORD" value="${db.pass}"/>
                <token key="DB_DATABASE" value="${db.name}"/>
            </replacetokens>
        </filterchain>
    </copy>
</target>

This task copies application/configs/application.ini.dist to application/configs/application.ini and replaces tokens like ##DB_HOSTNAME## with the value from the phing property ${db.host}

Diluent answered 13/7, 2011 at 7:40 Comment(1)
That looks like a much cleaner way of doing it rather than creating my own task. I'm pretty new to phing and wasn't aware of the filter/token functionality. Thanks!Mcclelland
Q
0

I wanted the convenience of using Zend_Config while preserving the ability to use the APPLICATION_PATH constant so I ended up fixing the file with a simple regex after Zend_Config_Writer saves the file.

$writer->write();

// Zend_Config_Writer messes up the settings that contain APPLICATION_PATH
$content = file_get_contents($filename);

file_put_contents($filename, preg_replace('/"APPLICATION_PATH(.*)/', 'APPLICATION_PATH "$1', $content));
Quarta answered 11/9, 2012 at 6:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.