Wyszukiwarka
Logowanie
Dobra wiadomość dla oczekujących php 6 - spora część nowych funkcji zostanie zaimplementowana już w wersji 5.3, która jako ostatnia stabilna "piątka" ujrzy światło dzienne jeszcze w pierwszej połowie tego roku. Fakt ten ucieszy również osoby, których dostawca usług hostingowych zwlekać będzie z upgradem serwerów do php 6.
Poniżej prezentuję niektóre z nowych funkcji, których możemy się spodziewać w wersji 5.3.
<?php
class User {
public function set( $attribute, $value ) { ... }
public function save() { ... }
}
$user = new User();
$user->set('fullname', 'Ben Balbo');
$user->save();
?>
W przykładzie tym, metoda "save" nie koliduje z żadną inną metodą gdyż zawiera się w klasie "user". Pojawia się natomiast inny problem: klasa "user" może już być zdefiniowana w innej części systemu (np. jeśli nasz blog działa w obrębie większego systemu CMS). Rozwiązanie tej sytuacji przynosi słowo kluczowe "namespace", określające przestrzeń nazw:
<?php
namespace MyCompany::Blog;
class User {
public function set( $attribute, $value ) {
$this->$attribute = $value;
}
public function save() {
echo '<p>Blog user ' . $this->fullname . ' saved</p>';
}
}
?>
<?php
$user = new MyCompany::Blog::User();
$user->set('fullname', 'Ben Balbo');
$user->save();
?>
Z pozoru, szufladkowanie naszych funkcji przy użyciu przestrzeni nazw nie daje zbyt wiele korzyści - zmiana "MyCompany_Blog_User" na "MyCompany::Blog::User" wydaje się mało istotna. Mimo to możemy teraz stworzyć klasę "user" dla systemu CMS w innej przestrzeni:
<?php
namespace MyCompany::CMS;
class User { public function set( $attribute, $value ) {
$this->$attribute = $value;
}
public function save() {
echo '<p>CMS user ' . $this->fullname . ' saved</p>';
}
}
?>
W ten sposób umożliwiliśmy sobie użycie dwóch klas "MyCompany::Blog::User" i "MyCompany::CMS::User"
Używanie klas z wykorzystaniem pełnych nazw ich przestrzeni skutkuje dość długim kodem. Jeśli zamierzamy wywoływać wiele klas z przestrzeni "MyCompany::Blog", pisanie pełnej ścieżki za każdym razem może skutecznie uprzykrzyć kodowanie. W takim przypadku korzystnie jest wykorzystać słowo kluczowe "use". Rozpatrzmy poniższy kod, dodający nowy post:
<?php use MyCompany::Blog; $user = new Blog::User(); $post = new Blog::Post(); $post->setUser( $user ); $post->setTitle( $title ); $post->setBody( $body ); $post->save(); ?>
Za pomocą słowa "use" można również importować do skryptów pojedyncze klasy:
<?php use MyCompany::Blog::User; $user = new User(); ?>
Prędzej czy później konieczne będzie wykorzystanie dwóch klas o identycznych nazwach (ale innych przestrzeniach) w obrębie jednego skryptu. W takiej sytuacji moglibyśmy importować przestrzenie lub same klasy z wykorzystaniem aliasów, tak jak w poniższym przykładzie:
<?php
use MyCompany::Blog::User as BlogUser;
use MyCompany::CMS::User as CMSUser;
$bloguser = new BlogUser();
$bloguser->set('fullname', 'John Doe');
$bloguser->save();
$cmsuser = new CMSUser();
$cmsuser->set('fullname', 'John Doe');
$cmsuser->save();
?> Stałe (constants) można będzie definiować z poziomu klasy. Oto przykład:
<?php
namespace MyCompany;
class Blog {
const VERSION = '1.0.0';
}
?>
<?php
echo '<p>Blog bersion ' . MyCompany::Blog::VERSION . '</p>';
use MyCompany::Blog;
echo '<p>Blog version ' . Blog::VERSION . '</p>';
use MyCompany::Blog::VERSION as Foo;
echo '<p>Blog version ' . Foo . '</p>';
?> W dzisiejszych czasach coraz rzadziej używa się pojedynczych funkcji. Mimo to, możliwe jest przypisanie funkcji do wybranej przestrzeni. Oto przykład:
<?php
namespace bundle;
function foo() { echo '<p>This is the bundled foo</p>'; }
foo(); // Wyświetli 'This is the bundled foo'
?><?php
function foo() { echo '<p>This is the global foo</p>'; }
require( 'lib/bundle.class.php');
bundle::foo(); // Wyświetli 'This is the bundled foo'
foo(); // Wyświetli 'This is the global foo'
?> Przestrzeń globalna jest warta rozpatrzenia jeśli używasz pojedynczych funkcji. Analizując powyższy przykład można stwierdzić, że nie ma żadnego sposobu aby wywołać globalną funkcję "foo" z poziomu kodu w przestrzeni "bundle".
Aby wywołania funkcji były w pełni poprawne można użyć bieżącej przestrzeni. Jeśli funkcja nie może być odnaleziona, poszukiwana będzie funkcja wewnętrzna o tej samej nazwie. Inne przestrzenie nie są przeszukiwane.
Aby wywołać globalną funkcję "foo" z poziomu przestrzeni "bundle" przywołujemy bezpośrednio przestrzeń globalną - podwójny dwukropek:
<?php
namespace bundle;
function foo() { echo '<p>This is the bundled foo</p>'; }
foo(); // Wyświetli 'This is the bundled foo'
::foo(); // Wyświetli 'This is the global foo'
?> Podczas definiowania funkcji "__autoload" (która załącza pliki klas na żądanie) posługujemy się zazwyczaj katalogiem zawierającym pliki klas. Możliwość użycia przestrzeni nazw wymaga rozszerzenia funkcji "__autoload", gdyż mogą pojawić się pliki klas o takich samych nazwach. Na szczęście funkcja "__autoload" wywoływana będzie z parametrem określającym również używaną przestrzeń.
__autoload( 'MyCompany::Blog::User' );
Zamieniając podwójne dwukropki na znak "/" lub "\" możemy z łatwością dołączyć pliki znajdujące się w podkatalogach:
function __autoload( $classname ) {
$classname = strtolower( $classname );
$classname = str_replace( '::', DIRECTORY_SEPARATOR, $classname );
require_once( dirname( __FILE__ ) . '/' . $classname . '.class.php' );
}
Powyższy przykład dołączy plik "./classes/mycompany/blog/user.class.php".
Niebawem kolejna część artykułu.
Tego mi najbardziej brakuje w PHP. Jeszcze jedno zastosowanie Przestrzeni nazw można w koncu fragmenty kodu grupować w określone zestawy klas. Yupi! Zapewne ucieszy to w szczególności byłych lub aktualnych programistów C++, jeszcze brakuje wielokrotnego dziedziczenia i przejścia na pełną obiektowość oraz wymuszania typów np przy argumentach wejściowcyh funkcji. Nie mówię żeby język PHP był w pełni typowy tylko żeby pozwalał definiować że do funkcji może wejść w danej chwili tylko integer albo double i koniec... bo pisanie w środku dodatkowych funkcji typu is_int czy is_string jest wg mnie bez sensu i znacznie spowalnia aplikację :) ... czekam z niecierpliwością na PHP6 - bo nadchodzi rewolucja...
Mały błąd merytoryczny:
"Powyższy kod wyświetli:
Blog bersion 1.0.0
Blog version 1.0.0
Blog version Foo"
Powinno być:
"Powyższy kod wyświetli:
Blog bersion 1.0.0
Blog version 1.0.0
Blog version 1.0.0"
Dzięki za te przykłady! Przydadzą się na pewno i takich informacji szukałem a znaleźć nie mogłem.
Bardzo fajniem, że się pojawiło infoa temat NS w php 5.3 - jakiś czas temu szukałem info i nie znalazłem ;/
więc
Bartek, :*