Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM    Subskrybuj kanał ATOM dla tagu php Kanał ATOM (tag: php)

Autor wpisu: sokzzuka, dodany: 10.08.2010 22:15, tagi: php

Nie jest to dokładnie kolejna część cyklu o Domain Driven Design, ponieważ nie zawiera żadnej konkretnej treści. Umieszczam tutaj kilka linków do artykułów o DDD wraz z krótkim opisem, które mogą okazać się przydatne dla wszystkich zainteresowanych tą metodyką. Życzę miłego czytania ;) http://msdn.microsoft.com/en-us/magazine/dd419654.aspx – MVP Microsoftu opisuje metodologie DDD na przykładzie aplikacji dla firmy ubezpieczeniowej, bardzo wartościowy artykuł

http://art-of-software.blogspot.com/search/label/Domain%20Driven%20Design – kopalnia wiedzy (po polsku!), niestety mało przykładów na żywym kodzie

http://www.opentaps.org/docs/index.php/Domain_Driven_Architecture – wiki z przykładową aplikacją

przykladowe aplikacje (wszystkie w c#) :

http://code.google.com/p/ndddsample/

http://myshop.codeplex.com/

http://dddpds.codeplex.com/

http://www.fincher.org/tips/General/SoftwareEngineering/DomainDrivenDesign.shtml – dziwnie wyglądający blog ale merytorycznie artykuł ok

http://www.developerfusion.com/article/9794/domain-driven-design-a-step-by-step-guide-part-1/ – seria o ddd

http://www.infoq.com/minibooks/domain-driven-design-quickly – książka o ddd do ściągnięcia

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: sokzzuka, dodany: 10.08.2010 09:49, tagi: php

Dzisiaj kolejny post z nieoficjalnej serii „zaprzyjaźnij się z PHP” :P a dokładnie z php 5.3. Opiszę w nim jak zbudować generator. Czym jest generator ? Jak wyjaśnia nam Wikipedia generator jest rodzajem Iteratora, który zamiast zwracać wygenerowaną wcześniej zawartość oblicza nam ją wraz z kolejnym przebiegiem, dzięki czemu nie musimy od razu pobierać np. całej zawartości jakiejś kolekcji. Nasz mały generator będzie implementował interfejs „Iterator” i pobierał w konstruktorze jako swój argument dowolną anonimową funkcję, która będzie generować kolejny wynik. Kod:

class Generator implements Iterator {
 
    protected $_function;
    protected $_maxN;
    protected $_n = 0;
 
    public function __construct($function, $maxN) {
        $this->_function = $function;
        $this->_maxN = $maxN;
    }
 
    public function current() {
        $fFunc = $this->_function;
        return $fFunc($this->_n);
    }
 
    public function key() {
        return $this->_n;
    }
 
    public function next() {
        $this->_n++;
    }
 
    public function rewind() {
        $this->_n = 0;
    }
 
    public function valid() {
        if ($this->_n < $this->_maxN) {
            return true;
        }
        return false;
    }
}

Nasz generator użyjemy do wygenerowania pierwszych n elementów ciągu fibonnaciego. Najpierw funkcja:

$cFib = function($n) use (&$cFib) {
            if ($n == 0) {
                return 0;
            }
            if ($n == 1) {
                return 1;
            }
            return $cFib($n - 1) + $cFib($n - 2);
        };

Jak widzimy jest to klasyczna implementacja funkcji obliczającej kolejny element ciągu fibonacciego. Z rzeczy które warto zauważyć – jest to domknięcie (closure) i aby funkcja mogła się rekurencyjnie wywołać musi dostać referencje do samej siebie (trochę jest to hak ale inaczej się nie da, __FUNCTION__ nie działa tak jak powinno).

Zastosowanie:

$oGenerator = new Generator($cFib, 5);
foreach($oGenerator as $n => $value){
    echo $n, ' ', $value, '<br/>';
}

Wynik: 0 0 1 1 2 1 3 2 4 3

Koniec końców uzyskaliśmy wygodną klasę do generowania kolejnych wartości. Przy odrobinie większym wysiłku, można by do implementować jeszcze interfejs ArrayAccess i mieć już całkowitą iluzję obcowania z tablicą -

echo $oGenerator[4];
//zwroci 3

Autor wpisu: eRIZ, dodany: 08.08.2010 23:27, tagi: php

Od momentu wprowadzenia namiastki obiektów do naszego kochanego języka, coraz bardziej zaczęły nasilać się narzekania, że PHP jest sto lat za konkurencją pod wieloma względami. Pewnie lista narzekań ciągnęłaby się aż do wyczerpania zapasów papieru toaletowego w WC, ale na pewne rzeczy progamista nie ma po prostu wpływu.

Jeśli nie da się czegoś rozwiązać wprost, zawsze można spróbować to… obejść. Wbrew pozorom, w programowaniu zdarza się to nierzadko. ;)

A o czym chcę napisać? O wyrzucaniu błędów przez PHP zamiast wyjątków.

Autor wpisu: batman, dodany: 08.08.2010 19:08, tagi: php

Microsoft wypuścił drugą wersję sterownika SQL Server przeznaczonego dla języka PHP. W nowej wersji dodano przede wszystkim wsparcie dla PDO. Dodanie wsparcia dla PDO nie oznacza, że przestaną działać dotychczasowe rozwiązania. Wydanie drugiej wersji sterownika było dobrą okazją do przepisania biblioteki odpowiedzialnej za łączność z bazą danych SQL Server. Nowa wersja została tak napisana, aby wszystkie wspóle elementy wydzielić do osobnej warstwy, z której korzystają różne mechanizmy do łączenia się z bazę.

Jak widać na powyższym obrazku (źródło: Microsoft SQL Server Driver for PHP Team Blog) w drugiej wersji sterownika można korzystać z dwóch sposobów łącznia się bazą, co w przypadku kod będzie wyglądało nastęująco.

<?php
// SQLSRV driver:
$serverName = "(local)\sqlexpress"; 
$connectionOptions = array( "Database"=>"AdventureWorks" );

/* Connect to SQL Server using Windows Authentication. */ 
$conn = sqlsrv_connect( $serverName, $connectionOptions );

/* Get products by querying against the product name.*/ 
$tsql = "SELECT ProductID, Name, Color, Size, ListPrice FROM Production.Product";

/* Execute the query. */ 
$getProducts = sqlsrv_query( $conn, $tsql );

/* Loop thru recordset and display each record. */ 
while( $row = sqlsrv_fetch_array( $getProducts, SQLSRV_FETCH_ASSOC ) ) 
{ 
	print_r( $row ); 
}

/* Free the statement and connection resource. */
sqlsrv_free_stmt( $getProducts );
sqlsrv_close( $conn );
<?php
// PDO_SQLSRV driver:
$serverName = "(local)\sqlexpress"; 

/* Connect to SQL Server using Windows Authentication. */ 
$conn = new PDO( "sqlsrv:server=$serverName;Database=AdventureWorks" );

/* Get products by querying against the product name.*/ 
$tsql = "SELECT ProductID, Name, Color, Size, ListPrice FROM Production.Product";

/* Execute the query. */ 
$getProducts = $conn->query( $tsql );

/* Loop thru recordset and display each record. */ 
while( $row = $getProducts->fetch( PDO::FETCH_ASSOC ) ) 
{ 
	print_r( $row );
}

/* Free the statement and connection resource. */
$getProducts = NULL;
$conn = NULL;

źródło: Microsoft SQL Server Driver for PHP Team Blog

Autor wpisu: cojack, dodany: 08.08.2010 13:55, tagi: php

PHP Jako iż każdy chce po sobie zostawić ślad tak i ja mam taki plan. Moje założenie: Napisać prosty i ciekawy system, który byłby fundamentem do tworzenia stron, stąd też nazwa Basic PHP Develop Tools, czyli podstawowe narzędzia. Zarazem podstawowe narzędzia i pełna moc w pisaniu aplikacji. Na pewno nie jeden z Was spotkał się z Drupalem, i opiniami o nim jaki to on nie jest wyczesany, jaki to on jest wspaniały, no cud malina. Tak tylko czy ktoś próbował w nim pisać cokolwiek? No właśnie i ja podziękuje za taką fanaberię. Prędzej bym „wyklikał” w nim moduł niż go napisał. Ale nie w tym sęk, chciałbym by ta aplikacja nie przerodziła się w Frameworka, nie chce nazywać tego Frameworkiem, i nie chce by ktokolwiek o nim w ten sposób myślał. Bardzo nie lubię tego stwierdzenia, i w ogóle nie przypada mi do gustu, powiem więcej wręcz się nim brzydzę.

Założenia do BDT

- W pełni obiektowy - Podstawowe narzędzia dla developera - Darmowy na licencji GPL

to by było na tyle ;)

Użyte narzędzia

- Horde Routes - Cache by MatheW ( linki na dole ) - Laptop, klawiatura, myszka, monitor, trochę palców… własne pomysły + podpatrzone.

Co już mam zrobione

- Obsługa akcji, - Routing (ta już był tylko zaimplementować), - Cache (j/w), - System szablonów ( php + html, żadne smarty opty i inne śmiecie ), - Obsługa błędów ( wyjątki + trigger_error ), - Obsługa SQL w 40%, - Confingi ( w XML )

Czego jeszcze nie mam zrobione

- Requesty (ale mam już koncept) - Weryfikacja danych (j/w) - Headery (szczerze, to mi się w to nie chce bawić, oprócz takich podstawowych jak 404 itp) - MultiLanguage ( dla błędów to będzie na 100% gettext, i l18n dla treści ) - Instalator ( jeszcze nie wiem czy będzie )

Co chcę uzyskać

Chcę napisać wydajny system, który usprawni mi pracę, która sprawi mi jeszcze więcej przyjemności niż Wam się wydaje, gdyż dla mnie programowanie to frajda. Olałem Doctrine, gdyż z tymi pajacami z dev nie można się w żaden sposób dogadać, myślą że pozjadali wszystkie rozumy i są najlepsi na świecie, także ORM będzie trochę inny niż wszystkie. Piszę swój system do zarządzania SQL’em, oczywiście nie będzie tam żadnych INSERT, UPDATE czy DELETE w kodzie wykonanego wszystko będzie oparte o język proceduralny PL/pgSQL nazwałem tą aplikację PGFM (PostgreSQL Function Mapper) … ( przy okazji refaktoryzacji kodu już zdążyłem zmienić nazwy większości klas, także ciekawe co z tego wyjdzie…) . Czyli dodanie rekordów do bazy danych czy ich aktualizacja lub/i usunięcie będzie się wykonywało poprzez procedury. W pewnym stopniu jest to przeniesienie logiki aplikacji do SQL’a, ale dlaczego nie? Jest to ciekawe rozwiązanie i nigdzie wcześniej nie widziałem takiego rozwiązania ( no prawie nigdzie ale nie mogę powiedzieć gdzie ;] domyślcie się gdzie ).

Dlaczego darmowy?

Dlatego że chce by każdy miał dostęp do innego spojrzenia na problem by też mógł się rozwijać analizując czyjś kod, może znajdzie ktoś jakiś błąd i pomoże mi go naprawić. Ale szczerze powiedziawszy nie liczę na to że będziecie chcieli używać tych narzędzi, nie zależy mi na tym. Piszę go dla siebie i dla firmy mojego kolegi ;)

Bezpieczeństwo

Dużą wagę przekładam na bezpieczeństwo aplikacji, zatem data wydania będzie się przeciągać w czasie, będę chciał uniknąć falstartów i śpieszyć się z tym byście ujrzeli moje wypociny, jakoś mi się nie śpieszy. Rdzeń aplikacji będzie a przynajmniej będę miał takie założenie, odporny na taki typu sql injecty, xss’y i masę innych dupereli.

Słów kilka na zakończenie

Pewnie nie jeden z Was zapyta się po co to piszę? No napisałem powyżej, chce to zrobić by zostawić jakiś ślad po sobie. Oraz piszę też to po to by się samemu rozwijać, widzieć problem i znaleźć rozwiązanie dla niego. Na prawdę fajnie się idzie owkurw**** jak coś nie wychodzi, a później olśnienie i tona euforii jak zaczyna działać. To jest właśnie to dlaczego piszę swoją aplikację. Poza tym TAO programowania.

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Vokiel, dodany: 06.08.2010 23:00, tagi: php

Autentyfikacja HTTP

Ostatnio, podczas przenosin dość starej aplikacji na nowy serwer natknąłem się na problem z powodu wykorzystania autentyfikacji HTTP. Problem okazał się błachy, jednak w momencie przenosin i pierwszych testów miałem problem z diagnozą przyczyn takiego stanu rzeczy.

Opis sytuacji

Na wstępie krótko opiszę sytuację, objawy jakie się pojawiły. W dalszej części pokażę sposób poradzenia sobie z problemem.

Na starym serwerze PHP działał sobie jako zwykły moduł apache. Jako, że aplikacja była pisana dawno temu, wówczas system logowania oparty na autentyfikacji HTTP wydawał się wystarczający. Tym bardziej, iż była to aplikacja intranetowa. Po przenosinach na nowy serwer okazało się, że okienko autentyfikacji nie przestawało wyskakiwać nawet po podaniu poprawnego loginu i hasła. Na pierwszy ogień poszło sprawdzenie poprawności przeniesionej bazy danych, użytkownika bazy, zawartości tabel. Okazało się, że wszystko jest ok, zatem na warsztat poszedł test systemu logowania.

System logowania oparty o autentyfikację HTTP

System logowania był bardzo prosty. Pobrane dane z $_SERVER['PHP_AUTH_USER'] oraz $_SERVER['PHP_AUTH_PW'] były porównywane z tymi w bazie danych. Jeśli autoryzacja nie przebiegała pomyślnie wyświetlany był odpowiedni komunikat i po trzech sekundach strona była odświeżana z ponownym wyświetleniem okienka autentyfikacji.

Skrócony na potrzeby przykładu plik index.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
if (empty($_SERVER['PHP_AUTH_USER'])) {
	header('WWW-Authenticate: Basic realm="Logowanie"');
	header('HTTP/1.0 401 Unauthorized');
	sleep(3);
	exit;
}else {
	DEFINE ('LOGINSALT','TESTOWYSALTLOGOWANIA');
 
	require_once 'class/db/db.class.php';
	require_once 'class/login.class.php';
 
	$login_string = md5($_SERVER['PHP_AUTH_USER'].LOGINSALT.md5($_SERVER['PHP_AUTH_PW']));
	$logowanie = new login($login_string);
	$logowanie->login();
	if ($logowanie->isLogged()){
		// ok
	} else {
		include 'notLogged.php';
		sleep(3);
		header('WWW-Authenticate: Basic realm="Logowanie"');
		header('HTTP/1.0 401 Unauthorized');
		exit;
	}
}
?>

Jak widać jest to bardzo proste, wręcz banalne rozwiązanie. Z tą różnicą względem podstawowych systemów opartych na .htpasswds, że dane użytkowników są przechowywane w bazie danych.

Sama klasa logowania też jest bardzo prosta. Jednak w tym wypadku, doskonale spełniała swoje założenia. Wersja odchudzona:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<?php
/**
 * Klasa logowania
 *
 * @param string $login_string - Ciąg danych logowania md5(login+salt+md5(hasło))
 */
class login{
	/**
	 * Ciąg logowania
	 *
	 * @var string
	 */
	private $_login_string;
	/**
	 * Stan zalogowania
	 *
	 * @var bool $_logged
	 */
	private $_logged = false;
	/**
	 * Id zalogowanego użytkownika
	 *
	 * @var int
	 */
	private $_id;
	/**
	 * Konstruktor klasy logowania
	 *
	 * @param string $login_string
	 */
	public function __construct($login_string){
		$this->_login_string = $login_string;
	}
	/**
	 * Logowanie użytkownika
	 *
	 * @return bool
	 */
	public function login(){
		$db = new db_class(DB_HOST,DB_LOGIN,DB_PASS,DB_NAME);
		$query = "SELECT `ID` FROM `LISTA_USR` WHERE md5(CONCAT(`LOGIN`,'".LOGINSALT."',`PASS`))='".$this->_login_string."' ;";
		$db->sqlQuery($query);
		if ($db->sqlNumRows()>0){
			$row = $db->getRow();
			$this->_id = $row['ID'];
			$this->_logged = true;
			return true;
		}
		return false;
	}
	/**
	 * Sprawdzenie czy zalogowany
	 *
	 * @return bool $this->_logged
	 */
	public function isLogged(){
		return $this->_logged;
	}
	/**
	 * Pobranie ID zalogowanego użytkownika
	 *
	 * @return int $this->_id;
	 */
	public function getUsrId(){
		return $this->_id;
	}
}
?>

Rozwiązanie proste jak budowa cepa. Nie ma się tu nad czym rozwodzić. Niestety w trybie CGI się nie sprawdza, gdyż w zmiennej $_SERVER nie ma zmiennych $_SERVER['PHP_AUTH_USER'] oraz $_SERVER['PHP_AUTH_PW'].

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Zyx, dodany: 06.08.2010 13:37, tagi: php

W naszej opowieści o wzorcu MVC pora zrobić krok dalej. Do eksperymentalnej implementacji Trinity dodaliśmy już całą procedurę rozruchową, moduły oraz hierarchiczne cegiełki pozwalające składać kontroler z mniejszych klocków. Mając już pewne rozeznanie, jak MVC działa i jakie możliwości, tudzież ograniczenia wprowadza w porównaniu z tym, co się implementuje we frameworkach, jesteśmy gotowi do rozważań na temat bardziej namacalny dla użytkownika końcowego, czyli nawigacji. Zastanowimy się, jak umieścić jej generowanie w strukturze wzorca oraz omówimy możliwe rozwiązania techniczne.
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.