For debugging purposes, when working on PHP projects with many file / many include (example: Wordpress code), I would sometimes be interested in seeing the "unwrapped" code, and to amalgamate / flatten ("flatten" is the terminology used in Photoshop-like tools when you merge many layers into one layer) all files into one big PHP file.
How to do an amalgamation of multiple PHP files?
Example:
$ php index.php --amalgamation
would take these files as input:
vars.php
<?php
$color = 'green';
$fruit = 'apple';
?>
index.php
<?php
include 'vars.php';
echo "A $color $fruit";
?>
and produce this amalgamated output:
<?php
$color = 'green';
$fruit = 'apple';
echo "A $color $fruit";
?>
(it should work also with many files, e.g. if index.php includes vars.php which itself includes abc.php).
We can write an amalgamation/bundling script that fetches a given file's contents and matches any instances of include|require, and then fetches any referred files' contents, and substitutes the include/require calls with the actual code.
The following is a rudimentary implementation that will work (based on a very limited test on files with nested references) with any number of files that include/require other files.
<?php
// Main file that references further files:
$start = 'test/test.php';
function bundle_files(string $filepath)
{
// Fetch current code
$code = file_get_contents($filepath);
// Set directory for referred files
$dirname = pathinfo($filepath, PATHINFO_DIRNAME);
// Match and substitute include/require(_once) with code:
$rx = '~((include|require)(_once)?)\s+[\'"](?<path>[^\'"]+)[\'"];~';
$code = preg_replace_callback($rx, function($m) use ($dirname) {
// Ensure a valid filepath or abort:
if($path = realpath($dirname . '/' . $m['path'])) {
return bundle_files($path);
} else {
die("Filepath Read Fail: {$dirname}/{$m['path']}");
}
}, $code);
// Remove opening PHP tags, note source filepath
$code = preg_replace('~^\s*<\?php\s*~i', "\n// ==== Source: {$filepath} ====\n\n", $code);
// Remove closing PHP tags, if any
$code = preg_replace('~\?>\s*$~', '', $code);
return $code;
}
$bundle = '<?php ' . "\n" . bundle_files($start);
file_put_contents('bundle.php', $bundle);
echo $bundle;
Here we use preg_replace_callback() to match and substitute in order of appearance, with the callback calling the bundling function on each matched filepath and substituting include/require references with the actual code. The function also includes a comment line indicating the source of the included file, which may come in handy if/when you're debugging the compiled bundle file.
Notes/Homework:
You may need to refine the base directory reference routine. (Expect trouble with "incomplete" filepaths that rely on PHP include_path.)
There is no control of _once, code will be re-included. (Easy to remedy by recording included filepaths and skipping recurrences.)
Matching is only made on "path/file.php", ie. unbroken strings inside single/double quotes. Concatenated strings are not matched.
Paths including variables or constants are not understood. Files would have to be evaluated, without side-effects!, for that to be possible.
If you use declare(strict_types=1);, place it atop and eliminate following instances.
There may be other side-effects from the bundling of files that are not addressed here.
The regex does no lookbehind/around to see if your include/require is commented out!
If your code jumps in and out of PHP mode and blurts out HTML, all bets are off
Managing the inclusion of autoloaded classes is beyond this snippet.
Please report any glitches and edge cases. Feel free to develop and (freely) share.
I want to print php variable in a text file.
Example :
<?php
$name='x' ;
?>
I want to put name value in text file for print it as hard copy .
Following is how to accomplish it.
<?php file_put_contents('filename', 'content');
Have a look at this function at PHP.net
Since your question does not include anything you have tried on your own (Which is generally recommended). Here is somewhere for you to start - the php file_put_contents function.
You can try something like this:
<?php
$file = 'some-file.txt';
$name = "x";
// Write the contents to the file
file_put_contents($file, $name);
?>
A few Google searches will surely provide some insight here as well.
Hope it helps!
I wonder what ist he best way to do the following.
I am creating a webseite CMS. Through CMS I am creating new folders with index.php files in them. For example I have created folder with the site new_folder_name/index.php
I wonder what ist the best way to make an interaction between the created index.php files and database. For example I am creating the php file with another php file
<?php
$dir = "../new_folder_name";
$file_to_write = "index.php";
$content_to_write = '
<?php
//// php code
$foo=‘3‘:
?>
if( is_dir($dir) === false )
{
mkdir($dir);
}
$file = fopen($dir . '/' . $file_to_write,"w");
fwrite($file, $content_to_write);
fclose($file);
include $dir . '/' . $file_to_write;
?>
I am putting a variable $foo that needs to be changed with every new php file created. I could create $foo=GET(´SOEMTHING´) but this GET is making problems since this variable needs to be changed, and only for this file a unique value. I do not know if I explained it properly but I hope I did. In which way can I create a php file with specific $foo value or change the created file with php in order to get the $foo value which I want.
you can do
$content_to_write = '
<?php
//// php code
$foo=\'$_GET[\'something\']\';
?>';
this is make your new script to read $_GET['something']
OR
this example, read this script's $_GET['something'] and put it's value in script...
$content_to_write = '
<?php
//// php code
$foo=\''.$_GET['something'].'\';
?>';
since you use single quote $_GET didn't get parse with original script. If you want to use that simply concatenate it. Alternatively you can concatinate '$' in between string to make variable just variables.
I have two configuration files. One is ini one is php. They look like below. I need to update the database file name but the rest of the files must be unchanged. Any idea how to do so?
config.ini
; Turning Debugging on
[test]
developer = true
; Production site configuration data
[production]
database.params.dbname = /var/lib/firebird/data/radek_db.gdb
and setting.php
<?php
/**
The settings file
*/
#This will be done automatically if u want to override it uncomment the next line few lines
/*
$Path = 'mainline';
#Database to connect to:
$Database = "radek_db";
?>
Could you read the file to a string with file_get_contents(), do a str_replace() or preg_replace() on it, and then save over it with file_put_contents()?
I'd link those all to the documentation, but I don't have the reputation to make more than one link...
EDIT: If all you know is the name of the option, you can use preg_match to find the option name with a regexp (something like '/^database\.params\.dbname = (.*)$/') and then do a str_replace on the name you find.
Something like this:
$file = file_get_contents('/path/to/config/file');
$matches = array();
preg_match('/^database\.params\.dbname = (.*)$/', $file, $matches);
$file = str_replace($matches[1], $new_value, $file);
file_put_contents('/path/to/config/file', $file);
For reading ini files, there's parse_ini_file. For the rest, you'll have to write a simple script for that purpose... or use sed.
I have a config.inc file in a web application that I am building. It contains an array with configuration values for things like the MySQL database, etc. I would like these to be entered by using a simple form, that asks for the server, login/password for the database, etc, then these get written to the configuration file.
Is there a preferred method of doing this? I am not sure how to write to a file, and update an array.
You just want writing, correct? Is it a serialized array or is it parsed?
One way to read a config file is parse_ini_file(). I wouldn't necessarily call it preferred, but it's a method. You'd still need to write the file.
Another way would to write a "config.inc.php" and just include it in, to write it you'd just output actual PHP code (e.g. $var = "myval";).
This is a way you could write a simple "output" function that took an array of configuration values and output them as name=value, assuming $config was an associative array.
foreach ($config as $name => $value) {
$output .= $name . '=' . $value . "\n";
}
if (!file_put_contents($filename, $output)) {
die("Error writing config file.");
}
There's a lot of decent ways to do it. It's really based on your requirements. Does it need to be in a specific format or do you have leeway?
It is not recommended to modify PHP configuration files via your application, you should use CSV files or a database table.
In case you want to save it in a CSV file then I suggest you keep a CSV file for each configuration type (e.g CSV file for database configurations) and always overwrite the previous one using file_put_contents
Save data example:
$csvStructure = array("dbUser","dbPassword","dbHostname","dbPort"); // array used for both loading data and saving it
$csvData = array();
foreach ($csvStructure as $field) {
$csvData[] = $_POST[$field]; // so it'd get $_POST["dbUser"],$_POST["dbPasword"], etc..
}
file_put_contents("filename",implode("\t",$csvData));
Load data example:
$csvStructure = array("dbUser","dbPassword","dbHostname","dbPort"); // array used for both loading data and saving it
$dbConfig = array();
$csvData = explode("\t",file_get_contents("filename"));
foreach ($csvStructure as $key => $field) { // $key would have the location of the requested field in our CSV data (0,1,2, etc..).
$dbConfig[$field] = $csvData[$key]; // populate $dbConfig["dbUser"],$dbConfig["dbPasword"], etc..
}
I believe using an ini file is a wise option, because user, password, schema, paths, etc. are things that usually will be modified by hand, so using var_export isn't because modifying it by hand it's not so clean and may crash your application if you make a mistake in the PHP syntax.
But parsing big ini files can be expensive, so it would be OK to cache the ini with var_export() or serlialize(). It's a better choice, I think, and read the ini only when the cache file doesn't exists.
PHP has a dedicated function for this, its called var_export();
Just do:
file_put_contents("config.php",var_export($config,true));
Well, to write a file, fwrite() php function does exactly what you want. From its PHP.NET documentation page (see example below).
Now, on the question as to what to output to that file - I'm assuming that file will have to be included as a configuration .php file into the rest of the project. I'm imagining you'll do something like this - where you're creating strings with PHP code on the fly, based on the submitted form:
$strDatabaseConfig = "\$databaseConfig = array('" . $_POST['login'] . "," . $_POST['password'] . "');";
And here's the snippet for fwrite:
$filename = 'test.txt';
$somecontent = "Add this to the file\n";
// Let's make sure the file exists and is writable first.
if (is_writable($filename)) {
// In our example we're opening $filename in append mode.
// The file pointer is at the bottom of the file hence
// that's where $somecontent will go when we fwrite() it.
if (!$handle = fopen($filename, 'a')) {
echo "Cannot open file ($filename)";
exit;
}
// Write $somecontent to our opened file.
if (fwrite($handle, $somecontent) === FALSE) {
echo "Cannot write to file ($filename)";
exit;
}
echo "Success, wrote ($somecontent) to file ($filename)";
fclose($handle);
} else {
echo "The file $filename is not writable";
}
Here's one way: wp-admin/setup-config.php from WordPress.
I prefer to have a file with a bunch of define statements.
These are constants globally available (and of course immutable) which is what you need for configuration settings.
Constants offer better memory management and efficiency in reading as they don't need the extra memory required by a variable so that it can be changed.
Let's say your config.inc file looks like this:
$config = array(
'blah' => 'mmm',
'blah2' => 'www',
//...
);
You want to update it, so you create a simple form, fill text fields with current values. PHP script that overwrites current configuration could looks like this:
$newConfig = ...; // data from form - of course validate it first
$config = ...; // data from config.inc
$config = array_merge($config, $newConfig);
file_put_contents('config.inc', '<?php $config = ' . var_export($config, true));
And you're done.