Laravel - referencing the class - php

I've been reading a lot of documentation for Laravel during last week for the sake of learning what kind of beast it is.
I noticed one thing that whenever somebody references some class he references to it as string, e.g.:
public function user()
{
return $this->belongsTo('App\User');
}
Pay attention to 'App\User'
Taken from here https://laravel.com/docs/5.5/eloquent-relationships#polymorphic-relations
I wonder why don't they reference it as App\User::class ?
In this case it's easier to type and support the code, because it's easier later to follow the class pressing Ctrl+B. Also refactoring is easier and it's harder to make a mistake because IDE will warn you that class doesn't exist if you make a typo.
I see no reasons to reference class User as 'App\User' instead of App\User::class.
Do you see any?

Taking from PHP doc Class Constants:
The special ::class constant are available as of PHP 5.5.0, and allows for fully qualified class name resolution at compile, this is useful for namespaced classes:
This means that using User::class will at runtime resolve to 'App\User' according to the example you gave. So the choice is yours.
On a personal note, In order to avoid typographical mistakes with strings I prefer to use the class constant resolution, and also I can easily check the usage from my IDE.
Also I do not have to memorise the namespace of the class I am using.
Apart from these benefit, I do not see any difference unless there is performance difference which obviously does not seem so.

The actual string is used to illustrate that it is the full class name of the related model. You can very easily use Model::class. The example in the docs is explicit and removes any potential guess work from someone reading that argument.

Related

Why use the "use" keyword in PHP to import core identifiers?

Sometimes in some libraries like thephpleague/csv, I see the use keyword to import core identifiers (e.g. functions, classes or constants) but I can't understand why they are being imported at all.
See the following example:
use Generator;
use SplFileObject;
use function filter_var;
use function get_class;
use function mb_strlen;
use function rawurlencode;
use function sprintf;
use function str_replace;
use function str_split;
use function strcspn;
use function strlen;
use const FILTER_FLAG_STRIP_HIGH;
use const FILTER_FLAG_STRIP_LOW;
use const FILTER_SANITIZE_STRING;
Or more from here.
These classes, functions and constants that are imported in this file are belong to PHP core, so we wouldn't actually need to import them.
Why this and other libraries import these?
The objective with this is to perform a (micro) performance optimization, as described here. (Archived link, just in case).
The idea being that by using avoiding the global name lookup and skipping the fall-back rules, some performance can be gained.
Note that with any real-life workload these gains are negligible and inconsequential, and they are mostly made irrelevant by opcode caching. Nevertheless, the performance gain, minute as it may be, exists.
You can read some lengthy and interesting discussion about this:
Reddit discussing the article linked above
Symfony project deciding not to apply this optimization
Readme file for a script that performs this optimization automatically
When you're in a namespace, every bare name refers to a name within that namespace. I.e.:
namespace Foo;
echo bar();
bar here really means Foo\bar.
There are rules for fallbacks to global names if the name doesn't exist within this namespace. If you don't want to rely on those rules, or if you do actually have those names defined in your namespace and you don't want to have to constantly write \bar() explicitly, that's when you may explicitly use those global names to make it unambiguous that bar refers to \bar and not Foo\bar.
It's probably not necessary most of the time for PHP builtin names, but perhaps the project author has simply established that as a rule to avoid bugs due to namespace resolution ambiguity.

Can I put PHP extension classes, functions, etc. in a namespace?

I am writing a PHP extension in C, and I would like to put the classes, functions, and variables I am creating in a namespace. I have not been able to find anything in the extension documentation regarding namespaces. To be clear, I want the equivalent of
namespace MyNamespace{
class MyClass{
}
}
but in a C extension. More specifically, I am looking for a function or macro in the Zend C API that allows me to assign a PHP namespace to a class or function I have written in C. Is this possible?
Putting a class in a namespace is very simple. Where normally you would initialize a class with
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "MyClass", my_class_methods);
instead write the second line as
INIT_CLASS_ENTRY(ce, "MyNamespace\\MyClass", my_class_methods);
The namespace does not need to be included in the method declarations or in the members of the my_class_methods array to properly match them with the class.
To use Namespaces in PHP extensions, you are basically just putting a prefix in front of the class or function name.
I'm not really a PHP internals developer, so the specifics are not entirely clear to me how this works, unfortunately there is very, very little information online that I could find about this as well (I really put Google through it's paces), and the article below is the best I could find.
However, it seems this article hints at the correct solution, which seems to be, that when you register the function with the Zend engine/PHP internals, you do so like "myNS\\MyFunc" and it should then be accessible from the myNS defined there. I would try out a few different variations with this, and see how far that gets you.
Your best option would be to ask in #php-internals on Freenode (if you can get an invitation) or on the PHP Mailing list.
If you manage to find a solution, the Internet seems to be in need of a good article on how one would accomplish this.
Source http://www.php-cpp.com/documentation/namespaces
A namespace is nothing else than a class or function prefix. If you want your classes or functions to appear in a specific namespace, you simply have to add a prefix to the class or function name....
Update: I've updated my answer to try to be more clear. I'm sorry it took so long, I originally replied from my Phone while I was traveling, with every intention of coming back and responding to your original comment, but I genuinely forgot about it until I got a notification from SO about comments. My apologies.

Method name clashing with language construct

I simply want to name a method in my class list(). If I try and do so:
class MyClass {
function list () {
// Do some stuff here
}
}
...I get a parse error (Unexpected T_STRING...). The same is true if I use echo or print - so I am guessing that I am not allowed to name a class method the same as a language construct, and while I cannot find any documentation that explicitly states this to be the case, I suppose it does make sense.
My question is, does anyone know of a work around to this, that will work in PHP 4.3.10? I know this can be done in PHP 5.3+ with closures (or I assume it can, I haven't actually tried) No versions of PHP to date support doing this with closures, but can anyone think of a work-around that does not rely on this, baring in mind that it is the method name that is important here?
EDIT N.B.
I am fully aware of how ancient and dead PHP4 is, but I have no option for this particular project. It is to be run on a platform distributed with PHP 4.3.10, which is a very low resource BusyBox platform with a MIPS processor, for which no compilers are provided. I have managed to create a cross-compiler and successfully build PHP 5.2 for it (I haven't tried 5.3 yet, it would probably involve compiling a newer Apache as well) but regardless of this, the manufacturer insist that this invalidates their warranty.
The dilemma you face will stay until you choose A or B.
A: Choose another function name, one that is not a reserved word.
B: Change PHP so that it provides the language features you need.
__call is not available in PHP 4. list is a reserved word since long time.
And you have not outlined what your specific problem with the class interface is, so I don't see much room for more alternatives.
As B does not look like a real option here, you need to take A.
Hope this helps that you can come to a conclusion.
Reserved keywords are reserved:
you cannot use any of the following words as constants, class names, function or method names
So rename your methods.
You've got two options.
1) rename your method. Unless there's a real reason you can justify your method's name then this is the one you should do.
2) namespace your class. If you wrap your class in its own namespace then you can reuse names that are normally reserved or predefined functions, or defined elsewhere. However you should only use this approach if you know what you're doing, otherwise you can end up causing a lot of confusion.
I'd opt for option 1 unless you have a really really compelling reason why your method name must have the same name as a PHP reserved word.
EDIT: You're using PHP 4 so option 2 is off the table. Your only choice is using a different name for your method. That, or upgrade to PHP 5.3. Even if you don't go with namespacing in the end I'd strongly advise upgrading to PHP 5.3 anyway, as PHP 4 is dead and has been for a long time. There will be no security patches released for it ever again so by running it you're basically making your server very insecure.
Kind of a dirty hack, but you could use the magic methods. PHP4 doesn't really support the __call like php5 does, but it could work with the 'overload' construct. I haven't tested this so I can't be sure..
( http://php.net/manual/en/function.overload.php )
class MyClass {
function __call($func, $args){
if ($func == 'list')
return $this->_list($args);
}
function _list () {
// Do some stuff here
}
}
overload('MyClass');
$myclass = new MyClass();
$myclass->list();

Is it ever okay to have a class as a collection of methods and no properties?

I'm writing a bunch of generic-but-related functions to be used by different objects. I want to group the functions, but am not sure if I should put them in a class or simply a flat library file.
Treating them like a class doesn't seem right, as there is no one kind of object that will use them and such a class containing all these functions may not necessarily have any properties.
Treating them as a flat library file seems too simple, for lack of a better word.
What is the best practice for this?
Check out namespaces:
http://www.php.net/manual/en/language.namespaces.rationale.php
Wrapping them in a useless class is a workaround implementation of the concept of a namespace. This concept allows you to avoid collisions with other functions in large projects or plugin/module type deployments.
EDIT
Stuck with PHP 5.2?
There's nothing wrong with using a separate file(s) to organize utility functions. Just be sure to document them with comments so you don't end up with bunchafunctions.php, a 20,000 file of procedural code of dubious purpose.
There's also nothing wrong with prefixes. Using prefixes is another way to organize like-purpose functions, but be sure to avoid these "pseudo-namespaces" already reserved by the language. Specifically, "__" is reserved as a prefix by PHP [reference]. To be extra careful, you can also wrap your function declarations in function_exists checks, if you're concerned about conflicting functions from other libraries:
if (!function_exists('myFunction')) {
function myFunction() {
//code
}
}
You can also re-consider your object structure, maybe these utility functions would be more appropriate as methods in a base class that all the other objects can extend. Take a look at inheritance: http://www.php.net/manual/en/language.oop5.inheritance.php. The base class pattern is a common and very useful one:
abstract class baseObject {
protected function doSomething () {
print 'foo bar';
}
public function getSomething () {
return 'bar foo';
}
}
class foo extends baseObject {
public function bar () {
$this->doSomething();
}
}
$myObject = new foo();
$myObject->bar();
echo $myObject->getSomething();
You can experiment with the above code here: http://codepad.org/neRtgkcQ
I would usually stick them in a class anyway and mark the methods static. You might call it a static class, even though PHP actually has no such thing (you can't put the static keyword in front of a class). It's still better than having the functions globally because you avoid possible naming conflicts. The class becomes a sort of namespace, but PHP also has its own namespace which may be better suited to your purpose.
You might even find later that there are indeed properties you can add, even if they too are static, such as lazy-loaded helper objects, cached information, etc.
I'd use classes with static methods in such case:
class Tools {
static public function myMethod() {
return 1*1;
}
}
echo Tools::myMethod();
EDIT
As already mentioned by Chris and yes123: if the hoster already runs PHP 5.3+, you should consider using namespace. I'd recommend a read of Matthew Weier O'Phinney's article Why PHP Namespaces Matter, if you're not sure if it's worth switching to namespaces.
EDIT
Even though the ones generalizing usage of static methods as "bad practice" or "nonsense" did not explain why they consider it to be as such - which imo would've been more constructive - they still made me rethinking and rereading.
The typical arguments will be, that static methods can create dependencies and because of that can make unit testing and class renaming impossible.
If unit testing isn't used at all (maybe programming for home/personal use, or low-budget projects, where no one is willing to pay the extra costs of unit testing implementations) this argument becomes obsolete, of course.
Even if unit testing is used, creation of static methods dependencies can be avoided by using $var::myMethod(). So you still could use mocks and rename the class...
Nevertheless I came to the conclusion that my answer is way too generalized.
I think I better should've wrote: It depends.
As this most likely would result in an open ended debate of pros and cons of all the different solutions technically possible, and of dozens of possible scenarios and environments, I'm not willing going into this.
I upvoted Chris' answer now. It already covers most technical possibilities and should serve you well.
Treating them as a class does give you the benefit of a namespace, though you could achieve the same thing by prefixing them like PHP does with the array_* functions. Since you don't have any properties, that basically implies that all your methods are static (as Class::method()). This isn't an uncommon practice in Java.
By using a class, you also have the ability, if necessary, to inherit from a parent class or interface. An example of this might be class constants defined for error codes your functions might return.
EDIT: If PHP 5.3+ is available, the Namespace feature is ideal. However, PHP versions still lag in a lot of hosts and servers, especially those running enterprise-stable Linux distributions.
I've seen it a few different ways, all have their warts but all worked for the particular project in which they were utilized.
one file with all of the functions
one file with each function as its own class
one massive utilities class with all of the methods
one utils.php file that includes files in utils folder with each
function in its own file
Yes, it's OK formally... As any class is methods + properties. But when you pack in class just some functions -- it`s become not ideal OOP. If you have bunch of functions, that groupped, but not used some class variables -- it' seems, that you have somewhere a design problem.
My current feeling here is "Huston, we have a problem".
If you use exactly functions, there one reason to wrap them in static class - autoloader.
Of course, it creates high coupling, and it's may to be bad for testing (not always), but... Simple functions are not better than static class in this case :) Same high coupling, etc.
In ideal OOP architecture, all functions will be methods of some objects. It's just utopia, but we should to build architecture as close as we can to ideal.
Writing a bunch of "generic-but-related" functions is usually bad idea. Most likely you don't see problem clear enough to create proper objects.
It is bad idea not because it is "not ideal OOP". It is not OOP at all.
"The base class pattern" brought by Chris is another bad idea - google for: "favor composition over inheritance".
"beeing extra careful" with function_exists('myFunction') is not but idea. It is a nightmare.
This kind of code is currently avoided even in modern javascript...

How unique is PHP's __autoload()?

PHP's __autoload() (documentation) is pretty interesting to me. Here's how it works:
You try to use a class, like new Toast_Mitten()(footnote1)
The class hasn't been loaded into memory. PHP pulls back its fist to sock you with an error.
It pauses. "Wait," it says. "There's an __autoload() function defined." It runs it.
In that function, you have somehow mapped the string Toast_Mitten to classes/toast_mitten.php and told it to require that file. It does.
Now the class is in memory and your program keeps running.
Memory benefit: you only load the classes you need. Terseness benefit: you can stop including so many files everywhere and just include your autoloader.
Things get particularly interesting if
1) Your __autoload() has an automatic way of determining the file path and name from the class name. For instance, maybe all your classes are in classes/ and Toast_Mitten will be in classes/toast_mitten.php. Or maybe you name classes like Animal_Mammal_Weasel, which will be in classes/animal/mammal/animal_mammal_weasel.php.
2) You use a factory method to get instances of your class.
$Mitten = Mitten::factory('toast');
The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"
Therefore, you can start out using a generic mitten throughout your code, and when the day comes that you need special behavior for toast, you just create that class and bam! - your code is using it.
My question is twofold:
(Fact) Do other languages have similar constructs? I see that Ruby has an autoload, but it seems that you have to specify in a given script which classes you expect to use it on.
(Opinion) Is this too magical? If your favorite language doesn't do this, do you think, "hey nifty, we should have that" or "man I'm glad Language X isn't that sloppy?"
1 My apologies to non-native English speakers. This is a small joke. There is no such thing as a "toast mitten," as far as I know. If there were, it would be a mitten for picking up hot toast. Perhaps you have toast mittens in your own country?
Both Ruby and PHP get it from AUTOLOAD in Perl.
http://perldoc.perl.org/perltoot.html#AUTOLOAD:-Proxy-Methods
http://perldoc.perl.org/AutoLoader.html
Note that the AutoLoader module is a set of helpers for common tasks using the AUTOLOAD functionality.
Do not use __autoload(). It's a global thing so, by definition, it's somewhat evil. Instead, use spl_autoload_register() to register yet another autoloader to your system. This allows you to use several autoloaders, what is pretty common practice.
Respect existing conventions. Every part of namespaced class name is a directory, so new MyProject\IO\FileReader(); should be in MyProject/IO/FileReader.php file.
Magic is evil!
The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"
Rather such tricky code, use simple and verbose one:
try {
$mitten = new ToastMitten();
// or $mitten = Mitten::factory('toast');
} catch (ClassNotFoundException $cnfe) {
$mitten = new BaseMitten();
}
I think this feature comes in very handy, and I have not seen any features like it else where. Nor have I needed these features else where.
Java has something similar. It's called a ClassLoader. Probably other languages too, but they stick with some default implementation.
And, while we're at this. It would have been nice if __autoload loaded any type of symbols, not just classes: constants, functions and classes.
See Ruby's Module#const_missing
I just learned this: Ruby has a method on Module called const_missing that gets called if you call Foo::Bar and Bar isn't in memory yet (although I suppose that Foo has to be in memory).
This example in ruby-doc.org shows a way to use that to implement an autoloader for that module. This is in fact what Rails uses to load new ActiveRecord model classes, according to "Eloquent Ruby" by Russ Olsen (Chapter 21, "Use method_missing for flexible error handling", which also covers const_missing).
It's able to do this because of the "convention over configuration" mindset: if you reference a model called ToastMitten, if it exists, it will be in app/models/toast_mitten.rb. If you could put that model any place you wanted, Rails wouldn't know where to look for it. Even if you're not using Rails, this example, and point #1 in my question, shows how useful it can be to follow conventions, even if you create them yourself.

Categories