Let me put the requirement to satisfy first
A PHP gateway, and a set of request handlers which uses many constants which currently i am defining in a constants.php with define('conts','value');
I can define this constants in a property file like
const1 =val1
const2 = val2
const3 = val3
in some external file say gateway.properties and load it to define() at runtime. Can this be a one-time action, so that as many threads created by the php can access this constant further, with out reloading it again?
I dont know if this is really possible, i want an expert advice.
Thanks
I would handle this by stuffing the resulting object in memcached.
There is obviously some overhead with this. You will need to weigh whether or not it makes sense for your situation. For 3 variables, it won't make sense at all. For 300,000, maybe it will. Test it and see.
In PHP it is preferred to use .ini files and use
http://php.net/manual/en/function.parse-ini-file.php
or php.net/manual/en/function.parse-ini-string.php if you have read the file to a string already.
You can use apc to cache it in memory with a fallback to reading a file if not already cached and then cache it.
<?php
$ini = apc_fetch('configuration');
if (!$ini) {
$ini = file_get_contents('path/to/ini.ini');
if ($ini) {
apc_store('configuration',$ini);
}
}
$config = parse_ini_string($ini);
You could read each line, parse out the = and define in a for loop.
The easiest way to do this is to store your values in a .ini file, and then read the file in with parse_ini_file(). The ini file would look like:
var1 = 'blah blah blah'
var2 = 'more blah'
PHP reads these files pretty quickly. I suggest that, rather than turn all the values into constants, you store the associative array you get from the .ini file in a single global variable. Let work, same visibility.
If you're really set on caching, you could use the APC cache. It'll save a few miliseconds, but it won't make a difference unless you're talking about a pretty large set of values. And you'll still have to call define() for each value, if you're going to insist on turning them all into constants. Still much faster to save a single global associative array.
Consider using a static class which is globally easy to access.
You can create a class with only public static members and CLASS::init() calls an optional configuration file to replace the variables.
If the value is missing it will stay at it's default.
So you can access the configuration from everywhere using CLASS:$STATIC_VAR
The init function:
$vars = parse_ini_file(dirname(__FILE__) .'/'. $filename,true,INI_SCANNER_TYPED);
if ($vars)
{
foreach ($vars as $key => $val)
{
if (property_exists(get_called_class(),$key)) self::$$key=$val;
}
}
Related
I want to know a clean way of defining Application Constants in Codeigniter. I don't want to change any native file of codeigniter. Hence I don't want to define it in application/config/constants.php as when I need to migrate to newer version of code-igniter I will not be able to copy the native files of codeigniter directly.
I created a file application/config/my_constants.php and defined my constants there. 'define('APP_VERSION', '1.0.0');'
I loaded it using $this->load->config('my_constants');
But I am getting a error
Your application/config/dv_constants.php file does not appear to contain a valid configuration array.
Please suggest me a clean way of defining application level constants in code-igniter.
Not using application/config/constants.php is nonsense! That is the only place you should be putting your constants. Don't change the files in system if you are worried about upgrading.
just a complete answer. (None of the answers show how to use the constants that were declared)
The process is simple:
Defining a constant. Open config/constants.php and add the following line:
define('SITE_CREATOR', 'John Doe')
use this constant in another file using:
$myVar = 'This site was created by '.SITE_CREATOR.' Check out my GitHub Profile'
Instead of using define(), your my_constants.php file should look something like this:
$config['app_version'] = '1.0.0';
Be careful with naming the array key though, you don't want to conflict with anything.
If you need to use define(), I would suggest doing it in the main index.php file, though you will still need to use APP_VERSION to get the value.
config file (system/application/config/config.php) to set configuration related variables.
Or use
constant file (system/application/config/constants.php) to store site preference constants.
=======================
DEFINE WHAT YOU WANT
=======================
$config['index_page'] = 'home';
$config['BASEPATH'] = 'PATH TO YOUR HOST';
Please refer this:
http://ellislab.com/forums/viewthread/56981/
Define variable in to constants & add value on array
$ORDER_STATUS = array('0'=>'In Progress','1'=>'On Hold','2'
=>'Awaiting Review','3'=>'Completed','4'
=>'Refund Requested','5'=>'Refunded');
You can accomplish your goal by adding constants to your own config file, such as my_config.php.
You would save this file in the application/config folder, like this:
application/config/my_config.php.
It is very common to have a separate config file for each application you write, so this would be easy to maintain and be understood by other CI programmers.
You can instruct CI to autoload this file or you can load it manually, as needed. See the CI manual on "Config class".
Let me suggest that you use composer.json to autoload your own Constants.php file, like this:
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
I have a PHP script that is called in 2 ways from a Dojo Ajax xhrGet call.
The first time it is called with an "init" argument which causes the script to create an instance of the StateList class and read in a file of state names.
session_start();
#include('StateList.php');
require_once('phplog.php');
//start executing here
$comd=$_GET['nexturl'];
if($comd=="init") {
$st = new StateList("../data/statestxt.txt");
$_SESSION['statefile'] = $st;
}
The second and further times, another xhrGet call passes a "getstate" argument and the following code tries to get the instance ofr the StateList class from the SESSION array.
if($comd =="getstate") {
$st= $_SESSION['statefile'];
phplog("size=".$st->getSize());
}
However, the getSize() method is never executed, nor can I call any other method
on the reconstituted StateList class instance.
Note that this is one PHP script that DOES include the class definition at the top
and thus the class methods should be known and avaialble.
What am I missing here?
You need to include the class definition before you call session_start(), otherwise the object will not be deserialized correctly and will be an instance of __PHP_Incomplete_Class. Otherwise what you have should work fine.
You may need to serialize the $st object/variable before you store it. This will ensure that everything is saved to the session. This is definitely the way to go for object oriented code. When you want to use the data again, you must unserialize it.
This is one of those things that's hard to debug in isolation. Storing instantiated objects in PHP Sessions is always a little tricky, and not 100% guaranteed to work. Here's some general debugging tips that may help you figure this out.
First, check your apache error log. Are you getting a "method called on non-object error"? If so, this means you're not getting an object back out of the session. If not, is there an error that indicated your method call is failing for another reason?
Second, check to see what you're really getting out of your session.
if($comd =="getstate") {
$st= $_SESSION['statefile'];
//get the class of st
phplog("instance=".get_class($st));
//get a reflection dump of st
$ref = new ReflectionClass($st);
$string = $ref->__toString();
phplog("reflection=".$string);
}
Third, look at the serialized string value that is being stored in the session itself. Are you actually storing a serialized object? In your dev environment, set the session.save_path ini value in php.ini to something like /tmp, (or use the ini_set method to do the same thing):
session.save_path = "/tmp"
and then examine the files created in /tmp (or whatever folder). You should see a string that starts with:
statefile:O:..........
The name of the class that instantiated the object will also be included in there, as well as values saved to properties.
If you are going to store an object in the session it must be link text.There are a LOT of problems with serializing objects in PHP, let alone storing them in the session. I recommend against doing this altogether, and finding a different solution for your problem. If you are going to do it though, you should look into the 'magic methods' link text which you should define in your class to facilitate it's reinstantiation when it is called from the session.
Do you have session.auto_start enabled? The manual's session page states that if you do, you have to load the class definition differently:
If you turn on session.auto_start then the only way to put objects into your sessions is to load its class definition using auto_prepend_file in which you load the class definition else you will have to serialize your object and unserialize it afterwards.
http://php.net/manual/en/intro.session.php
As that page says, the serialization/unserialization of the object will normally be done automatically by PHP, but having session.auto_start enabled will change this.
Try this:
include('StateList.php');
require_once('phplog.php');
// start your session after including your class file
session_start();
//start executing here
$comd=$_GET['nexturl'];
if($comd=="init") {
$st = new StateList("../data/statestxt.txt");
$_SESSION['statefile'] = $st;
}
if($comd =="getstate") {
// the ampersand creates a reference, preserving any further changes to your session data
$st = &$_SESSION['statefile'];
phplog("size=".$st->getSize());
}
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.