Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Espacios de nombres PHP en menos de 5 minutos

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

¡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

Conoce a Foo: una clase de PHP perfectamente aburrida:

9 lines Foo.php
... lines 1 - 2
class Foo
{
public function doAwesomeThings()
{
}
}

¡Saluda a Foo! Divertidísimo.

10 lines Foo.php
... 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

Namespaces: Haciendo a Foo más Hipster

¡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:

12 lines Foo.php
... 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!

Utilizar una clase con espacio de nombres

¡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!

La declaración de uso mágica y opcional

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.

Clases Básicas de PHP

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 doAwsomeThingsdentro de nuestro amigo Foo:

15 lines Foo.php
... 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

15 lines Foo.php
... 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

17 lines Foo.php
... 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!

Leave a comment!

12
Login or Register to join the conversation
Coaching T. Avatar
Coaching T. Avatar Coaching T. | posted hace 2 años | edited

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:


namespace App;

use App\Domain\Foo;
use App\Utils\Foo as UtilsFoo;

class Bar {

  public function foobar() {
    $foo = new Foo();
    $utilFoo = new UtilsFoo();

   $foo->doStuff();
   $utilFoo->doStuff();
  }

}
2 Reply

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!

Reply
Herman Avatar

It's very similar to packages in Java

Reply

Hey Herman,

Yep, exactly... the concept is not unique, and it's used in many programming languages actually :)

Cheers!

Reply
Terrence Avatar
Terrence Avatar Terrence | posted hace 6 meses | edited

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.

Reply

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!

Reply
Terrence Avatar

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.

Reply

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!

Reply
Eduard Avatar

So it is the equivalent to packages in Java?

Reply

Hey Eduard

Yeah something like this :)

Cheers!

Reply
Default user avatar
Default user avatar Dan Marshall | posted hace 4 años

Thanks for the tutorial, great! Could you elaborate on the backslashes, though? Should it be 'use \...' or 'use ...' from inside a namespace?

Reply
Default user avatar
Default user avatar C Silkey | posted hace 4 años

Thanks, kept your 120 second promise :)

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

userVoice