I understand that the question is rather hard to understand, I didn't know how to ask it better, so I'll use this code example to make things more clear:
If I have the following files:
test.php:
<?php
include('include.php');
echo myClass::myStaticFunction();
?>
include.php
<?php
__autoload($classname){
include_once("class/".$classname.".php"); //normally checking of included file would happen
}
?>
class/myClass.php
<?php
class myClass{
public static function myStaticFunction(){
//I want this to return test.php, or whatever the filename is of the file that is using this class
return SOMETHING;
}
?>
the magic FILE constant is not the correct one, it returns path/to/myClass.php
in case you need to get "test.php" see $_SERVER['SCRIPT_NAME']
I ended up using:
$file = basename(strtolower($_SERVER['SCRIPT_NAME']));
I am using
$arr = #debug_backtrace(false);
if (isset($arr))
foreach ($arr as $data)
{
if (isset($data['file']))
echo $data['file'];
// change it to needed depth
}
This way you don't need to modify the file from which your file is included. debug_backtrace might have some speed consenquencies.
Related
I got two files:
get_path.php:
function get_path() {
echo basename(__FILE__);
}
main.php
require("get_path.php");
get_path();
// This echos out "get_path.php", however i want it to echo out main.php
Does somebody know how to achieve this?
Thank you very much in advance!
Assuming that your function is as stated in the get_path.php file you can rewrite your function like this:
function get_path() {
$included_files = get_included_files();
foreach($included_files as $k=>$value){
if($value===__FILE__) return basename($included_files[$k-1]);
}
}
I use return but you can use echo and just after break; this return the file which directly include get_path.php but if you want the first level path.I mean the first file which include all the other files you can use :
function getFirstLevelPath(){
$included_files = get_included_files();
return basename($included_files[0]);
}
the output of your main will be now
:
main.php
This is how I include files in the index.php now:
<?php include('class.register.php');?>
<!--additional files starts-->
<?php include('register/register-form.php');?>
<?php include('register/browse.php');?>
<?php include('register/alldone.php');?>
<?php include('search/browse.php');?>
<?php include('search/mobile-left-column.php');?>
<?php include('profile/mygloopal.php');?>
<?php include('profile/profile.php');?>
<?php include('profile/details.php');?>
<?php include('profile/posts.php');?>
<?php include('profile/create_post.php');?>
<?php include('profile/browse-search.php');?>
<?php include('profile/review.php');?>
<?php include('how.php');?>
<?php include('search/more-options.php');?>
I'm referring to this tutorial to study autoload with namespaces:
http://www.zainabed.com/2014/11/php-tutorials-autoload-php-classes.html
But it uses classname to define a page. For my case above, no class required to include the files. How do I go about it, please?
The question is a bit unclear, so I will answer it as I understand it. If the files you have labelled as <!--additional files starts--> are not classes, or are classes but are not named whereby spl_autoload_register() is an option, I generally make a function or class to auto-include files for me. Here is just an example. It is indiscriminate, meaning it will load everything in the folder but you could pass a second param that is an array that tells it specifically what to load:
class AutoloadFiles
{
public function fInclude($dir = false)
{
// If the directory does not exist, just skip it
if(!is_dir($dir))
return $this;
// Scan the folder you want to include files from
$files = scandir($dir);
// If there are no files, just return
if(empty($files))
return false;
// Loop through the files found
foreach($files as $file) {
// Include the directory
$include = str_replace("//","/","{$dir}/{$file}");
// If the file is a php document, include it
if(is_file($include) && preg_match('/.*\.php$/',$include))
include_once($include);
}
// Return the method just so you can chain it.
return $this;
}
}
To use:
$iEngine = new AutoloadFiles();
$iEngine ->fInclude(__DIR__)
->fInclude(__DIR__.'/classes/')
->fInclude(__DIR__.'/functions/');
I have a file called test1.php with lots of variable and some function definitions. I am trying to include this file to one another file called test2.php and use the variables and the functions.
test1.php
$i = "a";
$ii = "b";
$iii = "c";
function test1a(){ return "lol"; }
test2.php
function test2a(){ include 'test1.php'; return $i; }
function test2b() { include 'test1.php'; return test2c(); }
function test2c(){ include 'test1.php'; return $iii; }
function test2d() { include 'test1.php'; return test1a(); }
index.php
include 'test2.php'
echo test2a();
echo test2b();
echo test2c();
echo test2d();
Reason:
I have the same code base in two different servers. Only the test2.php file will be different.Each server will have different values inside the test2.php but with same variable name. test2.php will act somewhat like a localization file.
My problem is some of the variables or not showing up. Is there a better way to do this. I don't want to include the file in every function.
Thanks.
Just do it the other way round:
put all the different variables into one file in to an array, without any functions:
//config.php
$config['setting1'] = "val1";
$config['setting2'] = "val2";
$config['setting3'] = 42;
...
and further:
//index.php
include_once("config.php");
echo $config['setting1'];
....
now you may have different configs on different servers w/o need to change any functions.
You are trying to include file with one function several times. Functions are always global. So second include gives you an fatal error Fatal error: Cannot redeclare test1a() (previously declared in [..]).
You should put this function to separate file and use include_once.
Is it possible to call only the specific function from another file without including whole file???
There may be another functions in the file and don't need to render other function.
The short answer is: no, you can't.
The long answers is: yes, if you use OOP.
Split your functions into different files. Say you are making a game with a hero:
Walk.php
function walk($distance,speed){
//walk code
}
Die.php
function die(){
//game over
}
Hero.php
include 'Walk.php';
include 'Die.php';
class Hero(){
//hero that can walk & can die
}
You may have other functions like makeWorld() that hero.php doesn't need, so you don't need to include it. This question has been asked a few times before: here & here.
One of the possible methods outlined before is through autoloading, which basically saves you from having to write a long list of includes at the top of each file.
In PHP it's not available to get only a little part of a file.
Maybe this is a ability to use only little parts of a file:
I have a class that calls "utilities". This I am using in my projects.
In my index.php
include("class.utilities.php")
$utilities = new utilities();
The file class.utilities.php
class utilities {
function __construct() {
}
public function thisIsTheFunction($a,$b)
{
$c = $a + $b;
return $c;
}
}
And then i can use the function
echo $utilities->thisIsTheFunction(3,4);
include a page lets say the function is GetPage and the variable is ID
<?php
require('page.php');
$id = ($_GET['id']);
if($id != '') {
getpage($id);
}
?>
now when you make the function
<?php
function getpage($id){
if ($id = ''){
//// Do something
}
else {
}
}
?>
I want to get the name of the file that includes another file from inside the included file.
I know there is the __FILE__ magic constant, but that doesn't help, since it returns the name of the included file, not the including one.
Is there any way to do this? Or is it impossible due to the way PHP is interpreted?
So this question is pretty old, but I was looking for the answer and after leaving here unsatisfied, I came across $_SERVER['SCRIPT_FILENAME']; Of course this works if the php file doing the including is a web page.
This gives you the full path of the "including file" on the server. eg /var/www/index.php. so if you want just the filename, eg index.php, you will need to use basename() eg
basename($_SERVER['SCRIPT_FILENAME']);
So, if in your index.php you have the following line:
<?php include("./somephp.php"); ?>
and in somephp.php you have
echo "this is the file that included me: " . basename($_SERVER['SCRIPT_FILENAME']);
you will get
this is the file that included me: index.php
output to the browser. This also works if the user is accessing your file without explicitly including the filename in the url, eg www.example.com instead of www.example.com/index.php.
Solution
Knowing that the functions used to include files are include, include_once, require and require_once, also knowing that they are reserved words in PHP, meaning that it will not be possible to declare user functions with the same name, and based on wedgwood's idea of using debug_backtrace you can actually work out from what file the include was called.
What we are going to do is iterate over the backtrace untill we find the most recent call to any of the four include functions, and the the file where it was called. The following code demostrate the technique:
function GetIncludingFile()
{
$file = false;
$backtrace = debug_backtrace();
$include_functions = array('include', 'include_once', 'require', 'require_once');
for ($index = 0; $index < count($backtrace); $index++)
{
$function = $backtrace[$index]['function'];
if (in_array($function, $include_functions))
{
$file = $backtrace[$index]['file'];
break;
}
}
return $file;
}
The above code will return the absolute path of the file where the last include happened, if there hasn't been any include it will return false. Note that the file may has been include from a file that was included from another file, the above function only works for the deepest include.
With a simple modification, you can also get the last included file:
function GetIncludedFile()
{
$file = false;
$backtrace = debug_backtrace();
$include_functions = array('include', 'include_once', 'require', 'require_once');
for ($index = 0; $index < count($backtrace); $index++)
{
$function = $backtrace[$index]['function'];
if (in_array($function, $include_functions))
{
$file = $backtrace[$index - 1]['file'];
break;
}
}
return $file;
}
Observations
Note that __FILE__ is not the included file, but the current file. For example:
file A.php:
<?php
function callme()
{
echo __FILE__;
}
?>
file B.php:
<?php
include('A.php');
callme();
?>
file index.php:
<?php
include('B.php');
?>
In the above example, in the context of the file B.php the included file is B.php (and the including file is index.php) but the output of the function callme is the path of A.php because __FILE__ is in A.php.
Also note that $_SERVER['SCRIPT_FILENAME'] will give the the absolute path to the script requested by the client. If $_SERVER['SCRIPT_FILENAME'] == __FILE__ it means that the current file is the requested one, and therefore there probably hasn't been any includes...
The above method checks if the current file is the requested one, but not if it hasn't been included (below is an example of how the requested file can be included). An actual solution to check if there has not been any inclusions could be to check count(get_included_files()) == 1.
The requested file can be an included file in the following way:
file x.php
<?php
$var = 'something';
include('index.php');
?>
file index.php
<?php
if (!isset($var))
{
include('x.php');
exit;
}
echo 'something';
?>
In the above example, the file index.php will include x.php, then x.php will include index.php back, afterwards index.php outputs "something" and returns control to x.php, x.php returns control to index.php and it reaches exit;
This shows that even if index.php was the requested script, it was also included from another script.
I can't find the easy way to cover this.
But If the including one is really important to you, you could hack it with some global variable and your own include function.
e.g.
<?php
$g_including_files = array();
function my_include($file) {
$bt = debug_backtrace();
global $g_including_files;
$g_including_files[basename($file)] = $bt[0]['file'];
return include($file);
}
May that be helpful for you :)
This is actually just a special case of what PHP templating engines do. Consider having this function:
function ScopedInclude($file, $params = array())
{
extract($params);
include $file;
}
Then A.php can include C.php like this:
<?php
// A.php
ScopedInclude('C.php', array('includerFile' => __FILE__));
Additionally, B.php can include C.php the same way without trouble.
<?php
// B.php
ScopedInclude('C.php', array('includerFile' => __FILE__));
C.php can know its includer by looking in the $params array.
<?php
// C.php
echo $includerFile;