I have a PHP script that registers approximately 20 functions. Ideally it'd be loaded with require_once. I want make it so that even if somehow it does get loaded more than once, it wouldn't try to re-register the functions. I could wrap each declaration in !function_exists, but I'm wondering if there's a faster way. (Or do you think 20 calls to !function_exists is negligible?) I tried using exit but that causes an error. Is it possible to exit w/o throwing an error ?
if ( /* already loaded */ ) {
/* leave gracefully */
}
/* declare ~20 functions */
if (!defined('ALREADY_LOADED')) {
define('ALREADY_LOADED', true);
// rest of your code goes here
}
This checks to see if a constant ALREADY_LOADED is defined, and if it is not, it defines the constant and will do whatever else you want.
After it's been run once, the constant will be defined, and it will not run a second time.
I suggest using a more descriptive constant name than ALREADY_LOADED.
I think using OOP is the most practical way
Can be used as a class with static functions
class SimleClass{
public static function func1($arg){...}
}
use it
SimpeClass::func1($arg);
or sigleton
class SimleClass{
protected static $_instance=null;
private function __construct(){...}
public static function getInstance(){
if(is_null(self::$_instance)
self::$_instance=new SimpleClass();
return self::$_instance;
}
public function func1($arg){...}
}
use it
SimpleClass::getInstance()->func1($arg);
and how to connect it think itself
can use include_once
and can implement the autoloader class
function myClassLoader($className){
include_once "/lib/$className.php";
}
spl_autoload_register(myClassLoader);
=============================================================
for more concrete answer requires more data.
Perhaps your application, you can rearrange to get the more logical structure
If you as an author don't require it more then once, (or use require_once() consistantly) there shouldn't be a problem about re-registering functions.
As for exiting without an error, try die().
I would try not to redeclare functions in first step (here require more than once).
Doing 20x function_exists() does not cost anything, only some time writing and wrapping ;)
Perhaps you could try to use classes/methods instead.
function_exists is no bad.
You can write your php script files in the following manner.
/* file1.php */
if(!defined('FILE1')) {
define('FILE1', 1);
/////////////////////////
// PUT file contents here.
/////////////////////////
}// file.php finished.
Now you can include this file as many time as you want here and there. Nothing will be redefined again.
Related
I have a PHP file in which, on the top I create a file handle using fopen(). Then then file has a couple of classes, in the functions of which I write stuff to this text file. And ultimately, in the end, i.e. when I am done writing stuff to this file, I have to close this file handle using fclose().
The flow of control is such that, in the following pseudo-code, the function a_b() of class A is called LAST OF ALL in this PHP script. So, naturally, in the end of the body of a_b(), I decided to write fclose($fileHandle);.
BUT I got an ERROR: Notice: Undefined variable: fileHandle in C:\xampp\htdocs\Tests\Test.php on line 15
The question is why? Where should I write the statement fclose($fileHandle)? Should I write it at the very end of the file?
<?php
$fileHandle = fopen($pathToFileHandle, "a");
class A {
function a_a() {
...
fwrite($fileHandle, "blahBlahBlah");
}
function a_b() {
...
fwrite($fileHandle, "Whatever");
...
fclose($fileHandle);
}
}
class L {
function l_a() {
...
fwrite($fileHandle, "Some text");
...
}
}
?>
Having inline code (i.e. code which does something rather code which defines something to be invoked later) mixed up in the same file, is considered a bad thing - not least because it gives rise to the kind of problem you describe here.
You don't need to explicitly close a file handle - PHP will do this automatically when the script exits.
If you want to do more than just close the file, an alternative to explicitly invoking the close in your thread of execution is to ask PHP to call a function when the script finishes executing (note that a callback can also be an object - i.e. with associated data).
As Renee points out, your issue arises from scope. However its also bad design to split the file operations across two different classes and the procedural side effect. Use a single class to define all the file operations (open, close, read, write). Then pass a reference to that class to other classes which will supply or require data to/from the file.
Undefined variable: fileHandle in C:\xampp\htdocs\Tests\Test.php on line 15
PHP functions cannot access global variables by default. So:
$value = 'hello world';
class A {
public function b () {
return $value;
}
}
…does not work—$value is unavailable in the function.
Use the global keyword to make global variables available inside a function:
$value = 'hello world';
class A {
public function b () {
global $value;
return $value;
}
}
But, as commenters suggested, if possible it is better to keep the $fileHandle variable in the class that uses it and to close the handle as soon as possible.
I have a PHP class that needs some pre-defined globals before the file is included:
File: includes/Product.inc.php
if (class_exists('Product')) {
return;
}
// This class requires some predefined globals
if ( !isset($gLogger) || !isset($db) || !isset($glob) ) {
return;
}
class Product
{
...
}
The above is included in other PHP files that need to use Product using require_once. Anyone who wants to use Product must however ensure those globals are available, at least that's the idea.
I recently debugged an issue in a function within the Product class which was caused because $gLogger was null. The code requiring the above Product.inc.php had not bothered to create the $gLogger. So The question is how was this class ever included if $gLogger was null?
I tried to debug the code (xdebug in NetBeans), put a breakpoint at the start of Product.inc.php to find out and every time it came to the if (class_exists('Product')) clause it would simply step in and return thus never getting to the global checks. So how was it ever included the first time?
This is PHP 5.1+ running under MAMP (Apache/MySQL). I don't have any auto loaders defined.
Thanks for the informative answers guys. My belief was that when you
include a file PHP starts executing it line by line from line one, so
it would not allow me to include the file if the globals were not
defined. I will move the checks into the constructor. Based on the
original question, I accept the answer from #deceze
The file is parsed before it is executed. Classes are "loaded" by parsing, but functions are executed after the parsing. By putting the function call in the same file as the class, the class is always parsed and "loaded" before that function executes, thereby it's always true.
If you are always including the file using require_once (which is good), there's no point in that check anyway. A class definition shouldn't conditionally depend on some global variables. Rethink what you're doing here.
I see a main issue here:
// This class requires some predefined globals
That might be surprising to you, but I think what you actually want to do is, that if that is the case, you don't check that when you define the class, but when you instantiate it.
When a class is instantiated, it's constructor function is called. This seems like the perfect place to me to check for that:
class Product
{
public function __construct() {
// This class requires some predefined globals
$this->needGlobal('gLogger', 'db', 'glob');
}
private function needGlobal() {
foreach (func_get_args() as $global) {
if (!isset($GLOBALS[$global])) {
throw new RuntimeException(sprintf('Global %s needed but not set.', $global));
}
}
}
...
}
When you instantiate a Product it then automatically checks if the preconditions are met:
$blueShoes = new Product();
This will not work if the pre-conditions are not met, but it will work if.
But that is only partially solving your problem. The real problem with your code is that the Product needs global variables to work.
Instead make the product just take the things it needs to work with:
class Product
{
private $gLogger;
private $db;
private $glob;
public function __construct(LoggerInterface $gLogger, DbInterface $db, GlobInterface $glob) {
$this->gLogger = $gLogger;
$this->db = $db;
$this->glob = $glob;
}
...
}
Usage:
$redShoes = new Product($gLogger, $db, $glob);
And then you don't need to care about anything global inside Product any longer.
You commented you want to gradually improve the code. You can do so, here is how. As written the second variant above is the way to go, but currently the legacy code is not compatible with it. In any case if the Product class is new code, you should write it with dependency injection. This is important to separate the legacy code from the new code. You don't want to have the legacy stuff swallowed by your new code. That would make new code legacy code, so you would not be able to gradually improve. You would just add new legacy code.
So take the class definition with the dependency injection. For your legacy needs write a second class that is shielding this:
class ProductLegacy extends Product
{
public function __construct() {
// This class requires some predefined globals
list($gLogger, $db, $glob) = $this->needGlobal('gLogger', 'db', 'glob');
parent::__construct($gLogger, $db, $glob);
}
private function needGlobal() {
$variables = array();
foreach (func_get_args() as $global) {
if (!isset($GLOBALS[$global])) {
throw new RuntimeException(sprintf('Global %s needed but not set.', $global));
}
$variables[] = $GLOBALS[$global];
}
return $variables;
}
}
As you can see, this little stub brings together the global way of doing things with the new way. You can use the Product class in your new code, and if you need to interface with old code, you use the ProductLegacy class that works with the global variables for class instantiation.
You could also create a helper function that is doing this, so you can use it for different classes. Depends a bit on your needs. Just find a border where you can draw a clear line between old code and new code.
EDIT: Sorry guys, it was a typo =(
I feel embarrassed for wasting your time on this. I'm leaving this thread open in hopes that someone might find the discussed information useful.
To clarify further, the code below will work as expected, I mistyped 'classHandler' in my code, and that's the reason PHP couldn't find it.
Also, the syntax errors noted by some commenters have been corrected
I feel obligated to summarize the discussion on this thread:
#wimvds suggests using inheritance and that my implementation is not a good practice.
#Victor Nicollet disagrees saying extending the behavior of an existing instance is 1. impossible and 2. bad design
#ircmaxell adds: Remember, you should always favor composition over inheritance. And this isn't spaghetti code, it's a pretty standard method of implementing a stripped down notification system (You could build a full blown observer or mediator pattern, but for really simple tasks, this may be a whole lot better since it's easier to maintain).
#Victor asks for a minimal one file example returning this error. This is what helped me solve the issue. When I tried the sample file, it work perfectly leading me to believe that something else indeed was wrong.
#Shakti Singh suggests trying call_user_func( array( $this, $this->handler ), $var);
#Victor Nicollet responds saying This would attempt to call a member function $this->classHandler (which probably doesn't exist) instead of the global classHandler
#abesto gives it a shot, ends up with a very similar implementation as my own, which works without my typo.
#Victor Nicollet answers by claiming that the classHandler needs to be defined prior to the call.
#Blizz responds by saying that PHP parses classes and functions first and then the regular code.
MyClass.php ( singleton )
public $handler;
public function myMethod()
{
$var = "test";
call_user_func( $this->handler, $var );
// PHP Warning: First argument is expected to be a valid callback
}
Script.php
$myClass = new MyClass;
$myClass->handler = "classHandler";
$myClass->myMethod();
function classHandler( $var )
{
echo $var;
}
If this is incorrect, what is the commonly practiced means of invoking handlers / event handlers in php?
Note that this is a simplified version of the actual script
You have to call something like this
call_user_func( array( $this, $this->handler ), $var);
Read your Script.php code again. What it's doing is:
Instantiate MyClass (I'm assuming you forgot the new here).
Define the handler to be classHandler.
Run myMethod(), which attempts to call classHandler.
Define classHandler.
Obviously, if you run 3 before you run 4, it's not going to work. You must define the function first, and then run any code that might want to call it.
In the larger scheme of things, I suspect there is no file like Script.php, and instead file A defines the class, file B instantiates the class and runs myMethodand file C defines classHandler. In such a situation, you need to make sure that file C is loaded before B is run.
First of all: if by storing functions as strings you mean that the actual implementation is in the string, then this is bad practice. You don't have to do it to get what you want.
function afun($param) {}
class BClass { function bfun($param) {} }
call_user_func('afun', 'param'); // Calls function afun
$binstance = new BClass();
call_user_func(array($binstance, 'bfun'), 'param'); // Calls bfun on binstance
// Update according to comment
class CClass {
private $handler;
public function __construct($handler) { $this->handler = $handler; }
public foo() {
// do stuff
call_user_func($this->handler, 'param');
}
}
$cinstance = new CClass('afun');
$cinstance->foo();
Is there a way to determine the scope in which a function is called from inside the function itself? (Or method; I'll use function to mean either in the remainder of the post.)
What I do not want is to have to pass __FILE__ or __CLASS__ constants into the function. This information is available in stack traces, etc. so I know it's floating around somewhere, but I'd like to know how to introspect it at runtime without throwing exceptions.
If there are any performance particularities for a solution, I'd like to know about those as well.
There are two use-cases I'm interested in.
Determine which file / line / function called my function
Determine the class type that originated the function call
Basically what I want is this:
class util
{
public static function checkScope()
{
echo $magic_scope_stuff;
}
public static function blah()
{
util::checkScope();
}
}
util::checkScope(); // main, line 14
util::blah(); // class util, line 9
There's debug_backtrace() for that.
The resulting array gives you a call trace from the entry point until the invocation of debug_backtrace.
Please give me some real life examples when you had to use __destruct in your classes.
Ok, since my last answer apparently didn't hit the mark, let me try this again. There are plenty of resources and examples on the internet for this topic. Doing a bit of searching and browsing other framework's code and you'll see some pretty good examples...
Don't forget that just because PHP will close resources on termination for you doesn't mean that it's bad to explictly close them when you no longer need them (or good to not close them)... It depends on the use case (is it being used right up to the end, or is there one call early on and then not needed again for the rest of execution)...
Now, we know that __destruct is called when the object is destroyed. Logically, what happens if the object is destroyed? Well, it means it's no longer available. So if it has resources open, doesn't it make sense to close those resources as it's being destroyed? Sure, in the average web page, the page is going to terminate shortly after, so letting PHP close them usually isn't terrible. However, what happens if for some reason the script is long-running? Then you have a resource leak. So why not just close everything when you no longer need it (or considering the scope of the destructor, when it's no longer available)?
Here's some examples in real world frameworks:
Lithium's lithium\net\Socket class
Kohana's Memcached Driver
Joomla's FTP Implementation
Zend Frameworks's SMTP Mail Transport Class
CodeIgniter's TTemplate Class
A Tidy Filter Helper for Cake
A Google-Groups Thread about using Destructors For the Symfony Session Class
The interesting thing is that Kohana keeps track of the tags, so that it can delete by "namespace" later (instead of just clearing the cache). So it uses the destructor to flush those changes to the hard storage.
The CodeIgniter class also does something interesting in that it adds debugging output to the output stream in the destructor. I'm not saying this is good, but it's an example of yet another use...
I personally use destructors whenever I have long running processes on my master controller. In the constructor, I check for a pid file. If that file exists (And its process is still running), I throw an exception. If not, I create a file with the current processes id. Then, in the destructor I remove that file. So it's more about cleaning up after itself than just freeing resources...
There is another handy use to generate HTML page
class HTMLgenerator {
function __construct() {
echo "<html><body>";
}
function __destruct() {
echo "</body></html>";
}
}
With this class, you can write
$html = new HTMLgenerator();
echo "Hello, world!";
And the result is
<html><body>Hello, world!</body></html>
For example:
<?php
class Session
{
protected $data = array();
public function __construct()
{
// load session data from database or file
}
// get and set functions
public function __destruct()
{
// store session data in database or file
}
};
This is a good why to use destruct. You prevents reading and writing to a session source all the time and do this only at the start and at the end.
I create a php page what will generate a movie information jpg file. This page will have to gather a few information and run inkscape to convert template (an svg file) to a png before converting to jpg. The svg contain relative links to other image which must be a file. So my page download necessary files into a temporary folder, convert the svg file. At the end, the temporary folder must be deleted.
I put the temporary folder deletion into the destructor. Before there can be many reason the page ends unexpected and the only think I can be sure is that destructor will be call when page exit.
Hope this helps.
A destructor is extremely useful if you use a custom database connector/wrapper.
In the constructor, you can pass the connection information. Because you can use a destructor (rather than a finalizer, etc.,) you can rely on that to close the connection for you. It's more of a convenience, but it certainly is useful.
For example, when PHP decides to explicitly "free" the object (i.e., it is no longer used,) it will call the destructor at that time. This is more useful in the scenario I describe as you're not waiting for the garbage collector to run and call the finalizer.
$0.02
Ian
<?php
class Database
{
private $connection;
private $cache = array();
function __construct([$params])
{
//Connection here
}
//Query
public function query(Query $Query)
{
if($this->is_cached($Query->checksum))
{
return $this->get_cache($Query->checksum);
}
//...
}
public function __destruct()
{
unset($this->connection);
$this->WriteCache();
unset($this->cache);
shutdown_log($this,'Destruction Completed');
}
}
?>
theres an example that should make you understand.
If you use handles returned by fopen() for say, logging, you can use __destruct() to make sure fclose() is called on our resources when your class is destroyed.
You are right, __destruct is mostly unnecessary for the short running php scripts. Database connections, file handles and so on close on script exit or sometimes even earlier if variables run out of scope.
One example i can think of is writing logs to the database. Since we didn't want to fire one query per log entry that gets created somewhere in the script we wrote the "write to db" part in the __destruct of the logging class so when the script ends everything gets inserted into the database at one.
Another example: If you allow a user to upload files the destructor is sometimes a nice places to delete the temp file (in case something goes wrong in the script it at least get cleaned up)
But even for filehandles it can be useful. I've worked on a application that did use the old fopen etc. calls wrapped in objects and when using those on large filetrees php would run out of filehandles sooner or later, so cleaning up while the script was running was not only nice but necessary.
I use APC caching for large numbers of "low level" objects, that otherwise would use excessive memory; and I have a cacheCollection object that handles the reading and writing of those "low level" objects to and from APC during execution of the script. When the script terminates, the objects must be cleared down from APC, so I use the cacheCollection __destruct method to perform that function.
I have used __destruct() in a logging class that wrapped a database connection:
<?php
class anyWrap
{
private $obj,$calls,$log,$hooks;
function anyWrap($obj, $logfile = NULL)
{
if(is_null($logfile))
{
$this->log = dirname(__FILE__) . "/../logs/wrapLog.txt";
}
$this->hooks = array();
$this->dbCalls = 0;
$this->obj = $obj;
}
public function __set($attri, $val) {
$this->obj->$attri = $val;
}
public function __get($attri) {
return $this->obj->$attri;
}
public function __hook($method)
{
$this->hooks[] = $method;
}
public function __call($name,$args)
{
$this->calls++;
if(in_array($name,$this->hooks))
{
file_put_contents($this->log,var_export($args,TRUE)."\r\n",FILE_APPEND);
}
return call_user_func_array(array($this->obj,$name),$args);
}
//On destruction log diagnostics
public function __destruct()
{
unset($this->dbReal);
file_put_contents($this->log,$this->calls."\r\n",FILE_APPEND);
}
}
The script hooks into the database calls and logs the prepare statements, then when the script has run to an end (I don't always know when) it will finally log the number of calls to the database to the file. This way I can see how many times certain functions has been called on the database and plan my optimization accordingly.
If you are creating a view using a PHP script in a MySQL database, you must drop that view at the end of the script. Because if not, the next time that script is executed view will not be created, as there is already a view of similar name in the database. For this purpose you can use destructor.
Here's a rather unusual use case for destructors that I think libraries such as pest are using to combine method chaining with functions or in other words, to achieve fluent interface for functions, Which goes like this:
<?php
class TestCase {
private $message;
private $closure;
private $endingMessage;
public function __construct($message, $closure) {
$this->message = $message;
$this->closure = $closure;
}
public function addEndingMessage($message) {
$this->endingMessage = $message;
return $this;
}
private function getClosure() {
return $this->closure;
}
public function __destruct() {
echo $this->message . ' - ';
$this->getClosure()();
echo $this->endingMessage ? ' - ' . $this->endingMessage : '';
echo "\r\n";
}
}
function it($message, $closure) {
return new TestCase($message, $closure);
}
it('ok nice', function() {
echo 'what to do next?';
});//outputs: ok nice - what to do next?
it('ok fine', function() {
echo 'what should I do?';
})->addEndingMessage('THE END');//outputs: ok fine - what should I do? - THE END