gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
¡Tengo una idea! Dominemos los espacios de nombres de PHP... y hagámoslo en menos de 5 minutos. Toma un café... ¡vamos!
Conoce a Foo
: una clase de PHP perfectamente aburrida:
... lines 1 - 2 | |
class Foo | |
{ | |
public function doAwesomeThings() | |
{ | |
} | |
} |
¡Saluda a Foo
! Divertidísimo.
... lines 1 - 2 | |
class Foo | |
{ | |
public function doAwesomeThings() | |
{ | |
echo "Hi Foo!\n"; | |
} | |
} |
Para instanciar nuestra nueva clase favorita, me desplazaré a otro archivo y diré - redoble de tambores - $foo = new Foo()
:
... lines 1 - 2 | |
require 'Foo.php'; | |
$foo = new Foo(); |
¡Tada! Incluso podemos llamar a un método en ella: $foo->doAwesomeThings()
:
... lines 1 - 2 | |
require 'Foo.php'; | |
$foo = new Foo(); | |
$foo->doAwesomeThings(); |
¿Funcionará? ¡Por supuesto! Puedo abrir un terminal y ejecutar
php some-other-file.php
¡Ahora mismo, Foo
no tiene un espacio de nombres! Para que Foo
sea más hipster, vamos a arreglarlo. Encima de la clase, añade, qué tal, namespace Acme\Tools
:
... lines 1 - 2 | |
namespace Acme\Tools; | |
class Foo | |
{ | |
... lines 7 - 10 | |
} |
Normalmente el espacio de nombres de una clase coincide con su directorio, pero eso no es técnicamente necesario. ¡Esto lo acabo de inventar yo!
¡Enhorabuena! Nuestro amigo Foo
vive ahora en un espacio de nombres. Poner una clase en un espacio de nombres es muy parecido a poner un archivo en un directorio. Para referenciarla, utiliza la ruta completa y larga de la clase: Acme\Tools\Foo
:
... lines 1 - 2 | |
require 'Foo.php'; | |
$foo = new \Acme\Tools\Foo(); | |
... lines 6 - 8 |
al igual que puedes utilizar la ruta absoluta para referenciar un archivo en tu sistema de archivos:
ls /acme/tools/foo
Cuando probamos ahora el script
php some-other-file.php
¡Sigue funcionando!
Y... ¡eso es realmente! Los espacios de nombres son básicamente una forma de... ¡hacer más largos los nombres de tus clases! Añade el espacio de nombres... y luego haz referencia a la clase utilizando el espacio de nombres más el nombre de la clase. Eso es todo.
Pero... ¡tener estos largos nombres de clase justo en medio de tu código es un fastidio! Para solucionarlo, los espacios de nombres de PHP tienen una cosa más especial: la declaración use
. Al principio del archivo, añade use Acme\Tools\Foo as SomeFooClass
:
... lines 1 - 2 | |
require 'Foo.php'; | |
use Acme\Tools\Foo as SomeFooClass; | |
... lines 6 - 10 |
Esto crea una especie de... "acceso directo". En cualquier otro lugar de este archivo, ahora podemos escribir simplemente SomeClassFoo
:
... lines 1 - 2 | |
require 'Foo.php'; | |
use Acme\Tools\Foo as SomeFooClass; | |
$foo = new SomeFooClass(); | |
... lines 8 - 10 |
y PHP sabrá que realmente nos estamos refiriendo al nombre largo de la clase: Acme\Tools\Foo
.
php some-other-file.php
O... si omites la parte as
, PHP asumirá que quieres que este alias seaFoo
. Así es como suele quedar el código:
... lines 1 - 2 | |
require 'Foo.php'; | |
use Acme\Tools\Foo; | |
$foo = new Foo(); | |
... lines 8 - 10 |
Así pues, los espacios de nombres hacen que los nombres de las clases sean más largos... y las sentencias use
nos permiten crear atajos para poder utilizar el nombre "corto" en nuestro código.
En el código PHP moderno, casi todas las clases con las que tratas viven en un espacio de nombres... excepto las clases centrales de PHP. Sí, las clases principales de PHP no viven en un espacio de nombres... lo que significa que viven en el espacio de nombres "raíz", como un archivo en la raíz de tu sistema de archivos:
ls /some-root-file
Juguemos con el objeto del núcleo DateTime
: $dt = new DateTime()
y luegoecho $dt->getTimestamp()
con un salto de línea:
... lines 1 - 8 | |
$foo->doAwesomeThings(); | |
$dt = new DateTime(); | |
echo $dt->getTimestamp()."\n"; |
Cuando ejecutamos el script:
php some-other-file.php
¡Funciona perfectamente! Pero... ahora mueve ese mismo código al método doAwsomeThings
dentro de nuestro amigo Foo
:
... lines 1 - 2 | |
namespace Acme\Tools; | |
class Foo | |
{ | |
public function doAwesomeThings() | |
{ | |
echo "Hi Foo!\n"; | |
$dt = new DateTime(); | |
echo $dt->getTimestamp()."\n"; | |
} | |
} |
Ahora prueba el código:
php some-other-file.php
¡Ah! ¡Explota! ¡Y comprueba este error!
Clase
Acme\Tools\DateTime
no encontrada
El nombre real de la clase debería ser simplemente DateTime
. Entonces, ¿por qué PHP cree que esAcme\Tools\DateTime
? Porque los espacios de nombres funcionan como directorios! Foo
vive en Acme\Tools
. Cuando decimos simplemente DateTime
, es lo mismo que buscar un archivoDateTime
dentro de un directorio Acme/Tools
:
cd /acme/tools
ls DateTime # /acme/tools/DateTime
Hay dos formas de solucionar esto. La primera es utilizar el nombre de clase "totalmente cualificado". Así, \DateTime
... lines 1 - 2 | |
namespace Acme\Tools; | |
class Foo | |
{ | |
public function doAwesomeThings() | |
{ | |
... lines 9 - 10 | |
$dt = new \DateTime(); | |
... line 12 | |
} | |
} |
Sí... eso funciona igual que un sistema de archivos.
php some-other-file.php
O... puedes usar DateTime
... y luego eliminar el \
de abajo
... lines 1 - 2 | |
namespace Acme\Tools; | |
use DateTime; | |
class Foo | |
{ | |
public function doAwesomeThings() | |
{ | |
... lines 11 - 12 | |
$dt = new DateTime(); | |
... line 14 | |
} | |
} |
En realidad es lo mismo: no hay \
al principio de una declaración use
, pero debes fingir que lo hay. Esto hace que DateTime
pase a ser \DateTime
.
Y... ¡hemos terminado! Los espacios de nombres hacen que los nombres de tus clases sean más largos, las sentencias de uso te permiten crear "atajos" para que puedas utilizar nombres cortos en tu código y todo el sistema funciona exactamente igual que los archivos dentro de los directorios.
¡Diviértete!
Hey Ole,
Probably it was not so obvious. Yes, it's the way to avoid collisions with same class names. Thank you for sharing this tip with others!
Cheers!
Hey Herman,
Yep, exactly... the concept is not unique, and it's used in many programming languages actually :)
Cheers!
I'm not sure why I keep having error issues with some challenges. Its random. I tried 2 computers, 2 different browsers and I get this error for exercise 5 on this php namespace tutorial. Class Pizza and eat.php are locked and can't be edited. I've come across an error below like this before on another challenge.
Error! This PHP error is coming from your code. Read it carefully to debug!
( ! ) Fatal error: Uncaught Error: Class 'Pizza' not found in eat.php on line 5
>( ! ) Error: Class 'Pizza' not found in eat.php on line 5
Call Stack
#TimeMemoryFunctionLocation
... See the Browser below for the full output.
Hey Terrence,
As I already answered to your other comments, you just need to wait when the challenge is shut down, refresh the page so that the system create a new challenge instance for you and try again. It happens sometimes, though it depends on how you're using the system. Are you trying to open a few challenges at the same time in different tabs? Are you trying to solve it first or after the page is loaded you hit the Check button to see the error instead of trying to solve it? Please, share more details with us about how exactly you're using challenges and I'll be happy to check it further.
Cheers!
There were a couple times I tried hitting check to see if any errors show but the server kept crashing, so I stop doing that. I don't have challenges opened in more than 1 tab, so only working 1 challenge at a time.
What I have been doing now is try to solve it, then hit check and make updates if needed. Sometimes I have the answer exactly correct the first try and it shows the error. I verify its correct in the show answer section but it will still throw the error that doesn't make sense.
Hey Terrence,
I see... Thank you for sharing more information about how you're using the challenge system. We will try to take a look to improve it. I can only suggest you wait until the challenge instance is shut down and restart the page to recreate a new challenge instance from scratch - it should work the 2nd time. Sorry for the inconvenience!
Cheers!
Thanks for the tutorial, great! Could you elaborate on the backslashes, though? Should it be 'use \...' or 'use ...' from inside a namespace?
I miss the hint, that with the help of namespaces, you can have multiple classes with the same name, but in different namespaces and are able to reference them accordingly with the help of use statements and aliases, even on the same file: