I am wondering what is the best practice for including class specific exception files.
Say we have an init exception that extends base exception that extends Exception. Should these exceptions be included in global application scope or at the top of the class files they can throw from with include_once?
I know both methods work, but for testing it seems having the file included at the top would be easier as the dependency would be included with the class file.
They should only be included with the module that they are attached to. It doesn't make much sense to throw an exception for a module that isn't loaded. So when you load the module, load the exceptions as well. This can done in the module init code or simply including the file on top of the main module file.
Related
In my current lib, I have classes with static code outside the class definition, that I would like to execute when browsing a index.php file that has autoloading (with properly putting the class files into a PSR-4 folder structure, and calling composer install before).
It's not such a bad deal. For instance, in my custom Error.php class I could for instance call set_error_handler function outside the class so warnings could be catchable. And putting this file in a PSR-4 autoloading could ease the pain for not having to call any Error.php code in index.php to enable this catching. Every source that just uses my namespace and autoloads my lib would have that for granted.
I tried to include use \MyNamespace\Error; in the index.php file, but the code in Error.php, outside the Error class definition, isn't automatically executed.
The code outside the class is only executed when I call a class method inside my index.php file (the one that has the autoloading).
Can this be done ? Thanks for your time.
use \MyNamespace\Error; does not trigger autoloading, it just allows you to use shorter class name in code - new Error() instead of new \MyNamespace\Error(). If you want to include Error.php file, you need to use this class. Probably the safest way would to use class_exist():
class_exists(Error::class);
But honestly you should rethink your design, implicit registering error handler in file with class declaration is against PSR-1 and may be really annoying in big project.
Files SHOULD either declare symbols (classes, functions, constants, etc.) or cause side-effects (e.g. generate output, change .ini settings, etc.) but SHOULD NOT do both
https://www.php-fig.org/psr/psr-1/#23-side-effects
It would be less magical if you create separate method for registering error handler and call it explicitly in index.php:
Error::registerErrorHandler();
I am trying to implement autoloading of my classes. I separate my classes into two different folders:
/classes
/external
In my external folder, I keep everything third-party that I am using within my application. It may include classes, functions, etc. I like to keep that separate from my own code.
I want to include everything in the external directory manually. I only want files in the classes directory to be autoloaded. Here is what I have:
Files:
/classes/cache.class.php
/classes/db.class.php
/classes.mail.class.php
/external/hooks.php
And to autoload:
spl_autoload_register(function ($class_name) {
include dirname(__FILE__).'/classes/'.$class_name.'.class.php';
});
$Cache = new cache();
$Db = new db();
$Mail = new mail();
Somehow, this is attempting to load any class that exists in the external directory. I know this because in hooks.php I have:
class Hooks { ... } // Notice the capital H
And I am getting the error:
"Warning: include(/path/to/classes/Hooks.class.php): failed to open stream: No such file or directory"
How can I get spl_autoload_register to ignore all classes that exist outside of the classes directory?
The autoloader has no way of knowing in which folder a class is defined. The general flow is:
See an undefined class being used in the code being executed
Call all the functions registered with the spl_autoloader, and pass them the undefined class name
Since you didn't have any check for if the file exists, the autoloader function you registered is erroring out whenever you fail to include a non-autoloaded class before it's used. As #Forbs mentioned in his answer, just add a check in your autoloader function to see if the file exists before including the source file.
It's worth noting that Composer does this job for you very well already - unless you have some specific reason for wanting to use your own autoloader, I'd suggest just setting up composer for your project.
https://getcomposer.org/doc/00-intro.md
add this
if (file_exists(dirname(__FILE__).'/classes/.$class_name.'.class.php'))
right before your include
How to avoid "Cannot redeclare class" fatal error when two modules use the same class name in prestashop?
For example, I have module which declares and uses a helper class Foo.
I install a new module which has a different helper class but with the same name Foo. So that causes "Cannot redeclare class" fatal error when I go to modules page. I cannot even uninstall that new module.
When creating modules that use custom classes / object models, you need to namespace them. In PrestaShop you cannot use PHP's namespace feature (because the PrestaShop core is not adapted to work with it), but you can do it the old way by prefixing your class name. For example:
// Your module:
class MyModule extends Module
// Your custom ObjectModel:
class Message extends ObjectModel
Class name Message is very generic and will mostly like come to conflict with some other module that has poorly chosen to name it's classes.
To prevent this, you must prefix your class names:
class MM_Message extends ObjectModel
In this case MM_ is short for MyModule. This is much less likely to conflict with other modules or classes. Event a better way would be to prefix the whole module name:
class MyModule_Message extends ObjectModule
Also, name your database table according: ps_my_module_message. This also makes easy to navigate the database table. Prefixing class names is very good practice, in fact, I do it all the time. The downside might be longer class names.
P.S If you want to uninstall a module that is conflicting, you need to temporarily disable on of them. A good way would to temporarily rename the module folder to something else (folder of the module that you want to leave), then uninstall the other module. After that, restore the original folder name. Renaming module folder will prevent it from loading.
Technically your could try to disable it in back-office, if it's not loaded in BO
Well you'll have to edit one of those two modules and change its class declaration and every occurrence of that class in its other php files.
In the next version of Prestashop (1.7) the notion of namespaces will be introduced with the use of Symfony 2 Framework.
I have few PHP classes and files that I want to include in Joomla so that I can call those classes. I tried doing require_once config.php to include a PHP file which also includes all the classes that I would want to use in Joomla.
But each time I execute the page I receive the error below:
Fatal error: Class 'SomeClassName' not found
is there any other way to include external PHP classes or files in Joomla?
Thanks in advance!
Please use Joomla autoloader. Is better.
<?php
// Register an adhoc class.
JLoader::register('AdhocClass', '/the/path/adhoc.php');
// Register a custom class to override as core class.
// This must be done before the core class is loaded.
JLoader::register('JDatabase', '/custom/path/database_driver.php', true);
Edit:
Load classes with autoload instead of require/include have a better performance, because PHP will only read (require access to the disk) and compile (require memory and CPU usage) if you really use your class.
To do the same with require/include you have to be sure to only use if will really use the class.
Source:
http://developer.joomla.org/manual/ch01s04.html
require_once should work just fine within Joomla. Make sure the class you want to use is really loaded within your file, and the file is properly referenced in the require_once. Something is going wrong there and it has nothing to do with Joomla itself :-)
I am currently refactoring a project which has been halfheartedly ported to Yii. There are some classes in the components folder which are included in a controller with the PHP "use"-keyword. This gives me a "include(protected/components/classes/SClass.php): failed to open stream: No such file or directory" error though.
What's really strange about it is, that changing the name (used by "use") to a non-existent file gives me a fatal error. Any ideas?
The use keyword by itself in PHP does not do any including of other files. It merely tells PHP that the namespace defined in the use statement may be referenced by code further down in the current PHP file.
However, what is likely happening here is that your system has an autoload function defined. If there is an autoload function, PHP will call this function whenever it encounters a class name that it doesn't recognise. The autoload function searches for the class file to load and includes it if it can find it. This is probably where your errors are occurring.
In the first case, this is the sequence of events:
the use statement is referencing a valid namespace, but this is ignored until a class in that namespace is referenced in the code.
When the class is referenced, PHP says "I don't know this class yet, lets autoload it".
The autoloader function is run, and builds a path to include. This usually comes from the namespace and classname of the class, but can be whatever the autoload function is written to expect.
In this case, it sounds like the autoloader is building the path and running include() on that path, but the class doesn't exist where the autoloader expects. Hence the "file not found" error.
In the second case, where you change the use statement:
The use statement now references a different namespace, but you probably haven't changed the code later in the program that actually references the class.
The program reaches the code that calls the class, but it doesn't recognise the namespace because it doesn't match the use statement any more, so instant fatal error.
You might want to check the file ownership and permissions, and check for PHP security as is mentioned HERE