मैं ऑटोलॉड के साथ PHP नामस्थान का उपयोग कैसे करूं?


104

ऑटोलैड और नेमस्पेस का उपयोग करने की कोशिश करने पर मुझे यह त्रुटि मिलती है:

घातक त्रुटि: कक्षा 10 'क्लास 1' लाइन 10 पर /usr/local/www/apache22/data/public/php5.3/test.php में नहीं मिली

कोई मुझे बता सकता हैं मुझसे क्या गलती हो रही है?

यहाँ मेरा कोड है:

Class1.php:

<?php

namespace Person\Barnes\David
{
    class Class1
    {
        public function __construct()
        {
            echo __CLASS__;
        }
    }
}

?>

test.php:

<?php

function __autoload($class)
{
    require $class . '.php';
}

use Person\Barnes\David;

$class = new Class1();

?>

जवाबों:


119

Class1 वैश्विक दायरे में नहीं है।

काम के उदाहरण के लिए नीचे देखें:

<?php

function __autoload($class)
{
    $parts = explode('\\', $class);
    require end($parts) . '.php';
}

use Person\Barnes\David as MyPerson;

$class = new MyPerson\Class1();

संपादित करें (2009-12-14):

स्पष्ट करने के लिए, उदाहरण के रूप में "उपयोग ..." का मेरा उपयोग सरल बनाना था।

विकल्प निम्नलिखित था:

$class = new Person\Barnes\David\Class1();

या

use Person\Barnes\David\Class1;

// ...

$class = new Class1();

1
आप का उपयोग करने की जरूरत नहीं है AS। इसलिए यह समाधान काम नहीं करता है। आप बस आसानी से कर सकते हैं: use Person\Barnes\David\Class1;(जो इसके बराबर है use Person\Barnes\David\Class1 as Class1;)।
कार्टिबेस्फोरस

1
धन्यवाद, यह काम करता है। लेकिन मैं यह नहीं समझ सकता कि हम $ वर्ग = नई Class1 () का उपयोग क्यों कर सकते हैं; जब हमने पहले "पर्सन \ बरनेस \ डेविड?" का उपयोग पहले से परिभाषित किया है?
user345602

4
@ user346665 आपको ऐसा use Person\Barnes\David\Class1;करने के लिए उपयोग करना होगा $class = new Class1();। आपके साथ use Person\Barnes\David;अवश्य करना चाहिए $class = new David\Class1();useकीवर्ड से ही के बराबर है use Person\Barnes\David\Class1 as Class1;या use Person\Barnes\David as David;प्रत्येक उदाहरण के लिए, क्रमशः।
जस्टिन सी

2018 में पढ़ने वालों के लिए, @ prince-billy-graham solution with spl_autoload_register
Bruno de Oliveira

26

जैसा कि पास्कल मार्टिन ने कहा, आपको उदाहरण के लिए DIRECTORY_SEPARATOR से '\' को बदलना चाहिए:

$filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
include($filename);

इसके अलावा, मैं आपको सुधारात्मक संरचना को पुनर्गठित करने के लिए सुझाव दूंगा, ताकि कोड को अधिक पठनीय बनाया जा सके। यह एक विकल्प हो सकता है:

निर्देशिका संरचना:

ProjectRoot
 |- lib

फ़ाइल: /ProjectRoot/lib/Person/Barnes/David/Class1.php

<?php
namespace Person\Barnes\David
class Class1
{
    public function __construct()
    {
        echo __CLASS__;
    }
}
?>
  • आपके द्वारा परिभाषित प्रत्येक नामस्थान के लिए उप निर्देशिका बनाएं।

फ़ाइल: /ProjectRoot/test.php

define('BASE_PATH', realpath(dirname(__FILE__)));
function my_autoloader($class)
{
    $filename = BASE_PATH . '/lib/' . str_replace('\\', '/', $class) . '.php';
    include($filename);
}
spl_autoload_register('my_autoloader');

use Person\Barnes\David as MyPerson;
$class = new MyPerson\Class1();
  • मैंने ऑटोलैडर घोषणा के लिए php 5 पुनर्संयोजन का उपयोग किया। यदि आप अभी भी PHP 4 के साथ हैं, तो इसे पुराने सिंटैक्स के साथ बदलें: फ़ंक्शन __autoload ($ class)

18

आपके __autoloadफ़ंक्शन को नामस्थान सहित पूर्ण वर्ग-नाम प्राप्त होगा।

इसका मतलब है, आपके मामले में, __autoloadफ़ंक्शन को ' Person\Barnes\David\Class1' प्राप्त होगा , और केवल ' Class1' नहीं।

इसलिए, आपको उस तरह के "अधिक जटिल" नाम से निपटने के लिए, अपने ऑटोलोडिंग कोड को संशोधित करना होगा; एक समाधान अक्सर उपयोग किया जाता है अपनी फ़ाइलों को नामस्थानों के "स्तर" के एक स्तर का उपयोग करके व्यवस्थित करना है, और, जब ऑटोलडिंग, \द्वारा नामस्थान नाम में ' ' बदलें DIRECTORY_SEPARATOR


1
यह वह नहीं है जो मैंने पाया। जब मैंने स्टेटमेंट डाई ($ वर्ग) डाला; __autoload फ़ंक्शन में, इसने 'Class1 "छापा, न कि' Person \ Barnes \ David \ Class1 '
डेविड बार्न्स

सच। ऑटोलोड का $ वर्ग पैरामीटर कंस्ट्रक्टर कॉल में लिखे गए क्लास का नाम है।
तिश्मा

1
डाउनवोट के लिए "आपका __autoloadफ़ंक्शन नाम-नाम सहित पूर्ण वर्ग-नाम प्राप्त करेगा" - यह केवल सच है यदि आपने स्पष्ट रूप से useउस वर्ग को संदर्भित किया है जिसे आप संदर्भित करने का प्रयास कर रहे हैं, न कि यदि आप केवल useउस नामस्थान को प्राप्त कर रहे हैं जो उसका है। ओपी की गलती यह थी कि वह useएक क्लास वाले नेमस्पेस को डी करेगा और फिर अपने ऑटोलैड फंक्शन की उम्मीद कर रहा था कि जादुई रूप से किसी भी तरह पूरी क्लासपाथ पास कर ली जाए। यह उत्तर वास्तव में ओपी की गलती को संबोधित नहीं करता है।
मार्क अमेरी

15

मैं कुछ इस तरह से करता हूं: इस GitHub उदाहरण देखें

spl_autoload_register('AutoLoader');

function AutoLoader($className)
{
    $file = str_replace('\\',DIRECTORY_SEPARATOR,$className);

    require_once 'classes' . DIRECTORY_SEPARATOR . $file . '.php'; 
    //Make your own path, Might need to use Magics like ___DIR___
}

3
अच्छा और सरल। अगर किसी को उसकी तलाश होनी चाहिए।)
डेनिस

3

मुझे यह रत्न फ्लाईसिस्टम से मिला

spl_autoload_register(function($class) {
    $prefix = 'League\\Flysystem\\';

    if ( ! substr($class, 0, 17) === $prefix) {
        return;
    }

    $class = substr($class, strlen($prefix));
    $location = __DIR__ . 'path/to/flysystem/src/' . str_replace('\\', '/', $class) . '.php';

    if (is_file($location)) {
        require_once($location);
    }
});

3

मैं देखता हूं कि ऑटोलैड फ़ंक्शंस केवल "पूर्ण" क्लासनाम प्राप्त करते हैं - सभी नामस्थान इसे आगे बढ़ाने के साथ - निम्नलिखित निम्नलिखित मामलों में:

[a] $a = new The\Full\Namespace\CoolClass();

[b] use The\Full\Namespace as SomeNamespace; (at the top of your source file) followed by $a = new SomeNamespace\CoolClass();

मैं देखता हूं कि ऑटोलैड फ़ंक्शन निम्न मामले में पूर्ण क्लासनाम प्राप्त नहीं करता है:

[c] use The\Full\Namespace; (at the top of your source file) followed by $a = new CoolClass();

अद्यतन: [ग] एक गलती है और कैसे नाम स्थान वैसे भी काम नहीं करता है। मैं रिपोर्ट कर सकता हूं कि, [ग] के बजाय, निम्नलिखित दो मामले भी अच्छी तरह से काम करते हैं:

[d] use The\Full\Namespace; (at the top of your source file) followed by $a = new Namespace\CoolClass();

[e] use The\Full\Namespace\CoolClass; (at the top of your source file) followed by $a = new CoolClass();

उम्मीद है की यह मदद करेगा।


एक साइड नोट के रूप में, useकीवर्ड PHP इंटरेक्टिव कमांड-लाइन इंटरफ़ेस ( php --interactive) में ठीक से काम नहीं करता है ;
एंड्रयू लार्सन

3

मैं एक लाइन में इस सरल हैक का उपयोग करता हूं:

spl_autoload_register(function($name){
        require_once 'lib/'.str_replace('\\','/',$name).'.php';
    });

1

एक ही मुद्दा था और सिर्फ यह पाया:

जब आप एक सबफ़ोल्डर संरचना बनाते हैं जिसमें युक्त वर्गों के नाम स्थान होते हैं, तो आपको कभी भी ऑटोलैडर को परिभाषित करने की आवश्यकता नहीं होगी।

    spl_autoload_extensions(".php"); // comma-separated list
    spl_autoload_register();

इसने एक जादू की तरह काम किया

यहाँ अधिक जानकारी: http://www.php.net/manual/en/function.spl-autoload-register.php#92914

संपादित करें: यह बैकस्लैश के कारण लिनक्स पर समस्या का कारण बनता है ... यहाँ देखें कार्यशील समाधान के लिए immeëmosol द्वारा

Namespace Autoload विंडोज़ पर काम करता है, लेकिन लिनक्स पर नहीं


1

उपयोग करने के लिए एक गोचरा है, जबकि यह सबसे तेज़ विधि है, यह आपके सभी फ़ाइलनामों को कमतर करने की भी अपेक्षा करता है।

spl_autoload_extensions(".php");
spl_autoload_register();

उदाहरण के लिए:

वर्ग SomeSuperClass युक्त फ़ाइल को somesuperclass.php नाम देना होगा, यह एक ऐसा है जब लिनक्स जैसी संवेदनशील फ़ाइल प्रणाली का उपयोग करते समय, यदि आपकी फ़ाइल का नाम SomeSuperClass.php है, लेकिन Windows के लिए कोई समस्या नहीं है।

अपने कोड में __autoload का उपयोग करना अभी भी PHP के वर्तमान संस्करणों के साथ काम कर सकता है, लेकिन उम्मीद है कि यह सुविधा पदावनत हो जाएगी और अंततः भविष्य में हटा दी जाएगी।

तो क्या विकल्प बचे हैं:

यह संस्करण PHP 5.3 और उसके बाद के संस्करण के साथ काम करेगा और कुछ नामसुपरक्लासass.php और somesuperclass.php की अनुमति देता है। यदि आपका 5.3.2 और इससे अधिक का उपयोग हो रहा है, तो यह ऑटोलैडर और भी तेजी से काम करेगा।

<?php

if ( function_exists ( 'stream_resolve_include_path' ) == false ) {
    function stream_resolve_include_path ( $filename ) {
        $paths = explode ( PATH_SEPARATOR, get_include_path () );
        foreach ( $paths as $path ) {
            $path = realpath ( $path . PATH_SEPARATOR . $filename );
            if ( $path ) {
                return $path;
            }
        }
        return false;
    }
}

spl_autoload_register ( function ( $className, $fileExtensions = null ) {
    $className = str_replace ( '_', '/', $className );
    $className = str_replace ( '\\', '/', $className );
    $file = stream_resolve_include_path ( $className . '.php' );
    if ( $file === false ) {
        $file = stream_resolve_include_path ( strtolower ( $className . '.php' ) );
    }
    if ( $file !== false ) {
        include $file;
        return true;
    }
    return false;
});

2
एक साइड नोट के str_replace ([ '_','\\'] '/', $className );रूप में, दो str_replace की तुलना में दोगुना है
Itay Moav -Malimovka

जब तक कि यह कोई फर्क नहीं पड़ता कि php फ़ाइल ऊपरी / निचला आवरण है, निर्देशिका अभी भी केस सेंसिटिव बनी रहती है
माइक '

1

मुझे हाल ही में tanerkuc का जवाब बहुत मददगार लगा! बस जोड़ने के लिए है कि का उपयोग कर चाहता था strrpos()+ substr()थोड़ा तेज है की तुलना में explode()+ end():

spl_autoload_register( function( $class ) {
    $pos = strrpos( $class, '\\' );
    include ( $pos === false ? $class : substr( $class, $pos + 1 ) ).'.php';
});

1

मैं रिश्तेदार शुरुआती के लिए अपने दो सेंट में फेंक दूंगा या सभी सिद्धांत के बिना एक साधारण spl_autoload_register () सेटअप चाहने वाला नहीं होगा: प्रत्येक वर्ग के लिए बस एक php फ़ाइल बनाएं, उस php फ़ाइल को अपनी कक्षा के नाम के समान बनाएं, और अपनी कक्षा की फ़ाइलें रखें एक ही निर्देशिका में आपकी php फ़ाइल के रूप में सवाल है, तो यह काम करेगा:

spl_autoload_register(function ($class_name) {
    require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . $class_name . '.php';
});

इस फ़ंक्शन के अंदर के टुकड़ों को गुगली करके जवाब देना चाहिए कि यह कैसे काम करता है। PS: मैं लिनक्स का उपयोग करता हूं, और यह लिनक्स पर काम करता है। विंडोज लोगों को पहले इसका परीक्षण करना चाहिए।


1

https://thomashunter.name/blog/simple-php-namespace-friendly-autoloader-class/

आप अपनी श्रेणी की फ़ाइलों को एक फ़ोल्डर में रखना चाहते हैं Classes, जिसका नाम उसी निर्देशिका में है जो आपके PHP एप्लिकेशन में प्रवेश बिंदु के रूप में है। यदि कक्षाएं नाम स्थान का उपयोग करती हैं, तो नामस्थान को निर्देशिका संरचना में बदल दिया जाएगा।

बहुत से अन्य ऑटो-लोडर के विपरीत, अंडरस्कोर को डायरेक्टरी स्ट्रक्चर में नहीं बदला जाएगा (यह PHP <5.3 pseudo namespaces के साथ PHP> = 5.3 वास्तविक नामस्थानों को करने के लिए मुश्किल है)।

<?php
class Autoloader {
    static public function loader($className) {
        $filename = "Classes/" . str_replace("\\", '/', $className) . ".php";
        if (file_exists($filename)) {
            include($filename);
            if (class_exists($className)) {
                return TRUE;
            }
        }
        return FALSE;
    }
}
spl_autoload_register('Autoloader::loader');

आप निम्नलिखित कोड को अपनी मुख्य PHP स्क्रिप्ट (प्रवेश बिंदु) में रखना चाहेंगे:

require_once("Classes/Autoloader.php");

यहाँ एक उदाहरण निर्देशिका लेआउट है:

index.php
Classes/
  Autoloader.php
  ClassA.php - class ClassA {}
  ClassB.php - class ClassB {}
  Business/
    ClassC.php - namespace Business; classC {}
    Deeper/
      ClassD.php - namespace Business\Deeper; classD {}

0
<?php
spl_autoload_register(function ($classname){
   // for security purpose
   //your class name should match the name of your class "file.php"
   $classname = str_replace("..", "", $classname);
   require_once __DIR__.DIRECTORY_SEPARATOR.("classes/$classname.class.php");
});
try {
  $new = new Class1();
} catch (Exception $e) {
   echo "error = ". $e->getMessage();
}
?>

1
हालांकि यह कोड प्रश्न का उत्तर दे सकता है, लेकिन यह कोड इस और क्यों या कैसे का उत्तर देता है, इस संबंध में अतिरिक्त संदर्भ प्रदान करता है।
एथन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.