Visualizzazione dei risultati da 1 a 5 su 5
  1. #1

    [PHP OOP] Autoloading e PSR-0 Standard

    Buona sera ragazzi,

    piccolo regalino di pasqua

    In questo topic vi parlo di autoloading.

    L'autoloading è quel processo che ci permette di caricare una classe ed il relativo file senza bisogno di usare funzioni di include o require

    Partiamo dalla base, supponiamo di avere una classe user che dobbiamo istanziare e utilizzare
    Generalmente:
    Codice PHP:
    require_once( 'user.php' );
    $user = new user(); 
    E' buona norma scrivere la definizione della classe su file singolo per una migliore organizzazione del lavoro. Questo ci forzava a dover includere ogni file per ogni classe che dovevamo usare.

    La prima funzione che ci è venuta in aiuto dall'avvento di PHP 5 fu la magic function chiamata __autoload() . Questa funzione forniva un'ultima possibilità di caricare la definizione della classe in runtime prima di generare un errore.

    una semplicissima implementazione di questo metodo:
    Codice PHP:
    function __autoload$className ) {
        
    $filename $className ".php";
        if ( 
    is_readable$filename ) ) {
            require 
    $filename;
        }

    l'unica considerazione da fare qui è che è molto meglio usare la funzione is_readable() piuttosto che file_exists(). Un file potrebbe esistere ma non avere i permessi per essere letto, is_readable() effettua tutti e due i controlli.

    Questa soluzione però era limitativa in quanto si poteva definire una sola funzione di autoload.

    Fu cosi che da PHP 5.1.2 è stato introdotto spl_autoload() e le relative funzioni.

    spl_autoload() permette di registrare N funzioni di autoload tramite la funzione spl_autoload_register()

    Esempio:
    Codice PHP:
    function autoloadModels$className ) {
        
    $filename "models/" $className ".php";
        if ( 
    is_readable$filename ) ) {
            require 
    $filename;
        }
    }

    function 
    autoloadControllers$className ) {
        
    $filename "controllers/" $className ".php";
        if ( 
    is_readable$filename ) ) {
            require 
    $filename;
        }
    }

    spl_autoload_register'autoloadModels' );
    spl_autoload_register'autoloadControllers' ); 
    Ovviamente questi semplici esempi sono solamente una dimostrazione di come l'autoloading funzionava nelle versioni precedenti di PHP.

    Attualmente con l'avvento dei NAMESPACE le cose sono leggermente cambiate e ci sono degli standard che hanno preso piede.
    Il primo e l'oggetto del topic è lo standard PSR-0.

    Nel prossimo post vediamo cos'è e come si usa.
    Intanto buona lettura.

    Questa volta, più che un voto.. è favoreggiamento.

  2. #2
    Dopo la doverosa premessa fatta nel topic precedente arriviamo alla versione PHP 5.3.

    Da questa versione abbiamo il supporto completo dei namespace, questa nuova feature ha un po' scombussolato il mondo del caricamento files e uso delle classi..

    In sintesi molto stringata i namespace funzionano come le cartelle di una directory con la possibilità di inserire un numero indefinito di "sub-directory".

    Tutto questo ha portato la community PHP a fondare un gruppo di persone "Framework Interoperatability Group" (FIG) con lo scopo di scrivere alcuni standards e pratiche comuni.

    Uno di questi standard è il PSR-0.
    Questo standard richiede:
    - un namespace completo e la classe devono avere questa struttura: <Vendor Name>(<Namespace>)*<Class Name>
    - ogni namespace deve avere un namespace di primo livello (“Vendor Name”)
    - ogni namespace può avere tutti i sub-namespace che si desidera
    - ogni separatore di namespace viene convertito in un DIRECTORY_SEPARATOR durante il caricamento dal file system
    - ogni underscore nel nome della classe viene convertita in un DIRECTORY_SEPARATOR. L'underscore non ha un significato speciale nel namespace
    - al namespace e alla classe viene aggiunto il suffisso .php durante il caricamento
    - non c'è distinzione tra maiuscole e minuscole

    Seguendo queste direttive ci troviamo a lavorare con una struttura di questo tipo:

    Vendor
    |
    - - Package
    - - |
    - - - - Example.php

    che possiamo trasferire nella definizione della classe come:
    Codice PHP:
    namespace Vendor\Package;

    class 
    Example {

    Per fare un paio di esempi:
    la definizione per la classe Doctrine\Common\Connections si troverà su /path/to/project/lib/Doctrine/Common/Connections.php
    la definizione per la classe Symphony\Core\Request si troverà su /path/to/project/lib/Symfony/Core/Request.php

    Esistono diverse versioni di implementazione di questo standard, una è quella di Jonathan Wage. La sua classe vi permette di sfruttare lo standard PSR-0 se seguite le regole di interoperabilità dettate dallo standard

    La classe completa: https://gist.github.com/jwage/221634

    Nel prossimo post vi mostro alcuni esempi semplici e pratici
    Buona lettura intanto
    Questa volta, più che un voto.. è favoreggiamento.

  3. #3
    Vediamo se riesco a costruire un breve esempio per mostrare l'uso della classe SplClassLoader

    SplClassLoader.php
    Codice PHP:
    namespace test\loader;

    // incollare la definizione della classe di JWage 
    a.php
    Codice PHP:
    namespace test\common;

    use 
    PDO;

    class 
    {

      private 
    $pdo;

      public function 
    __constructPDO $pdo ) {
        
    $this->pdo $pdo;
      }

      public function 
    dump() {
        return 
    var_dump$this->pdo );
      }

    b.php
    Codice PHP:
    namespace text\common;

    class 
    extends {

    htmlWidgetInterface.php
    Codice PHP:
    namespace test\widget\html;

    interface 
    htmlWidgetInterface {
      public function 
    render();

    p.php
    Codice PHP:
    namespace test\widget\html;

    class 
    implements htmlWidgetInterface {

      private 
    $txt;

      public function 
    __construct$txt ) {
        
    $this->txt $txt;
      }

      public function 
    render() {
        return 
    '<p>' $this->txt '</p>';
      }

    queste sono le ipotetiche classi con cui lavorare

    vediamo la disposizione delle cartelle e files sul server:
    [root]/test/loader/SplClassLoader.php
    [root]/test/common/a.php
    [root]/test/common/b.php
    [root]/test/widget/html/htmlWidgetInterface.php
    [root]/test/widget/html/p.php

    dovrei avere una base per l'esempio, ora possiamo usare la classe di autoloading senza preoccuparci di scrivere require/include
    vedi il prossimo post
    Ultima modifica di Al_katraz984; 18-04-2014 a 17:17
    Questa volta, più che un voto.. è favoreggiamento.

  4. #4
    Dopo aver scritto una serie di classi inutili vediamo come ci possiamo semplificare la vita

    Ma prima un paio di considerazioni sulla classe di autoloading
    Codice PHP:
    $loader = new SplClassLoader( [namespace], [root/directory] );
    $loader->register(); 
    il costruttore della classe necessità di due parametri per funzionare
    - il namespace di riferimento
    - la directory di base per la ricerca dei files e il successivo autoload

    esistono altri metodi per impostare alcuni parametri opzionali ma vi invito a leggere la definizione della classe per saperne di più.

    Passiamo all'esempio

    [root]/index.php
    Codice PHP:
    namespace MyProject;

    use 
    PDO;
    use 
    test\loader\SplClassLoader;
    require_once( 
    'test/loader/SplClassLoader.php' );

    // 'test' è il namespace che vogliamo utilizzare sarà poi la classe a ricercare nei vari sub-namespace le classi
    // __DIR__ in questo caso ci dà la directory [root] 
    $loader = new SplClassLoader'test'__DIR__ );
    $loader->register();

    use 
    test\commmon\a;
    use 
    test\widget\html\p;

    define"DB_DNS"'mysql:host=you.host.net;dbname=dbname' );
    define"DB_USER"'dbuser' );
    define"DB_PASS"'dbpass' );

    try {
        
    $pdo = new PDODB_DNSDB_USERDB_PASS );

        
    $a = new a$pdo );

        
    $p = new p$a->dump() );
        echo 
    $p->render();

    } catch ( 
    Exception $e ) {
        echo 
    '<p>' $e->getMessage() . '</p>';
        echo 
    '<p>File: ' $e->getFile() . ' - line: ' $e->getLine() . '</p>';
        exit;

    Al di là di eventuali errori che possono uscire, il codice non l'ho ancora testato, è importante notare come non ci sia più il bisogno di scrivere una fila di include per caricare le classi necessarie alla nostra applicazione.

    Questa classe standard supporta sia i sistemi normali che i sistemi con namespace, è universale e standard. Esistono anche il PSR-1 e PSR-2 ma non sono ancora ufficiali, devo indagare
    Ultima modifica di Al_katraz984; 18-04-2014 a 17:49
    Questa volta, più che un voto.. è favoreggiamento.

  5. #5
    Per completare il tutto vediamo anche la versione senza namespace

    La definizione delle classi rimane uguale ma senza l'uso di namespace e use


    SplClassLoader.php
    Codice PHP:
    // incollare la definizione della classe di JWage 
    a.php

    Codice PHP:
    class {

      private 
    $pdo;

      public function 
    __constructPDO $pdo ) {
        
    $this->pdo $pdo;
      }

      public function 
    dump() {
        return 
    var_dump$this->pdo );
      }

    b.php

    Codice PHP:
    class extends {

    htmlWidgetInterface.php

    Codice PHP:
    interface htmlWidgetInterface {
      public function 
    render();

    p.php

    Codice PHP:
    class implements htmlWidgetInterface {

      private 
    $txt;

      public function 
    __construct$txt ) {
        
    $this->txt $txt;
      }

      public function 
    render() {
        return 
    '<p>' $this->txt '</p>';
      }


    da usare poi:
    index.php
    Codice PHP:
    require_once( 'test/loader/SplClassLoader.php' );

    // '' è il namespace globale da utilizzare
    // __DIR__ come prima ci dà la directory [root] 
    $loader = new SplClassLoader''__DIR__ );
    $loader->register();

    define"DB_DNS"'mysql:host=you.host.net;dbname=dbname' );
    define"DB_USER"'dbuser' );
    define"DB_PASS"'dbpass' );

    try {
        
    $pdo = new PDODB_DNSDB_USERDB_PASS );

        
    $b = new b$pdo );

        
    $p = new p$b->dump() );
        echo 
    $p->render();

    } catch ( 
    Exception $e ) {
        echo 
    '<p>' $e->getMessage() . '</p>';
        echo 
    '<p>File: ' $e->getFile() . ' - line: ' $e->getLine() . '</p>';
        exit;

    Buona pasqua a tutti e buon studio, spero possa essere interessante per qualcuno.
    Se avete dubbi e domandi siamo qui
    Andrea
    Questa volta, più che un voto.. è favoreggiamento.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.