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.
Related
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).
Imagine that you have interfaces which describe the data access layer of your application. You haven't decided yet what kind of storing mechanism you want to use, you just want to make sure, that whatever you choose, it will handle concurrent requests well. For that you have to write concurrency tests against those interfaces.
I think a schematic concurrency test should be something like this:
public function testMoneyIsNotLostByConcurrentTransfers(){
$accountRepository = DataAccessLayer::getBankAccountRepository();
$accountOfTom = $accountRepository->create(array(
'owner' => 'Tom',
'balance' => new Money(10000)
));
$accountOfBob = $accountRepository->create(array(
'owner' => 'Bob',
'balance' => new Money(10000)
));
$accountOfSusanne = $accountRepository->create(array(
'owner' => 'Susanne',
'balance' => new Money(10000)
));
$this->concurrentExecution(
function () use ($accountOfTom, $accountOfBob){
$accountOfTom->transfer($accountOfBob, new Money(5000));
},
function() use ($accountOfTom, $accountOfSusanne){
$accountOfSusanne->transfer($accountOfTom, new Money(5000));
}
);
$this->assertEquals($accountOfTom->getBalanceAmount(), 10000);
$this->assertEquals($accountOfBob->getBalanceAmount(), 15000);
$this->assertEquals($accountOfSusanne->getBalanceAmount(), 5000);
}
Is it possible to write such tests, test runner in PHP? Or is there any existing tool which can help by concurrency testing in PHP?
I could not find any test runner for such concurrency tests. I found only paratest, which can run independent tests, like unit tests parallel.
According to PHP - parallel task runner the best option I think is using pthreads with debug_backtrace. I think it will be hard even with that. I am looking forward the installing problems, thread safety, resource sharing difficulties, backtrace bugs, etc... I will have a great time I am sure...:S
I found async calls in the pthreads examples.
If I ever manage to solve this, I will share it on github and add a link here. Until then...
update
I just realized that I don't need multi thread or multi process applications to test concurrency. For example I can start two transactions with 2 database connections from the same php file. What I need is add event triggering for the statements the db driver does, so I can add breakpoints and wait the other task wherever I want. File locking is just the same... So coroutines or some hand made multi tasking and statement logging is just enough...
Concurrency should be built into your saving mechanism, not the execution layer.
For example, if you are using SQL, instead of setting the variable use += and -=.
I'm having a terrible amount of problems with an XML parsing script leaking some memory in PHP.
I've made a solution by rewriteing my whole OOP code to non OOP, which was mostly database checks and inserts, and that seemed to plug the hole, but I'm curious as to what caused it? I'm using Zend Framework and once I removed all of the model stuff, there are no leaks.
Just to give you and idea how bad it was:
I'm running through some 30k items on the same number of files. So, one per file. It started out by using 5mb!!! or RAM, when the file itself was only about 20kb big.
Could it be those referencing functions that I've read about? I thought that that bug was fixed?!
EDIT
I found out, that the leak was due to using Zend Framework database classes. Is there a way to call a shutdown function after each iteration, so that it would clear the resources?
Its pretty dificult to answer this as we have no code to work with.
Revert back to the OOP version of your sources and create a small class like so:
abstract class MemoryLeakLogger
{
public static $_logs = array();
public function Start($id,$action)
{
self::$_logs[$id] = array(
'action' => $action,
'start_ts' => microtime(),
'memory_start' => memory_get_usage()
);
}
public function End($id)
{
self::$_logs[$id]['end_ts'] = microtime();
self::$_logs[$id]['memory_end'] = memory_get_usage();
}
public static function GetInformation(){return self::$_logs;}
}
and then within your application do the following:
MemoryLeakLogger::Start(":xml_parse_links_set_2", "parsing set to of links");
/*
* Here you would do the relative code
*/
MemoryLeakLogger::End(":xml_parse_links_set_2");
And so forth throughout your application, you will need to create calculations to gather the offsets for memory usages and time taken per action, once your script is completed just debug the information by printing it in a readable fashion and look for peaks
You can also use xdebug to trace your application.
Hope this helps
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.