How to do you include a class in Symfony2? - php

I have read the Symfony documentation and I am still unsure of how to include a class. I want to include a Google Analytics PHP class into Symfony, but not sure on the following:
Where should it go? From the documentation I assume it should be under the vendor directory?
How would I then include the class? Ideally I would only like to include it where necessary (ie when I need it).
How would I then utilise the class?
Cheers
Adam

Use the app/autoload.php file to configure your autoload mechanism.
If your class doesn't follow PEAR style conventions or PSR-0 standards then you should plainly require it (as is the case with Swiftmailer in the same file)
If your class follows PEAR conventions then you should use registerPrefixes method else, if your class follows PSR-0 standard (maybe not the case), you should use the registerNamespaces method

Related

Can I use a PHP library file of classes with PSR-4 autoloading, and does it even make logical sense?

I envisage developing an API client library which may use many small utility classes. Do I have to have a separate file for each class if using PSR-4? Is my approach sound, and if so how can I achieve it?
Edit in response to answers:
I didn't understand the range of autoloading strategies in Composer particularly classmap autoloading and how that can better manage my own codebase.
Useful knowledge from Evert and Jeto.
Sample project layout:
src
myproject
client
apilib.php
apilib.php includes:
class Connection {}
class Statistics {}
class SomeOtherThing {}
Or am I stuck with creating these files?
client/apilib/Connection.php
client/apilib/Statistics.php
client/apilib/SomeOtherThing.php
What namespaces will my classes use?
PSR-4 maps classes and namespaces to file and directory paths, but you are not required to follow PSR-4.

How does the PHP 'use' keyword work (in Symfony 2)?

In Symfony 2, all requests are getting routed through app_dev.php (or app.php).
The first few lines look like:
<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Debug\Debug;
...
In theory, I get that this just imports the specified namespace (or class) to the current scope. What I don't understand is how PHP maps this to a file. For example, the Debug class is located in:
vendor/symfony/symfony/src/Symfony/Component/Debug/Debug.php
How does PHP know to look in vendor/symfony/symfony/src/?
I'm probably misunderstanding what is happening, but any clarification would be appreciated.
Knowing which file a class lives in isn't the job of the language, it's the job of the autoloader.
All the use keyword does is this instance is create an alias:
use Symfony\Component\HttpFoundation\Request;
This is saying in the following script, when I refer to Request I really mean Symfony\Component\HttpFoundation\Request. If I use Request object in some way (by either creating an instance or calling a static method on it) then the autoloader will go and try to load the file that class is defined in if it hasn't been loaded already.
The inner workings of the autoloader, though, is different from project to project. There has been a move to standardize autoloader behavior à la PSR-4, but there's nothing in the language saying that you have to adhere to that standard. You could, for instance, have a scheme where all class files reside in a single directory and your autoloader just loads all classes from there, regardless of what namespace they're in.
That scheme would suffer from the fact that you could only have a single class of every name, but there's nothing stopping you from doing it that way.
To answer your question: "How does it know that "Symfony\Component\Debug\Debug" is a valid namespace?"
It doesn't, because it's not actually going out and trying to load that class at this point. If in any random PHP script you put something like this at the top:
use \Non\Existant\ObjectClass;
But don't ever actually use ObjectClass anywhere, you will get no errors. If you try to say new ObjectClass, though, you will get a class not found error.
Simplistically speaking, you have to load all the files beforehand into memory for PHP. PHP does not inherently have any standards to where files are located, the rules for loading files has to be done by your code.
When PHP attempts to load a file, it will check its memory if the class definition exists, if not it will attempt to autoload the file that may contain your class definition; see PHP: Autoloading Classes and spl_autoload_register
Some common autoloading strategies have been defined by the PHP Framework Interop Group:
PSR-0 (Autoloading standard)
PSR-4 (Improved Autoloading standard)
In this case, autoloading is done by Composer, all you need to do is include vendor/autoload.php in any of your scripts and vendor code downloaded via composer can be autoloaded. You can manually add classes into the composer autoloader as well. See: Composer Autoloading

When I auto-load a class/file with composer, what is actually happening behind the scenes?

I haven't been able to find a strait answer to this question yet elsewhere online and was wondering how exactly composer autoloading worked.
When I autoload a class using PSR-0 or classmap what is actually happening behind the scenes? Is it just calling include(or some include variant) on the the specified file in the specified path. Is it actually skimming the file for class definitions and constructing its own file to include? Is it doing something that isn't analogous to a file include?
Thanks in advance!
A PSR-0 autoloader is simply a function attached to the global PHP process with spl_autoload_register(). That registered function is called whenever PHP needs to instantiate a class that isn't yet known, so this is the last moment to make the classes code known before PHP fails.
And the implementation of that autoloading can be either pretty sophisticated, or pretty simple, but in every case it will use either include() or require() (possibly with _once, but this is not really needed) to make the class code known to PHP. You could also implement a call to eval() to dynamically add some code that declares the class needed, but this would just be for academic used - I haven't seen it being used in real cases.
The same applies to the classmap loading. The classmap array contains names of classes as keys, and the filename of the containing file as value. This is for cases where there is no PSR-0-compatible ruleset mapping between class name and file path.
If you want more details of how Composer does the autoloading, you should have a look at the generated files inside vendor/composer. Basic knowledge about how PHP autoloading works in general would help understand what happens there.
Behind the scenes composer use spl_autoload_register to register an autoloader function which include your class.
The registered function follows a standardized namespace/path resolution algorithm (basically consider all "\" or "_" in your class name as path separators from a specified base directory) to find the php file to include.
Also, when you run composer install it create a cached index of relation between paths and namespace to speed up the path resolution.
You can dig in the Github repository and see it for yourself.

include on instantiate PHP

Well I have a question. On Zend Framework We use a very interesting structure because if you intanciate a class then automatically Zend include the class file and after instanciate it (Class obviously allow to ge the directory's structure Class: abc_def_pqr then path is abc/def/pgr.php)
Does anyone have any idea???
Zend Framework uses spl_autoload_register to register a function that is called when a class is called but does not exist.
The function then does as you say, replace the underscores with directory separators and tries to include the file.
See Autoloading Classes but note using spl_autoload_register instead of __autoload allows for multiple autoload functions, which is better practice. Especially if being used in conjunction with ZF or external libraries.

Can I include a non-Symfony class?

I'm actually learning Symfony and I don't understand the fact of including classes. Can I include a standalone class - this means, not designed for a framework - and then use it - let's say, Amazon S3 class -?
Just put your class in wherever lib (sub)directory it suits you the best. It will be autoloaded by the framework.
If you don't want it to be automatically autoloaded than put it somewhere in the lib/vendor directory.
If your class is reusable than it's the best to put it in a plugin.

Categories