Błąd SmartyPDT w Eclipse 3.3.2 i PDT 1.0.3 z JRE 1.6

Niedawno update’owałem swoje IDE, i natknąłem się na mały zgrzyt w Eclipse. Okazało się, że najnowsza wersja 0.5.4 plugin’a do Smarty’ego (SmartyPDT) nie chce działać w środowisku Eclipse PDT z zainstalowanym JRE 1.6.

Błąd

Otwarcie pliku *.tpl w domyślnym edytorze smarty’iego dawało błąd:

java.lang.IllegalAccessError?: tried to access field org.eclipse.php.internal.ui.editor.PHPStructuredEditor.isExternal from class org.eclipse.php.smarty.ui.editor.SmartyStructuredEditor?
    at org.eclipse.php.smarty.ui.editor.SmartyStructuredEditor?.doSetInput(SmartyStructuredEditor?.java:42) at org.eclipse.ui.texteditor.AbstractTextEditor?$19.run(AbstractTextEditor?.java:3003) at org.eclipse.jface.operation.ModalContext?.runInCurrentThread(ModalContext?.java:369) at 
etc...

Błąd w całości można obejrzeć tutaj. Po małym dochodzeniu okazało się, że wersja SmartyPDT 0.5.4 działa w co najwyżej 1.5 The J2SE Runtime Environment (JRE), natomiast na mojej maszynie zainstalowane jest najnowsze JRE 1.6.

Rozwiązanie

Aby SmartyPDT działało poprawnie trzeba ściągnąć nieoficjalną wersję 0.5.5, która dostępna jet tutaj. Następnie wgrać do katalogu eclipse, przejść Help->Software Updates->Manage Configuration i dać 'disable’ na wersji 0.5.4 i 'enable’ na wersji 0.5.5

Po restarcie Eclipse wszystko działa poprawnie.

Refleksja

Ciekawe dlaczego na stronie SmartyPDT nie ma słowa o tej niezgodności, oraz dlaczego w download’zie nie ma najnowszej wersji 0.5.5?

White SEO – podstawowe przykazania jak budować przyjazne strony www

Co to jest White SEO?
White SEO to zbiór technik pozwalających na optymalizacje witryn internetowych pod kontem wyszukiwarek internetowych. White SEO opiera się na czystych zasadach pozycjonowania, są to metody zgodne z zasadami tworzenia stron internetowych, są akceptowane, a nawet zalecane przez same wyszukiwarki.

Tytuł strony
Tytuł (<title>) każdej strony powinien być unikalny, krótki i zawierać esencję tego co się znajduje na stronie.

Opis strony
Pole <description> powinno być unikalne i zawierać streszczenie zawartości strony, treść z tego pola bardzo często pojawia się w wynikach wyszukiwania Google zatem tekst ten powinien przyciągać użytkownika na stronę.

Adresy URL stron
Adresy URL poszczególnych stron powinny zawierać słowa kluczowe pod którymi strona ma się pozycjonować. Adresy nie powinny być zbyt długie, powinny posiadać hierarchiczną strukturę (np. kolejne działy oddzielone slashem). Każdy adres URL powinien zawierać unikalną treść, strzeż się duplicate content.

Strony witryny
Strony witryny powinny być przejrzyste i łatwe do czytania zarówno przez człowieka jak i przez roboty, staraj się używać jak najwięcej CSS. Strony / działy powinny być zamknięte tematycznie.

Linki wewnętrzne
Linki w obrębie serwisu powinny być krótkie, tekstowe i opisujące stronę do której prowadzą. Zamiast nic nie mówiących: 'więcej’, 'następny’, podlinkuj np.: 'więcej o pozycjonowaniu’. Staraj się dobrze linkować serwis gdyż linki wewnętrzne posiadają moc.

Nagłówki
Używaj nagłówków <Hx> aby zaznaczyć ważność elementów na stronie.

Grafika
Zoptymalizuj zdjęcia i obrazki, każdy tak powinien mieć atrybut alt=”” opisujący co jest na tym obrazku, nazwy plików powinny być zwięzłe ale zawierać słowo kluczowe zdjęcia. Nawet nie masz pojęcia jak pozytywnie wpływa to na ruch organiczny z Google Images.

Promuj swoją witrynę w naturalny sposób
Staraj się prezentować na stronie aktualne, unikalne i ciekawe treści – dzięki temu użytkownicy sami, z własnej nieprzymuszonej woli będą linkować do Twojej strony. Taki naturalny (zwykle tematyczny) link jest wart więcej niż 100 linków ze śmieciowych katalogów.

W serwisach sprzedażowo-korporacyjnych dobrym kanałem promocyjnym jest ogólnoserwisowy blog z ciekawymi informacjami dotyczącymi bądź to samego serwisu lub branży.

Używaj ogólnodostępnych narzędzi monitoringu
Aby analizować statystyki odwiedzalności witryny zainstaluj Google Analytics, aby monitorować pozycje w Google dodaj witrynę do Google’s Webmaster, zbuduj Sitemap’e aby w łatwy sposób wyszukiwarki mogły indeksować Twoją witrynę.

Podsumowanie
Wyżej spisane przykazania same z siebie nie zagwarantują sukcesu Twojej witrynie, jednak z pewnością pomogą w jego osiągnięciu. Pomogą w ogólnej promocji serwisu w internecie. Wydawać się może, że opisują ogólnie znane prawdy – zgadzam się – prawdy są znane. Niestety rzadko stosowane – tym lepiej dla Ciebie gdyż możesz zdobyć przewagę nad konkurencją i zaoszczędzić pieniędzy wydawanych na 'firmę SEO’.

Interfejs a klasa abstrakcyjna

Interfejsy i klasy abstrakcyjne zostały wprowadzone do php od wersji 5.0. Konstrukcje te znacznie pomagają w uporządkowaniu struktury aplikacji, pozwalają na zachowanie kontroli typów, integralność oraz logiczną budowę aplikacji.

Dzięki wdrożeniu tych konstrukcji do aplikacji możemy w lepszy i logiczniejszy sposób odwzorować rzeczywistość a zarazem ustrzec się potencjalnych błędów, poza tym zyskujemy większą kontrolę nad modelowaną obiektową rzeczywistością.

Klasy abstrakcyjne
Klasy abstrakcyjne służą do modelowania rzeczywistości, którą chcemy przenieść do logiki swojej aplikacji. Klasa abstrakcyjna definiuje w dużej ogólności pewien podstawowy model i zachowanie obiektu.

Powiedzmy, że chcemy chcemy stworzyć wirtualne zoo. W zoo znajdować się będą różnorakie zwierzęta np: małpy, lisy, wiewiórki, motyle, pszczoły, żaby, jaszczurki.

Każde zwierzę opisywane jest przez podstawowe atrybuty jak: wiek, rozmiar oraz cechy taki jak: rodzenie, chodzenie, jedzenie.

Tworzymy zatem podstawową klasę abstrakcyjną 'Zwierze’ zawierającą abstrakcyjne metody: born, go, eat:

abstract class Animal {

	protected $age;
	protected $width;
	protected $height;

	abstract protected function born();
	abstract protected function go();
	abstract protected function eat();

	protected function setAge( $years ) {
		$this->age = $years;
	}

	protected function setSize( $width, $height ) {
		$this->width = $width;
		$this->height = $height;
	}
}

Dzięki użyciu klasy abstrakcyjnej mamy pewność, że nikt nie stworzy obiektu klasy 'Zwierze’. Z logicznego punktu jest to niemożliwe gdyż nie ma zwierzęcia 'Zwierze’ – taki byt w rzeczywistości nie istnieje gdyż jest to zbyt ogólne pojęcie.

Dodatkowo zadeklarowaliśmy metody born, go, eat jako abstrakcyjne co wymusi ich implementacje w klasach dziedziczących – to też jest jak najbardziej logiczne gdyż nie ma zwierzęcia, które nie może wykonywać tych czynności. Metody te deklarujemy jako abstrakcyjne gdyż nie znając zwierzęcia nie wiemy jeszcze jak je zaimplementować. Metody abstrakcyjne muszą być puste.

Zadeklarowaliśmy również podstawowe atrybuty ($age, $width, $height), które każde zwierze posiadać musi, oraz settery które je ustawiają. Przy setterach ustawiamy specyfikator dostępu protected, dzięki temu będą mogły być wywoływane jedynie z poziomu metod klas dziedziczących. Nie ustawiamy ich jako abstrakcyjnych gdyż ich implementacja w klasie 'Animal’ jest wystarczająca i klasy potomne będą z nich korzystać.

Tworzymy teraz klasę konkretnego zwierzęcia np. małpy:

require_once 'animal.php';

class Monkey extends Animal {

	public function born() {/*@TODO*/}
	public function go() {/*@TODO*/}
	public function eat() {/*@TODO*/}

	public function __construct( $age, $size ) {
		$this->setAge( $age );
		$this->setSize( $size[0], $size[1] );
	}
}

$monkey1 = new Monkey( 2, array( 100, 20 ) );
var_dump( $monkey1 );

Musi ona posiadać metody abstrakcyjne, w ciele klasy 'Monkey’, powinny one przybrać docelową formę. Jak widać nie ma setterów, jest za to konstruktor przyjmujący parametry obiektu i wywołuje odpowiednie settery z klasy bazowej 'Animal’.

Interfejs
Klasa abstrakcyjna jest dość mocno związana logicznie z obiektami z niej dziedziczącymi. Widać jasno, że małpa i lis są integralnie związane z definicją zwierzęcia. Interfejs natomiast jedynie narzuca klasie jakie metody powinna posiadać, interface definiuje pewne właściwości, które klasa musi spełniać. Sam w sobie nie definiuje logicznej zależności pomiędzy sobą a klasą go implementującą, definiuje natomiast powiązanie pomiędzy wszystkimi klasami go implementującymi. Agreguje klasy obiektów na których można wykonać pewne operacje.

Kontynuując przykład zoo… załóżmy, że zoo może sprzedawać i kupować zwierzęta zatem możemy stworzyć interface 'Trade’:

interface Trade {
	public function sell();
	public function buy();
}

Dodatkowo, zwierzęta podlegają ubezpieczeniom zatem tworzymy interface 'Insurance’:

interface Insurance {
	public function make();
	public function withdrawn();
}

Jedna klasa może implementować wiele interfejsów, w przykładzie zoo 'Animal’ będzie implementował zarówno 'Trade’, jak i 'Insurance’. Jak widać kolejne interfejsy nie są ze sobą związane jednak wpływają na zachowanie się obiektu zwierzęcia.

class Monkey extends Animal implements Trade, Insurance {
	public function born() {/*@TODO*/}
	public function go() {/*@TODO*/}
	public function eat() {/*@TODO*/}
	
	public function sell() {/*@TODO*/}
	public function buy() {/*@TODO*/}
	
	public function make() {/*@TODO*/}
	public function withdrawn() {/*@TODO*/}
	

	public function __construct( $age, $size ) {
		$this->setAge( $age );
		$this->setSize( $size[0], $size[1] );
	}
}

Ale przecież w zoo są nie tylko zwierzęta ale także budynki i ludzie. Budynki mogą być odprzedawane a ludzie ubezpieczani zatem klasy reprezentujące te obiekty także powinny implementować te interfejsy.

Klasa 'People’ powinna implementować 'Insurance’ a klasa 'Building’ interfejs 'Trade’.

class People implements Insurance {
	public function make() {/*@TODO*/}
	public function withdrawn() {/*@TODO*/}
}
class Building implements Trade {
	public function sell() {/*@TODO*/}
	public function buy() {/*@TODO*/}
}

Widzimy zatem, że klasy reprezentujące zupełnie różne obiekty (zwierzęta, budynki) w pewnym zakresie zachowują się tak podobnie (można je kupić i sprzedać) zatem implementują interface 'Trade’.

Dzięki zapisowi tych zależności nasza aplikacja nabiera logicznego kształtu a dodatkowo dzięki parserowi zyskujemy darmową walidację, gdyż w przypadku braku metody z interfejsu php zwróci błąd – zatem nie zapomnimy o jej implementacji.