views:

30

answers:

1

So I have a PHP file that I use to define all my constants but now want the flexibility of using a XML instead.

Example PHP Config file

define("LOGIN_URL", "secure_login.php");
define("REDIRECT", "redirect.php");

define("MAPPED_VALUE_GREEN", "object_green");
define("MAPPED_VALUE_KEY", "object_key_12345");

What I'm going to do is:

<scriptNameConfig>
  <urls>
     <url alias="LOGIN_URL" scriptname="secure_login.php" location="optional/path/to/file"/>
     <url alias="REDIRECTL" scriptname="redirect.php" location="optional/path/to/file"/>
  </urls>
  <mapping>
     <mapped name="MAPPED_VALUE_GREEN" data="object_green"/>
     <mapped name="MAPPED_VALUE_KEY" data="object_key_12345"/>
  </mapping>
</scriptNameConfig>

Now this is okay but I want to use XPATH to extract the values from this type of config file but would like it to be dynamic enough so I don't have to hard code the functions

This is my base class

class ParseXMLConfig {
    protected $xml;

    public function __construct($xml) {
        if(is_file($xml)) {
            $this->xml = simplexml_load_file($xml);
        } else {
            $this->xml = simplexml_load_string($xml);
        }
    }
}

And I extend it like this

class ParseURLS extends ParseXMLConfig {

public function getUrlArr($url_alias) {
        $attr = false;
        $el = $this->xml->xpath("//url[@alias='$url_alias']");
        if($el && count($el) === 1) {
            $attr = (array) $el[0]->attributes();
            $attr = $attr['@attributes'];
        } 
        return $attr; // this will return the element array with all attributes
    }
}

But the problem is if I wanted to introduce a new value in the confie file I have to add some sort of function for XPATH to parse it. wanted to know if anyone has an idea on how to go about doing this generic/dynamic so adding/changing or removing elements/attributes in the XML config file would be easier and less hard coding.

Thanks for any tips/examples/code/ideas, -Phill

+1  A: 

I'm curious - exactly what flexibility do you think you're getting from this? You're going through an awful lot of work to put stuff in XML just to convert it to PHP data.

If you're ok with ditching XML (i.e., nothing else is using this configuration), why not something like this?

class Config
{
  private static $urls = array(
      'LOGIN_URL' => array(
          'scriptname' => 'secure_login.php'
        , 'location'   => 'optional/path/to/file'
      )
    , 'REDIRECTL' => array(
          'scriptname' => 'redirect.php'
        , 'location'   => 'optional/path/to/file'
      )
  );

  public static function getUrlArr( $alias )
  {
    if ( isset( self::$urls[$alias] ) )
    {
      return self::$urls[$alias];
    }
    throw new Exception( "URL alias '$alias' not defined" );
  }
}

Also, as a side note, I have some reservations about your choice to put a verb (parse) in a class name. If you're gonna go that route, try using a noun-representation of that verb.

class XmlConfigParser {}

EDIT

In that case, then you can't have any method names that refer to the XML node structure (unless you want to get into the world of meta programming)

Really no matter what you do, you're just going to be creating syntactic sugar over an XPath expression

Here are examples of methods you might make

// Use XPath from the client
$config->fetchAttributesByXpath( "/urls/url[@alias='LOGIN_URL']" );

// Abstract away the XPah
$config->fetchAttributes( 'urls.url', 'alias', 'LOGIN_URL' );

For example, symfony does something like this with their config files, which are YAML. In a config file like such

// app.yml
urls:
  LOGIN_URL: {scriptname: 'secure_login.php', location='optional/path/to/file'}

You would retrieve the value like so

$values = sfConfig::get( 'app_urls_LOGIN_URL' );
Peter Bailey
I would like to but in my Org (Where I work) anything but an XML change needs to go through a release, which means downtime and a maint window and all that jazz. But if using XML I can configure all I want without all that headaches, so I don't mind a little work to get things as I would like them to be :)
Phill Pafford
Also in your example you are still coding for the URL specifically, I wanted to make this generic. So I could pass any XML structure, be able to search and pull elements with attributes at will
Phill Pafford
This does make more sense: class XmlConfigParser {}Thanks
Phill Pafford
Added stuff to respond to your comments.
Peter Bailey