Heim > php教程 > PHP开发 > Verwenden Sie PEAR, um Ihr nächstes PHP-Programm zu schreiben

Verwenden Sie PEAR, um Ihr nächstes PHP-Programm zu schreiben

高洛峰
Freigeben: 2016-11-29 09:58:57
Original
1107 Leute haben es durchsucht

Pear-Einführung: Verwenden Sie Pear, um Ihr nächstes PHP-Programm zu schreiben


Inhalt:

Was ist ススar
Warum sollten Sie pスear verwenden?
Welche Vorteile kann mir Birne bringen?
Codierungsregeln für ・pear
Beginnen Sie mit der Verwendung von スpear
Zusammenfassung
Verwandte Ressourcen
Über den Autor


Pan Fan (Night Sailer) (nightsailer@hotmail. com)
Beijing Saidi Information Technology Co., Ltd.
Juni 2001
Möglicherweise sind Sie bereits ein PHP-Veteran und haben viele großartige Codes geschrieben. Aber wenn Sie sie jetzt zu Ihrem aktuellen Projekt hinzufügen möchten, ist das dann etwas schwierig? Ihr Freund möchte Ihren Code als Modul in seinem Projekt verwenden, aber Sie stellen fest, dass Sie völlig andere Codierungsstile verwenden. Lassen Sie ihn ihn anpassen oder sogar neu schreiben!
Bitte folgen Sie mir und schreiben Sie Ihr PHP-Programm mit dem Pear-Standard. Ihr Programm und Ihr Code lassen sich problemlos in die Codes anderer Experten integrieren höhere Leistung erzeugen.
Was ist Birne?
Pear ist die Abkürzung für PHP-Erweiterung und Anwendungs-Repository. Es handelt sich um ein Code-Repository für PHP-Erweiterungen und -Anwendungen. Einfach ausgedrückt ist Pear das CPAN von PHP.
Warum Birne verwenden?
PHP ist eine sehr hervorragende Skriptsprache, prägnant und effizient. Mit der Veröffentlichung von 4.0 kann man sagen, dass PHP zu einer der besten Internet-Entwicklungssprachen geworden ist Insbesondere für Website-Entwickler, die schnell und effizient kleine und mittlere kommerzielle Anwendungen entwickeln müssen, ist PHP die bevorzugte Sprache. Da es jedoch immer mehr PHP-Anwendungen gibt, mangelt es an einheitlichen Standards und einer effektiven Verwaltung dieser Anwendungen. Daher ist es für die PHP-Community schwierig, den Code und die Anwendungen untereinander so bequem zu teilen wie die Leute in der Perl-Community PHP fehlt die Möglichkeit, Code und Anwendungen wie Cpan zu teilen. Eine einheitliche Codebasis zur Klassifizierung und Verwaltung von Anwendungscodemodulen (jeder, der mit Perl vertraut ist, weiß, dass es sich bei cpan um ein riesiges Perl-Erweiterungsmodullager handelt. Die geschriebenen Anwendungsmodule können in die entsprechende Klassifizierung eingeordnet werden Verzeichnis unter cpan, und andere Leute können es leicht wiederverwenden. Natürlich müssen Sie auch beim Schreiben von Anwendungsmodulen die Richtlinien befolgen.)
Aus diesem Grund wurde Pear ins Leben gerufen und wird seitdem mit dem PHP-Kern verteilt 4.04.
Welche Vorteile kann mir Birne bringen?
1. Wie oben erwähnt, verwaltet Pear die Codebasis der Pear-Anwendung nach bestimmten Kategorien. Ihr Pear-Code kann in entsprechenden Verzeichnissen organisiert werden, und andere Personen können Ihre Ergebnisse problemlos abrufen und teilen.
2.pear ist nicht nur ein Code-Repository, sondern auch ein Standard. Wenn Sie diesen Standard zum Schreiben Ihres PHP-Codes verwenden, verbessern Sie die Lesbarkeit und Wiederverwendbarkeit Ihres Programms und verringern das Fehlerrisiko.
3.pear erstellt für Sie ein Framework, indem es zwei Klassen zur Implementierung von Funktionen wie Destruktoren und Fehlererkennung bereitstellt. Sie können diese Funktionen durch Vererbung verwenden.
Pea's Codierungsregeln
Pea's Codierungsregeln umfassen Einrückungsregeln, Kontrollstrukturen, Funktionsaufrufe, Funktionsdefinitionen, Kommentare, eingebundener Code, PHP-Tags, Kommentarblöcke in Dateikopfzeilen, CVS-Tags, URL-Beispiele, Konstanten. Nennen Sie diese 11 Aspekte . Hier ist eine kurze Einführung:
Einrückungsregeln: In
pear sind 4 Leerzeichen erforderlich, um den Code einzurücken, und Tabulatoren werden nicht verwendet. Wenn Sie vim verwenden, fügen Sie die folgenden Einstellungen in Ihre ~/.vimrc ein:
set expandtab
set shiftwidth=4
set tabstop=4

Wenn Sie emacs/xemacs verwenden, ist dies erforderlich um den Einrückungs-Tabs-Modus auf Null zu setzen.
Aber wenn Sie wie ich gerne (x)emacs zum Bearbeiten von PHP-Dateien verwenden, empfehle ich Ihnen dringend, den PHP-Modus zu installieren, damit Ihr Einrückungsstil beim Schreiben von Pear-Code automatisch angepasst wird. PHP- mode Es gibt viele tolle Funktionen und Sie können die neueste Version von php-mode aus der Ressourcenliste herunterladen.
Kontrollstruktur:
Die hier genannten Kontrollstrukturen umfassen: if for while switch usw. Bei Kontrollstrukturen sollte nach dem Schlüsselwort ein Leerzeichen stehen (z. B. if for ..) und dann die Kontrollklammern, damit es nicht zu Verwechslungen mit Funktionsaufrufen kommt. Darüber hinaus sollten Sie versuchen, geschweifte Klammern {} zu verwenden. so vollständig wie möglich, auch wenn es syntaktisch optional ist. Dies verhindert logische Verwirrung oder Fehler, wenn Sie in Zukunft neue Codezeilen hinzufügen müssen. Hier ist ein Beispiel:
if ((Bedingung 1) && (Bedingung 2)) {
Aussage 1
}esleif ((Bedingung 3) || (Bedingung 4)) {
Aussage 2 ;
}else {
Anweisung 3;
}


Funktionsaufruf:
Beim Funktionsaufruf sollte zwischen dem Funktionsnamen und der linken Klammer kein Leerzeichen stehen ( , für Funktionsparameter muss die gleiche Leerzeichentrennung zwischen dem Komma und dem nächsten Parameter stehen, und es darf kein Leerzeichen zwischen dem letzten Parameter und der schließenden Klammer stehen. Das Folgende ist ein Standard-Funktionsaufruf; param1). , $param2, $param3);
Unregelmäßiges Schreiben:
$result=foo ($param1,$param2,$param3);
$result=foo( $param1,$param2, $ param3 );


Wenn Sie außerdem das Rückgabeergebnis der Funktion zuweisen möchten, muss zwischen dem Gleichheitszeichen und der zugewiesenen Variablen ein Leerzeichen stehen. Wenn es sich gleichzeitig um eine Reihe verwandter Zuweisungsanweisungen handelt, Sie fügen entsprechende Leerzeichen hinzu, sodass sie wie folgt ausgerichtet sind:
$result1 = $foo($param1, $param2, $param3);
$var2 = $foo($param3);
$var3 = $foo($param4 , $param5);


Funktionsdefinition:
Funktionsdefinition folgt der Konvention „eine wahre Klammer“:
function connect(&$dsn, $persistent = false )
{
if (is_array($dsn)) {
$dsninfo = &$dsn;
} else {
$dsninfo = db::parsedsn($dsn);
}
if (!$dsninfo || !$dsninfo['phptype']) {
return $this->raiseerror();
}
return true;
}

Wie oben Wie gezeigt sollten optionale Parameter am Ende der Parameterliste stehen und immer versuchen, sinnvolle Funktionswerte zurückzugeben.
Zu den Kommentaren:
Die Online-Dokumentation von Klassen sollte von phpdoc konvertiert werden können, genau wie Javadoc. phpdoc ist ebenfalls eine Birnenanwendung. Eine ausführlichere Einführung finden Sie unter http://www.phpdoc.de/. Zusätzlich zur Online-Dokumentation von Klassen wird empfohlen, zur Erläuterung Ihres Codes Kommentare zu verwenden, die nicht zur Dokumentation gehören. Wenn Sie einen Codeabschnitt sehen, denken Sie: Oh, ich glaube nicht, dass Sie ihn in der Dokumentation sorgfältig beschreiben müssen . Dann geben Sie diesem Code besser einen einfachen Kommentar, damit Sie nicht vergessen, wie er funktioniert. Für die Form von Kommentaren eignen sich cs /* */ und c++s //. Verwenden Sie jedoch nicht die #-Kommentarmethode von Perl oder Shell.
Code einbinden:
Immer wenn Sie bedingungslos in eine Klassendatei einbinden müssen, müssen Sie require_once verwenden; wenn Sie es bedingt in eine Klassendatei einbinden müssen, müssen Sie include_once verwenden. Dies kann sicherstellen, dass Sie dies möchten include Die Datei wird nur einmal eingebunden, und diese beiden Anweisungen verwenden dieselbe Dateiliste, sodass Sie sich keine Sorgen machen müssen, dass die beiden verwechselt werden. Sobald require_once eine Datei einschließt, schließt include_once dieselbe Datei nicht erneut ein und umgekehrt umgekehrt.
php-Code-Tag:
Verwenden Sie immer , um Ihren PHP-Code zu definieren, anstatt einfach zu verwenden Portierung.
Kommentaranweisung im Dateikopf:
Für alle PHP-Codedateien, die in die Pear-Core-Version aufgenommen werden müssen, müssen Sie die folgende Kommentaranweisung am Anfang der Datei hinzufügen:
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +--------------------------------- ----------------------------------------+
// |. PHP-Version 4.0 |
// +- ---------------------------- -------- ---+
// |. Copyright (c) 1997, 1998, 1999, 2000, 2001 die PHP-Gruppe |
// +- ----------------------------- ------- ----+
// |. Diese Quelldatei unterliegt der Version 2.0 der PHP-Lizenz, |
/ / |. Das ist in der Dateilizenz enthalten und ist im World Wide Web unter |
// |http://www.php.net/license verfügbar /2_02.txt. |. Wenn Sie keine Kopie der PHP-Lizenz erhalten haben und diese nicht über das World Wide Web erhalten können, senden Sie bitte eine Nachricht an |
// |. License@php.netdamit wir Ihnen sofort eine Kopie zusenden können |
// +--------- ----- ----------------------------------------+
/ / |. Autoren: Originalautor |
// |. Ihr Name |
// +------------ ----- -------------------------------------+
//
// $id $

Für Dateien, die nicht in der Pear-Core-Codebasis enthalten sind, wird empfohlen, dass Sie am Anfang der Datei auch einen ähnlichen Kommentarblock wie diesen haben, der das Urheberrecht, die Vereinbarung und den Autor angibt , usw. Gleichzeitig wird der ersten Zeile auch die Modeline von vim hinzugefügt, sodass der Codestil von Pear in vim beibehalten werden kann.
CVS-Tag:

Fügen Sie wie oben gezeigt den CVS-ID-Tag zu jeder Datei hinzu. Wenn die Datei, die Sie bearbeiten oder ändern, diesen Tag nicht hat, fügen Sie ihn bitte hinzu oder ersetzen Sie ihn durch etwas Ähnliches in der Originaldatei. Ausdrucksform (z. B. „zuletzt geändert“ usw.)

URL-Beispiel:
Sie können sich auf RFC 2606 beziehen und „http://www.example.com“ als alle URL-Beispiele verwenden.
Konstante Benennung:
Konstanten sollten so weit wie möglich in Großbuchstaben geschrieben werden, um das Verständnis zu erleichtern. Verwenden Sie Unterstriche, um die einzelnen Wörter zu trennen. Gleichzeitig sollten Sie den Paketnamen oder Klassennamen voranstellen, in dem sich die Konstante befindet. Beispielsweise sollten die Konstanten in der Bug-Klasse mit bug_ beginnen. Die oben genannten Codierungsregeln von Pear finden Sie in der Beschreibung der Datei „coding_standard“ in Pear. Um diese Codierungsregeln besser zu verstehen, können Sie auch auf den Code des vorhandenen Pear-Core-Moduls zurückgreifen.
Beginnen Sie mit der Verwendung von peear
pear
Die Verwendung von Pear ist sehr einfach, Sie müssen nur Ihr eigenes Pear-Programm wie folgt definieren:
require_once "pear.php";
class your_class_name erweitert Pear{
Ihre Klassendefinition...
}


Natürlich müssen Sie sich an die oben genannten Pear-Coding-Regeln halten, und dann können Sie das, was Sie tun möchten, in Ihrer Klasse umsetzen. Als nächstes wollen wir es besprechen. Tatsächlich stellt uns Pear zwei vordefinierte Klassen zur Verfügung:
Pear: Dies ist die Basisklasse von Pear, und alle Pear-Erweiterungen müssen von ihr erben und abgeleitet werden.
pear_error: Die Basisklasse der Pear-Fehlerbehandlung. Sie können Ihre eigene Fehlerbehandlungsklasse ableiten.
Im Allgemeinen sollten Sie keine Instanz von Pear direkt erstellen, sondern selbst eine neue Klasse ableiten und dann eine Instanz dieser neuen Klasse erstellen. Als Basisklasse stellt uns Pear einige nützliche Funktionen zur Verfügung, von denen die wichtigsten Destruktoren und Fehlerbehandlung sind.
Destruktor
PHP unterstützt Konstruktoren, unterstützt jedoch keine Destruktoren. PHP bietet jedoch die Funktion register_shutdown_function() kann Rufen Sie die registrierte Funktion zurück, bevor das Skript beendet wird. Daher verwendet Pear diese Funktion, um eine Simulation des Destruktors bereitzustellen. Wenn Sie eine Unterklasse von Pear namens Mypear haben, können Sie in der Mypear-Klasse eine Funktion definieren. Der Funktionsname ist ein Unterstrich plus Ihrem Klassennamen, _mypear(). Dieser Destruktor unterscheidet sich jedoch vom Destruktor in C++. Er wird nicht ausgeführt, wenn das Objekt gelöscht wird, sondern wenn das Skript endet. Da register_shutdown_function() verwendet wird, werden die gedruckten Informationen in Ihrem Destruktor nicht an den Browser zurückgegeben. Darüber hinaus müssen Sie in Ihrem Konstruktor den Konstruktor der übergeordneten Klasse aufrufen, da PHP den Konstruktor der übergeordneten Klasse nicht automatisch aufruft und der Destruktor im Konstruktor von Pear registriert werden muss. Wir können uns die Quelle von Pear ansehen Code:
<br>function pear() {<br>if (method_exists($this, "_".get_class($this))) {<br>global $_pear_destructor_object_list;<br>$ _pear_destructor_object_list[] = &$this;<br>} ;<br>}<br>....<br>function _pear_call_destructors() {<br>global $_pear_destructor_object_list;<br>if (is_array($_pear_destructor_object_list) && sizeof($_pear_destructor_object_list)) {<br>reset( $_pear_destructor_object_list);<br>while (list($k, $objref) = every($_pear_destructor_object_list)) {<br>$destructor = "_".get_class($objref);<br>if (method_exists ($objref , $destructor)) {<br>$objref->$destructor();<br>}<br>}<br>//Liste der registrierten Objekte löschen, <br>//Wiederholte Aufrufe verhindern <br>$ _pear_destructor_object_list = array();<br>}<br>}<br>....<br>register_shutdown_function("_pear_call_destructors");<br>


Das Obige Der Code zeigt, wie Pear den Destruktor implementiert. Wenn ja, wird die Referenz der aktuellen Klasse in eine globale Liste eingefügt Das Element in der globalen Liste verfügt über einen entsprechenden Destruktor. Wenn ja, rufen Sie ihn auf und löschen Sie schließlich die globale Liste.

Rufen Sie in der letzten Codezeile in pear.php register_shutdown_function("_pear_call_destructors") auf, um _pear_call_destructors zu registrieren, damit PHP diese Funktion bei der Ausführung des Skripts zurückruft. Mit dem Destruktor können Sie einige notwendige „Nachsorge“-Arbeiten durchführen, bevor Sie nach der Verarbeitung der Benutzeranforderung beenden. Typische Beispiele sind das Schließen geöffneter Dateien, das Trennen der Verbindung zur Datenbank und das Speichern bestimmter Daten auf der Festplatte usw.

Fehlerbehandlung
Mit Pear können Sie nicht nur einen Fehlercode oder Fehlerinformationen zurückgeben, sondern auch ein neues Fehlerobjekt zurückgeben aus.
Das Fehlerobjekt in Pear schränkt die spezifische Ausgabeform nicht ein. Es kann nur den Fehler erfassen, ohne zu viele Informationen an den Benutzer zurückzugeben, oder es kann gleichzeitig eine spezielle Fehlerbehandlungsfunktion aufrufen Wenn die Fehlermeldung ausgegeben wird, müssen Sie außerdem eine XML-, CSV- oder andere von Ihnen definierte Form verwenden. Sie müssen lediglich eine neue Klasse von „pear_error“ ableiten und diese dann erstellen und „werfen“. Zum richtigen Zeitpunkt reichen Objekte der neuen Klasse aus.
Einfache Fehlerbehandlung:
In Pear besteht die einfachste Fehlerbehandlung darin, den Fehler auszulösen. Sie müssen lediglich ein Pear_error-Objekt erstellen und zurückgeben. Hier ist ein einfaches Beispiel:
<br>function myconnect($host = "localhost", $port = 1080)<br>{<br>$fp = fsockopen($host, $port, $ errno, $errstr);<br>if (!is_resource($fp)) {<br>return new pear_error($errstr, $errno);<br>}<br>return $fp;<br>}<br>$sock = myconnect();<br>if (pear::iserror($sock)) {<br>print "connect error: ".$sock->getmessage()."<br>n" <br>}<br>

Wie im obigen Code gezeigt, müssen Sie nach der Ausführung eines Codeabschnitts, der möglicherweise einen Fehler erzeugt, den Iserror von Pear verwenden, um zu erkennen, ob ein Fehler vorliegt, und Sie können die Getmessage von Pear_error verwenden, um die neueste Fehlermeldung abzurufen. Hinweis: Stellen Sie sicher, dass Sie an wichtigen Stellen „pear::iserror“ und „raiseerror“ verwenden. Nach PHP4.0.5 verfügt „pear“ über zwei weitere Funktionen:
seterrorhandling($mode, $options = null)
„raiseerror“. ($message = null, $code = null, $mode = null, $options = null, $userinfo = null)

Ersteres kann den Standard-Fehlerbehandlungsmodus von Pear festlegen, und letzteres ist eine Wrapper-Funktion. Gibt ein Pear_error-Objekt zurück, was sich geringfügig von der direkten Erstellung und Rückgabe eines Pear_error-Objekts unterscheidet. Wenn Sie Parameter wie $mode, $options usw. weglassen, werden zum Erstellen des Pear_error-Objekts Standardwerte verwendet , Sie können seterrorhandling() zum Anpassen verwenden.

pear_error

pear_error ist eine Basisklasse des Pear-Fehlerobjekts. Im Allgemeinen können Sie eine Instanz von Pear_error direkt erstellen:
$error = new pear_error($message, $code, $mode, $options, $userinfo);
$message ist Ihre Fehlermeldung, $code ist die Fehlernummer des Fehlers und die letzten drei Parameter hängen eng zusammen:
$mode: ist dies Fehler Der Verarbeitungsmodus kann die folgenden Konstanten sein:
pear_error_return: gibt nur das Fehlerobjekt zurück (Standardmodus)
pear_error_print: gibt diese Fehlermeldung in der Build-Funktion aus, aber das aktuelle Programm wird weiterhin ausgeführt.
pear_error_trigger: Verwenden Sie PHPs trigger_error(), um einen Fehler auszulösen. Wenn Sie eine Fehlerbehandlungsfunktion eingerichtet haben oder die Fehlerbehandlungsebene von PHP auf e_user_error setzen, wird das aktuelle Programm beendet.
pear_error_die: Fehler ausgeben und beenden, das Programm wird beendet.
pear_error_callback: Verwenden Sie eine Rückruffunktion oder -methode, um den aktuellen Fehler zu behandeln und das Programm zu beenden.
$options: Dieser Parameter funktioniert nur, wenn $mode „pear_error_trigger“ und „pear_error_callback“ ist. Wenn es „pear_error_trigger“ ist, muss „$options“ eine der drei Konstanten e_user_notice, e_user_warning oder e_user_error sein, die mit dem Wert von „trigger_error“ in PHP übereinstimmt. Wenn $mode „pear_error_callback“ ist, kann „$options“ ein String sein, der den Namen der zurückzurufenden Funktion enthält, oder ein Array aus zwei Elementen, jeweils einer Objektvariablen und einem String (der die aufzurufende Methode angibt).
$userinfo: Speichert zusätzliche Benutzerinformationen. Hier können Sie relevante Debugging-Informationen eingeben.
Es gibt einige häufig verwendete Methoden in der PHP-Dokumentation. Sie werden hier einzeln aufgelistet:
int getmode: Gibt den aktuellen Fehlerbehandlungsmodus zurück, Ganzzahl.
string getmessage: Gibt die aktuelle vollständige Fehlermeldung zurück, string.
gemischter getcallback: Gibt die aktuellen Rückrufinformationen zurück, bei denen es sich um den Namen der Funktion handeln kann, die zurückgerufen wird, oder um ein Array von (Objekten, Methoden).
int getcode: Gibt einen ganzzahligen Fehlercode zurück.
string gettype: Gibt den falschen Typ zurück, nämlich den aktuellen Klassennamen, string.
string getuserinfo: Gibt zusätzliche Benutzerinformationen zurück, string.
string getdebuginfo: Der Inhalt ist derselbe wie oben.
string tostring: Gibt eine detaillierte String-Beschreibung des aktuellen Objekts zurück, einschließlich Fehlerbehandlungsmodus, Ebene, Fehlerinformationen, Fehlercode, zugehörige Rückruffunktionen usw.
Zusammenfassung
Dies ist das Ende der Einführung in die Birne. Zusammenfassend lässt sich sagen, dass Sie Folgendes tun müssen, wenn Sie eine Erweiterungsanwendung für Pear erstellen möchten:
require_once "pear.php"
Verwenden Sie die Klasse your_pear_extend erweitert Pear{}, um Ihre neue Klasse zu definieren.
Rufen Sie im Konstruktor Ihrer Klasse den Konstruktor der übergeordneten Klasse Pear auf:
function your_pear_extend{
$this->pear();
...
}

Definieren Sie bei Bedarf Ihren Destruktor _your_pear_extend

Leiten Sie bei Bedarf Ihre eigene Fehlerbehandlungsklasse von pear_error ab

Legen Sie Ihren Fehlerbehandlungsmodus fest und lösen Sie bei Bedarf Fehler aus.
Nachdem Sie Code ausgeführt haben, der möglicherweise Fehler generiert, verwenden Sie pear::iserror($obj), um die entsprechenden Fehler zu erfassen.
Implementieren Sie Ihre eigene Funktionalität.
In der neuesten Pear-Core-Version von php4.05 gibt es bereits viele hervorragende Anwendungsmodule, wie zum Beispiel: phpdoc, Cache, HTML ... Im Vergleich zu cpan ist Pear natürlich gerade erst gestartet und erfordert PHP Mit dem Joint Durch die Bemühungen der Menschen in der Community, es zu verbessern und zu verbessern, wird PHP immer leistungsfähiger.
Verwandte Ressourcen
Pear-Homepage
PHP-Homepage
PHPDoc-Homepage, die Javadoc-ähnliche API-Dokumente aus dem Quellcode Ihrer Pear-Anwendung generieren kann
PHP-Modus für xemacs/emacs, bereitgestellt für emacs/ Die Syntaxunterstützung von xemacs PHP kann den Pear-Code-Stil sehr gut unterstützen
vim homepage, ein sehr ausgezeichneter Editor, bietet auch gute Unterstützung für PHP

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Empfehlungen
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage