I have, let's say, five types of job A,B,C,D,E. Each has different configuration. I want to make a configuration system in PHP, which is solely in PHP. In this system I like to return an object of configuration on specifying job type:
$obj=new ServiceConfiguration(); $configForA= $obj->getConfig('A');
getConfig reads the config, which may contain URL, job server, port and set this in config object. In writing all this I want that proper design should be followed.
Should I write all config parameter in a PHP array in a config file or there is any better alternative to it? Can I use external parties like YAML to store config? I want to know the best way to achieve it. Please answer with the whole design.
NOTE: I want to write a third party which should be written in PHP and should have no or minimal dependency on external third parties like YAML.
I personnaly use JSON files for configuration and a PHP class to read thoses files.
Accessing a var is doing by giving a string with underscores, that way I can explore the depth of the JSON file
example :
database.json
{
"prod" :
{
"server" : "127.0.0.1"
},
"key_with_underscore" : "value"
}
script.php
Config::get('database_prod_server');
Config::get('database_key_with_underscore');
I also do some small treatment to access JSON array as PHP array but basically, that's it.
In fact the config class just transform a multidimensionnal array to one-dimensionnal array by flattening it and insert an underscore for each new "dimension", then I stock the result in a variable (and cache it).
Related
I have a PHP daemon script running on the command line that can be connected to via telnet etc and be fed commands.
What it does with the command is based on what modules are loaded, which is currently done at the start. (psuedocode below for brevity)
$modules = LoadModules();
StartConnection();
while(true){
ListenForCommands();
}
function LoadModules(){
$modules = Array();
$dir = scandir("modules");
foreach($dir as $folder){
include("modules/".$folder."/".$folder.".php");
$modules[$folder] = new $folder;
}
}
function ListenForCommands(){
if(($command = GetData())!==false){
if(isset($modules[$command])){
$modules[$command]->run();
}
}
}
So, an example module called "bustimes" would be a class called bustimes, living in /modules/bustimes/bustimes.php
This works fine. However, I'd like to make it so modules can be updated on the fly, so as part of ListenForCommands it looks at the filemtime of the module, works out if it's changed, and if so, effectively reloads the class.
This is where the problem comes in, obviously if I include the class file again, it'll error as the class already exists.
All of the ideas I have of how to get around this problem so far are pretty sick and I'd like to avoid doing.
I have a few potential solutions so far, but I'm happy with none of them.
when a module updates, make it in a new namespace and point the reference there
I don't like this option, nor am I sure it can be done (as if I'm right, namespaces have to be defined at the top of the file? That's definitely workaroundable with a file_get_contents(), but I'd prefer to avoid it)
Parsing the PHP file then using runkit-method-redefine to redefine all of the methods.
Anything that involves that kind of parsing is a bad plan.
Instead of including the file, make a copy of the file with everything the same but str_replacing the class name to something with a rand() on the end or similar to make it unique.
Does anyone have any better ideas about how to either a) get around this problem or b) restructure the module system so this problem doesn't occur?
Any advice/ideas/constructive criticism would be extremely welcome!
You should probably load the files on demand in a forked process.
You receive a request
=> fork the main process, include the module and run it.
This will also allow you to run several commands at once, instead of having to wait for each one to run before launching the next.
Fork in php :
http://php.net/manual/en/function.pcntl-fork.php
Tricks with namespaces will fail if module uses external classes (with relative paths in namespace).
Trick with parsing is very dangerous - what if module should keep state? What if not only methods changed, but, for example, name of implemented interface? How it will affect other objects if they have link to instance of reloaded class?
I think #Kethryweryn is something you can try.
In order to localize strings used within my javascript, I want scan all my js files for such strings.
I am using a t() function to request string translations as follows:
t("Hello world");
or with dynamic portions:
t("Hello #user", {"#user": "d_inevitable"});
I want to detect all calls to the t() function and thus gather the strings contained in the first argument in a php "build" script, but skipping the following:
function foo(t) {
t("This is not the real t, do not localize this!");
}
function bar() {
var t = function(){}; //not the real t either...
}
function zoo() {
function t() {
//This also isn't the real t() function.
}
}
t("Translate this string, because this is the real t() in its global scope");
So the simple rule here is that the t function being invokes must be in global scope in order for the first argument to qualify as a translation string.
As a rule, dynamic runtime data as first argument is not allowed. The first argument to t() must always be a "constant" literal string.
I think php codesniffer will help me do it, however all the documentation I could find on it is about enforcing code standard (or detecting violations of it). I need lower level access to its js lexer.
My question is:
Would the php codesniffer's js lexer be able to help me solve my problem?
If so how do I access that lexer?
Are there any other php libs that could help me find the calls to t()?
Please do not suggest stand-alone regular expressions as they cannot possibly solve my problem in full.
Thank you in advance.
What you are describing is basically a coding standard. Certainly, ensuring strings are localised correctly is part of many project standards. So I think PHPCS is the right tool for you, but you will need to write a custom sniff for it because nothing exists to do exactly what you are after.
The best thing to do is probably clone the PHPCS Git repo from Github and then create a new directory under CodeSniffer/Standards to contain your custom sniff. Let's say you call it MyStandard. Make sure you create a Sniffs directory under it and then a subdirectory to house your new sniff. Take a look at the other standards in there to see how they work. You'll also find it easier to copy an existing ruleset.xml file from another standard and just change the cotent to suit you. if you don't want to include any other sniffs from anywhere (you just want to run this one check over your code) then you can just specify a name and description and leave the rest blank.
There is a basic tutorial that covers that.
Inside your sniff, you'll obviously want it to check JS files only, so make sure you specify that in the supportedTokenizers member var (also in the docs). This will ensure PHP and CSS files are always ignored.
When you get down to the actual checking, you'll have full low-level access to the parsed and tokenised content of your file. There are a lot of helper functions to check things like if the code inside other scopes, or to help you move backwards and forwards through the stack looking for bits of code you need.
TIP: run PHPCS using the -v option to see the token output on your file. It should help you see the structure more easily.
If you want to really do things properly, you can even create a nice unit test for your sniff to make sure it keeps running over time.
After all this, you'd check your code like this:
phpcs --standard=MyStandard /path/to/code
And you can use a lot of integrations that exist for PHPCS inside code editors.
You might decide to add a new more sniffs to the standard to check other things, which you can then do easily using your ruleset.xml file or by writing more custom sniff classes.
I hope that helps a bit. If you do decide to write your own sniff and need help, just let me know.
My latest idea for do settings across my php project I am building was to store all my settings in a config PHP file, the php file will just return an array like this...
<?php
/**
* #Filename app-config.php
* #description Array to return to our config class
*/
return array(
'db_host' => 'localhost',
'db_name' => 'socialnetwork',
'db_user' => 'root',
'db_password' => '',
'site_path' => 'C:/webserver/htdocs/project/',
'site_url' => 'http://localhost/project/',
'image_path' => 'C:/webserver/htdocs/fproject/images/',
'image_url' => 'http://localhost/project/images/',
'site_name' => 'test site',
'admin_id' => 1,
'UTC_TIME' => gmdate('U', time()),
'ip' => $_SERVER['REMOTE_ADDR'],
'testtttt' => array(
'testtttt' => false
)
);
?>
Please note the actual config array is MUCH MUCH larger, many more items in it...
Then I would have a Config.class.php file that would load my array file and use the magic method __get($key). I can then autoload my config class file and access any site settings like this...
$config->ip;
$config->db_host;
$config->db_name;
$config->db_user;
So I realize this works great and is very flexible, in my class I can have it read in a PHP file with array like I am doing now, read INI file into array, read XML file into array, read JSON file into array. So it is very flexible for future projects but I am more concerned about performance for this particular project that I am working on now, it will be a social network site like facebook/myspace and I have had one before prior to this project and once I got around 100,000 user's performance became very important. So I am not "micro-optimizing" or "premature optimizing" I am stricly looking to do this the BEST way with performance in mind, it does not need to be flexible as I will only need it on this project.
So with that information, I always read about people trying to eliminate function calls as much as possible saying function calls cause more overhead. SO I am wanting to know from more experienced people what you think about this? I am new to using classes and objects in PHP, so is calling $config->db_user; as costly as calling a function in procedural like this getOption('db_user'); ? I am guessing it is the same as every time I would call a setting it is using the __get() method.
So for best performance should I go about this a different way? Like just loading my config array into a bootstrap file and accessing items when I need them like this...
$config['db_host'];
$config['db_username'];
$config['db_password'];
$config['ip'];
Please give me your thoughts on this without me having to do a bunch of benchmark test
From tests I've seen, I believe Alix Axel's response above is correct with respect to the relative speed of the four methods. Using a direct methods is the fastest, and using any sort of magic method usually is slower.
Also, in terms of optimization. The biggest performance hit for any single request in the system you describe will probably be the parsing of the XML/INI/JSON, rather than the accessing of it via whichever syntax you decide to go with. If you want to fix this, store the loaded data in APC once you parse it. This will come with the one caveat that you will want to only store static data in it, and not dynamic things like the UTC date.
Firstly, instead of an included file that returns an array I would instead use an .ini file and then use PHP's parse_ini_file() to load the settings.
Secondly, you shouldn't worry about function calls in this case. Why? Because you might have 100,000 users but if all 100,000 execute a script and need some config values then your 100,000 function calls are distributed over 100,000 scripts, which will be completely irrelevant as far as performance goes.
Function calls are only an issue if a single script execution, for example, executes 100,000 of them.
So pick whichever is the most natural implementation. Either an object or an array will work equally well. Actually an object has an advantage in that you can do:
$db = $config->database->hostname;
where $config->database can implicitly load just the database section of the INI file and will create another config object that can return the hostname entry. If you want to segment your config file this way.
IMO these are the fastest methods (in order):
$config['db_user']
$config->db_user directly
$config->db_user via __get()
getOption('db_user') via __get()
Also, you've already asked a lot of questions about your config system, not that I mind but I specifically remembered that you asked a question about whether you should use parse_ini_file() or not.
Why are you repeating the basically same questions over and over again?
I think you're taking premature optimization to a whole new level, you should worry about the performance of 100,000 users iff and when you get 50,000 users or so, not now.
I am trying to decide on the best way to store my applications configuration settings. There are so many options.
The majority of applications I have seen have used a simple require and a PHP file that contains variables. There seem to be far more advanced techniques out there.
What have you used?
What is most efficient?
What is most secure?
We use a file called Local.php which is excluded from the SCM system. It contains several constants or global variables. For example:
// Local.php
class Setting
{
const URL = 'http://www.foo.com';
const DB_User = 'websmith';
}
And it can be referred to anywhere simply by:
Setting::URL
If you need the settings to be writable at runtime, I suggest you use public static variables instead.
The best thing you can do is the simplest thing that could possibly work (php variables) and wrap it up in a class. That way you can change the implementation later without changing any client code. Create an interface that the configuration class implements and make the client code use the interface methods. If you later decide to store configuration in a database or JSON or whatever, you can simply swap out the existing implementation with a new one. Make sure your configuration class is testable and write unit tests.
Try to use php-arrays config files using technique described here: http://www.dasprids.de/blog/2009/05/08/writing-powerful-and-easy-config-files-with-php-arrays
This method allows you to write app configuration in this way:
app.config.php
<?php
return array(
'appname' => 'My Application Name',
'database' => array(
'type' => 'mysql',
'host' => 'localhost',
'user' => 'root',
'pass' => 'none',
'db' => 'mydb',
),
);
This method is secure, cache-able by opcode cachers (APC, XCACHE).
How about:
; <?php die('Direct access not allowed ;') ?>
; The above is for security, do not remove
[database]
name = testing
host = localhost
user = root
pass =
[soap]
enableCache = 1
cacheTtl = 30
Save as config.php (or something like that, must have php extention), and then just load it with:
parse_ini_file('config.php', true);
And you could use
array_merge_recursive(parse_ini_file('config-default.php', true), parse_ini_file('config.php', true))
to merge a default config file with a more specific config file.
The point here is that you can use the very readable ini format, but still be able to have your config file in a public directory.
When you open the file with your browser, php will parse it first and give you the result, which will just be "; Direct access not allowed ;". When you parse the file directly as an ini file, the php die statement will be commented out according to the ini syntax (;) so it will not have any effect then.
I find Zend_Config to be a good solution. You can load the configuration from a simple array, from an INI style file, or from an XML document. Whichever you choose, the configuration object is the same, so you can switch storage formats freely. Zend_Config objects can also be merged, depending on your application this may be useful (a server config, then a per site/installation config).
As with most (or all) things in the Zend Framework, you can easily use Zend_Config by itself.
Considering efficiency, I'd say the fastest method would be to use an array, since that requires less (in this case no) string parsing. However, a INI/XML format may be easier for some to maintain. Of course some caching would give you the best of both worlds.
Also, using INI files with Zend_Config allow you to define sections of configurations that inherit from each other. The most common use is a 'development' section that inherits from the 'production' section, then redefines the DB/debugging settings.
As for security, keeping the config file out of the web root is the first step. Making it read only and limiting access could make it more secure; however, depending on your hosting/server configuration you may be limited in what can be done there.
Just an example of how to implement a central XML/Xpath configuration.
class Config {
private static $_singleton;
private $xml;
static function getInstance() {
if(is_null (self::$_singleton) ) {
self::$_singleton = new self;
}
return self::$_singleton;
}
function open($xml_file) {
$this->xml = simplexml_load_file($xml_file);
return $this;
}
public function getConfig($path=null) {
if (!is_object($this->xml)) {
return false;
}
if (!$path) {
return $this->xml;
}
$xml = $this->xml->xpath($path);
if (is_array($xml)) {
if (count($xml) == 1) {
return (string)$xml[0];
}
if (count($xml) == 0) {
return false;
}
}
return $xml;
}
}
Example call
Config::getInstance()
->open('settings.xml')
->getConfig('/settings/module/section/item');
In my view good solution would be ini files.
I don't prefer config file using arrays/variables for storing settings; here is why:
What if a user accidently re-named your setting variable?
What if a variable with similar name is defined elsewhere too by the user?
Variables in config file may be overwritten some where deep in the script or even included files.
and possibly more problems....
I like to use ini file for setting of my php apps. Here is why:
It is section based
It is easier
You can set values by friendly names
You don't have to worry about variables being overwritten because there are no ones.
No conflict of variables of course.
It allows more flexibility in specifying the types of values.
Note: You need to use parse_ini_file function to read ini files.
It is best to do any core configuration in PHP itself, but if you are using a database and don't mind the extra overhead - you may find some flexibility in storing some settings in the database with a single extra query (assuming you organize it properly).
Either way, storing this data in JSON, INI, XL, etc is just another unneeded abstraction that is done way too much nowadays on the web. Your best bet is pure PHP, unless you like the flexibility of some settings being in the database.
The only reason I can think of to not use php vars as others are suggesting is if you need to switch between configurations in a controlled manner, so there data/behavior consistency during the switch. For example, if you're switching databases, then the system could write locked until the switch-over occurs (to prevent ghost-writes, but dirty reads are still possible).
If things like this are a concern, then you could write a special admin page in your app(pref local access only for security) that locks the system temporarily, then reads and deploys all your changes before unlocking.
If you're running a high traffic site where consistency matters, this is something you'll want to consider. If you can deploy during off hours when there is little/no traffic, then php vars or other standard text formats will be fine.
I like the idea of having "namespaces" or some kind of tree
so you can have:
db.default.user
or
db.readonly.user
and so on.
now regarding code what I did was an interface for the config readers: so you can have a memory reader, array reader, db reader, etc.
and a config class that uses those readers and allow you have a config from any kind of source
What's the easiest way of storing a single number on a server so that any script can access it, using PHP? Currently, I have a number stored in a file, but this seems somewhat inelegant.
There's no right answer here, but most modern PHP systems for building web applications have some kind of Configuration object. This is often implemented as a singleton
//brain dead config object
class NamespaceConfiguration {
public static function getInstance() {
if (!self::$instance instanceof self) {
self::$instance = new self;
}
return self::$instance;
}
public static function set($key,$value){
//code to set $key/$value paid
}
public static function get($key){
//code to get a $value based on a $key
}
}
$config = NamespaceConfiguration::getInstance();
$config->set('myNumber',42);
....
function somewhereElse(){
$config = NamespaceConfiguration::getInstance();
$myNumber = $config->set('myNumber');
}
This class is loaded on every page requiest. This gives every developer a standard API to call when they want to get or set single configuration values, and allows a single developer to control the where of storage and the how of retrieval (which may be a flat file, XML file, memory cache, MySQL database, XML file stored in a MySQL Database, XML File stored in a MySQL Database that contains a node which points to a file that contains the value, etc.)
The where and how of retrieval is going to depend on your application environment, although by using a configuration object you can create some efficiencies up front (storing already retrieved values in a property cache, pre-fetching certain values on instantiation, etc.)
Since your application probably already have some sort of include-file on the top "header.php" or simular, you could just create a constant/variable in that file, and all the files that include the header will also have access to the constant.
This may help you to define the constant:
http://php.net/constant
That depends on the characteristics of the number. Is it updated/modified often? Is it the only such number? If it isn't changed it's probably better to do as Espo suggests and store it as a php constant that can be included when necessary. If you have other such numbers you can put them all in that file. If they are updated often it's probably better to put it in the database.
But. If it's a single number, that is subject to change, and you don't forsee any need for storing other numbers, why not use a file? Just remember to use flock() when updating it to avoid concurrency issues.
Your best bet would be to put it in a MySQL table for fetching later. That's probably the best way to store information in PHP.
If it is a variable that is more of a environmental nature you could always use set those in Apache
in your httpd.conf file you can set the following:
SetEnv myVar myValue
You can then use $_SERVER to fetch it
$_SERVER['myVar']
I usually set varibles on this if i am to setup same application on a few different virtual hosts but dont want them to have different parameters in the config file.
A config file will also meet your needs.
There is some easy to use classes in Zend framework that can help out
http://framework.zend.com/manual/en/zend.config.html
more specific section 7.3 and 7.4 describes how you can write config parameters in a plain text file or in XML.
if you prefer plain old php you have the function parse_ini_file that lets you read in config parameters from a text file
http://us.php.net/parse_ini_file
You can also use the Alternative PHP Cache or other caching options.
http://www.php.net/manual/en/function.apc-add.php
And you can use this in combination with the other solutions listed above, e.g saving a config to cache.