I have 2 projects that'll like to share functions. Function-A, in project-A, should be called by function-B, in project-B. Any quickest way to achieve it?
Example function-A
function upload($file, $path){
$CFG->file = $file;
$CFG->path = $path;
}
How do I call this function in function-B, project-B
function callUpload( ){
upload( "a.png", "application/path/file" );
}
Create a file that you include() at the top of each one. This file would contain the function, and then can be used across script:
include('functions.php');
Or create a Class and use that in the same way.
functions.php
function upload($file, $path){
$CFG->file = $file;
$CFG->path = $path;
}
scriptA.php & scriptB.php
include('functions.php');
upload($file, $path);
For further reference, check this out: How to call function of one php file from another php file and pass parameters to it?
I have a function log($text)
all this does is write $text to a database.
I would like to include __LINE__ and __FILE__, but don't want to include it as a parameter each time as I currently do:
function log($text,$file = null, $line = null){
// write $text to db using the three paramters
}
If I change $file = null to $file = __FILE__ it uses the file name that the function lives in, rather than where the function is being called.
Is there any way around this?
Although the question is identical, the answers seem to focus on some other topic: function name($param, $line = __LINE__, $file = __FILE__) {};
also, not using Zend framework: how to have php get the __LINE__ or __FILE__ value where a function is called
Anyone can help me get the basename of directory where the function called? I mean:
file /root/system/file_class.php
function find_file($dir, $file) {
$all_file = scandir($dir);
....
}
function does_exist($file) {
$pathinfo = pathinfo($file);
$find = find_file($pathinfo["dirname"], $pathinfo["basename"]);
return $find;
}
file /root/app/test.php
$is_exist = does_exist("config.php");
Under /root/app i have file "config.php, system.php". Do you know how to get the directory where does_exist() called? In function find_file() argument $dir is important, since scandir() function need directory path to scaned. I mean, when i want to check file config.php i doesn't need to write /root/app/config.php. If i not provide fullpath in $file argument, the $pathinfo["dirname"] will be ".". I've try to use dirname(__file__) in file_find() function but it's return the directory /root/system not /root/app where it is the directory of does_exist() function called.
I need create those function since i can't use file_exists() function.
Found Solutions:
I'm using debug_backtrace() to get the recent file and line number of where users calling function. For example:
function read_text($file = "") {
if (!$file) {
$last_debug = next(debug_backtrace());
echo "Unable to call 'read_text()' in ".$last_debug['file']." at line ".$last_debug['line'].".";
}
}
/home/index.php
16 $text = read_text();
The sample output: Unable to call 'read_text()' in /home/index.php at line 16.
Thanks.
Use any of PHP magic constants
__DIR__
__FILE__
http://php.net/manual/en/language.constants.predefined.php
Or use realpath("./");
To define your own constant paths:
define("MYPATH", realpath("./") . "/dir/dir/";
You can then call this MYPATH from everywhere this code (file) is included.
I'm trying to create a small template system and have a function that loops over an array of items.
Currently I'm using the output buffering functions and include so i can load up the template file while it has scope to the class.
function loadTemplate($name, $vars) {
$buf = '';
$path = $name . '.html';
if (file_exists($path)) {
$this->vars = $vars;
ob_start();
include($path);
$buf = ob_get_clean();
}
return $buf;
}
I was just wondering if I could store the initial template in an array then have it run (As if it was included) while keeping scope, like.
function loadTemplate($name, $vars) {
$buf = $template = '';
if (isset($this->cache[$name]))
$template = $this->cache[$name];
else {
$path = $name . '.html';
$template = file_get_contents($path);
$this->cache[$name] = $template;
}
//Exec template here with scope.
}
Or am i just being pedantic and trying to micro optimize :)
If i were you and had complex operations in the template files I would save them to filesystem. I've modified your function, I think you'll understand what happens there:
<?php
function template($name, $vars = array())
{
$cache = 'cache/'; // Path to cache folder, must be writeable
$expire = 3600 * 3; // Cache lifetime, 3 hours
$path = $name . '.html';
$cache_file = $cache . sha1($path) . '.txt'; // Generate cache file path and hash-name
// If cache file exists and it hasn't expired yet we must get cached data
if (file_exists($cache_file) && filemtime($cache_file) > (time() - $expire))
{
return unserialize(file_get_contents($cache_file));
}
// Return NULL if template file doesn't exist
if (!file_exists($path))
{
return null;
}
$this->vars = $vars;
ob_start();
include_once $path;
$output = ob_get_clean();
// Save output to the cache file
file_put_contents($cache_file, serialize($output));
return $output;
}
?>
P.S. Haven't tested the function.
That's most useless cache you can implement.
You'd better think of HTTP conditional get implementation which will make no need to call temlpate at all. And then go for opcode cache which will cache your includes automatically.
But at firs you have to profile your app/templater to see if you need any cache at all
Just keep including it. The only alternative would be to read the contents then eval them, and that's going to be worse. The overhead of the second include should be significantly less since the page is already parsed into opcode...
Will be looking into CakePHP as per NullUserException's comment :)
I don't think that it makes much difference if you include an template once again, as you said yourself... it would be micro optimizing.
But, what you could do is to save the already included templates source to an array and use the template name as the key for the array.
When you run your loadTemplate function, you can just do a array_key_exists to see if it is included already.
But if I may, I would recommend the smarty template engine. I used it in my projects and find it just perfect. I have adapted it a bit to run smoother with my code, but now it really is perfect for me.
In PHP can I include a directory of scripts?
i.e. Instead of:
include('classes/Class1.php');
include('classes/Class2.php');
is there something like:
include('classes/*');
Couldn't seem to find a good way of including a collection of about 10 sub-classes for a particular class.
foreach (glob("classes/*.php") as $filename)
{
include $filename;
}
Here is the way I include lots of classes from several folders in PHP 5. This will only work if you have classes though.
/*Directories that contain classes*/
$classesDir = array (
ROOT_DIR.'classes/',
ROOT_DIR.'firephp/',
ROOT_DIR.'includes/'
);
function __autoload($class_name) {
global $classesDir;
foreach ($classesDir as $directory) {
if (file_exists($directory . $class_name . '.php')) {
require_once ($directory . $class_name . '.php');
return;
}
}
}
I realize this is an older post BUT... DON'T INCLUDE YOUR CLASSES... instead use __autoload
function __autoload($class_name) {
require_once('classes/'.$class_name.'.class.php');
}
$user = new User();
Then whenever you call a new class that hasn't been included yet php will auto fire __autoload and include it for you
this is just a modification of Karsten's code
function include_all_php($folder){
foreach (glob("{$folder}/*.php") as $filename)
{
include $filename;
}
}
include_all_php("my_classes");
How to do this in 2017:
spl_autoload_register( function ($class_name) {
$CLASSES_DIR = __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR; // or whatever your directory is
$file = $CLASSES_DIR . $class_name . '.php';
if( file_exists( $file ) ) include $file; // only include if file exists, otherwise we might enter some conflicts with other pieces of code which are also using the spl_autoload_register function
} );
Recommended by PHP documentation here: Autoloading classes
You can use set_include_path:
set_include_path('classes/');
http://php.net/manual/en/function.set-include-path.php
If there are NO dependencies between files... here is a recursive function to include_once ALL php files in ALL subdirs:
$paths = [];
function include_recursive( $path, $debug=false){
foreach( glob( "$path/*") as $filename){
if( strpos( $filename, '.php') !== FALSE){
# php files:
include_once $filename;
if( $debug) echo "<!-- included: $filename -->\n";
} elseif( is_dir($filename)) { # dirs
$paths[] = $filename;
}
}
# Time to process the dirs:
for( $i=count($paths)-1; $i>=0; $i--){
$path = $paths[$i];
unset( $paths[$i]);
include_recursive( $path, $debug);
}
}
include_recursive( "tree_to_include");
# or... to view debug in page source:
include_recursive( "tree_to_include", 'debug');
<?php
//Loading all php files into of functions/ folder
$folder = "./functions/";
$files = glob($folder."*.php"); // return array files
foreach($files as $phpFile){
require_once("$phpFile");
}
If you want include all in a directory AND its subdirectories:
$dir = "classes/";
$dh = opendir($dir);
$dir_list = array($dir);
while (false !== ($filename = readdir($dh))) {
if($filename!="."&&$filename!=".."&&is_dir($dir.$filename))
array_push($dir_list, $dir.$filename."/");
}
foreach ($dir_list as $dir) {
foreach (glob($dir."*.php") as $filename)
require_once $filename;
}
Don't forget that it will use alphabetic order to include your files.
If your looking to include a bunch of classes without having to define each class at once you can use:
$directories = array(
'system/',
'system/db/',
'system/common/'
);
foreach ($directories as $directory) {
foreach(glob($directory . "*.php") as $class) {
include_once $class;
}
}
This way you can just define the class on the php file containing the class and not a whole list of $thisclass = new thisclass();
As for how well it handles all the files? I'm not sure there might be a slight speed decrease with this.
I suggest you use a readdir() function and then loop and include the files (see the 1st example on that page).
Try using a library for that purpose.
That is a simple implementation for the same idea I have build.
It include the specified directory and subdirectories files.
IncludeAll
Install it via terminal [cmd]
composer install php_modules/include-all
Or set it as a dependency in the package.json file
{
"require": {
"php_modules/include-all": "^1.0.5"
}
}
Using
$includeAll = requires ('include-all');
$includeAll->includeAll ('./path/to/directory');
This is a late answer which refers to PHP > 7.2 up to PHP 8.
The OP does not ask about classes in the title, but from his wording we can read that he wants to include classes. (btw. this method also works with namespaces).
By using require_once you kill three mosquitoes with one towel.
first, you get a meaningful punch in the form of an error message in your logfile if the file doesn't exist. which is very useful when debugging.( include would just generate a warning that might not be that detailed)
you include only files that contain classes
you avoid loading a class twice
spl_autoload_register( function ($class_name) {
require_once '/var/www/homepage/classes/' . $class_name . '.class.php';
} );
this will work with classes
new class_name;
or namespaces. e.g. ...
use homepage\classes\class_name;
Answer ported over from another question. Includes additional info on the limits of using a helper function, along with a helper function for loading all variables in included files.
There is no native "include all from folder" in PHP. However, it's not very complicated to accomplish. You can glob the path for .php files and include the files in a loop:
foreach (glob("test/*.php") as $file) {
include_once $file;
}
In this answer, I'm using include_once for including the files. Please feel free to change that to include, require or require_once as necessary.
You can turn this into a simple helper function:
function import_folder(string $dirname) {
foreach (glob("{$dirname}/*.php") as $file) {
include_once $file;
}
}
If your files define classes, functions, constants etc. that are scope-independent, this will work as expected. However, if your file has variables, you have to "collect" them with get_defined_vars() and return them from the function. Otherwise, they'd be "lost" into the function scope, instead of being imported into the original scope.
If you need to import variables from files included within a function, you can:
function load_vars(string $path): array {
include_once $path;
unset($path);
return get_defined_vars();
}
This function, which you can combine with the import_folder, will return an array with all variables defined in the included file. If you want to load variables from multiple files, you can:
function import_folder_vars(string $dirname): array {
$vars = [];
foreach (glob("{$dirname}/*.php") as $file) {
// If you want to combine them into one array:
$vars = array_merge($vars, load_vars($file));
// If you want to group them by file:
// $vars[$file] = load_vars($file);
}
return $vars;
}
The above would, depending on your preference (comment/uncomment as necessary), return all variables defined in included files as a single array, or grouped by the files they were defined in.
On a final note: If all you need to do is load classes, it's a good idea to instead have them autoloaded on demand using spl_autoload_register. Using an autoloader assumes that you have structured your filesystem and named your classes and namespaces consistently.
Do no write a function() to include files in a directory. You may lose the variable scopes, and may have to use "global". Just loop on the files.
Also, you may run into difficulties when an included file has a class name that will extend to the other class defined in the other file - which is not yet included. So, be careful.