I have a class where I want to use an API, and I've got the api keys in a separate file in another directory.
The api key file is literally as simple as this:
$id = 'xxxxxxx';
$key = 'xxxxxxx';
This doesn't work:
include '/path/to/file-with-api-keys.php';
class MyApiClass {
public function __construct($id, $token) {
$this->client = new Client($id, $token);
}
}
The code where I instantiate the class is in another php file I'm using to test, and it's extremely simple, just includes the class and then instantiates it:
include '/path/to/MyClass.php';
$result = new MyClass();
$result->myMethod();
echo $result;
The error I get is basically saying the 2 variables are null.
TWO QUESTIONS:
1) How can I access the value of the variables in my constructor? I've read elsewhere that using an include file directly in the method is bad practice, and also that using a global variable would be bad practice as well.
2) Somewhat related question, these files where I'm storing the api keys are in the same directory with my database connection details, but the directory is not outside the root. In this directory I have an .htaccess file with "Deny From All". Is this sufficient from a security standpoint, or should I do something else?
ok 3 questions...
3) Should I even bother keeping the api keys in separate files within this directory or just embed them into my class?
Hoping someone can give me best practices here. Thanks!
The constructor won't read the variables from file-with-api-keys.php automagically. You must specify them like this when instantiating the class: $result = new MyClass($id, $key);
The best practice is to store all your PHP scripts outside the webroot directory except index.php (aka front controller).
Yes, you should bother :) All configuration, API keys etc. should be stored in separate files, outside your classes code. You shouldn't mix these two things. If you're going to use some version control system like Git, then you're going to commit your classes code without any configuration details. The latter will be in your .gitignore file. If you ever work in a team of programmers, then every one of them is going to have his separate configuration files.
Related
I have an old site to bring up to standard but I have to approach things in a certain way due to timing issues and certain restrictions preventing my urge to restructure the whole site properly from the bottom up.
Most of the work involves updating various include files.
So, these include files are called into a page which uses a class to generate an object, as usual,
The Problem:
There are lots of pages and they are not consistently coded (thanks to sub-standard previous developers on the site), so sometimes the class I want to use is in an object called $database, sometimes on other pages the object is called $dataBase, $connection, etc. etc.
There are several includes that I am working on and I feel that having to create a new object for each include on each page is extremely inefficient, hence this question:
Can I find out from PHP which, if any, object variables use a certain class?
An illustration:
Page index.php
require "class.sausages.inc.php";
$hotdog = new sausages();
$hotdog->somefunction();
//etc. etc.
include "some_file_i_need_to_work_on.php";
include "/folder/some_other_file_I_work_on.php";
//etc. etc.
Page index2.php
require "class.sausages.inc.php";
$hotdogs = new sausages();
$hotdogs->someOtherfunction();
//etc. etc.
include "some_file_I_need_to_work_on_3.php";
include "/folder/some_other_file_I_work_on.php";
//etc. etc.
So I need to work on the includes and so for each include file I do not know for sure the $name of the variable object created in the includes parent file. All I have is that it uses the class sausages.
Solution attempts
I read how to check if object of a class already exists in PHP? which has pretty much the same issue but the solution marked here is to generate a global, which I'm feeling is another layer and to be honest I'm not quite comfortable with it as an efficient solution.
What I am trying to avoid is a situation where each include on a particular page has to generate its own object, all from the same class (usually) established in the parent page.
As there's no guarentee in one include if another include is included, I don't think I can generate an object that the includes can all use collectively, or if I can, how can I do that?
What I would Like
I want to be able to find a way to establish in PHP:
has any object been generated using this class?
yes? Use that object in this include.
no? generate a new object from the class file.
Is this possible?
Notes:
There are about a dozen include files,
There are a lot of parent pages (50+). I think editing each one would be inefficient (but this will be done at a future point)
Some parent pages contain some include files, some contain others. There's no guarentee which includes are included in which files ( as far as I can tell so far).
Most but not all parent pages have already established a class object.
PHP 5.6.16
as per:
http://php.net/manual/en/internals2.opcodes.instanceof.php
You can check if certain variable is an instance of certain class:
if ($hotdog instanceof sausages){
// use $hotdog
}
else {
// create and use $hotdog
}
But it will not tell you anything about other variables.
You can also use this:
http://php.net/manual/en/function.get-defined-vars.php
to get a list of all defined vars into an array. You can then loop through the array to see if there are any instances of the class that you are interested in.
foreach (get_defined_vars() as $var)
{
if ( $var instanceof sausage) {
// use this var
}
}
This solution will do what you want, however you should note that it is probably safer to create a new object. When you use an already instantiated object inside an include, you have no idea what other operations have been performed with that object. THe sausage may have very well be fried by the time you start using it and it may not do exactly what you want.
You should also look into a singleton pattern .
Using this pattern you can always get an instance of the same class and be sure that there is only one instance created across the app.
To go back to your old app, say that you want to make sure there is only one instance of sausages class across the app.
define a singleton method inside the sausages class
search/replace all the occurances of new sausages with sausages::singleton()
inside the include, you can then safely use $hotdogs = sausages::singleton();
This will make much cleaner code than trying to detect wether there are any global instances of sausages.
For conclusion; I ended up taking Karolis' answer and generating a search system for the correct object variable, without needing to instigate a new one if one is already defined:
At the top of each of my includes:
foreach (get_defined_vars() as $varKey => $variable) {
if(is_object($variable) && $variable instanceof sausages) {
$$varKey = $variable;
}
}
//$$varKey = this is the instance object.
Obviously code for if no instanceof is set is not detailed here, but this code works for me so far.
I'm trying to improve my website engine. So I can stop setting global $vars inside functions
So now I'm setting all my global site vars with this instead:
define('ROOT_prefix', 'mysitename_');
define('ROOT_support', 'support#mysite.com');
I can access them anywhere. But it does not feel as good (or smart) practice..
I know very little about classes.. but couldn't/should't I use a class for this instead?
This works:
class ROOT {
public static $prefix = 'mysitename_';
public static $support = 'support#mysite.com';
}
And then anywhere on my site I can use this (even inside functions):
echo '<h1>Please contact support at: '.ROOT::$support.' </h1>';
Is this a good way, or is there a better way?
If the value of these "globals" will not be changed for the entire run-time of the script, then you absolutely should use constants, as this is exactly what they are for.
You should keep them all centralized in a common include file for readability.
(Edit based on comments follows)
Since it looks like you're using constants for some kind of localization of content, it might be prudent to use a class for this. As I have said: using constants for non-changing values in a procedurally oriented script isn't bad practice in itself, but in the context of localization, there are better ways.
One such would be to create a class with some static methods to translate a string based on the passed ini file, this would be in line with the dependency injection mentioned in other comments and answers here.
An example of such a class would look something like this:
class Localizer {
public static function localize($langFile, $string) {
if (!file_exists($langFile)) {
throw new Exception($langFile . 'not found!');
}
$lang = parse_ini_file($langFile);
return (!empty($lang[$string])) ? $lang[$string] : false;
}
}
You can use it like this:
echo Localizer::localize('./english.ini', 'hello') . "\n";
echo Localizer::localize('./english.ini', 'email') . "\n";
This assumes an ini file that looks like this:
; english.ini
hello = 'Hello!'
email = 'test#test.com'
Realistically, this is probably a more "proper" way than declating a boat load of constants for each language your application runs in, but it is going to open the file every time you need to localize a string, which wouldn't be optimal for a very high volume application on a large system. But, as with a constant, you will be able to access the static methods of a class in the scope of any function in your application so long as the class was included beforehand. No need to use constants or declare globals.
The most proper and efficent way to do it would be to instantiate a class instead of using static methods, which would load the files into memory once and keep them there, eliminating the need to open the file for every string translated. But this would require that you are able to pass the variable containing the instantiation of this class to every function in your code that requires it, or declare it as global, which was exactly what you were trying to avoid in the first place.
So in order to do this, you would probably need to re-structure your code to allow for dependency injection throughout.
To continue with your current code and structure, you can continue using generated constants, which will be much messier, less "proper", and not expandable, but the advantage is that you will only read the ini files once, and keep them in memory.
Or you can use a static method, which is more "proper" but needs to read a file every time you localize a string, meaning that on large systems, it could cause some inefficiency. Realistically though, if your application in low volume, you will likely never see problems arise from this.
The main advantages of this method are expandability, and clean code. While declaring constants might be more efficient in terms of file opening and memory usage in the very short term, in most cases, it's not as expandable, because you can have an unlimited number of strings and language files, which means you could end up in a situation in the future where your loading thousands and thousands of constants every time your application loads.
If you use a class, and only load the files/strings that are needed by that specific user at run time, you can avoid this, no matter how many languages and strings you support.
Static class variables aren't any better than constants. They're still globally accessible values. There's no real change.
If you want to be improving your style, you should be using dependency injection. This simply means that you pass all variables that a function or class needs into the function/class as parameters. It's that simple, really. If you want to decouple your code, you need to create borders between different pieces. That means one piece does not "reach out" and get a global variable; instead you define that piece as accepting a parameter and write another piece that passes it that parameter.
Please read How Not To Kill Your Testability Using Statics for an in-depth explanation of this topic.
You may set variable to global when you need it. Just use global ${$variablename};.
where $variablename contain name of needs variable. For example it may be array keys or values.
Declaring your properties as public allows for their modification.
If you want them to be constants, as they were when created with define, you'll have to declare them as protected and use methods to access them :
class ROOT {
protected $prefix = 'mysitename_';
protected $support = 'support#mysite.com';
public static getPrefix(){
return $this->prefix;
}
public static getSupport(){
return $this->getSupport;
}
}
This way is actually quite better than using define() actually.
It's a step forward to singleton patterns (http://en.wikipedia.org/wiki/Singleton_pattern).
Next step is the building of an Application class (ROOT name sounds fine) which would contain these constants, and perhaps load them from a configuration file.
In this Application singleton, you can build some main function, like an init() for a bootstrap, inclusion of other classes, database configuration, logging system, templating system, and so on...
I'm modifying a website and I would like to add a config file for it so that when when moving the website to another server, I only need to change environment parameters like database information only once. But I don't know how to apply the config file for the whole site. I tried to use include_once() and make it global using keyword global but it only works in the current file. If I don't use define() to make these parameters as constant, are there any other way to achieve this? Thank you.
You can create a class Config and store your config parameters as Class Constants. Then include this class everywhere you need it, or use Autoload it.
class Config {
const databaseUsername = "user123";
const databasePassword = "pass456";
}
echo Config::databaseUsername;
echo Config::databasePassword;
But as in my experience, define() works perfectly well, unless you need to store more complicated data types (arrays for example).
To avoid include the config file everywhere, you could set auto_prepend_file in your PHP.ini, but I personally find this solution obscure, since it's not obvious for another developer working on your code that a PHP file is auto-included.
I often switch between .NET and PHP development. With ASP.NET sites I save configuration information (e.g. connection strings, directories, application setting) in the web.config file which is appropriately protected and easy to access the values, etc.
In PHP, I solve this with a class that has static methods for each variable:
class webconfig {
public static function defaultPageIdCode() {
return 'welcome';
}
}
The file is included by the app variables are accessed with a one-line:
$dp = webconfig::defaultPageIdCode();
And since PHP isn't compiled, it is easy to telnet in and change a value for a website anyway, so this solution works fairly well and gives me these two advantages:
I can add logic to a config variable without breaking its interface with the application
these config variables appear as intellisense in my e.g. Eclipse, NetBeans, etc.
But I can imagine there are other ways people solve saving web config settings in PHP which may have other advantages.
Especially those who have experience with a number of PHP frameworks, what are other ways of saving config variables and their advantages and disadvantages?
I've decided to list all known methods along with their advantages and disadvantages.
I've marked this answer as a community wiki so collaboration is easier.
Global Constants
Assigning:
define('CONFIG_DIRECTIVE', 'value');
Accessing:
$object = new MyObject(CONFIG_DIRECTIVE);
Advantages:
Has global scope.
Autocompleted by most IDEs.
Has an agreed upon naming convention (UPPERCASE_UNDERSCORE_SEPARATED).
Disadvantages:
Directives cannot contain arrays (prior to v7.0.0).
Special Notes:
Cannot be reassigned.
Alternate Syntax Files
For example: XML, INI, YAML, etc.
Assigning:
Simply edit the file in it's specific language. (For example, for INI files: config_directive = value.)
Accessing:
The config file needs to be parsed. (For example, for INI's: parse_ini_file().)
Advantages:
Most likely has a syntax more suited for a config file.
Disadvantages:
Possible overhead of accessing and parsing the file.
Array
Assigning:
$config['directive'] = 'value';
Accessing:
The cleanest method of accessing configuration values using this method is to pass the required values to the object that needs them on creation, or pass them to your container object and let it handle passing them out internally.
$object = new MyObject($config['directive']);
$container = new MyContainer($config);
Advantages:
Directives can be arrays.
Disadvantages:
No autocompletion.
Special Notes:
Variable collisions can occur. If this is a concern, name your array appropriately to avoid them.
Class
Assigning:
There are many different class based implementations.
Static class.
myCfgObj::setDirective('DIRECTIVE', 'value');
Instanced class.
myCfgObj->setDirective('DIRECTIVE', 'value');
Accessing:
Again there are various class based implementations.
Static class.
$object = new MyObject(myCfgObj::getDirective('DIRECTIVE'));
Instanced class.
$object = new MyObject(myCfgObj->getDirective('DIRECTIVE'));
Advantages:
Can be autoloaded.
Disadvantages:
Tends to be a bit verbose.
Can be hard to maintain if a container class is not being used.
I tend to use a Settings static class in PHP, this is because
It has a global scope.
You can enable/disable changes to protected configs.
You can add any settings during anywhere within runtime.
You can make the class automated to fetch public configs from a file/database.
Example:
abstract class Settings
{
static private $protected = array(); // For DB / passwords etc
static private $public = array(); // For all public strings such as meta stuff for site
public static function getProtected($key)
{
return isset(self::$protected[$key]) ? self::$protected[$key] : false;
}
public static function getPublic($key)
{
return isset(self::$public[$key]) ? self::$public[$key] : false;
}
public static function setProtected($key,$value)
{
self::$protected[$key] = $value;
}
public static function setPublic($key,$value)
{
self::$public[$key] = $value;
}
public function __get($key)
{//$this->key // returns public->key
return isset(self::$public[$key]) ? self::$public[$key] : false;
}
public function __isset($key)
{
return isset(self::$public[$key]);
}
}
Then within your runtime, if you loaded this file first, followed by your database config file, your database config file would look like so:
<?php
Settings::setProtected('db_hostname', 'localhost');
Settings::setProtected('db_username', 'root');
Settings::setProtected('db_password', '');
Settings::setProtected('db_database', 'root');
Settings::setProtected('db_charset', 'UTF-8');
//...
echo Settings::getProtected('db_hostname'); // localhost
//...
Settings::setPublic('config_site_title', 'MySiteTitle');
Settings::setPublic('config_site_charset', 'UTF-8');
Settings::setPublic('config_site_root', 'http://localhost/dev/');
As you can see the we have a method __get that should only be allowed to grab public variables, An example of why we have this is as follows:
$template = new Template();
$template->assign('settings', new Settings());
Regardless the fact that we have used this object as a static object, the values should still stand so within the template you can now do, lets say.
<html>
<head>
<?php echo isset($settings->config_site_title) ? $settings->config_site_title : 'Fallback Title'; ?>
</head>
</html>
And this will only allow you to have access to the public data during the initialized period.
This can get a lot more complex but more system friendly, some examples:
A loadConfig method to automatically parse a config file, xml, php, yaml.
If you register an shutdown_function you can auto update the database with new settings.
You can auto-populate the class with config from that database.
You can implement iterators to make it compatible with looping.
Lots more.
This too me is by far the best methods to complete this job.
The way I do it is directly store them in an array and save the file as config.php
<?php
$config['dbname'] = "mydatabase";
$config['WebsiteName'] = "Fundoo Site";
$config['credits'] = true;
$config['version'] = "4.0.4";
?>
Thi is the way most PHP frameworks like Wordpress, etc do it.
In PHP I always use a ".htaccess" to protect my config file (Double protection)
Note: "Best way" never exists. Every application and framework doing it their own style. While your example is doing the trick i think it's a little bit resource-heavy for a simple config file.
You can do it with single variables like Amber pointed out
You can do it with arrays this is the most common approach and you can always easily edit your config file.
You can do it with .ini files that PHP easily parsing
Edit:
Edward please take a look at parse_ini_file's examples. You can load the .ini file with a simple command then you can use the variables in a class like in your example.
There are pretty much possibilities I think, but the most common methods are storing as plain text in files like .csv, .ini, .xml. With little tricks you can protect these files, so that no one can load the files directly.
an INI-File example:
;<?php die(); ?>
[config1]
var1 = 'value1';
var2 = 'value2';
...
[config2]
...
The ; is considered a comment in ini files. So when you read in the file with an ini-parser, this line will be ignored. If someone accesses the file directly via url the die()-function will be executed. This works only, if the INI-file wears a file-extension like .php so that the server knows that this should be executed and not diplayed as plain text.
Possible disadvantage of most file-base-config-storages are problems with some utf8-characters.
Zend_Config is a component of the Zend-Framework, which provides possibilities for several storage-adapters with an easy to use api.
Since PHP is able to use OO, I like to go with a "Config class":
class Config
{
/**
* ---------------------------------
* Database - Access
* ---------------------------------
*/
/**
* #var String
*/
const DB_DRIVER = 'pgsql';
const DB_USER = 'postgres';
const DB_PASSWORD = 'postgres';
const DB_NAME = 'postgres';
}
It is easy accessable with Config::DB_DRIVER. No need to include the file since the application autoloader will do that for you. Of course, protecting the file still needs to be done.
Telnet? OMG I've fallen into a timewarp and arrived in 1992!
But seriously, IIRC there are tools which allow asp.net (and other languages) to parse session data - which is just a serialized php array. I'd have a go at implementing the global settings as a sort of shadow session within PHP. Even if you don't store your config settings as a serialized PHP array, you could map them into the session at runtime using your own session handler.
In terms of where you store the data - that's a more tricky one when you're presumably running on a Microsoft platform. Obviously you don't want the expense of disk access for every request. Although NT does some disk caching it's not (IME) quite as effective as other OS. Memcached appears to be one solution to this. It does appear to be usable from asp.net.
HTH
The usual route is to use define:
define('MYSQL_USER', 'ROOT');
and access it all over the application via MYSQL_USER :
$user = MYSQL_USER;
However arrays are not supported in this way.
There are few possibilities:
You can use config file (ini, json, xml or yaml). For ini you have parse_ini_file, for JSON there is json_decode (+file_get_contents), for YAML you have to use external library (search for sfYaml)
You can have a config file with variables or constants (better for immutable config and accessible in all scopes), which you includes in your script:
define('ROOT_DIR', '\home\www');
$sRootDir = '\home\www';
If you are OO-oriented, you can wrap it in class, as properties - you do not have getter method for every property, you can just have:
class Config
{
public $var1 = 'xxx';
public $var2 = 'yyy';
}
($c = new Config(); print $c->var1)
or
static class Config
{
public static $var1 = 'xxx';
public static $var2 = 'yyy';
}
(print c::$var1)
The best is to have registry-type class, implementing singleton pattern and capable to read config from given file.
In order to be testable, I use a Config class that holds the actual configuration data and an AppConfig static class that holds a reference to a Config object loaded at bootstrap from application wide configuration files (dependency injected at bootstrap). In the tests environment, I only change the Config object. See https://github.com/xprt64/Config
On my site I have a config file which has many settings that need to be accessed in many pages, including inside many class files. The config file is included into the header of every page build. Since I will be using a registry method to store some objects in, I am wondering if it would be better for me to store some setting in this class ass well since it will be available to all my other objects? From my experience over the last couple days, it seems accessing CONSTANTS inside of my class files is difficult sometimes. I am just not sure if it would be a good idea as it would need to call several methods to set and get the settings. Is it common practice to store settings in a registry type object? I have seen on some large projects that they have the methods in place to set/get settings but I have never really seen it in action.
I avoid constants in PHP, they make untestable. This is the gist of my preferred solution:
whatever.ini:
<?php
return array(
'setting-1' => 'value',
'setting-2' => 'another value',
);
config.php:
class config
{
public function __construct($path)
{
$this->cfg = include $path;
}
private $cfg;
public function get($key, $default)
{
return array_key_exists($this->cfg, $key)
? $this->cfg[$key]
: $default
;
}
}
index.php:
$cfg = new config('my.ini');
...
I like to keep things like this in a registry of some sort. Although for me this is because
the majority of my configuration
values are actually multiple parts
(ie arrays) so to map much of this
out using constants would get pretty
long winded. Additionally i dont
use php for my config files i always
use XML or YAML which is then parsed
any way so it jsut makes more sense
to go ahead and stick them in a
registry as opposed to using constant or globals.
It allows for a single api to get
these type of values whther its a db
connection object or the path to the
webroot on the filesystem
With that said i think it really depends on what the values are and how you intend to use them and if they are structure or essentially flat.
I use a combination of two approaches:
1: In every class/controller, I always start with a require_once('app_config.php') in which I have code like:
define('APP_SMTP_SERVER', 'mail.company.com');
that I can then reference as a constant.
2: I have a singleton "Registry" class where I can store keys and values. It has two exposed methods, getAttribute($key) and setAttribute($key, $value). When I save it to the database, I serialize the value, so it can store any data type you throw at it (single values or arrays, etc.).