I would like to know how to create a php function that can be installed in php
just like the already built in functions like :
rename
copy
The main point I would like to achieve is a simple php function that can be called from ANY php page on the whole host without needing to have a php function within the php page / needing an include.
so simply I would like to create a function that will work like this :
location();
That without a given input string will output the current location of the file via echo etc
Well, there are a couple of options here. One of them is to actually extend the language by writing an extension. You'd have to muck around with the PHP source code, write it in C, and deal with the Zend Engine internally. You probably wouldn't be able to use this on a shared host and it would be quite time consuming and probably not worth it.
What I would do is put all of your functions into a separate PHP file, say helper_functions.php. Now, go into your php.ini and add the directive: auto_prepend_file = helper_functions.php. This file should be in one of the directories specified in your include_path (that's a php.ini directive too).
What this does is basically automatically put include 'helper_functions.php'; on every script. Each and every request will have these functions included, and you can use them globally.
Read more about auto_append_file.
As others have said, there's probably an easier, better way to do most things. But if you want to write an extension, try these links:
http://docstore.mik.ua/orelly/webprog/php/ch14_01.htm
http://www.tuxradar.com/practicalphp/2/3/0
So you want to extend PHP's core language to create a function called location(), written in C, which could be done in PHP by:
echo __FILE__;
Right. Have fun doing that.
Related
I have a PHP routing script, like this:
include_once('routing-functions.php');
// pathMatches was imported from routing-functions.php
if(pathMatches('/blog/*')){
include_once('actual-script.php');
}
The problem I have is the following: the functions and global variables from routing-functions.php could potentially conflict with the included file. Additionally, I don't want actual-script.php to have access to any of the variables of the router.
I am looking for a way to completely wipe the PHP context, so that the file is included as if it were directly requested, so doing the following is not an option because it changes the context/scope in which actual-script.php is executed:
if(pathMatches('/blog/*')){
function $sandbox(){
include_once('actual-script.php');
};
$sandbox();
}
Additionally, sending a local request to the file (e.g. with cURL) is also not an option, because it has a negative impact on performance and I want it to run as if it were under the /blog/ URL.
The problem is easy to solve with .htaccess, however, I need a dynamic solution that uses a PHP router.
If anyone has had a similar problem before or knows of a good solution it would be greatly appreciated.
Edit: I thought about a possible solution, but I made another question as it is very specific: see AJAX proxy with PHP, is it possible?
A couple of times I've encountered this problem...
I create sites that have a certain degree of modularity. So, it is possible that there are "components" (think of a rough CMS) which carry their own PHP code, CSS, and JavaScript, all dynamically included. Think about a structure like:
{siteroot}/component/datagrid/datagrid.php
{siteroot}/component/datagrid/js/datagrid.js
{siteroot}/component/datagrid/css/datagrid.css
{siteroot}/component/datagrid/ajax/getsomedata.php
Now, the question is: for JavaScript files, and expecially AJAX calls, how do I make them context-aware with the URLs?
For example, if in datagrid.js I want to call siteroot/component/datagrid/ajax/getsomedata.php with AJAX I should write (with JQuery):
$("#ajax").load("siteroot/component/datagrid/ajax/getsomedata.php");
First problem: siteroot changes on different installations. I've managed that by including a general
var codeBase = <? echo json_encode(Config::$siteRoot); ?>
with PHP on every page, from a Config file that can be easily edited for every installation, so I can do with whatever JavaScript something like:
$("#ajax").load(codeBase + "/component/Datagrid/ajax/getsomedata.php");
What do you think of this approach?
Second problem: but I have PHP functions that return to me also the components folder, or the folder of other components. It would be nice to make the whole URL dynamic. This would account also for changes in the structure of the component if I want.
The only solution I've found is to use a .js.php dynamic Javascript. This is very unelegant, and I have to include all the framework in the JavaScript file, like:
<?php
include "../../libs/framework.php"; // get my functions...
$myUrl = Config::$siteRoot . Framework::getComponentAjaxDir("datagrid") . "/getsomedata.php";
?>
$("#ajax").load(<?=json_encode($myUrl)?>);
Another side effect is that I have to know exactly the include the path for framework.php... I don't want this so hard-codedin my ".js.php" file.
Any smart solutions about that?
As nobody answered in a suitable way, I answer to myself to provide a solution I've found out that can be useful.
The key to my solution is simple:
I create an AJAX proxy at a fixed location in my site structure, so I can use codeBase to reference the proxy from JavaScript
I call this proxy with two parameters: plugin and action, which identify a) the plugin folder in which the "real" ajax is and b) the ajax file to use, along with the other params:
$("#...").load( codeBase + "/main/ajax.php?plugin=Datagrid&action=gettable&otherparams"...)
In ajax.php I sanitize the parameters, and use plugin and action to obtain the "real" ajax file:
{serverRoot}/components/{plugin}/ajax/{action}.php
Then i simply include that file in ajax.php
To be honest your problems are realistic options and aren't that bad practice in general quite frankly.
But let's explore this a little further.
What would be the best approach is for you to have 1 main config.php file which you can then specify modules, i.e. your datagrid etc.
You could store all modules in an array variable like so:
$_SITE_PATH = "/var/www/html/";
$_HTTP_PATH = "http://example.com/";
$_MODULES_PATH = $_SITE_PATH."modules/"
$_MODULES = array(
"datagrid"=>$_MODULES_PATH."datagrid/init.php",
"something_else"=>$_MODULES_PATH."something_else/init.php"
);
Each module would have it's own directory with instantiation init.php so that it would load all it required to get going.
This way you could code as you liked and when you needed something (preferably in the header state) do something like this.
global $_MODULES;
require_once($_MODULES["datagrid"]);
Everything will be easily available as and when required without any variable path issues later down the line.
From what I understand using something like require_once will essentially copy and paste the code from one file into another, as if it was in the first file originally.
Meaning if I was to do something like this it would be valid
foo.php
<?php
require_once("bar.php");
?>
bar.php
<?php
print "Hello World!"
?>
running php foo.php will just output "Hello World!"
Now my question is, if I include require_once inside a method, will the file that is included be loaded when the script is loaded, or only when the method is called?.
And if it is only when the method is called, is there any benefit performance wise. Or would it be the same as if I had kept all the code into one big file.
I'm mainly asking as I've created an API file, which handles a large amount of calls, and I wan't to simplify the file. (I know I can do this just be creating separate classes, but I thought this would be good to know)
(Sorry if this has already been asked, I wasn't sure what to search for)
It will only include when the method is called, but have you looked at autoloading?
1) Only when the method is called.
2) I would imagine there's an intangible benefit to loading on the fly so the PHP interpreter doesn't have to parse extra code if it's not being used.
I usually use the include('bar.php'); i use it for when i use databvase information, i have a file called database.php with login info and when the file loads it calls it right up. I don't need to call up the function. It may not be the most effective and efficient but it works for me. You can also use include_once... include basically does what you want it to, it copies the code essencially..
As others have mentioned, yes, it's included just-in-time.
However, watch out for variable definitions (require()ing from a method will only allow access to local variables in that method's scope).
Keep in mind you can also return values (i.e. strings) from the included file, as well as buffer output with ob_start() etc.
Heads up: I dont have the possibility to rename the classes or use name spaces for this.
Im looking for any crazy way to subvert class redeclaration issues in php. I actually only need 3 static variables from a web application, but the only way to get them requires including a file that declares a user class. However I already have a user class, so I get an error.
I tried to no avail to include the file in a class hoping it would isolate the included file - But no.
I tried reading an interface file I created that just echos the 3 values, but that actually just reads the php code and not the rendered values.
Is there anything like an opto-isolation system for code?
The only think I can think of is using ajax to do it, but it seems super sketchy. Is there a plain php version of this?
(Was a comment, but got too long.) Doesn't sound doable with your constraints. (You might need to show some code.) -- But if you are asking for a crazy way, and the option to rename the classes just applies to not editing the php script, then:
Load the include file into a variable, then transform it, and finally eval:
$source = file_get_contents("user.php");
$source = str_replace("class user", "class workaround_123", $source);
eval($source); // will give you a workaround_user instead of class conflict
Someone will probably comment on the advisability of eval... But it foremost depends on your code/situation if that's an applicable wacky workaround.
Alternatively you could invoke the user fetching code with a separate PHP process :
exec("QUERY_STRING=user=123 php-cgi user.php");
You could tokenize the whole file and go through it "by hand" to find the values you need.
Is it possible with PHP(5) or other Linux tools on an apache debian webserver to get the file requests a single http request made?
for performance reasons i would like to compare them with the cached "version" of my cake app.
non-cached that might be over 100 in some views.
cached only up to 10 (hopefully).
afaik there are 3 main file functions:
file_get_contents(), file() and the manual fopen() etc
but i cannot override them so i cannot place a logRequest() function in them.
is there any other way? attaching callbacks to functions? intercepting the file requests?
This suggestion does not seems intuitive, but you can take look on xdebug - function trace
Once you have xdebug installed and enabled, you can using all sort of configuration to save the profiling into a disk file and you can retrieve it later. Such as profiling results for different URL save into different disk file.
To monitoring file system related functions, you can do a parse of the text file(profiling results) and do a count of matchable functions (programmable or manually)
The way I would do it would be to create a custom function that wraps around the one you need.
function custom_file_get_contents($filename) {
$GLOBALS['file_get_contents_count']++;
return file_get_contents($filename);
}
And just replace all of your calls to file_get_contents with custom_file_get_contents. This is just a rudimentary example, but you get the idea.
Side note, if you want to count how many files your script has included (or required), see get_included_files()
You can use Xdebug to log all function calls
Those so-called "function traces" can be a help for when you are new to an application or when you are trying to figure out what exactly is going on when your application is running. The function traces can optionally also show the values of variables passed to the functions and methods, and also return values. In the default traces those two elements are not available.
http://www.xdebug.org/docs/execution_trace
Interesting question. I'd start with the stream_wrapper ... try to replace them with custom classes.
There is a pecl extention called ADB (Advanced PHP Debugger) that has tow functions that would be very useful for a cse like this - override_function() and rename_function(). You could do something like this:
rename_function('file_get_contents', 'file_get_contents_orig');
function file_get_contents($filename) {
logRequest();
return file_get_contents_orig($filename);
}
It looks like ADB is pretty easy to install, too.
See http://www.php.net/manual/en/book.apd.php