Is it bad to use the keyword use even though we only call a function once?
E.g. I have my own typo3 extension, and I am accessing a typo3 core function in my controller, but only once.
$message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
I could also make use of use:
use \TYPO3\CMS\Core\Utility\GeneralUtility;
...
$message = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
In my opinion the second variant is much cleaner, but are there any performance issues if I make use of use only for one call?
In theory, there should be no performance hit. You're calling a function (and thus an autoloader) either way (which is where any performance hit will be).
To explain why, your use statement is simply an alias. Your autoloader will do the same work either way. And it will likely be opcode cached, so any performance hit (we're talking milliseconds here, if that) will only be on the first run.
It's much cleaner to import the classes and then use ::class to reference them e.g...
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Mail\MailMessage;
$message = GeneralUtility::makeInstance(MailMessage::class);
I particularly prefer the second choice too. And there is no performance hit. You can use the second one without any concern.
First option is faster when in namespace context and it could be more readable because of FQNS (it's a matter of taste). When there is a lot of "imports"
it may indicate too high a degree of dependence and break of the single responsibility principle. So I often use inline namespacing using FQNS.
Optimizing PHP performance by using fully-qualified function calls
https://veewee.github.io/blog/optimizing-php-performance-by-fq-function-calls/
Try to profile your code to get the answer.
Related
When using namespaces in PHP, you have a choice for how to refer to them. You can put them at the top of your class
use Symfony\Component\HttpFoundation\JsonResponse;
Or you can include them as you call the class:
return Symfony\Component\HttpFoundation\JsonResponse::create($data);
My question is, are there any performance considerations which would favor one method over the other?
I could imagine, based on no real knowledge whatsoever, that it's possible that declaring use in a class might sort of pre-load class definitions that never wind up getting used in the actual code execution, depending on the data-- which would be addressed by only referencing the namespaced class when you're actually calling it. Or, if you make a declaration during development, but never end up calling that class, but don't think to delete it when you're wrapping up, your code would always loading that class definition, and never using it.
Continuing to use my very spotty knowledge of PHP at runtime, it's possible that declaring namespaces at the class definition gets compiled, making it run faster when you actually call that class, instead of having to make some sort of 'dynamic' lookup when calling the class.
Or are useing namespaces at the top of class declarations only there for the developer's convenience, to avoid a lot of repetitive typing?
I found this question, Are namespaces bad for performance?, but it is only asking if using namespaces at all, anywhere in the code, have a negative impact on performance. Also it's 7 years old; it's possible the information is outdated.
I would say both, for example in the script:
use my\php\namesapce\TestClass;
echo TestClass::class;
$instance = new TestClass();
It is good for the performance because:
PHP just needs to read/evaluate a single word (namely TestClass) each time.
PHP internally stores the name (TestClass) as key for the full-path in a key-value pair temporarily (as long as the file is being read).
The file takes less space and hence less time to be loaded in the first place.
It is more convenient because the developer does not need to write the whole path each time.
And it does not affect the way that the auto-loader works (see another related post) because:
PHP will call the autoloaders exactly the same way with exactly the same parameters, with or without the use-statement.
If I need to use only ::class property in my code, should I import a whole class like this?
use my\namespace\MyClass;
MyClass::class;
Or should I do this?
my\namespace\MyClass::class;
Which is a faster/better solution? Or there is no difference?
I'm using the Yii2 framework if it matters
There is no difference, it is only matter of code style. Both variants generates the same opcodes, so they work the same and there is no performance difference between them. You can use version which suits you better, but importing classes using use statement have some advantages:
It is more DRY: if you need to use the same class twice, you don't need to repeat FQN twice. It also ensures consistency - there is no risk that in one place you use my\namespace\MyClass and in other some\vendor\namespace\MyClass.
It generates less fuss on refactoring - changing class namespace will only affect import section without touching actual code that uses this class (no meaningless changes in git blame).
"import everything" is easier to follow and configure CS fixers to ensure this as CS rule.
As a result you always have a nice list of classes used in specific file, which may help you find some bugs ("uh, this should be my\namespace\MyClass instead of some\vendor\namespace\MyClass") and architectural issues ("hmm, there is 60 classes imported in this file, maybe it has too much responsibilities...").
Namespace :
Both are valid and working properly but in terms of simplicity you can declare it in one line
my\namespace\MyClass::class;
Suppose you have a global method().
You can move it into a namespace and a class, and call it something like
\\Namespace\Class::method();
Is there any difference? Is one better than another?
Essentially you have not change anything and the method is for all intents and purposes just as global as it has been before - you can still call it from anywhere, but you have to type more characters. Did I miss something embarrassingly basic?
Namespaces and classes will not only help you with compartimentalization of your code and help you avoid name collissions, but actually make it faster by being able to use autoloaders and only load what you need when you need it.
It's very unlikely you'd call your method like this:
\\Namespace\Class::method();
You are much more likely to declare use Namespace\Class statements at the top of your file, and just do Class::method();.
And even more likely (and quite probably better) you'll actually instantiate a real object instead of using static methods (which are convenient, but can really break down encapsulation). In your example you are using an static method, which for a lot of people are not particularly object-orientedy.
Functionally, considered in isolation, there is no real difference between a method and a function. But a method has access to class properties and private methods, so it further helps you to build a system where responsibilities are properly distributed.
But to be meaningful, the difference has to be more than cosmetic. If you are using classes and objects, read on SOLID principles and design patterns (a bit at a time) and embrace the advantages of OOP.
This question is a bit odd and really hard to explain so I'll try my best.
Basically, I've been wondering how to actually use classes inside their own files and then use the namespace for that class elsewhere.
As an example most PHP developers might know, like Laravel does with routes, you have routes.php file that is for routes only, there's no namespace defined at the top e.g: use Acme\Router - However, the class still works and doesn't spit any errors. How is this accomplished?
Example
My index loads in composer autoloader which also loads my application class
<?php
// Used namespace here to actually make it function
use Acme\Application as App;
require_once __DIR__ . '/vendor/autoload.php';
$app = new App;
$app->launch();
The launch is for things that the application should do once launched, here I am thinking loading in the routes and etc. (I am not sure if this is the proper way to handle this, but it's my best shot.)
The class is like so:
<?php
namespace Acme;
class Application
{
public function __construct()
{
}
public function launch()
{
// Require routes etc.
}
}
What I was thinking initially was requiring the files, but I was thinking it would be bad practice to require files within a method. And even so, that would also become a huge list of things it should require.
However whatever I have tried didn't work out, what I am trying to do is avoid having use in my routes.php or etc to avoid a list of things I want to use such as:
use Acme\Database\Handler;
use Acme\Router;
because in the long run, this can become pretty massive.
What am I doing wrong and how should I actually approach this?
You probably didn't clearly state your question, so I'm doing a bit of guessing from my encounters with less experienced developers from the past.
I think we can stop discussing "requiring the files", because you should use autoloading to make classes, interfaces or traits available. And it is easy to do so because you are already using Composer. Check.
The remaining point is that you are afraid to add a huge number of "use" statements to your Acme\Application class because of the size of that list. There's two answers to that.
First, there is a bit of basic PHP knowledge about the "use" statement. You can address explicit classes with it, like you did in use Acme\Application as App;, but you can also address namespace prefixes, like use Acme\Models; and make use of it like this: new Models\User. This will both shorten the list of use statements (because one statement will cover more than one used class), and also make the code more readable because you have to add more namespace as context (new User; is less descriptive than new Models\User). Readability is a good thing, because you'll write the code only once, but read it plenty of times thereafter. And you don't want to invent alias names every time you encounter ambigous class names (which is a strong indicator that you should add that piece of context, and on the other hand always inventing alias names will likely start to confuse the reader).
Second, if you have to deal with a lot of classes, you have to deal with a lot of classes. There is no other way around but to separate the task that is dealing with all these classes. Then you still have to deal with all of them, but not in the same place. And you probably don't want to do everything that's done in this launch() method every time unless you know your application will need it right now in this request.
You may want to read about two topics: Dependency injection, and lazy loading, because I think your question is more directed towards application architecture.
So after more research into this I found out what I was trying to achieve was Facades not application structure, as I said it was hard to explain so I'm going to throw the solution to my problem out there.
Basically since this approach comes from using Laravel a lot I asked in the Laracasts forum which gave me exactly what I was looking for, it has a link to a working repository as well.
Thanks for the help regardless!
Solution including repository
i am in a situation where i need to fetch data from 6 models. i can't use associations as they are not related. So what should i use $uses or request action or any other solution
I'd recommend you to use
ClassRegistry::init("model_name")
or
loadModel("model_name")
instead.
E.g.
To use a User model
$this->User = ClassRegistry::init('User');
Or
$this->loadModel('User');
Then you can do some query like
$this->User->find("all");
If you are going to need those models for only one find call with associtaions needed, I recommend using bindModel, see Creating-and-Destroying-Associations-on-the-Fly.
I disagree with Travis. It is much better to use loadModel then you can be sure you're loading what you need when you need it. Who's to say you won't extend the model to include methods that don't require all those other models?
Cut and paste is a big boost to programmer performance.
You could try $uses, or, if you want to only load the models when and where you need them, you could use loadModel (http://book.cakephp.org/view/845/loadModel). LoadModel is better that $uses, performance wise.
As others recommended, you should use Controller::loadModel().
Additionaly, I'd suggest you make something like YourController::_loadMyMegaData() which would load all the necessary models and set your data. This will avoid loading those models by accident and spare you any if blocks later on.
Also, avoid requestAction() whenever possible, it's not only ugly, you also take a performance hit. (It has it's use of course, but that doesn't happen very often:))
You can use the following:
$this->loadModel('ModelName');
$this->ModelName->find();
If you are retrieving only single field than you can use virtual fields