I have a mail script that I use in one of my projects, and I’d like to allow customization of this letter. the problem is that parts of the email are dynamically generated from the database. I have predefined tokens that I use to describe what should replace the token, but I’d like to simplify this but writing a better parser that can interpret the token and figure out which variable to use to replace it.
Right now I have a very large array with all the possible tokens and their corresponding values, like so:
$tokens['[property_name]'] = $this->name;
and then I run through the template and replace any instance of the key with it’s value.
I’d prefer to just run through the template, look for [] or whatever I use to define a token, and then read what’s inside and convert that to a variable name.
I need to be able to match a few levels of relationships so $this->account->owner->name;
as an example, and I need to be able to reference methods. $this->account->calcTotal();
I thought I might be able to take the example [property_name] and replace the instance of _ with -> and then call that as a variable, but I don’t believe it works with methods.
You’re creating sort of a template system. You can either re-invent the wheel (sort of) by coding this on your own or just using a lighweight template system like mustache.
For a very lightweight approach you can make use of regular expressions to formulate the syntax of your template variables. Just define how a variable can be written, then extract the names/labels used and replace it at will.
A function to use for this is
preg_replace_callback. Here is some little example code (Demo) which only reflects simple substitution, however, you can modify the replace routine to access the values you need (in this example, I’m using a variable that is either anArrayor implementsArrayAccess):This does not look spectacular so far, it’s just substituting the template tags to a value. However, as already mentioned you can now inject a resolver into the template that can resolve template tags to a value instead of using an simple array.
You’ve outlined in your question that you would like to use the
_symbol to separate from object members / functions. The following is a resolver class that will resolve all global variables to that notation. It shows how to handle both, object members and methods and how to traverse variables. However, it does not resolve to$thisbut to the global namespace:This resolver class can be used then to make use of some example values:
See the full demo in action.
This will only need a slight modification to fit your needs then finally.