Using PHP Namespaces - php

I have been searching websites to try and get a handle on using PHP namespaces, but they all seem quite vague but what they're trying to do is easy to understand!
My question is: I have a file called people.php and in it is defined class called people. If I create another file called managers.php in the same folder can I define a class again called people which extends the original people class but in the namespace of managers, if so do I have to 'include' the original people.php and if so do I put the include after the writing: namespace managers?

Namespaces are a way to group your related classes in packages. What you describe could best be put under a single namespace like
<?php // people.php
namespace com\example\johnslibrary\people;
abstract class People {
}
and then
<?php // manager.php
namespace com\example\johnslibrary\people;
require_once 'path/to/People.php'; // can better use autoloading though
class Manager extends People {
}
because a Manager is a subclass of People, so there is not much of a reason to put them into their own namespace. They are specialized People.
If you want to Managers to be in their own namespace, you can do so, but have to use the fully qualified name when using the extends keyword, e.g.
<?php // manager.php
namespace com\example\johnslibrary\managers;
require_once 'path/to/People.php';
class Manager extends \com\example\johnslibrary\people\People {
}
or import the People class first
<?php // manager.php
namespace com\example\johnslibrary\managers;
use com\example\johnslibrary\People as People;
require_once 'path/to/People.php';
class Manager extends People {
}
See the PHP Manual on Namespaces for extensive documentation.

// people.php
<?php
namespace People;
class People {}
// managers.php
<?php
namespace Managers;
require_once __DIR__.'/people.php';
class People extends \People\People {}

I have old PHP Class and i need to use it in new PHP file as for example:index.php has to use iClass.php. But before using the OLD iClass.php i have to modify it as below, so that i can use it in index.php.
iClass.php:
namespace ic;
class iClass {
public static function callMeFromClass() {
echo 'OK - you have called me!';
exit;
}
}
index.php
namespace inex;
require_once 'iClass.php';
use ic\iClass;
iClass::callMeFromClass();

Related

Are namespaces in PHP "inherited"?

EDIT:
Yes the problem was using \ at the beginning of the use statement. As M1ke pointed out, use goes from the root element.
Original post
I think is a PHP question but it may be Drupal.
I'm working on a headless Drupal project where is using a class (which I call Entity Model) that uses a Drupal class called EntityFieldQuery.
Before a create or use this class I bootstrap Drupal using:
require_once DRUPAL_ROOT.'/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
The entity model class is in the Models names space like so:
namespace Models;
use \EntityFieldQuery;
class EntityModel
{
.....
$query = new EntityFieldQuery();
$query->doSomething();
......
}
The EntityFieldQuery is found perfectly as I use the "\" because this class is out of the Models namespace.
The problem is when this class is created is uses other classes that don't use any namespace, and I have the following error:
class Models\InsertQuery not found in ....
Here is the class used by EntityFieldQuery that uses InsertQuery
class InsertQuery_mysql extends InsertQuery ...
I don't understand why InsertQuery_mysql is found but InsertQuery
I ended up adding a "\" in InsertQuery to fix the problem like so:
class InsertQuery_mysql extends \InsertQuery ...
Actually this class in a php file called query.inc that contains two defitinion classes (in the same file, I don't know this is a a problem too)
class InsertQuery_mysql extends InsertQuery
....
class TruncateQuery_mysql extends TruncateQuery
I thought that if I use "new \ClassName()" the "default namespace" inside this class would be "\" too and not the first called class's namespace.
I don't like to modify 3rd party libraries, is any way to avoid this? I guess is a architecture problem rather than a lack of definition if someone has a better idea, I appreciate.
Thanks!
EDIT2: Adding more info...
In order of execution.
index.php:
require_once 'vendor/autoload.php';
require_once DRUPAL_ROOT.'/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
...
app/SiteController.php:
use Models\Campaign;
class SiteController {
...
$campaing = new Campaign();
...
app/Models/Campaing.php:
namespace Models;
class Campaign extends EntityModel {
...
app/Models/EntityModel.php:
namespace Models;
use \EntityFieldQuery; //<-- this should go without \ as I say in EDIT section
class EntityModel {
...
public function getAll() {
$query = new EntityFieldQuery(); //<--throwed Models\InsertQuery not found. It must have \ at the beginning of the class name.
To answer the base question (and pending further code) PHP namespaces are set by whichever namespace is declared in the file.
// Bar.php
namespace Foo;
class Bar {}
// some other file
use Foo\Bar;
$test = new Bar(); //works
// different file
namespace Foo;
$test = new Bar(); // works
// another file
require 'Bar.php';
// won't work because we are not in namespace "Foo"
$test = new Bar();
In your specific case it the use \EntityLoader should be use EntityLoader because you're exiting the namespace you want to be inside.

PHP Extending Class one Folder Back

I have a base abstract class, say Base.php located at /lib/Helper/Base.php. Now, I have another class, say Awesome.php located at /lib/Helper/Awesome/Awesome.php, and this class needs to extend Base.
I have defined my namespaces as follows:
Base.php
<?php namespace Helper;
abstract class Base
{
}
Awesome.php
<?php namespace Helper\Awesome;
class Awesome extends Base
{
}
Right now, this says that class Base was not found. I tried to use require_once and/or include to the path of Base.php and they also didn't work. What am I doing wrong?
You are including the file, and that is the right thing to do. But you are also using
namespaces.
the namespace is not a folder, that means the namespace 'Helper' is not a folder but a logical hierarchy. In order to use the class Base in he logical namespace Helper the Awesome class needs to extend the Base class with the full logical path i.e. \Helper\Base.
namespace Helper\Awesome;
class Awesome extends \Helper\Base {
}
or use the use/as keyword instead (like c# using statement) .
namespace Helper\Awesome;
use \Helper\Base as Base;
class Awesome extends Base
{
}
more information can be fount at the php.net site.
here is a direct reference: http://php.net/manual/en/language.namespaces.importing.php

Confusion with PHP Namespace

I'm using php for my new project which is quite large. I feel the need to employ namespaces.
I have read many docs on it, but am confused practically about. Here is the scenario:
I have defined the following namespace and class:
namespace urlNS;
class URL
{
// content of the class
}
And then in another file, I want to define a class in the same namespace (urlNS) and also extend the URL class (which is a subset of urlNS namespace), and to do this, I have done:
namespace urlNS:
class Inc extends urlNS\url
{
// content
}
Now, I wanted to make use of a defined namespace twice (or even more), did I do it in a right way?
Base class definition:
<?php
namespace urlNS;
class URL {}
Subclass:
<?php
namespace urlNS;
class Inc extends URL {}
Using:
<?php
$url = new urlNS\URL();
$suburl = new urlNS\Inc();
Or with use keyword:
<?php
use urlNS\URL;
$url = URL();

How to include a custom class in a Symfony Bundle?

I have a Symfony bundle where I will have to use a custom class. This class does not have to be accessible from all the website, but just in a controller of this bundle.
I have seen a few solutions relative to the vendors, but this is quite heavy and not necessary in my case.
Does someone have a simpler solution?
This is what namespaces are for.
From php.net:
What are namespaces? In the broadest definition namespaces are a way of encapsulating items.
Simply put, include your namespace at the top of your custom class.
src/Acme/DemoBundle/Model/MyClass.php
<?php
namespace Acme\DemoBundle\Model;
class MyClass { // ...
and use it in your Controller:
src/Acme/SomeOtherBundle/Controller/DefaultController.php
<?php
namespace Acme\SomeOtherBundle\Controller;
// ...
use Acme\DemoBundle\Model\MyClass; # can be used in any class in any bundle
// ...
class DefaultController extends Controller { // ...
Class must be created in Acme\Bundle\Model namespace and folder, not \Class! Who says this?!
// ../src/Acme/Bundle/Model/Utility.php
<?php namespace Acme\Bundle\Model;
class Utility:
..
Using in controllers:
<?php ..
use Acme\Bundle\Model\Utility;
$x = new Utility(); // FINE!:)
Name of file (Utility.php) must be equal to the class name.

php psr autoload ambiguity

I am working on a php sdk rewrite project and the client wants to get PSR standards done. I am looking at the standards page here
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
One thing what i am not able to understand, if i use name spaces in my class do i still need to use include or require or use. I mean the whole reason of autoload beats the purpose right ?
For example, say i have a class this way,
namespace Employee\Department;
Class Department
{
//code
}
and i have another class which uses this class by extending it,
namespace Employee\community;
Class Community extends Department
{
//code
}
so does the above code make it to psr-0 standard considering that i have an autoload function exactly thats on the link above.
The second example is going to assume Department is in the Community namespace so in this case you would need a use statement. Also both of your examples would use the namespace Employee not Employee\Whatever for example lets assume the following layout:
Employee/
Community.php
Community/
Manager.php
Department.php
Department/
Manager.php
Then we would see the class/namespaces like the following
namespace Employee;
class Department {
}
///////////
namespace Employee;
class Community extends Department {
}
/////////////
namespace Employee\Department;
class Manager {
}
/////////////
namespace Employee\Community;
use Employee\Department\Manager as BaseManager;
Class Manager extends BaseManager {
}
For your understanding, autoloading works by registering the autoload function in the autoload stack via spl_autoload_register; this allows the function to be invoked whenever a new Class() statement is executed (more info).
On the other hand, the FIG standard for autoloading, PSR-0, defines how a namespace will be translated into a filename by a PSR-0 autoloader function. For example, given the namespace Vendor\Foo, the autoloader will look for the file Vendor/Foo.php having the following code
namespace Vendor;
class Foo
{
public function do()
{
echo "Foo";
}
}
Therefore, following the mandatory requirements, a PSR-0 compliant namespace resolves to the correct PHP file which could otherwise have been included using a require or include.
If I read your intentions correctly, you just need the following namespace in both code snippets:
namespace Employee;
Of course, this is not a PSR-0 namespace because there is no vendor name (unless your vendor name is 'Employee'). Anyway, using this namespace in your two code snippets will work fine.
However, if you intended to keep them in separate namespaces, then the autoloader won't figure out Department in extends Department in the second snippet. You will have to either import the namespace or explicitly specify it as so:
namespace Employee\community;
class Community extends Employee\Department\Department
{
//code
}
I imagine that you did not expect the full class names from your snippets to be Employee\Department\Department, and that is why I first suggested keeping the same namespace for your purposes.

Categories