Como a palavra-chave “use” funciona no PHP e posso importar classes com ele?


136

Eu tenho um arquivo com uma classe Resp. O caminho é:

C:\xampp\htdocs\One\Classes\Resp.php

E eu tenho um index.phparquivo neste diretório:

C:\xampp\htdocs\Two\Http\index.php

Neste index.phparquivo, quero instanciar uma classe Resp.

$a = new Resp();

Eu sei que posso usar requireou includepalavras-chave para incluir o arquivo em uma classe:

require("One\Classes\Resp.php");       // I've set the include_path correctly already ";C:\xampp\htdocs". It works.
$a = new Resp();

Mas quero importar classes sem usar requireou include. Estou tentando entender como a usepalavra-chave funciona. Eu tentei essas etapas, mas nada funciona:

use One\Classes\Resp;
use xampp\htdocs\One\Classes\Resp;
use htdocs\One\Classes\Resp;
use One\Classes;
use htdocs\One\Classes;    /* nothing works */

$a = new Resp();

Diz:

Fatal error: Class 'One\Classes\Resp' not found in C:\xampp\htdocs\Two\Http\index.php

Como a palavra-chave usefunciona? Posso usá-lo para importar classes?


1
Você não pode sem importar os arquivos. Por favor, não mude o fluxo. Também os namespaces realmente não são usados ​​no PHP. Assim como o VB.NET
Cole Johnson

13
@ cole-johnson, não concordo com você. Symfony é construído em torno de namespaces. De fato, não existe nenhum Symfony se você não usa espaços para nome
Green

Respostas:


80

usenão inclui nada. Apenas importa o namespace (ou classe) especificado para o escopo atual

Se você deseja que as aulas sejam carregadas automaticamente - leia sobre o carregamento automático


@ G-Man responde às próprias perguntas.
zerkms 27/03

188

Não, você não pode importar uma classe com a usepalavra - chave. Você tem que usar include/ requiredeclaração. Mesmo se você usar um carregador auto PHP, ainda autoloader terá que usar includeou requireinternamente.

A palavra-chave Objetivo do uso :

Considere um caso em que você tem duas classes com o mesmo nome; você achará estranho, mas quando estiver trabalhando com uma grande estrutura MVC, isso acontece. Portanto, se você tiver duas classes com o mesmo nome, coloque-as em espaços para nome diferentes. Agora considere quando o seu carregador automático está carregando as duas classes (faz por require) e você está prestes a usar o objeto da classe. Nesse caso, o compilador ficará confuso sobre qual objeto de classe carregar entre dois. Para ajudar o compilador a tomar uma decisão, você pode usar a useinstrução para que ele possa tomar uma decisão na qual será usada.

Atualmente, as principais estruturas usam includeou requirevia composerepsr

1) compositor

2) Carregador automático PSR-4

Passar por eles pode ajudá-lo ainda mais. Você também pode usar um alias para abordar uma classe exata. Suponha que você tenha duas classes com o mesmo nome, digamos, Mailercom dois namespaces diferentes:

namespace SMTP;
class Mailer{}

e

namespace Mailgun;
class Mailer{}

E se você quiser usar as duas classes Mailer ao mesmo tempo, poderá usar um alias.

use SMTP\Mailer as SMTPMailer;
use Mailgun\Mailer as MailgunMailer;

Posteriormente no seu código, se você quiser acessar esses objetos de classe, poderá fazer o seguinte:

$smtp_mailer = new SMTPMailer;
$mailgun_mailer = new MailgunMailer;

Ele fará referência à classe original.

Alguns podem ficar confusos com o fato de que, então, não há nomes de classes semelhantes, então não há uso de usepalavras-chave. Bem, você pode usar a __autoload($class)função que será chamada automaticamente quando a useinstrução for executada com a classe a ser usada como argumento e isso pode ajudá-lo a carregar a classe no tempo de execução em tempo real, conforme necessário.

Consulte esta resposta para saber mais sobre o carregador automático de classes.


por que não usar apenas um nome de classe diferente?
divino

15
@divino. As aulas podem ser de vendedores 3rd party
Dayo

3
@divino. E se as duas classes de colisão forem de terceiros?
Dayo

2
@divine Por convenção, o namespace será <vendorName> / <packageName>, dessa forma, já foi resolvido. Após a convenção, é impossível que o packagist aceite o mesmo nome de fornecedor de outra pessoa. E o packagist.org é um repositório PHP usado para instalação de pacotes pelo compositor.
22417 Tpojka

1
O @root não importa, apenas informa ao tempo de execução o que deve ser usado. como se você estivesse dirigindo um carro e o sinal lhe dissesse que avançasse e quebre, a useinstrução way dirá ao compilador carregar isso para mim agora. Entendi querido!
Rajan Rawal

23

Não pense demais sobre o que é um espaço para nome .

O espaço para nome é basicamente apenas um prefixo de classe (como o diretório no sistema operacional) para garantir a exclusividade do caminho da classe .

Além disso, para esclarecer as coisas, a instrução use não está fazendo nada apenas com alias nos seus Namespaces, para que você possa usar atalhos ou incluir Classes com o mesmo nome, mas com Namespace diferente no mesmo arquivo.

Por exemplo:

// You can do this at the top of your Class
use Symfony\Component\Debug\Debug;

if ($_SERVER['APP_DEBUG']) {
    // So you can utilize the Debug class it in an elegant way
    Debug::enable();
    // Instead of this ugly one
    // \Symfony\Component\Debug\Debug::enable();
}

Se você quiser saber como os namespaces do PHP e o carregamento automático (tanto da maneira antiga quanto da nova com o Composer) funcionam, você pode ler a postagem do blog que acabei de escrever sobre este tópico: https://enterprise-level-php.com/ 2017/12/25 / the-magic-behind-autoloading-php-files-using-compositer.html


8

Você precisará incluir / exigir a classe de qualquer maneira, caso contrário, o PHP não saberá sobre o espaço para nome.
Você não precisa fazê-lo no mesmo arquivo. Você pode fazer isso em um arquivo de inicialização, por exemplo. (ou use um carregador automático, mas esse não é o assunto)


4

O problema é provavelmente o de que você precisará usar um carregador automático que pegue o nome da classe (neste caso, use '\') e mapeie-o para uma estrutura de diretórios.

Você pode conferir este artigo sobre a funcionalidade de carregamento automático do PHP. Já existem muitas implementações desse tipo de funcionalidade em estruturas.

Na verdade, eu implementei um antes. Aqui está um link .


Há um problema com isso, no entanto. Ele precisa de um modelo recursivo para permitir a construção de um caminho completo. No momento, ele lida apenas com namespaces de nível único.
Tyler Carter

3

Concordo com o Green, o Symfony precisa de espaço para nome, então por que não usá-lo?

É assim que uma classe de controlador de exemplo é iniciada:

namespace Acme \ DemoBundle \ Controller;

use Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller;

classe WelcomeController estende o Controller {...}


3

Posso usá-lo para importar classes?

Você não pode fazer isso além dos exemplos acima. Você também pode usar a palavra-chave usedentro de classes para importar características , desta forma:

trait Stuff {
    private $baz = 'baz';
    public function bar() {
        return $this->baz;
    }
}

class Cls {
    use Stuff;  // import traits like this
}

$foo = new Cls;
echo $foo->bar(); // spits out 'baz'

3

A usepalavra-chave é para alias no PHP e não importa as classes. Isso realmente ajuda
1) Quando você tem classes com o mesmo nome em diferentes espaços para nome
2) Evite usar um nome muito longo de classe repetidamente.


2

O espaço para nome é usado para definir o caminho para um arquivo específico que contém uma classe, por exemplo

namespace album/className; 

class className{
//enter class properties and methods here
}

Você pode incluir essa classe específica em outro arquivo php usando a palavra-chave "use", assim:

use album/className;

class album extends classname {
//enter class properties and methods
}

NOTA: Não use o caminho para o arquivo que contém a classe a ser implementada; o uso prolongado é usado para instanciar um objeto, mas somente o espaço para nome.


2

Usar a palavra-chave "use" é para encurtar literais de namespace. Você pode usar ambos com alias e sem ele. Sem alias, você deve usar a última parte do espaço para nome completo.

<?php
    use foo\bar\lastPart;
    $obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.