assume i have a code as below:
index.php
<?php
require 'file_1.php';
// file_1.php contents can go here, but i'm trying to make this simple and clutter free, thus clean.
// The reason being to not centralize all code in a single file should file_2.php, file_3.php, file_n.php exist.
$app = new type_of_object();
$app->intialize_some_stuff();
?>
file_1.php
<?php
$app->access_some_method($param1, new function($app) {
// do some logic here...
});
?>
doing this approach, i get an error such as below:
Notice: Undefined variable: app in X:\project_folder\file_1.php on line 2
to summarize, i'm trying to decentralize all codes from being defined in index.php and instead, have them hosted by different files such as file_1.php to file_n.php. The problem is, i'd be needing to access the $app variable from index.php on the required files such as file_1.php to file_n.php since i'll only need 1 instance of this, no duplicates allowed.
i'm also open to being taught another approach on this.
cheers!
EDIT: its worth nothing that i'm fairly new in PHP, and that i've already done few research. except that what i'm getting is the opposite of my issue. also, the need to access $app of index.php from other php files is the very center of my question.
Splitting code can be a good idea to achieve a better maintainability. You should avoid unclear scripts name.
at a high degree, you want definitely go on composer approach to maintain packages.
Anyway, for a basic code splitting, the rules are the same than a regular script. Code is interpreted at the time it is read. Just rewrite your example in one script :
<?php
$app->access_some_method($param1, new function($app) {
// do some logic here...
});
$app = new type_of_object();
$app->intialize_some_stuff();
?>
See the problem ? $app is simply not initialized when calling the access_some_method.
So, this will work :
<?php
$app = new type_of_object();
$app->intialize_some_stuff();
require 'file_1.php';
?>
But the gain is poor. If you already have a class, there's a few cases where it can be interesting to split logic among many files. I think this one is a better example (all files in the same folder, no namespaces) :
<?php
require('App');
require('AppRequest');
$app = new App();
$request = new AppRequest();
$app->process($request);
With this way, you can split the main app logic and the request analysis logic for instance
Security release 5.5.42 "disables all serialization / unserialization of cookie values" - https://laravel-news.com/laravel-5-6-30
But I have my values serialized still, only not unserialized. While I do
Cookie::get('key')
I get something like
"s:5:"value";"
Setting protected static $serialize = true; in App\Http\Middleware\EncryptCookies helps, and so does
unserialize(Cookie::get('key'))
But as I understand unserialize() itself is the source of the problem with this security release, not what I do with the unserialized value later, so this kinda beats the purpose of the update.
Why are my cookies serialized here and how to fix this?
This is actually worth an answer as the question itself is quite interesting.
From a Laravel perspective this isn't a cookie problem as much as it's a APP_KEY config key problem combined with serialize/unserialize.
Relevant quote from the docs:
However, if your application's encryption key is in the hands of a
malicious party, that party could craft cookie values using the
encryption key and exploit vulnerabilities inherent to PHP object
serialization / unserialization, such as calling arbitrary class
methods within your application.
The relevant part is this vulnerabilities inherent to PHP object serialization / unserialization.
Usually the form of explot is Object Injection(the most common at least).
OWASP has a very good example here.
Even php.net has a red warning for it's unserliaze function.
Warning
Do not pass untrusted user input to unserialize()
Cookies come from a user and users are NOT to be trusted.
Since an example is in order I'll just leave the OWASP one here too:
class Example1
{
public $cache_file;
function __construct()
{
// some PHP code...
}
function __destruct()
{
$file = "/var/www/cache/tmp/{$this->cache_file}";
if (file_exists($file)) #unlink($file);
}
}
// some PHP code...
$user_data = unserialize($_GET['data']);
// some PHP code...
In this example an attacker might be able to delete an arbitrary file via a Path Traversal attack, for e.g. requesting the following URL:
http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}
With that said, I highly recommend reading(even briefly) about serialize/unserliaze vulnerabilities.
If you're using a proper framework, usually, you'll have most security things taken care of IF you don't go out of your way to introduce some vulnerability and you stick to the framework's standards.
It's less efficient but in case of structured data, I replace serialize/unserialize with json_encode/json_decode.
I want to create a config file for my PHP project, but I'm not sure what the best way to do this is.
I have 3 ideas so far.
1-Use Variable
$config['hostname'] = "localhost";
$config['dbuser'] = "dbuser";
$config['dbpassword'] = "dbpassword";
$config['dbname'] = "dbname";
$config['sitetitle'] = "sitetitle";
2-Use Const
define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', 'localhost');
define('TITLE', 'sitetitle');
3-Use Database
I will be using the config in classes so I'm not sure which way would be the best or if there is a better way.
One simple but elegant way is to create a config.php file (or whatever you call it) that just returns an array:
<?php
return array(
'host' => 'localhost',
'username' => 'root',
);
And then:
$configs = include('config.php');
Use an INI file is a flexible and powerful solution! PHP has a native function to handle it properly. For example, it is possible to create an INI file like this:
app.ini
[database]
db_name = mydatabase
db_user = myuser
db_password = mypassword
[application]
app_email = mailer#myapp.com
app_url = myapp.com
So the only thing you need to do is call:
$ini = parse_ini_file('app.ini');
Then you can access the definitions easily using the $ini array.
echo $ini['db_name']; // mydatabase
echo $ini['db_user']; // myuser
echo $ini['db_password']; // mypassword
echo $ini['app_email']; // mailer#myapp.com
IMPORTANT: For security reasons the INI file must be in a non public folder
I use a slight evolution of #hugo_leonardo 's solution:
<?php
return (object) array(
'host' => 'localhost',
'username' => 'root',
'pass' => 'password',
'database' => 'db'
);
?>
This allows you to use the object syntax when you include the php : $configs->host instead of $configs['host'].
Also, if your app has configs you need on the client side (like for an Angular app), you can have this config.php file contain all your configs (centralized in one file instead of one for JavaScript and one for PHP). The trick would then be to have another PHP file that would echo only the client side info (to avoid showing info you don't want to show like database connection string). Call it say get_app_info.php :
<?php
$configs = include('config.php');
echo json_encode($configs->app_info);
?>
The above assuming your config.php contains an app_info parameter:
<?php
return (object) array(
'host' => 'localhost',
'username' => 'root',
'pass' => 'password',
'database' => 'db',
'app_info' => array(
'appName'=>"App Name",
'appURL'=> "http://yourURL/#/"
)
);
?>
So your database's info stays on the server side, but your app info is accessible from your JavaScript, with for example a $http.get('get_app_info.php').then(...); type of call.
The options I see with relative merits / weaknesses are:
File based mechanisms
These require that your code look in specific locations to find the ini file. This is a difficult problem to solve and one which always crops up in large PHP applications. However you will likely need to solve the problem in order to find the PHP code which gets incorporated / re-used at runtime.
Common approaches to this are to always use relative directories, or to search from the current directory upwards to find a file exclusively named in the base directory of the application.
Common file formats used for config files are PHP code, ini formatted files, JSON, XML, YAML and serialized PHP
PHP code
This provides a huge amount of flexibility for representing different data structures, and (assuming it is processed via include or require) the parsed code will be available from the opcode cache - giving a performance benefit.
The include_path provides a means for abstracting the potential locations of the file without relying on additional code.
On the other hand, one of the main reasons for separating configuration from code is to separate responsibilities. It provides a route for injecting additional code into the runtime.
If the configuration is created from a tool, it may be possible to validate the data in the tool, but there is no standard function to escape data for embedding into PHP code as exists for HTML, URLs, MySQL statements, shell commands....
Serialized data
This is relatively efficient for small amounts of configuration (up to around 200 items) and allows for use of any PHP data structure. It requires very little code to create/parse the data file (so you can instead expend your efforts on ensuring that the file is only written with appropriate authorization).
Escaping of content written to the file is handled automatically.
Since you can serialize objects, it does create an opportunity for invoking code simply by reading the configuration file (the __wakeup magic method).
Structured file
Storing it as a INI file as suggested by Marcel or JSON or XML also provides a simple api to map the file into a PHP data structure (and with the exception of XML, to escape the data and create the file) while eliminating the code invocation vulnerability using serialized PHP data.
It will have similar performance characteristics to the serialized data.
Database storage
This is best considered where you have a huge amount of configuration but are selective in what is needed for the current task - I was surprised to find that at around 150 data items, it was quicker to retrieve the data from a local MySQL instance than to unserialize a datafile.
OTOH its not a good place to store the credentials you use to connect to your database!
The execution environment
You can set values in the execution environment PHP is running in.
This removes any requirement for the PHP code to look in a specific place for the config. OTOH it does not scale well to large amounts of data and is difficult to change universally at runtime.
On the client
One place I've not mentioned for storing configuration data is at the client. Again the network overhead means that this does not scale well to large amounts of configuration. And since the end user has control over the data it must be stored in a format where any tampering is detectable (i.e. with a cryptographic signature) and should not contain any information which is compromised by its disclosure (i.e. reversibly encrypted).
Conversely, this has a lot of benefits for storing sensitive information which is owned by the end user - if you are not storing this on the server, it cannot be stolen from there.
Network Directories
Another interesting place to store configuration information is in DNS / LDAP. This will work for a small number of small pieces of information - but you don't need to stick to 1st normal form - consider, for example SPF.
The infrastucture supports caching, replication and distribution. Hence it works well for very large infrastructures.
Version Control systems
Configuration, like code should be managed and version controlled - hence getting the configuration directly from your VC system is a viable solution. But often this comes with a significant performance overhead hence caching may be advisable.
Well - it would be sort of difficult to store your database configuration data in a database - don't ya think?
But really, this is a pretty heavily opinionated question because any style works really and it's all a matter of preference. Personally, I'd go for a configuration variable rather than constants - generally because I don't like things in the global space unless necessary. None of the functions in my codebase should be able to easily access my database password (except my database connection logic) - so I'd use it there and then likely destroy it.
Edit: to answer your comment - none of the parsing mechanisms would be the fastest (ini, json, etc) - but they're also not the parts of your application that you'd really need to focus on optimizing since the speed difference would be negligible on such small files.
You can create a config class witch static properties
class Config
{
static $dbHost = 'localhost';
static $dbUsername = 'user';
static $dbPassword = 'pass';
}
then you can simple use it:
Config::$dbHost
Sometimes in my projects I use a design pattern SINGLETON to access configuration data. It's very comfortable in use.
Why?
For example you have 2 data source in your project. And you can choose witch of them is enabled.
mysql
json
Somewhere in config file you choose:
$dataSource = 'mysql' // or 'json'
When you change source whole app shoud switch to new data source, work fine and dont need change in code.
Example:
Config:
class Config
{
// ....
static $dataSource = 'mysql';
/ .....
}
Singleton class:
class AppConfig
{
private static $instance;
private $dataSource;
private function __construct()
{
$this->init();
}
private function init()
{
switch (Config::$dataSource)
{
case 'mysql':
$this->dataSource = new StorageMysql();
break;
case 'json':
$this->dataSource = new StorageJson();
break;
default:
$this->dataSource = new StorageMysql();
}
}
public static function getInstance()
{
if (empty(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
public function getDataSource()
{
return $this->dataSource;
}
}
... and somewhere in your code (eg. in some service class):
$container->getItemsLoader(AppConfig::getInstance()->getDataSource()) // getItemsLoader need Object of specific data source class by dependency injection
We can obtain an AppConfig object from any place in the system and always get the same copy (thanks to static). The init () method of the class is called
In the constructor, which guarantees only one execution. Init() body checks
The value of the config $dataSource, and create new object of specific data source class. Now our script can get object and operate on it, not knowing
even which specific implementation actually exists.
Define will make the constant available everywhere in your class without needing to use global, while the variable requires global in the class, I would use DEFINE. but again, if the db params should change during program execution you might want to stick with variable.
If you think you'll be using more than 1 db for any reason, go with the variable because you'll be able to change one parameter to switch to an entirely different db. I.e. for testing , autobackup, etc.
Here is my way.
<?php
define('DEBUG',0);
define('PRODUCTION',1);
#development_mode : DEBUG / PRODUCTION
$development_mode = PRODUCTION;
#Website root path for links
$app_path = 'http://192.168.0.234/dealer/';
#User interface files path
$ui_path = 'ui/';
#Image gallery path
$gallery_path = 'ui/gallery/';
$mysqlserver = "localhost";
$mysqluser = "root";
$mysqlpass = "";
$mysqldb = "dealer_plus";
?>
Any doubts please comment
One of the simplest form to use config with multiple files is like this:
Files hierarchy:
config
- mail.php
- database.php
mail.php
return [
'smtp_debug' => 0,
];
A helper function:
function config($configFilename, $key)
{
$path = sprintf("config/%s.php", $configFilename);
if (file_exists($path)) {
$config = include sprintf("config/%s.php", $configFilename);
if (isset($config[$key])) {
return $config[$key];
}
}
return '';
}
And you can call it in elegant way:
config('mail','smtp_debug')
I normally end up creating a single conn.php file that has my database connections.
Then i include that file in all files that require database queries.
What about something like this ?
class Configuration
{
private $config;
public function __construct($configIniFilePath)
{
$this->config = parse_ini_file($configIniFilePath, true);
}
/**
* Gets the value for the specified setting name.
*
* #param string $name the setting name
* #param string $section optional, the name of the section containing the
* setting
* #return string|null the value of the setting, or null if it doesn't exist
*/
public function getConfiguration($name, $section = null)
{
$configValue = null;
if ($section === null) {
if (array_key_exists($name, $this->config)) {
$configValue = $this->config[$name];
}
} else {
if (array_key_exists($section, $this->config)) {
$sectionSettings = $this->config[$section];
if (array_key_exists($name, $sectionSettings)) {
$configValue = $sectionSettings[$name];
}
}
}
return $configValue;
}
}
if i have a config file like config.conf (it can be htttp://example.com/config.conf)
user=cacom
version = 2021608
status= true
this is my function:
function readFileConfig($UrlOrFilePath){
$lines = file($UrlOrFilePath);
$config = array();
foreach ($lines as $l) {
preg_match("/^(?P<key>.*)=(\s+)?(?P<value>.*)/", $l, $matches);
if (isset($matches['key'])) {
$config[trim($matches['key'])] = trim($matches['value']);
}
}
return $config;
}
we can use:
$urlRemote = 'http://example.com/default-config.conf';
$localConfigFile = "/home/domain/public_html/config.conf";
$localConfigFile2 = "config.conf";
print_r(readFileConfig($localConfigFile2));
print_r(readFileConfig($localConfigFile));
print_r(readFileConfig($urlRemote));
You can use this simple one:
define('someprop', 0);
and
echo someprop; // output 0
Here it is
<?php
$server = "localhost";
$username = "root";
$password = "";
$db = "your_db_name";
$conn = mysqli_connect($server, $username, $password, $db);
if(!$conn){
die('Error in connecting to server or Database');
}
?>
I'm using the code below to automatically load and declare classes so that I only need to put class files in a folder named classes. The part in spl_autoload_regsister() may seem to be unnecessary for you but it is needed to work as a WordPress plugin without errors.
It uses eval() and I've seen so many web pages talking about using eval() is bad and can create a security hole. So how could this be dangerous?
$strDirPath = dirname(__FILE__) . '\\classes\\';
$arrClassFiles = array_map(create_function( '$a', 'return basename($a, ".php");' ), glob($strDirPath . '*.php'));
spl_autoload_register(
create_function('$class_name', '
global $arrClassFiles, $strDirPath;
if (in_array($class_name, $arrClassFiles))
include($strDirPath . $class_name . ".php");' )
);
foreach ($arrClassFiles as $strClassName) {
$strClassName_alpha = $strClassName . "_Alpha";
eval("class $strClassName_alpha extends $strClassName {};");
}
print_r(get_declared_classes());
Maybe, somebody can put a file name of php code in the folder? But I don't see it can compromise the system.
If they can name a class file something like randomclass {}; echo $db_password;//.php, then you could have a code execution attack.
I'm pretty sure that's not a valid file name, but there are people far wilier than me at crafting valid malicious inputs.
It's just usually not an attack surface you need to open yourself up to, given that it's practically always possible to avoid with better code structure.
If an error condition is handled, I don't see a problem here.
Just be sure that if someone tries to call a different class that does exist (i.e. code that would be valid here, but that you wouldn't want your hacker to run directly because it would bypass a restriction on your system), that it won't be a security problem - or that it wouldn't be possible to run that class at all from this context.
Just in case, deny any attempts to run code with the words "class," or other keywords, or any built in class names, or built in function names, other builtins, etc. and you should be fine, but even that probably isn't necessary in your particular case here because would probably result in an error.
Is it a good practice to initialize an object for an authentication class that does various stuff like register user, login user etc. inside a config file?
The config file mostly does stuff like setting db username, password and site name etc.
Please provide a reason if you don't find this a standard practice. Just to let you know most of the code is procedural except for this particular class.
// MySQL connection settings
$db_host = "localhost";
$db_user = "someuser";
$db_pass = "some pass";
$db_name = "somedb";
// Name of the site
$site_name = "MyDomainName";
$auth = new auth();//initialize Authentication class
$auth->set_auth();//Check if user autorized
In my opinion this is not a good idea. A config file is for configuration, not for execution. I would put this code into a bootstrap.php, so, when you have to edit your code in the future, you know exactly where you can find your configurations and instantiations.
index.php:
include('bootstrap.php');
bootstrap.php:
include('config.php');
$auth = new auth();
$auth->set_auth();
config.php:
$db_host = "localhost";
$db_user = "someuser";
$db_pass = "some pass";
$db_name = "somedb";
The authentication class should be responsible for authenticating, not handling user-specific functions like register/edit/delete. The config object should be available to object needing the configuration data, not the other way around.
The config file should not contain anything other then config data.
I wouldn't do this. "Code" is best kept completely separate from the "configuration files" for a number of reasons. One is that you might have sensitive information in the config files (e.g. passwords) and would want to keep them in a different repository than the code itself. Putting initialisation (which is code) into the Config will mean that it is controlled in two source repositories. Secondly, stuff that "runs" might not be idempotent. The new auth() might set up some state which will make "reloading" the Config a bit of a pain.
It's best you keep a "Config loader" which creates a Config object that contains instantiated classes etc. after reading information from a config file rather than put that init code directly into the file. Also, I wouldn't recommend using executable code as a config file (although this seems to be practice in the PHP world). I would use a format like .ini or yaml and load it up rather than risk evaluating code that's outside my core application.
It is good practice to abstract your code into chunks that have a single purpose, in your case: a config object and a authentication handler. This is related to the KISS Principle, which dictates simplicity by design. In this case: simplicity in code. When you're mixing code, like you're describing, your code gets more complex, because it does more things.
While at first it may not seem complex, this design eventually leads to complex code. For instance: what if another developer joins your team? You'll need to add another config, and conditions to select the right config. This is also the case when working with different environments (development/production).
And what if in some cases you don't want to use the authentication handler? Maybe you're executing an action that doesn't require authentication, or better yet: when authentication is unwanted. More code, more complexity.
By creating chunks of code, whether this is a class, function or an include, you're using loose coupling. This means the chunks don't know about each other, but they can interact. This interaction typically is done by giving the authentication handler a config object that it can use, rather than letting the handler decide what config it uses. This is called dependency injection and is considered a very good way of decoupling your code.
Second, quality code mostly documents itself. Let's say I have to work in your code, I don't know that including a configuration file actually does authentication. I can spend minutes, maybe hours trying to figure out why a session is created when, looking at the code, nothing seems to indicate this.
In your example, I would use something like this:
<?php
include 'config.php'; // contains function that returns config object/array
include 'auth.php'; // contains functions for authentication
// determine environment, based on server variables (ip, script path, etc)
$environment = getEnvironment($_SERVER);
// get config based on environment
$config = getConfig($environment);
// see if authentication is needed
if (needsAuthentication()) {
// perform authentication based on request variables (eg: submitted form fields)
$auth = new auth();
$auth->doAuth($config, $_REQUEST);
}