AVELX

Looking for services?

Consultations

You've come so far why not go the whole hog?

Training

You've come so far why not go the whole hog? Join all the fun!

Code Reviews

You've come so far why not go the whole hog?

Push Title

Get unlimited access to source code, repositories, source code and cheatsheets.

PHP Namespace’s & group use declarations
Education, Hacks and Strategy

Free educational material provided by Avelx, ensuring clean and clear delivery on all aspects of programming and architecture

When it comes to large scale applications we need to make sure we don’t have conflicting class, function and constant name’s, otherwise we could end up stepping on our own toes. The danger is if we overwrite our classes in PHP, how would we know? We don’t! Until the program is compiles and errors.

To save grief we have namespace’s to keep all class, function and constant name’s seperate from one another by keeping them in a unique namespace which we can define. Lets take a look at an example:

<?php
	class MyClass1 { }
	class MyClass2 { }
	function MyFunc1( ) { }
	function MyFunc2( ) { }
	const CON1 = 'Unchangable string';
	const CON2 = 'Unchangable string 2';

This looks simple enough; we have classes, functions and constants. Each one has a specific name so we can address it. However what happens when I create another file in my project which has exactly the same class, function and constant name's which I've already used? Well PHP will just error. To follow along create File1, File2 and the Index PHP files within your project's directory:

FILE1.php

<?php
	class MyClass1 { }
	class MyClass2 { }
	function MyFunc1( ) { }
	function MyFunc2( ) { }
	const CON1 = 'Unchangable string';
	const CON2 = 'Unchangable string 2';

FILE2.php

<?php
	class MyClass1 { }
	class MyClass2 { }
	function MyFunc1( ) { }
	function MyFunc2( ) { }
	const CON1 = 'ERROR File1.php already has CON1 constant!!!';
	const CON2 = 'ERROR File1.php already has CON2 constant!!!';

Index.php

<?php
	require( 'File1.php' );
	require( 'File2.php' );

If you now open your browser and navigate to index.php you'll find an error message will show because File1.php and File2.php will have conflicting class, function and constant name's which cannot be overwritten, causing an error. If this happened in a large scale project it'd be disastrous! The solution is to use namespaces to prevent our class, function and constant name's from clashing like so:

FILE1.php

<?php
	namespace avelx;

	class MyClass1 { }
	class MyClass2 { }
	function MyFunc1( ) { }
	function MyFunc2( ) { }
	const CON1 = 'Unchangable string';
	const CON2 = 'Unchangable string 2';

FILE2.php

<?php
	namespace avelx\anotherNamespace;

	class MyClass1 { }
	class MyClass2 { }
	function MyFunc1( ) { }
	function MyFunc2( ) { }
	const CON1 = 'ERROR File1.php already has CON1 constant!!!';
	const CON2 = 'ERROR File1.php already has CON2 constant!!!';

Index.php

<?php
	require( 'File1.php' );
	require( 'File2.php' );

Now when you run Index.php you'll notice there's no error and our class, function and constant name's maintain their integrity. Lets now use these namespace's to return or invoke every piece of data within File1 and File2.

Index.php

<?php
	require( 'File1.php' );  // namespace avelx;
	require( 'File2.php' ); // namespace avelx\anotherNamespace;

	new avelx\MyClass1;
	new avelx\MyClass2;
	avelx\MyFunc1( );
	avelx\MyFunc2( );
	avelx\CON1;
	avelx\CON2;

	new avelx\anotherNamespace\MyClass1;
	new avelx\anotherNamespace\MyClass2;
	avelx\anotherNamespace\MyFunc1( );
	avelx\anotherNamespace\MyFunc2( );
	avelx\anotherNamespace\CON1;
	avelx\anotherNamespace\CON2;

You'll notice all our names from File1 and File2 are separated and don't conflict. However typing all these namespaces each time is tedious and could lead to mistyping the namespace causing further errors. Lets now solve the problem with aliases; for example my namespace is 'Lawrence Anthony Turton' but people don't say "hi Lawrence Anthony Turton all the time", they say "hi Loz". 'Loz' is my alias which people typically use because saying my full name is too cumbersome. So an alias is simply a nickname, it doesn't replace my name but people can use the alias to address me.

Now lets create an alias in my Index.php where I'm pulling in File1 and File2. Once these files have been pulled in and their respective namespace's; we can create an alias, a nickname, for each namespace. We say use as for example, my namespace alias would be: use as . Take a look:

Index.php

<?php
	require( 'File1.php' );  // namespace avelx;
	require( 'File2.php' ); // namespace avelx\anotherNamespace; 

	use avelx as av;
	use avelx\anotherNamespace as av2;

	new av\MyClass1;
	new av\MyClass2;
	av\MyFunc1( );
	av\MyFunc2( );
	av\CON1;
	av\CON2;

	new av2\MyClass1;
	new av2\MyClass2;
	av2\MyFunc1( );
	av2\MyFunc2( );
	av2\CON1;
	av2\CON2;

You can see I've given the namespace 'avelx' the alias of 'av' and 'avelx\anotherNamespace' of 'av2'. So now you can see how simpler and cleaner the code is. So this is giving an entire namespace an alias and then we have to use that alias to fetch any class, function or constant within that namespace.

However what if we don't want to use the namespace alias at all. We want to use the original names of our classes, function's or constant's. This can be done, 'use' or 'use as' statements can target a specific class, function or constant. Note a use statement for a function is 'use function' and for a constant 'use const'; however for a class it's just the regular use statement. Here's an example:

Index.php

<?php
	require( 'File1.php' );  // namespace avelx;
	require( 'File2.php' ); // namespace avelx\anotherNamespace; 

	use avelx\MyClass1;
	use avelx\MyClass2;
	use function avelx\MyFunc1;
	use function avelx\MyFunc2;
	use const avelx\CON1;
	use const avelx\CON2;

	new MyClass1;
	new MyClass2;
	MyFunc1( );
	MyFunc2( );
	CON1;
	CON2;

Notice the namespace 'avelx' is missing; we can just call that class, function or constant directly by its name. However this again may cause conflict because I have two namespaces, 'avelx' and 'avelx\anotherNamespace' which has conflicting class, function and constant name's which in turn means if we try this...

Index.php

<?php
	require( 'File1.php' );  // namespace avelx;
	require( 'File2.php' ); // namespace avelx\anotherNamespace; 

	use avelx\MyClass1;
	use avelx\MyClass2;
	use function avelx\MyFunc1;
	use function avelx\MyFunc2;
	use const avelx\CON1;
	use const avelx\CON2;

	use avelx\anotherNamespace\MyClass1;
	use avelx\anotherNamespace\MyClass2;
	use function avelx\anotherNamespace\MyFunc1;
	use function avelx\anotherNamespace\MyFunc2;
	use const avelx\anotherNamespace\CON1;
	use const avelx\anotherNamespace\CON2;

... This will error because we now have conflicting class, function and constant name's which must never be the case. But there is a way to solve this, because you can create custom aliases for your function, class or constant name's. So lets solve this problem:

Index.php

<?php
	require( 'File1.php' );  // namespace avelx;
	require( 'File2.php' ); // namespace avelx\anotherNamespace; 

	use avelx\MyClass1;
	use avelx\MyClass2;
	use function avelx\MyFunc1;
	use function avelx\MyFunc2;
	use const avelx\CON1;
	use const avelx\CON2;

	use avelx\anotherNamespace\MyClass1 as CL1;
	use avelx\anotherNamespace\MyClass2 as CL2;
	use function avelx\anotherNamespace\MyFunc1 as F1;
	use function avelx\anotherNamespace\MyFunc2 as F2;
	use const avelx\anotherNamespace\CON1 as C1;
	use const avelx\anotherNamespace\CON2 as C2;

	new MyClass1;
	new MyClass2;
	MyFunc1( );
	MyFunc2( );
	CON1;
	CON2;

	/* avelx\anotherNamespace... */

	new CL1;
	new CL2;
	F1( );
	F2( );
	C1;
	C2;

This code will not error because we've directly applied aliases to all the classes, function's and constant's that belong to the 'avelx\anotherNamespace'. So this resolves the issue; but each of our class, function and constant name's have a 'use' or 'use as' statement which becomes very inefficient when considering our namespace could contain many classes, function's or constant's making this approached pretty much a non starter.

PHP7+ allows grouping of 'use' or 'use as' statements which makes for cleaner syntax. Take a look at the same code but it in PHP7+:

Index.php

<?php
	require( 'File1.php' );  // namespace avelx;
	require( 'File2.php' ); // namespace avelx\anotherNamespace;

	use avelx\{ MyClass1, MyClass2 };
	use function avelx\{ MyFunc1, MyFunc2 };
	use const avelx\{ CON1, CON2 };

	use avelx\anotherNamespace\{ MyClass1 as CL1, MyClass2 as CL2 };
	use function avelx\anotherNamespace\{ MyFunc1 as F1, MyFunc2 as F2 };
	use const avelx\anotherNamespace\{ CON1 as C1, CON2 as C2 };

	new MyClass1;
	new MyClass2;
	MyFunc1( );
	MyFunc2( );
	CON1;
	CON2;

	/* avelx\anotherNamespace... */

	new CL1;
	new CL2;
	F1( );
	F2( );
	C1;
	C2;

Take a deep breath. Here's what we've covered:

1. Namespaces separate only class, function or constant name's.
2. Namespaces can have an alias or nickname to make things easier.
3. We can 'use' the class, function or constant name by targeting it directly in that namespace. For example: use avelx\MyClass1; now I can call MyClass1 directly without typing the namespace.
4. We can also create aliases, or nicknames, directly for a given class, function or constant within a namespace. For example: use avelx\anotherNamespace\MyClass1 as CL1; . Which I can now use the alias CL1 to instantiate MyClass1 in the avelx\anotherNamespace like so... $var = new CL1; .
5. PHP7+ allows for multiple class, function and constant name's to be done within one statement. For example: use avelx\{ MyClass1, MyClass2 }; .
6. PHP7+ allows multiple aliases to be setup for classes, function's and constant's within a namespace. For example: use avelx\{ MyClass1 as CL1, MyClass2 as CL2 }; .

Hopefully that recap helped sum things up. Now you can understand namespaces and their functionality for your large scale modular PHP program's.

Consultations

You've come so far why not go the whole hog?

Training

You've come so far why not go the whole hog? Join all the fun!

Code Reviews

You've come so far why not go the whole hog?