PHP [PHP] Chiarimento sull'inclusione delle classi in altri file

Stato
Discussione chiusa ad ulteriori risposte.

ken_korn

Utente Bronze
27 Aprile 2017
28
11
4
40
Ultima modifica:
In questi giorni sto affrontando lo studio del PHP OOP e vorrei porre un paio di domande da principiante.
Ho questi due file:
Index.php
PHP:
<?php

require 'Person.php';

$name = new Persona("Gianni");
echo $name->getName();

?>

Person.php
PHP:
<?php

class Persona {
    //proprietà
    public $name_1 = "";
   
    //costruttore
    public function __construct($name) {
        $this->name_1 = $name;
    }
   
    //metodi
    public function getName() {
        //$this rappresenta l'oggetto che sarà costruito a runtime
        return $this->name_1;
    }
       
}
?>
Ecco quindi un paio di dilemmi da principiante:
1) Io ho usato l'istruzione require per includere la classe Persona nel file index.php, ma che differenze ci sono nell'usare require(o include), namespace o use? Quale sintassi è meglio adottare?
2) Simile alla domanda 2, ho letto di alcune librerie PHP (es. Twig e SwiftMailer) che non hanno namespace ma possono essere comunque integrate in pagine PHP che ne fanno uso tramite diversi espedienti. Non capendo la spiegazione data nella guida chiedo a chi di competenza una delucidazione a riguardo.

Spero che qualche anima pia mi aiuti XD
 
Vedi come hai impostato la classe e la funzione su public.
Poi dovrebbe andare bene:
PHP:
include_once 'path/to/functions.php';
require_once 'path/to/functions.php';
require 'path/to/functions.php';
require_once $class_name . '.php';
se non funge scusami, ma non sono un esperto di php, ma dovrebbe andare cosi'
 
Ultima modifica:
Vedi come hai impostato la classe e la funzione su public.
Poi dovrebbe andare bene:
PHP:
include_once 'path/to/functions.php';
require_once 'path/to/functions.php';
require 'path/to/functions.php';
require_once $class_name . '.php';
se non funge scusami, ma non sono un esperto di php, ma dovrebbe andare cosi'
Grazie per la risposta Gorate, ho risolto il primo problema (era dovuto a un altro errore nello script, perciò ho riformulato la domanda).
Aspetto che qualcuno mi dia qualche spiegazione riguardo gli altri due punti
 
include e require sono praticamente uguali, entrambi ti permettono di includere un file, con un'unica differenza:
  • include, nel caso in cui non trova il file, ti genera un messaggio di warning.
  • require, nel caso in cui non trova il file, ti genera un fatal error.
Per quanto riguarda la differenza tra warning e fatal error, detta in parole povere:
  • Il messaggio di warning, ti mostra un messaggio di avvertimento senza interrompere l'esecuzione del tuo script.
  • il fatal error, interrompe l'esecuzione dello script e ti mostra il messaggio di errore:
Ad accompagnare, trovi anche include_once e require_once. Fanno la stessa cosa con la differenza che prima di includere il file controllano se sia stato già incluso, e se lo è evitano di includerlo un'altra volta.

Quindi? Cosa usare? Io parto dal presupposto che un file nel 99% dei casi, di norma, non va incluso più di una volta durante l'esecuzione della pagina. Quindi usare i costrutti con prefisso _once può essere un controllo in più che non ti reca alcun problema, anche se non ci si dovrebbe affidare al controllo di questo costrutto per evitare l'inclusione dello stesso file più volte, ma si dovrebbe indagare più a fondo nel problema e cercare di evitarlo. Dopodiché se includi un file .php, sempre nel 99% dei casi, il file è strettamente necessario per la corretta esecuzione del tuo script (se no che lo includi a fare?), quindi nel caso estremo in cui non trova il file, è meglio affidarsi a un fatal error (bloccando l'esecuzione dello script) che a un messaggio di warning.

Quindi.. il consiglio è di usare sempre require_once per l'inclusione dei file. Mentre l'include_once usalo nei casi in cui credi che il file incluso possa essere omesso nel caso estremo in cui non viene trovato (per esempio l'inclusione di un file .html per un sistema di template).

Per quanto riguarda namespace e use, non sono da confondere con require/include. Perché require e include ti permettono di includere un file, mentre namespace e use sono delle keyword che ti permettono di raggruppare le tue classi in dei pacchetti/cartelle. Ovviamente HTML.it te l'ha messo li in mezzo solo per confonderti di più le idee, io non lo avrei mai messo all'inizio mentre si insegnano le basi. Ti farei degli esempi e ti spiegherei al meglio il suo utilizzo però c'è un articolo che lo spiega veramente bene e dovrebbe chiarirti le idee: PHP Namespaces Explained

Per quanto riguarda la seconda domanda: ignora. Di certo quando arriverai al livello di usare dei framework e se userai quelli citati, lo capirai durante l'utilizzo che bisogna agire in determinate maniere. Sicuramente non deve essere una guida che ti insegna le basi a dovertelo dire. Quelle cose le hanno dette (male) solo per introdurti l'uso della keyword use. Leggendo l'articolo che ti ho mandato dovrebbe farti capire meglio.

Tornando quindi alla tua domanda principale: si, come hai incluso la classe va bene, potrei solo dirti che personalmente io preferisco usare sempre require_once per i motivi che ti ho detto prima.

Mentre per l'uso di namespace e use.. diciamo che il loro utilizzo torna utile principalmente in due casi:
  • Se fai una classe in cui decidi di metterla open source. Per esempio fai una classe sulla gestione degli utenti e la chiami "user". La pubblichi in giro e ti rendi conto che il nome della classe usato è troppo generico e potrebbe essere una classe che già esiste per chi decide di usarlo sul suo sito (creando quindi conflitto). Quindi come risolvere? O cambi il nome della classe con un nome di merd* però andresti ad assegnare un nome che non c'entra niente con la funzionalità della classe, oppure metti la tua classe dentro una "cartella" tramite l'uso dei namespace.
  • Quando vai a creare un progetto abbastanza ampio e ti sarà utile organizzare le varie classi in delle "cartelle" (perché alla fine è questo che fa la keyword namespace) in modo da avere più dinamicità sulla gestione delle classi (un esempio sono i framework o dei sistemi avanzati di template).
Come potresti utilizzarlo nel tuo caso?

Usalo magari per dare un tocco di personalizzazione alle classi che crei, segnandole tutte sotto il tuo nome:

Person.php
PHP:
<?php

namespace ken_korn;

class Persona {
    //proprietà
    public $name_1 = "";
 
    //costruttore
    public function __construct($name) {
        $this->name_1 = $name;
    }
 
    //metodi
    public function getName() {
        //$this rappresenta l'oggetto che sarà costruito a runtime
        return $this->name_1;
    }
     
}
?>

Index.php

Codice:
<?php

require 'Person.php';

$name = new ken_korn\Persona("Gianni");
echo $name->getName();

?>
 
La risposta due è abbastanza ovvia, il sito la fa troppo lunga.
Se ad esempio sei nel namespace "Caccola" e vuoi utilizzare delle classi che sono senza namespace(come le librerie che mi hai citato, anche se non so se ancora sono senza namespace) devi riferirti alla classe utilizzando il backslash all'inizio, così dici al PHP che la classe che vuoi usare deve essere presa senza namespace(Il "\" all'inizio sta a simboleggiare il namespace "root").
Codice:
//File1.php
class Person {

}

//File2.php
namespace Caccola;
include "File1.php";
$person = new Person;//Errore, classe Caccola\Person non presente
$person = new \Person; //Ok, classe trovata nel namespace "globale"

L'uso dei namespace è il modo principale in cui l'Autoloading(la magia che permettere di non usare piu gli include/require) decide da dove prendere le classi.
 
include e require sono praticamente uguali, entrambi ti permettono di includere un file, con un'unica differenza:
  • include, nel caso in cui non trova il file, ti genera un messaggio di warning.
  • require, nel caso in cui non trova il file, ti genera un fatal error.
Per quanto riguarda la differenza tra warning e fatal error, detta in parole povere:
  • Il messaggio di warning, ti mostra un messaggio di avvertimento senza interrompere l'esecuzione del tuo script.
  • il fatal error, interrompe l'esecuzione dello script e ti mostra il messaggio di errore:
Ad accompagnare, trovi anche include_once e require_once. Fanno la stessa cosa con la differenza che prima di includere il file controllano se sia stato già incluso, e se lo è evitano di includerlo un'altra volta.

Quindi? Cosa usare? Io parto dal presupposto che un file nel 99% dei casi, di norma, non va incluso più di una volta durante l'esecuzione della pagina. Quindi usare i costrutti con prefisso _once può essere un controllo in più che non ti reca alcun problema, anche se non ci si dovrebbe affidare al controllo di questo costrutto per evitare l'inclusione dello stesso file più volte, ma si dovrebbe indagare più a fondo nel problema e cercare di evitarlo. Dopodiché se includi un file .php, sempre nel 99% dei casi, il file è strettamente necessario per la corretta esecuzione del tuo script (se no che lo includi a fare?), quindi nel caso estremo in cui non trova il file, è meglio affidarsi a un fatal error (bloccando l'esecuzione dello script) che a un messaggio di warning.

Quindi.. il consiglio è di usare sempre require_once per l'inclusione dei file. Mentre l'include_once usalo nei casi in cui credi che il file incluso possa essere omesso nel caso estremo in cui non viene trovato (per esempio l'inclusione di un file .html per un sistema di template).

Per quanto riguarda namespace e use, non sono da confondere con require/include. Perché require e include ti permettono di includere un file, mentre namespace e use sono delle keyword che ti permettono di raggruppare le tue classi in dei pacchetti/cartelle. Ovviamente HTML.it te l'ha messo li in mezzo solo per confonderti di più le idee, io non lo avrei mai messo all'inizio mentre si insegnano le basi. Ti farei degli esempi e ti spiegherei al meglio il suo utilizzo però c'è un articolo che lo spiega veramente bene e dovrebbe chiarirti le idee: PHP Namespaces Explained

Per quanto riguarda la seconda domanda: ignora. Di certo quando arriverai al livello di usare dei framework e se userai quelli citati, lo capirai durante l'utilizzo che bisogna agire in determinate maniere. Sicuramente non deve essere una guida che ti insegna le basi a dovertelo dire. Quelle cose le hanno dette (male) solo per introdurti l'uso della keyword use. Leggendo l'articolo che ti ho mandato dovrebbe farti capire meglio.

Tornando quindi alla tua domanda principale: si, come hai incluso la classe va bene, potrei solo dirti che personalmente io preferisco usare sempre require_once per i motivi che ti ho detto prima.

Mentre per l'uso di namespace e use.. diciamo che il loro utilizzo torna utile principalmente in due casi:
  • Se fai una classe in cui decidi di metterla open source. Per esempio fai una classe sulla gestione degli utenti e la chiami "user". La pubblichi in giro e ti rendi conto che il nome della classe usato è troppo generico e potrebbe essere una classe che già esiste per chi decide di usarlo sul suo sito (creando quindi conflitto). Quindi come risolvere? O cambi il nome della classe con un nome di merd* però andresti ad assegnare un nome che non c'entra niente con la funzionalità della classe, oppure metti la tua classe dentro una "cartella" tramite l'uso dei namespace.
  • Quando vai a creare un progetto abbastanza ampio e ti sarà utile organizzare le varie classi in delle "cartelle" (perché alla fine è questo che fa la keyword namespace) in modo da avere più dinamicità sulla gestione delle classi (un esempio sono i framework o dei sistemi avanzati di template).
Come potresti utilizzarlo nel tuo caso?

Usalo magari per dare un tocco di personalizzazione alle classi che crei, segnandole tutte sotto il tuo nome:

Person.php
PHP:
<?php

namespace ken_korn;

class Persona {
    //proprietà
    public $name_1 = "";
 
    //costruttore
    public function __construct($name) {
        $this->name_1 = $name;
    }
 
    //metodi
    public function getName() {
        //$this rappresenta l'oggetto che sarà costruito a runtime
        return $this->name_1;
    }
     
}
?>

Index.php

Codice:
<?php

require 'Person.php';

$name = new ken_korn\Persona("Gianni");
echo $name->getName();

?>
Ti ringrazio tanto per la dettagliatissima ed esaustiva risposta, rileggendo poi anche l'articolo che mi hai linkato ha chiarito ogni mio dubbio, grazie!
 
La risposta due è abbastanza ovvia, il sito la fa troppo lunga.
Se ad esempio sei nel namespace "Caccola" e vuoi utilizzare delle classi che sono senza namespace(come le librerie che mi hai citato, anche se non so se ancora sono senza namespace) devi riferirti alla classe utilizzando il backslash all'inizio, così dici al PHP che la classe che vuoi usare deve essere presa senza namespace(Il "\" all'inizio sta a simboleggiare il namespace "root").
Codice:
//File1.php
class Person {

}

//File2.php
namespace Caccola;
include "File1.php";
$person = new Person;//Errore, classe Caccola\Person non presente
$person = new \Person; //Ok, classe trovata nel namespace "globale"

L'uso dei namespace è il modo principale in cui l'Autoloading(la magia che permettere di non usare piu gli include/require) decide da dove prendere le classi.
Perfetto, grazie di avermi chiarito in maniera cosí "sobria" la cosa XD
 
Stato
Discussione chiusa ad ulteriori risposte.