Symfony class loader - usage? no examples of actual usage - php

I've been playing a bit with the Symfony class loader (read about others, the concept and started implementing).
I've read http://symfony.com/doc/current/components/class_loader.html as well
I've changed the directories structure to fit and all. Here's a small source-code which fails:
Filename: test.php , dir: C:/test/BE/src/main.php
<?php
define('BASE_DIR','/../..');
echo BASE_DIR.'/BE/libs/symphony/component/ClassLoader/2.1.0/UniversalClassLoader.php';
require_once BASE_DIR.'/BE/libs/symphony/component/ClassLoader/2.1.0/UniversalClassLoader.php';
use Symfony\Component\ClassLoader\UniversalClassLoader;
$loader = new UniversalClassLoader();
$loader->registerNamespace('App\Location\Location', 'Location/Location');
// You can search the include_path as a last resort.
$loader->useIncludePath(true);
$loader->register();
use App\Location\Location;
new App\Location\Location(); //Fatal error: Class 'App\Location\Location' not found in C:/test/BE/src/main.php
file name: Location.php , dir: C:/test/BE/src/Location/Location.php
namespace App\Location;
class Location{
private $lat;
private $lng;
}

By registering your namespace as follows:
$loader->registerNamespace('App\Location\Location', 'Location/Location');
autoloader will look for the App\Location\Location class in the Location/Location/App/Location/Location.php file. Note that file/directory names are case sensitive.
First parameter of registerNamespace() is either a namespace or part of the namespace. Second parameter is a path to a PSR-0 compliant library. That means that directory structure inside that path should follow PSR-0 standard. This path is not used when calculating path for given namespace.
If you want to keep your current directory structure following code should work for you:
$loader->registerNamespace('App', __DIR__);
I'd rather put your source code in one common directory, for example src:
src/
App/
Location/
Location.php
And then register namespaces as follows:
$loader->registerNamespace('App', 'src');
By doing that you're simply telling an autoloader that it should look for App namespaced classes in the src folder. Note that it will work for every class in the App namespace (following PSR-0).
Some time ago I wrote a blog post about the Symfony autoloader. You might find it helpful: Autoloading classes in an any PHP project with Symfony2 ClassLoader component
Since you plan to use Pimple and some of the Symfony components take a look at Silex microframework. Might be it's something you need to implement.

You use:
$loader->registerNamespace('Pimple', BASE_DIR.'/BE/libs/Pimple/1.0.0/lib/Pimple');
To register the Pimple namespace for Pimple is useless, as Pimple is one class in the default namespace (it has no namespace).
The UniversalClassLoader does only work for PSR-0 and PEAR compatible directory layouts. If your layout is not, you should not expect it to work nor to be documented that it works for incompatbile layouts.
Explicit Note: You are using the wrong tool to do the job. All file layouts you have shared over the last hours are incompatible with UniversalClassLoader.
Apart from that if you give the wrong values for it's parameters, the class just won't work.

Related

PHP issue with namespaces in index.php

trying to work something out. I have my root folder which has index.php. Inside this folder is another folder called classes. Inside classes, I have three classes which have the namespace classes e.g.
<?php
namespace classes;
class MyClass {
...
Now back to index.php, this is not a class. However, I need to use these classes in the classes folder. I am trying without success
<?php
$reader = new \classes\MyClass();
With this I get the error that the class is not found. I have also tried using a require, but because MyClass requires the use of another class in the folder, it means I have to require both classes to get it working. So my only solution at the moment is
<?php
require_once('classes/MyClass.php');
require_once('classes/MySecondClass.php');
$reader = new \classes\MyClass();
For some reason I do not think this is the correct way to do it. What is the appropriate way to use my classes in index.php?
Thanks
When you try to work with namespaces you could use the PSR-4 convention and you could use the composer autoloader. Its very simple and you have a good structure.
http://jessesnet.com/development-notes/2014/php-composer-autoloading/
Here is a good article that describes how to use the PSR-4 autoloader. It's the new way in working with Files and dependencies. And you have the ability to work with all other packages that use composer, too.
Use autoloader see here
and here

inheritance and external files. How do I go about it?

I have 3 files.
vehicleClass.php
motorbikeClass.php (extends vehicleClass)
index.php
My question is... How do I connect all 3. On my index page, do I have to have
include 'classes/vehicleClass.php';
Do I need to have an include for the motorbike class or will the extend (inheritence) cover this?
You can let php autoload your files, by registering your own autoload function. If you have, in example, all your class files in the directory DOCROOT . 'classes' (DOCROOT being your document root), you can use a function like this (example):
function class_loader($class) {
include DOCROOT . 'classes/' . $class . '.class.php';
}
spl_autoload_register('class_loader');
Now if you try to create an object of class 'foo', it will try to include the file DOCROOT . '/classes/foo.class.php' before creating the object. You might want to extend the function a bit, eg. to lowercase file names (include DOCROOT . 'classes/'. strtolower($class) .'.class.php';). This way you can place class Foo in foo.class.php.
Short answer: a class that is extending (or otherwise using) another class must already have defined the parent class before the definition of the child class. Your assumption is correct, your VehicleClass must be included (or better, require'd) prior to your definition of MotorBike class.
However, most frameworks don't go about and include every depedency before all class definitions. This would become unwieldy on any system that has any amount of complexity to it. Instead, the developers of PHP have provided methods for autoloading classes. Using spl_autoload_register will allow you to write a function that will attempt to load in the source file for a given class whenever it is referenced but a definition for it has not yet been found.
Furthermore, once you get a system together that becomes complex, you don't want to store all of your files in a single place. Most frameworks leverage the filesystem and namespaces to help better organize all of their classes. Because of this, the PSR-0 standard was developed in order to help facilitate autoloading between frameworks. Take a look at this question for examples of PSR-0 compliant autoloaders.
Example of PSR-0 compliant class:
<?php namespace Vendor\Package;
class ClassName { }
This file would live in the filesystem at /Vendor/Package/ClassName.php
What you have to do is include 2 files in the index.php.
For example, your index.php page could be something like this.
<?php
require 'classes/vehicleClass.php';
require 'classes/motorbikeClass.php';
// Assuming your class name is MotorBike
$motorBike = new MotorBike();
// And just call the method you want, for example If you have a method called bikeName
echo $motorBike->bikeName();
?>
I hope you get an idea now.
P/S: I prefer require over include. :) Include() should work fine too.

Storing PHP OPP classes

I have a site which uses the library file lib.client.php which is stored in the php folder in my standard website root and contains a series of classes I have built.
The library file contains about 5 or so classes, should I leave this file as one or break up the classes into their own files and include them all individually? Are there any best practice naming conventions I should use for these file(s)?
(As you can see at the moment I'm using lib. and I also use inc. - only because I have seen it done a few times before).
UPDATE:
I am remodelling my structure to comply with the PSR-0 Standard. I now have:
CCall (Vendor)
Core
Connection
Gateway.php
GatewayDSN.php
GatewayException.php
Components
Environment.php
EnvironmentRequest.php
Centre.php
Access
User.php
UserSession.php
RenderException.php
I want to create a new Environment() in index.php, and its __construct method calls Gateway::checkInstance().
How would I manage namespace use in this model? What would have its own namespace and where would I define this?
How would I use an autoload with these namespace definitions (and where?)
Is there an equivalent standard for method and property naming?
I am using this https://gist.github.com/jwage/221634/download#
Break classes into their own files and follow the PSR-0 standard as a best practice.
http://phpmaster.com/autoloading-and-the-psr-0-standard/
If you are using a PSR-0 autoload:
add this in Environment.php
namespace Components;
and add a reference to Gateway
use Core\Connection\Gateway;
of course you need this line inside Gateway.php
namespace Core\Connection;
Then:
new Components\Environment();

require_once at symfony

I'm making now things with php + Symfony2 framework, and I have the following code:
require_once("one_file.php");
require_once("another_file.php");
... and so on.
The problem is, how to "Symfonyze" these uncomfortable require sentences, and after, how to include these files in the Symfony2 package?
We've thought about two possibilities:
Include the file at /vendors directory of symfony, or
Include each class as a service.
If these classes reside inside bundle then you could use as below:
Suppose your bundle name is AcmeDemoBundle. Place this file inside Acme/DemoBundle/Model/
//one_file.php
namespace Acme/DemoBundle/Model;
class one_file {
...........
}
To use this file inside your controller or any other file:
Here for Acme/DemoBundle/Controller/UserController.php
namespace Acme/DemoBundle/Controller
use Acme/DemoBundle/Model/one_file
class UserController {
public $one_file=new one_file();
}
In php 5.3 onwards, namespaces has been introduced. You should probably look at namespaces and its uses in php documentation
You can follow the PSR-0 standard to let the autoloader handle this. See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md and http://getcomposer.org/doc/04-schema.md#psr-0 .
Or you could keep your files as is, and tell composer to require them each time : http://getcomposer.org/doc/04-schema.md#files
You have to make a folder in your acme folder like lib puts these files in lib folder then use this statement
use Acme\DemoBundle\lib\Abc; // its your class name
You want to follow these other answers, especially the approved one, but if you are using a third party library with tons of PHP files, you can do require_once(__DIR__.'/path/to/file.php') as a quick fix.

require_once() and autoloader - How to load flat php?

I have a file (an xmlrpc library for PHP) that I would like to use into a Symfony2 class (so inside a Symfony2 project).
I can't use autoloader because as written here
which is able [the autoloader] to load classes from files that
implement one of the following conventions:
1) The technical interoperability standards for PHP 5.3 namespaces and
class names;
2) The PEAR naming convention for classes.
If your classes and the third-party libraries you use for your project
follow these standards, the Symfony2 autoloader is the only autoloader
you will ever need.
the class that I'll go to use, didn't satisfies one of those requirements.
So if I can't autoload that file, since isn't possible (as I understand, but I can go wrong) to use require_once (or simply require) with namespace, what is the solution for this issue?
Assuming you have a file named xmlrpc.lib.php with the following content:
<?php
class XMLRPC_Server {
// ...
}
class XMLRPC_Request {
// ...
}
class XMLRPC_Response {
// ...
}
You can create an instance of MapClassLoader to handle it's autoloading:
// Create map autoloader
$mapLoader = new MapClassLoader(array(
'XMLRPC_Server' => __DIR__.'/../library/xmlrpc.lib.php',
'XMLRPC_Request' => __DIR__.'/../library/xmlrpc.lib.php',
'XMLRPC_Response' => __DIR__.'/../library/xmlrpc.lib.php',
));
// Register autoloader
$mapLoader->register();
When one of these classes will be auto-loaded, others will be auto-loaded too because they share the same PHP file.

Categories