Vra

Ek wonder wat die beste praktyk is vir die hantering van die probleem met hoef te "sluit" so baie lêers in my PHP skrifte ten einde te verseker dat al die klasse wat ek nodig het om te gebruik is toeganklik vir my script.

Op die oomblik is ek net die gebruik van include_once om die sluit klasse ek toegang direk. Elkeen van dié sal die klasse wat hulle toegang include_once.

Ek het gekyk na die gebruik van die __autoload funksie, maar hoed lyk nie goed werk as jy van plan is om jou klas lêers georganiseer in 'n gids boom het. As jy dit gedoen het, dit lyk asof jy uiteindelik loop die gids boom totdat jy die klas wat jy is op soek na 'gevind. Ook, ek is nie seker hoe hierdie effekte klasse met dieselfde naam in verskillende naamruimtes.

Is daar 'n makliker manier om dit te hanteer?

Of is PHP net nie geskik vir " enterprisey " tipe aansoeke met baie verskillende voorwerpe almal geleë in afsonderlike lêers wat gebruik kan word in baie verskillende dopgehou.

Was dit nuttig?

Oplossing

Ek my aansoeke Ek het gewoonlik setup.php lêer wat al kern klasse (dit wil sê raamwerk en gepaardgaande biblioteke) sluit. My persoonlike klasse is gelaai met behulp van Auto Loader aangehelp deur gids uitleg kaart.

Elke keer as nuwe klas bygevoeg ek hardloop command line bouer script wat geheel gids boom skanderings op soek vir model klasse dan bou assosiatiewe skikking met klasname as sleutels en paaie as waardes. Dan, __autoload funksie opkyk klas naam in daardie reeks en kry insluit pad. Hier is die kode:

autobuild.php

define('MAP', 'var/cache/autoload.map');
error_reporting(E_ALL);
require 'setup.php';
print(buildAutoloaderMap() . " classes mapped\n");

function buildAutoloaderMap() {
    $dirs = array('lib', 'view', 'model');
    $cache = array();
    $n = 0;
    foreach ($dirs as $dir) {
        foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $entry) {
            $fn = $entry->getFilename();
            if (!preg_match('/\.class\.php$/', $fn))
                continue;
            $c = str_replace('.class.php', '', $fn);
            if (!class_exists($c)) {
                $cache[$c] = ($pn = $entry->getPathname());
                ++$n;
            }
        }
    }
    ksort($cache);
    file_put_contents(MAP, serialize($cache));
    return $n;
}

autoload.php

define('MAP', 'var/cache/autoload.map');

function __autoload($className) {
    static $map;
    $map or ($map = unserialize(file_get_contents(MAP)));
    $fn = array_key_exists($className, $map) ? $map[$className] : null;
    if ($fn and file_exists($fn)) {
        include $fn;
        unset($map[$className]);
    }
}

Let daarop dat die lêer Naming Convention moet wees [class_name] .class.php. Verander die dopgehou klasse sal kyk in autobuild.php. Jy kan ook hardloop autobuilder van autoload funksie wanneer klas nie gevind nie, maar wat kan jou program kry in oneindige lus.

serialized skikkings is darn vinnig.

@JasonMichael: PHP 4 is dood. Kry oor dit.

Ander wenke

Jy kan verskeie autoloading funksies te definieer met spl_autoload_register:

spl_autoload_register('load_controllers');
spl_autoload_register('load_models');

function load_models($class){
    if( !file_exists("models/$class.php") )
        return false;

    include "models/$class.php";
    return true;
}
function load_controllers($class){
    if( !file_exists("controllers/$class.php") )
        return false;

    include "controllers/$class.php";
    return true;
}

Jy kan ook programmaties die ligging van die klas lêer bepaal deur gebruik te maak van gestruktureerde benoemings konvensies wat karteer om fisiese dopgehou. Dit is hoe Stuur doen dit in Stuur Framework . So wanneer jy Zend_Loader::loadClass("Zend_Db_Table"); noem dit ontplof die classname in 'n verskeidenheid van gidse deur te verdeel op die onderstreping, en dan die Zend_Loader klas gaan na die verlangde lêer te laai.

Soos al die Zend modules, sou ek verwag dat jy kan net die loader gebruik op sy eie met jou eie klasse, maar ek het net gebruik dit as deel van 'n webwerf met behulp van Stuur se MVC.

Maar daar is kommer oor prestasie onder vrag as jy enige soort van dinamiese klas laai gebruik is, byvoorbeeld sien hierdie blog post Zend_Loader vergelyk met harde laai van klas lêers.

Sowel as die prestasie straf van om te die PHP soek insluit pad, dit nederlae opcode kas. Van 'n opmerking op daardie pos:

  
    

Wanneer die gebruik van enige Dynamic klas loader APC kan nie hierdie lêers kas ten volle as sy nie seker watter lêers op 'n enkele aanvraag sal laai. Deur harde laai van die lêers APC hulle kan kas in volle.

  

__autoload werk goed as jy 'n bestendige naamkonvensie vir jou klasse wat die funksie waar hulle gevind in die gids boom vertel. MVC leen hom baie goed vir hierdie soort van ding, want jy kan maklik die klasse in modelle, sienings en beheerders kan verdeel.

As alternatief, hou 'n assosiatiewe skikking van name aan plekke vir jou klas te dien en laat __autoload navraag hierdie skikking.

Van die voorstelle so ver, Ek is gedeeltelike om Kevin se, maar dit hoef nie absolute te wees. Ek sien 'n paar ander opsies om te gebruik met __autoload.

  1. Sit al die klas lêers in 'n enkele gids. Noem die lêer na die klas, dit wil sê, classes/User.php of classes/User.class.php.
  2. Kevin se idee om modelle in een gids, beheerders in 'n ander, ens Werk goed as al jou klasse mooi inpas by die MVC raamwerk, maar soms, dinge deurmekaar.
  3. Sluit die gids in die classname. Byvoorbeeld, sou 'n klas met die naam Model_User eintlik geleë op classes/Model/User.php. Jou __autoload funksie sal weet om 'n onderstreep vertaal in 'n gids separator om die lêer te vind.
  4. Net parse die hele gids struktuur keer. Óf in die __autoload funksie, of selfs net in dieselfde PHP lêer waar dit gedefinieer, lus oor die inhoud van die classes gids en kas wat lêers is waar. Dus, as jy probeer om die User klas te laai, dit maak nie saak of dit in classes/User.php of classes/Models/User.php of classes/Utility/User.php. Sodra dit iewers bevind User.php in die classes gids, sal dit weet wat lêer in te sluit wanneer die User klas moet autoloaded.

@Kevin:

  

Ek is net probeer om daarop te wys dat spl_autoload_register is 'n beter alternatief vir __autoload sedert jy verskeie loaders kan definieer, en hulle sal nie in stryd met mekaar. Handig as jy moet biblioteke wat 'n __autoload funksie sowel definieer sluit.

Is jy seker? Die dokumentasie anders sê:

  

As jou kode het 'n bestaande __autoload funksie dan hierdie funksie moet uitdruklik geregistreer op die __autoload stapel. Dit is omdat spl_autoload_register () effektief sal vervang die enjin kas vir die __autoload funksie deur óf spl_autoload () of spl_autoload_call ().

=> wat jy hoef te uitdruklik registreer __autoload enige biblioteek se as well. Maar afgesien van wat jy natuurlik reg, hierdie funksie is die beter alternatief.

__autoload sal nie, maar slegs in PHP 5 werk.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top