I'm searching for following issue i have.
The class file names of our project are named logon.class.php
But the interface file for that class is named logon.interface.php
My issue i have is that when the autoload method runs I should be able to detect if it is a class call or an interface call.
<?php
function __autoload($name){
if($name === is_class){
include_once($name.'class.php');
}elseif ($name === is_interface){
include_once($name.'interface.php');
}
}
?>
You can use ReflectionClass::isInterface to determine if the class is an interface.
$reflection = new ReflectionClass($name);
if ($reflection->isInterface()){
//Is an interface
}else{
//Not an interface
}
In your case, you would probably have to use file_exist first on $name.interface.php and $name.class.php to determine if they exist, require the one that exists, then check if it's an interface.
However, my opinion is that this might cause problems down the track. What if you have MyClass.class.php and MyClass.interface.php?
You should have some naming conventions for your classes and interfaces e.g. your class name is logon and interface name logon_interface, then you can easily differentiate between the two. For example, explode $name by underscore and check if last element is interface.
To avoid class name clashes you can use namespaces. Check The PSR-0 specifications.
Also check this post. If you read the contents of the file before including it, you can tokenize it and figure if the file contains an Interface or a class, without actually loading the class/interface. Keep in mind that interfaces and classes can't have the same name
Note: Using this method you can actually change the name of the interface at runtime (before loading the class, although that does seem very good practice)
Related
As I looked for the new PHP7-features I stumbled upon anonymous classes.
I didn't understand when they should become useful, and looked for an example.
I read this article, but I don't see the benefits of this feature.
In the last section before the conclusion they wrote the following about the advantages:
One advantage is that we no longer need the named extension. Normally the named extension would be hidden away in some included file, if you ever needed to see how it is defined you have to start searching for it. With anonymous classes the definition is in the same place the object is created.
On the other hand, I see a big disadvantage because you can use this anonymous class only at the place it is defined.
Can someone please explain when this feature is useful?
Especially if it can help when building custom systems or extending a CMS like WordPress (preferably in German, although English is also welcome).
Anonymous classes could be useful in writing implementation classes for listener interfaces, so you don't need to create a file or a generic class just to implement once.
One of the most elegant things about anonymous classes is that they
allow you to define a one-shot class exactly where it is needed. In
addition, anonymous classes have a succinct syntax that reduces
clutter in your code. Java in a nutshell
So, you can have an anonymous implementation of an interface or even extend a class, with additional properties or overwritten methods.
Example:
return new class(10) extends SomeClass implements SomeInterface {
private $num;
public function __construct($num)
{
$this->num = $num;
}
};
Another situation:
Provide a simple implementation of an adapter class. An adapter class is one that defines code that is invoked by some other object. Take, for example, the list() method on a class called File. This method lists the files in a directory. Before it returns the list, though, it passes the name of each file to a FilenameFilter object you must supply. This FilenameFilter object accepts or rejects each file. When you implement the FilenameFilter interface, you are defining an adapter class for use with the $file->list() method. Since the body of such a class is typically quite short, it is easy to define an adapter class as an anonymous class.
$file = new File("/src");
// Now call the list() method with a single FilenameFilter argument
// Define and instantiate an anonymous implementation of FilenameFilter
// as part of the method invocation expression.
$filelist = $file->list(new class extends FilenameFilterClass {
public function accept(File $f, string $otherInfo) {
return pathinfo($f, PATHINFO_EXTENSION) === ".php";
}
});
Some nice basic understanding and use about anonymous classes could be found on Java (I know its not PHP, but it helps on understanding) examples at https://www.geeksforgeeks.org/anonymous-inner-class-java/
I should use a anonymous class only if this class is not used anywhere else and if these class isn't changed since the first coding.
So for example a database class could maybe a candidate for using a anonymous class because it should be use only once and could be included in any other php file. In most cases the data for accessing the database is in the config file. Therefore this file should be loaded for every php file that is using the database when you want to avoid the hard coding of the database params (which is a bad idea). If you coded these class as an anonymous class in the config file you have eliminated one include whithout losing the maintainance.
I've seen a bunch of examples using PSR to do autoloading with namespaces. Maybe this is a dumb question, but why isn't this bad practice? Doesn't that defeat the purpose of having namespaces?
For example, say you have two libraries, FormBuilder and MySweetForms, and both have a Form class. Locations are at:
lib/FormBuilder/Core/Form.php and lib/MySweetForms/Form.php
If you autoload based on the namespaces those Form classes are in, aren't you going to run into the exact problem that namespaces are meant to prevent: ambiguous identifiers of classes and methods?
Won't it fail when you successfully locate another class in the MySweetForms namespace, say AjaxFileField, that relies on \MySweetForms\Form, but it finds the FormBuilder's implementation of the Form class?
Because of namespaces, the autoloading won't find the FormBuilder's implementation of the Form class when it's looking for the MySweetForms implementation, provided the autoloader and the two libraries follow best (or close to best) practices and are implemented correctly.
If the MySweetForms/AjaxFileField.php file defines a class inside the MySweetForms namespace as shown:
namespace MySweetForms;
class AjaxFileField
{
public function doFormStuff()
{
$form = new Form();
}
}
Then the reference to the Form class inside AjaxFileField is really a short-hand for the fully qualified class name MySweetForms\Form.
When the autoloader is invoked to load the class, it will be asked to load the class based on it's fully qualified name. A PSR-0 autoloader would translate the MySweetForms\Form classname into the MySweetForms/Form.php path, and (provided it was told to look in the lib directory) it would find it's way to the correct file. If that file was missing, the autoloader would ultimately fail. Similarly, if that file defined a Form class but neglected to supply a namespace the actual class (MySweetForms\Form) would not exist (instead, a global class Form would) -- that doesn't match the fully qualified name of the class referred to in the AjaxFileField class, so an error would occur.
Note that if the code had included $form = new \FormBuilder\Core\Form(); instead the class name would already be fully qualified, and the autoloader would be asked to load the FormBuilder\Core\Form class (and would expect it to be in the FormBuilder/Core/Form.php file).
If we had used $form = new \Form(); we would be referring to the Form class in the global namespace and the autoloader would be asked to find Form (it would look in the Form.php file directly inside the lib folder at this point).
The key is to recognize that there are not, really, two Form classes -- there is one class with a fully qualified name of FormBuilder\Core\Form and one with a fully qualified name of MySweetForms\Form -- and a properly implemented autoloader will expect them in completely different locations, and will not try to load one file in place of the other.
The combination of namespaces and the PSR style of organizing files into directories based on their namespaces makes it very easy to re-use common words without causing conflicts, and to predictably map fully qualified class names to the corresponding files.
The resolution of class names to fully qualified class names is key to this, and is discussed in the PHP manual (the namespace FAQ has a couple of points about it: http://www.php.net/manual/en/language.namespaces.faq.php). The PSR-0 standard itself is also a useful reference: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
So I have an idea, but I'm thinking I need to run it by StackOverflow before I do something stupid.
I want to have an associative array of class names => filepaths. If PHP ever runs into a fatal error where the class is not defined, it will check if the key exists in my array and then require_once the class. This will prevent unnecessary bulk loading of classes that may never be used.
Bad idea?
How about trying PHP's built in autoloading.
Autoloading is the right way to do it, but spl_autoload_register is a cleaner way than __autoload, because it allows multiple autoloaders. Function __autoload also AFAIK stops working when spl_autoload_register is called, unless __autoload is also registered.
You can write your own autoload or use an existing one. For example, Zend Framework has an autoloader that uses conventions (Foo_Bar is in Foo/Bar.php). Nette Framework has RobotLoader, that indexes your classes and uses the index when neccessary. However, unless you use other things from the framework, it is probably too large.
see: http://www.php.net/manual/en/function.spl-autoload-register.php
If you are on PHP5, you can use __autoload().
makes your code a bit more manageable , although performance-wise, it's a bad choice. But I wouldn't worry it unless I'm building a Facebook.
What you are trying to do is already handled by the php __autoload function. You can read all about it here: http://php.net/manual/en/language.oop5.autoload.php
So, not a bad idea at all ;)
you should use autoloading with specified clas name structure, here is an example
the class names should should be only alpha and _ case-insensitive.
Lets take this directory structure and files
/classes/class.php
/classes/input/input.php
/classes/output/output.php
/classes/regex/regex.php
/classes/interface/parser/interface_parser.php
/classes/parser/parser.php
/classes/parser/xml/parser_xml.php
/classes/parser/html/parser_html.php
having the structure like this is good as it encourages you to code better when it comes to OOP.
Now if we take a look at the /classes/parser/html/html_parser.php file:
class Parser_Html extends Parser implements Interface_Parser
{
//looks nice in here
}
usually you would have to make sure the interface and the extended class is loaded, but these get autoloaded as well if they have not already.
creating the auto load system for this is not that complex, its just 1 function.
function __autoload($name)
{
//Classes
$parts = explode('_',strtolower($name));
$path = '/classes/';
foreach($parts as $p)
{
$path .= $p;
}
$path .= '/' . $name . '.php';
if(file_exists($path))
{
require_once $path;
}
}
so instead of including the class file first just run the class initiation.
$HtmlParser = new Parser_Html();
as the file has not been include the __autoload is run with a param of the class name, the autoload then looks in the directory that's relevant to the class name to try and load it.
also as your using the extend keyword in the class file shown above the class that is to be the parent gets run threw trhe autoloader aswell so you do not need to pre-load interfaces and classes etc.
Hope this helps you.
Note:
All code provided is untested and written for informational purposes, I would recommend you research the techniques more in detail before any implementation is done.
I have recently learnt about namespaces in PHP, and was wondering, would it be bad practice to do this?
<?php
namespace String; // string helper functions
function match($string1, $string2)
{
$string1 = trim($string1);
$string2 = trim($string2);
if (strcasecmp($string1, $string2) == 0) // are equal
{
return true;
} else {
return false;
}
}
?>
Before I had this as a static method to a String class, but this always seemed wrong to me... Which is the better alternative? I have a desire to categorise my helper functions, and want to know which is the better way to do it.
Edit
So how do I then access the match function if I have declared it in a namespace? How do I stop the namespace declaration, say if I include a file beneath it which declared a new namespace, would it automatically stop references to the first? And how do I go about returning to global namespace?
I'd put it in a namespace. A class is a describes a type in php, and though you maybe operating over a type with a similar name, it's not the same type, strictly speaking. A namespace is just a way to logically group things, which is what you're using a class to do anyways. The only thing you lose is extensibility, but as you said, it's only a collection of static methods.
If they're all string-related functions, there's nothing wrong with making them static methods.
A namespace would be the better choice if you've got a bunch of global functions and/or variables which you don't want cluttering up global scope, but which wouldn't make sense in a class. (I've got a class in my own code which would be a lot better suited to a namespace).
It's good practice to stick everything in some sort of container if there's any chance your code will get reused elsewhere, so you don't scribble on other people's global vars...
As for your edit there:
Namespaces are tied to the file they're defined in, IIRC. Not sure how this affects included files from there but I'd guess they aren't inherited.
You can call the global scope by saying ::trim().
Because namespaces are so new to php, people have been doing for a long time what you did - create a class, add static methods, and use the class as if it were a namespace. It looks to me as if you are thinking about it properly.
You would use classes to categorized some sort of functions on a certain dat. Like let say you have a Student class which will hold student information and student age and student ID number;and alose there some sort of methods that return and set these data.
Moreover, you would use namespace to categorized the Classes;let say now you have another class which handle the University registration for those students and alose the other classes for managing courses. Personaly, I would put all these classes under a category (i.e. namespace) called University.
Thus, it is not even a bad practice, also it gives you more readability in your code. And that would be more underestandable for other programmers if you are working in a group.
So personally I strongly suggest you use those in your project wherever you think it is proper to use it.
Ideally, it would be best to put functions in a namespace. If you depend on autoloading though, which only works for classes, you need to put them in one or more classes.
I am using Kohana and just found this piece of code in their autoloading method
// Class extension to be evaluated
$extension = 'class '.$class.' extends '.$class.'_Core { }';
// Start class analysis
$core = new ReflectionClass($class.'_Core');
if ($core->isAbstract())
{
// Make the extension abstract
$extension = 'abstract '.$extension;
}
// Transparent class extensions are handled using eval. This is
// a disgusting hack, but it gets the job done.
eval($extension);
basically what it does is when I am referring to a class that doesn't exist (through object instantiation, calling class_exists() etc.), Kohana will create a class (eg. Foo) that extends a library class that follows certain naming convention (eg. Foo_Core). just being curious, is there any way to do something similar but without the use of eval?
If you are looking to create a dynamic class then eval() is the goto function (pun intended.) However kind of related, I've found that you can put a class declaration within an if-then statement. So you can do the following:
if(true)
{
class foo
{
// methods
}
}
I use this to check to see if dynamically created classes (from a configuration file) are current... if so then load the class, otherwise... regenerate the class, and load the new one. So if you're looking to create dynamic classes for similar reasons this might be a solution.
I think you're stuck with eval() for that.
It's marked as a "disgusting hack" so that makes it OK :)
I'd be interested to know what you do with such an empty class...
If you were wanting to be able to cache your dynamically created classes, you could write out to a file and require it instead. This could be considered equally hack-ish, but it is an option. For classes that are created once and used often, it might be a good solution. For classes that need to be dynamic every time, sticking with eval is probably the best solution.
$proxyClassOnDisk = '/path/to/proxyCodeCache/' . $clazz .'.cachedProxyClass';
if ( ! file_exists($proxyClassOnDisk) ) {
// Generate the proxy and put it into the proxy class on disk.
file_put_contents($proxyClassOnDisk, $this->generateProxy($object));
}
require_once($proxyClassOnDisk);
In this example, the idea is that you are creating dynamic proxies for the class of $object. $this->generateProxy($object) will return the string that looks more or less like what $extension looks like in the original question.
This is by no means a complete implementation, just some pseudo code to show what I'm describing.