Yii2: Config params vs. const/define - php

When should I use what?
I have the option to define constants in the index.php entry script file like it is recommended in Yii2 guide: constants. Or I could use the params in the configuration - explained in YII2 guide: params. Both are per application and not really global.
Currently, it seems to me that params are a bit less comfortable if I want to combine values like this:
define('SOME_URL', 'http://some.url');
define('SOME_SPECIALIZED_URL', SOME_URL . '/specialized');
Besides, accessing is bit more code (Yii::$app->params['something']) compared to constants.
So when should or could I use what?
Small update: in PHP 7 define() supports arrays as well, so the whole params structure can be configured as a constant. Probably better supported by IDEs.

I tend to use the Yii application parameters. The main reason for this is the values held in these kind of parameters tend to change depending on the environment that the code is run in. So I will have a build system that runs (I use Phing) and pulls in settings from a non-version controlled file such as build.properties.
So any dev database settings, dev domain settings, api sandbox addresses etc will be loaded in in my development environment and the correct production values will be used when a build is run on a live server.
If you were settings these values in some kind of php file, then tracking with version control becomes problematic because each time you build in your dev environment changes would be made to your index.php file. Someone might even end up committing these changes in by mistake.
So in summary, I would say if they are true constants - the same in any environment in which the code runs - they maybe a constant is fine. If these values might change, depending on where the code is run, then my preference is to place them in params and let your build system load them from a non-version controlled file.

The main disadvantage (and advantage at the same time) of constants is that they're... constant. Once you set it, you can't change it. This is the only thing that should matter here. You should use constants for values that should never change during execution, and params for everything else.
Constants may be a real PITA when you start writing tests for your app. It will show you that many things that you considered as constant are not really constant. At this point params are more flexible - you can easily change them or adjust at configuration level using merging of configuration arrays. Using constants may drive you into a trap of unconfigurable application that cannot be installed on different environment without modification of hardcoded constant.
Besides, accessing is bit more code (Yii::$app->params['something']) compared to constants.
This is completely irrelevant. As a programmer you spend less than 5% of your time on actually writing a code. Additional 10 keystrokes will do not make any difference. You should always think about it in terms of readability. You write code once and read it hundreds of times, so it is much more important how much time you will need to read and understand code than the time you spent on writing it. And using known conventions (and Yii::$app->params is one of them) makes your code easier to understand, especially for other programmers.
But if you really want to write less code, you can always create a wrapper function for short access to params.
function p($name) {
return Yii::$app->params[$name];
}
echo p('my-param');

Related

TYPO3 Override $GLOBALS[‘TYPO3_CONF_VARS’] in Site Configuration?

I want some of the $GLOBALS['TYPO3_CONF_VARS'] values (namely, those of the Mail API) to be site-specific. After reading Configuration Overview, Site Handling, and GLOBALS - TYPO3_CONF_VARS, I'm still not sure how would it be an idiomatic way to do this.
Also, I'm using helhum/typo3-config-handling for the TYPO3 configuration. The idea is basically having the same functionality that we have with the contexts (i.e having prod.settings.yaml and dev.settings.yaml load different values) but with sites, e.g. I want to have a different $GLOBALS[‘TYPO3_CONF_VARS’]['MAIL']['defaultMailFromAddress'] value wether if I'm in one of my sites or another.
I actually don't know if this is possible to do. Maybe these are thought to be that, just global, and I have to come up with a more ad-hoc solution. E.g. changing the $GLOBALS[‘TYPO3_CONF_VARS’] array beforehand every time some process that accesses it.
Thanks a lot in advance!
You can access Environment variables for domain specific configuration.
Or you use conditions in PHP.
Anyway you need to make your assignments in typo3conf/AdditionalConfiguration.php as all non constant values might get overwritten in typo3conf/LocalConfigurathion.php.

is this the proper use of auto_prepend_file

Looking at building my first PHP application from the ground up. So pardon the noob question.
Is it proper to use auto_prepend_file to manage common variables like a default db connection or run session_start() or is there a more favorable way to define "application" variables and add session management to every page?
I'm asking because I came across a warning in netbeans when using a variable defined in an include. Searching google I saw a few posts stating that defining the variables in an include was bad practice; so what's the good practice in PHP?
Thanks
Most modern php application layouts do not have the required resources loaded in the code.
Instead most often there is an autloader that parses the requested resource (class name) and loads the correct file. Then most things are encapsulated in objects and classes.
The most common standard now is PSR-0
Configs are mostly stored in config files of various formats, like xml. Then there is often an object that is used to read those configs. From this object the configuration is then obtained to be used in certain places like database connections.
Also those things that get executed are mostly not executed in the code but rather execute themselves by attaching themselves to certain points in a program.
Most php frameworks have a thing called "hooks" or "events". Basically it's nothing else but a simple list with event names and for each entry a list of functions that should be executed.
When some part of the code "fires" it uses a helper class that walks through the entries of the list and executes those as well.
You ask yourself, can't you have loops there? The simple answer is, yes.
The whole idea behind all this stuff is that you have to change no existing code anywhere if you want to bring new code into your application.
Is that good practice? I honestly don't know.
If a project exceeds a certain size and multiple persons are programming on it, some standard may be necessary. And the way not to modify existing code has proven good in practice.
Regarding auto_prepend_file, that is something that I would not do.
I may do it if I have no other way. For example, if I want to execute some code that protects my application from ddos or security injections. And I just do not want to mess with the application itself.
But if I design something from the start, I would not do it.
Why? Maybe I want to switch to a new webserver, or even execute my program in the command line. Then I have a problem if I defined my auto prepending in apache...
Or maybe I have some code where I do not want that at all? Just one file within my application where I just do not want it because I do not need it and it takes up resources or is a security risk?
I often write an application where I have for example the database username and password directly in the function that establishes the link.
Why? Why not? Because I do not want to have it available on a global scale. If it's in the function code, its harder for other, possibly insecure code, to access it.
The very most common mean is to have a config file and just require it somewhere in your application.
Also most modern applications do not have different php files that get loaded by the webserver, so there is no need for having the same code at multiple places.
Instead most modern applications have a single php file (mostly index.php) that serves as a so called "bootstrap" file. The webserver rewrites every request instead of the requests to static resources like images to there, and everything else, like deciding what content to show when looking at the requested url, is handled in the application.

Getting base url, development variable, the best way, without using globals

In my application architecture I want to replace my globals with something that ain't gonna burn most of the developer's eyes, because I am using globals like this,
define('DEVELOPMENT_ENVIRONMENT', true);
// Shorten DIRECTORY_SEPARATOR global,
define('DS', DIRECTORY_SEPARATOR);
// Set full path to the document root
define('ROOT', realpath(dirname(__FILE__)) . DS);
how could I prevent this? I tried creating a class that reads an xml file, but this will give me a longer code like this
$c = new Config();
if($c->devmode === TRUE) {}
or maybe something like this
$c = new Config()
echo $c->baseurl;
Any better ways to do this?
I think questions like yours can not be generally answered but they probably deserve an answer anyway. It's just that there is not the one golden rule or solution to deal with this.
At the most bare sense I can imagine the problem you describe is the context an application runs in. At the level of human face this is multi-folded, just only take the one constant:
define('DEVELOPMENT_ENVIRONMENT', true);
Even quite simple and easily introduced, it comes with a high price. If it is already part of your application first try to understand what the implications are.
You have one application codebase and somewhere in it - in concrete everywhere the constant is used - there are branches of your code that are either executed if this constant is TRUE or FALSE.
This on it's own is problematic because such code tends to become complex and hard to debug. So regardless how (constant, variable, function, class) you first of all should reduce and prevent the usage of such constructs.
And honestly, using a (global) constant does not look that wrong too me, especially compared with the alternatives, it first of all is the most preferable one in my eyes because it lies less and is not complicated but rather straight forward. You could turn this into a less-dynamic constant in current PHP versions by using the const keyword to declare it however:
const DEVELOPMENT_ENVIRONMENT = TRUE;
This is one facet of this little line of code. Another one is the low level of abstraction it comes with. If you want to define environments for the application, saying that a development environment is true or false is ambiguous. Instead you normally have an environment which can be of different types:
const ENVIRONMENT_UNSPECIFIED = 0;
const ENVIRONMENT_DEVELOPMENT = 1;
const ENVIRONMENT_STAGING = 2;
const ENVIRONMENT_LIVE = 3;
const ENVIRONMENT = ENVIRONMENT_DEVELOPMENT;
However this little example is just an example to visualize what I mean to make it little ambiguous. It does not solve the general problem outlined above and the following one:
You introduce context to your application on the level of global. That means any line of code inside a component (function, class) that relates to anything global (here: DEVELOPMENT_ENVIRONMENT) can not be de-coupled from the global state any longer. That means you've written code that only works inside that applications global context. This stands in your way if you want to write re-usable software components. Re-usability must not only mean a second application, it already means in testing and debugging. Or just the next revision of your software. As you can imagine that can stand in your own way pretty fast - or let's say faster then you want.
So the problem here is less the constant on it's own but more relying to the single context the code will run in or better worded global static state. The goal you need to aim for when you would like to introduce changes here for the better is to reduce this global static state. This is important if you're looking for alternatives because it will help you to do better decisions.
For example, instead of introducing a set of constants I have in the last code-example, find places that you make use of DEVELOPMENT_ENVIRONMENT and think why you have put it in there and if it is not possible to remove it out there. So first think about if it is needed at all (these environment flags are often a smell, once needed in a quick debugging or because it was thought "oh how practical" - and then rotting in code over weeks of no use). After you've considered whether it is needed or not and you came to the point it is needed, you need to find out why it is needed at that place. Does it really belong there? Can't it - as you should do with anything that provides context - turned into a parameter?
Normally objects by definition ship with their own context. If you've got a logger that behaves differently in development than in live, this should be a configuration and not a decision inside the application code somewhere. If your application always has a logger, inject it. The application code just logs.
So as you can imagine, it totally depends on many different things how and when you can prevent this. I can only suggest you to find out now, to reduce the overall usage.
There are some practical tips on the way for common scenarios we face in applications. For the "root-path problem" you can use relative paths in conjunction with magic constants like __DIR__. For example if the front-endpoint in the webroot (e.g. index.php) needs to point to the private application directory hosting the code:
<?php
/**
* Turbo CMS - Build to race your website's needs to the win.
*
* Webroot Endpoint
*/
require(__DIR__ . '/../private/myapp/bootstrap.php');
The application then normally knows how it works and where to find files relative to itself. And if you return some application context object (and this must not be global(!)), you can inject the webroot folder as well:
<?php
/**
* Turbo CMS - Build to race your website's needs to the win.
*
* Webroot Endpoint
*/
/* #var $turboAppContext Turbo\App\WebappContext */
$turboAppContext = require(__DIR__ . '/../private/myapp/bootstrap.php');
$turboAppContext->setWebroot(__DIR__);
Now the context of your webserver configures the application defaults. this is a crucial part actually because this touches a field of context inside your application (but not in every component) that is immanent. You can not prevent this context. It's like with leaking abstractions. There is an environment (known as "the system") your application runs in. But even though, you want to make it as independent as possible.
Like with the DEVELOPMENT_ENVIRONMENT constant above, these points are crucial to reduce and to find the right place for them. Also to only allow a very specific layer to set the input values (to change context) and only some high-level layers of your software to access these values. The largest part of your code-base should work without any of these parameters. And you can only control the access by passing around parameters and by not using global. Then code on a level that is allowed to access a certain setting (in the best meaning of the word), can access it - everything else does not have that parameter. To get this safety, you need to kill globals as best as possible.
E.g. the functionalitly to redirect to another location needs the base-url of the current request. It should not fetch them from server variables but based on a request-object that abstracts access to the server variables so that you can replace things here (e.g. when you're moving the application behind a front-proxy - well not always the best example but this can happen). If you have hard-coded your software against $_SERVER you would then need to modify $_SERVER in some stages of your software. You don't want that, instead you move away from this (again) global static state (here via a superglobal variable, spot those next to your global constants) by using objects that represent a certain functionality your application needs.
As long as we're talking about web-applications, take a look at Symfony's request and response abstraction (which is also used by many other projects which makes your application even more open and fluent). But this is just a side-note.
So whatever you want to base your decision on, do not get misguided by how many letters to type. The benefit of this is very short-sighted when you start to consider the overall letters you need to type when developing your software.
Instead understand where you introduce context, where you can prevent that and where you can't. For the places you can't, consider to make context a parameter instead of a "property" of the code. More fluent code allows you more re-usable code, better tests and less hassles when you move to another platform.
This is especially important if you have a large installation base. Code on these bases with global static state is a mess to maintain: Late releases, crawling releases, disappointed developers, burdensome development. There are lessons to learn, and the lessons are to understand which implications certain features of the language have and when to use them.
The best rule I can give - and I'm not an academic developer at all - is to consider global as expensive. It can be a superb shortcut to establish something however you should know about the price it comes with. And the field is wide because this does not only apply to object oriented programming but actually to procedural code as well. In object oriented programming many educational material exists that offers different ways to prevent global static state, so I would even say the situation there is quite well documented. But PHP is not purely OOP so it's not always that easy as having an object at hand - you might first need to introduce some (but then, see as well the request and response abstractions that are already available).
So the really best suggestion I can give to improve your code in context of this question is: Stick to the constant(s) (maybe with const keyword to make them less dynamic and more constant-ly) and then just try to remove them. As written in comments already, PHP does a very fine job about cross-platform file-access, just use / as directory separator, this is well understood and works very well. Try to not introduce a root-path constant anyway - this should not be constant for the code you write but a parameter on some level - it can change, for example in sub-requests or sub-apps which can save you a life-span before re-inventing the wheel again.
The hard task is to keep things simple. But it's worth.
Just put some server variable to the vhost config and prepare different config files for each option. Using apache it would be (you'll need mod_env module):
SetEnv ENVIRONMENT dev
And then in index just use something like:
$configFileName = getenv ('ENVIRONMENT').'.ini';
Now just load this file and determine all the application behaviour on the values given. Ofcourse you can facilitate it further if you use some framework but this would be a good start.
You can encapsulate your constants in a class and then retrieve it by a static methods :
if(Config::devMode()) {}
echo Config::baseUrl();
This way you save a line and some memory because you don't need to instantiate an object.

What's the best way (coding-wise) to store system configuration in a PHP application?

Note: Configuration are being kept in a PHP file, config.php.
I've seen this done differently, here's a short list of examples (I'm storing DB info in these examples):
Constants: global, readonly
define('DB_USER','user12');
define('DB_PASS','21user');
Using GLOBALS array: global, changeable, repetitive, mixed with other globals
$GLOBALS['DB_USER']='user12';
$GLOBALS['DB_PASS']='21user';
Using a non-global array but raised globaly: possibly worse than the 2nd option
$config=array(); ...
$config['DB_USER']='user12';
$config['DB_PASS']='21user';
... global $config;
mysql_connect('localhost',$config['DB_USER'],$config['DB_PASS']);
Defining class properties: (global, enumerable)
class Config {
public $DB_USER='user12';
public $DB_PASS='21user';
}
Criteria/Options/Features:
ease of coding: you wouldn't want to check if the setting exists, or initialize it
ease of modification: a non-programmer/layman could easily modify the settings
stored in a clean place: not mixed with other variables (can be stored in a sub-array)
runtime modification: in some cases, other devs may easily modify existing settings
The configuration might need to be changed some time during the running of the system, so option 1 is already not viable. The third option is not too clean either.
While writing this, I'm getting a big warning on the discussion being subjective and closed. So please keep up to the topic and give valid reasons to your answers.
This is a pretty obvious question, and considering I'm well familiar with different answers, you might ask, why am I making all this fuss? The thing is, I'm developing a framework, and unlike another framework (*ahem* joomla *ahem*) I don't want to pass through their mistake of throwing in a miss-informed solution which ends up having to be changed/re-purposed in the future.
Edit: First of, the location of the config file does not concern me. I'll make sure people can easily change location, if they want to, but this will not be a requirement.
First of, cheap webhosts does not allow doing this, secondly, as far as security goes, this is really not a good option. Why? Because, the framework needs to know where the config is. Really, security through obscurity does not work. I'd rather fix all RFI and XSS (for instance) than be paranoid on hiding the config file under several layers.
Hard-coded data may not be an option where people doing reconfiguration are not code-adept. Consider using parse_ini_file().
Why not use Zend_Config? It creates a common interface for configuration options that can be stored in a confing file or a database (with a proper adapter). And it's lightweight; you don't have to bring in the entire Zend framework to use it.
BTW, since you're building a framework, you should keep pollution of the global namespace to a minimum. Something like your 3rd option, and if you're targeting 5.3 exclusively, look at using proper namespaces.
A bit late, but this might be of interest to you: http://milki.include-once.org/genericplugins/genconfig.html
It provides a simple API to edit PHP config files in-place. It keeps comments and other code in-tact. And it allows for a global $config array/ArrayObject and defining constants. It operates almost automatically if combined with plugin configuration comments. However, it's a lot of code. But maybe worth checking out for the concept. (I'm also using a readable config.php, as it seems the most useful configuration format for me.)
Put in a common file and include it every where you need. The benefit when you go live or move to your test server you just need to edit just this one file and all configs are changed. Method 2 is better as it allows you to change it.
Remember once you connect to mysql if you need to change the user and pass you have to re-connect

Distributing a small PHP application

I wrote a small PHP application that I'd like to distribute. I'm looking for best practices so that it can be installed on most webhosts with minimal hassle.
Briefly: It's simple tool that lets people download files once they login with a password.
So my questions are:
1) How should I handle configuration values? I'm not using a database, so a configuration file seems appropriate. I know that other php apps (e.g. Wordpress) use defines, but they are global and there is potential that the names will conflict. (Global variables also have the same problem, obviously.) I looked at the "ini" file mechanism built into PHP. It only allows comments at the top - so you can't annotate each setting easily - and you can't validate syntax with "php -f". Other options?
2) How to handle templating? The application needs to pump out a form. Possibly with an error message. (e.g. "Sorry, wrong password.") I've have a class variable with the HTML form, but also allow an external template file to be used instead (specified in the config). I do some trivial search and replace - e.g. %SCRIPT% to the name of the script, %STATUS% to hold the error message. This feels a bit like reinventing the wheel, but including a templating system like Smarty is overkill. (Plus they may already have a templating system.) Other options?
3) i18n - There are only 3 message strings, and gettext doesn't seem to be universally installed. Is it such a bad idea just to make these three strings parameters in the config file?
4) How to best integrate with other frameworks? My app is a single class. So, I thought I could just include a php script that showed how the class was called. It would be a starting point for people who had to integrate it into another framework, but also be fine as-is for those not interested in customizing. Reasonable?
5) GET/POST parameters - Is it bad form for a class to be looking at $_GET and $_POST? Should all values be passed into my class during construction?
Thanks.
Configuration
You can use a php file like this:
<?php
return array(
'option1' => 'foobar',
'option2' => 123,
//and so on...
);
?>
And in the main class just use:
$config = (array) include 'path/to/config/file';
And if you plan to mostly distribute your class as a component in other applications, then simply put config array/object as a parameter in your class' constructor and leave the details to the user.
Templating
For such simple application the method your described should be enough. Remember that one can always extend your class and overload your outputting method with his own.
I10N
As mentioned before, for 3 variables anything more than storing them as config is just overkill.
Integration
Comment each public method (or even better also protected and private ones) with explanations what do they do and what parameters are needed. If you combine that with an example, it should be enough for most users.
GET vs POST
Your class uses passwords and you even think of sending them via GET? ;)
Think of browser history, referer headers etc - your users' passwords would be visible there.
Can config be local to class instances? Or could you create a little class that you could create an instance of to query for config values? Also prepending any global vars with you application's name should go some way to stop clashes.
If your templating is really simple, just write a short templater. It'll be easier than trying to fend off problems people get with any 3rd party templater. It might also simplify licensing issues. If you start worrying about what they already have, you'll never release anything. There are too many combinations.
For 3 strings? Yeah do those the same way you're handling config.
Good comments throughout with an intro explaining how you use the class.
I don't think so. If it bothers you, you could use default arguments to use given arguments first, then search for GET/POST values if none are provided (though that might be a security risk)
There are other things to take into consideration. Lots of people are on shared hosts and as a result, don't have control over their php.ini or their php version. You need to make sure you're only using features that are as commonplace as possible.
One example is that shorttags aren't enabled on some hosts (you have to use <?php ... ?> and <?php echo "..."?> instead of <? ... ?> or <?= "..." ?>) which can be a royal PITA.
In addition to Krzysztof's good advice:
Use <?php only
If you use functions that can be disabled, use function_exists() to ensure they're available. #missing_function() makes PHP die silently without any error logged.
You can't rely on things that can be disabled/changed via php.ini. Use ini_get() to adapt to different settings.
If magic_quotes are enabled, strip slashes only on from your copy of input – don't modify global arrays! Security of some lame code may rely on these slashes being present.
Expect that users will mindlessly copy&paste code from your documentation/website.

Categories