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

Autor wpisu: Michal Wachowski, dodany: 08.11.2011 22:18, tagi: php

Tak na prawdę, to ten wpis pierwotnie miał być odpowiedzią na blogu Tomasza Kowalczyka, ale rozrósł się na tyle, by stać się samodzielnym wpisem.

Autor wpisu: singles, dodany: 07.11.2011 18:38, tagi: internet, php

Od prawie dwóch lat chodził mi po głowie pomysł meetupa poświeconego typowo PHP. Gdzie spotkać mogliby się programiści doświadczeni, jak i Ci dopiero zaczynający swoją przygodę z językiem. Spotkania, które zwracałyby uwage na dobrę praktyki, a nie pisanie kodu PHPa na zasadzie „byle tylko działało”. Spotkania, które pokaże, że dowcip „programista PHP” nie zawsze jest prawdziwy.

Poźniej poznałem ludzi nastawionych pozytywnie to tego pomysłu (głównie za sprawą wszelkiego typu konferencji). W międzyczasie wystartowało meet.js (zbieżność nazw wcale nie jest przypadkowa;), które udowadnia, że da się realizować darmowe meetupy z powododzeniem. Tak więc, zachęcony sukcesem meet.js, z przyjemnością prezentuję inicjatywę meet.php.

Informacje

Nie będę podawał szczegółów tutaj, tylko odeślę na stronę meet.php. Tam znajdziecie informacje na temat pierwszego spotkania – datę, miejsce spotkania, listę prelegentów. Jesteśmy także na Twitterze i Facebooku. Feedback jak najbardziej wskazany i porządany:) Zapraszam do odwiedzin!

Prośba

Tutaj prośba do „braci” ze środowiska PHPowego (i nie tylko) o rozpropagowanie informacji o evencie. Jakakolwiek forma będzie dobra – krótki wpis na blogu, retweet, „lajk” czy też „plus jedynka” ;) Z góry dziękuję za okazaną pomoc :)

Podziękowania

Mimo tego, że projekt tej jest wspólnym dziełem moim oraz Daniela Mendalka (@daniula), ogromne podziękowania należą się także członkom Akademickiego Koła Aplikacji Internetowych oraz ekipie Coworking ZOO.

Autor wpisu: batman, dodany: 07.11.2011 08:00, tagi: php

Dwa tygodnie temu uzyskałem dostęp do nowej chmury przeznaczonej dla PHP, stworzonej przez firmę Zend. Zend Developer Cloud, bo o niej mowa, jest już trzecią chmurą dedykowaną PHP i podobnie jak PHPFog znacząco upraszcza proces tworzenia aplikacji, zdejmując z barków programisty kwestie administracyjne. W przeciwieństwie do PHPFog, Zend Developer Cloud jest darmowa.

Jak zacząć?

Proces tworzenia aplikacji na Zend Developer Cloud rozpoczyna się od utworzenia pojemnika (container). Jest to przestrzeń dla naszych aplikacji, coś w rodzaju serwera, na którym będą uruchamiane aplikacje.

image

Kilka minut po utworzeniu pojemnika, będziemy mogli wejść na wskazany przez nas adres. W efekcie ujrzymy poniższą stronę. Ważne jest aby zapisać hasło do pojemnika, ponieważ hasło to będzie używane w bazie MySQL oraz w większości innych miejsc, wymagających potwierdzenia naszej tożsamości.

image

I to wszystko co musimy zrobić, aby rozpocząć pracę w chmurze Zenda. Kolejny krok, to instalacja aplikacji.

Tworzymy aplikację

Stworzenie aplikacji jest równie banalne jak stworzenie pojemnika ją przechowującą. W chwili obecnej nie mamy zbyt dużego wyboru, który zamyka się w obrębie następujących rozwiązań:

  • pusta aplikacja PHP – standardowa aplikacja oparta o PHP
  • pusta aplikacja Zend Framework – szkielet aplikacji ZF
  • pusta aplikacja Zend Framework 2 – szkielet aplikacji ZF2
  • Drupal 7.8 – znany i lubiany CMS
  • Joomla 1.7 – j.w.
  • Magento 1.5.1 – system eCommerce zbudowany w oparciu o Zend Framework
  • WordPress 3.2.1 – znany i lubiany system blogowy
  • phpBB 3.0.9 – znane i lubiane forum

Tworząc nowy projekt warto wiedzieć, że wszystkie aplikacje zostaną utworzone w domenie pojemnika w podkatalogu o nazwie jaką dla aplikacji wybierzemy.

Z racji zainteresowań, do testów wybrałem Zend Frameworka w wersji pierwszej. Po kliknięciu w przycisk Deploy application, zostałem poproszony o podanie nazwy aplikacji i katalogu, w którym będzie się ona znajdować.

image

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

Autor wpisu: Kamil Adryjanek, dodany: 07.11.2011 00:14, tagi: symfony2, php

Od jakiegoś czasu starałem się znaleźć odpowiedni moment / trochę wolnego czasu na zapoznanie się z najnowszą wersją frameworka Symfony. Jako, że wiele osób zastanawia się / rozważa migrację swoich dotychczasowych projektów, bądź też rozpoczęcie nowych na Symfony2 postanowiłem przedstawić moje subiektywne obiektywne zdanie na temat możliwości Symfony2.

Ogromną zaletą Symfony2 jest w pełni przepisany silnik frameworka, który w pełni wykorzystuje możliwości PHP 5.3. Przestrzenie nazw nie tylko rozwiązuje problem konfliktów i długich nazw ale także sprawiają, że ładowanie potrzebnych klas jest teraz znacznie prostsze.

Instalacja

Do ściągnięcia dostępna jest gotowa paczka zawierająca wszystkie biblioteki niezbędne do rozpoczęcia pracy. Osobiście polecam instalację framewokra z Gita (najwygodniej pod Linuxem, chociaż jest też ciekawa wersja pod Windowsa dla zainteresowanych). Dzięki temu wszelkie aktualizacje zewnętrznych bibliotek, czy tez bibliotek frameworka sprowadzają się do aktualizacji plików deps i deps.lock, a następnie wywołania z wiersza poleceń komendy:

</p>
<p>php bin/vendors update</p>
<p>

Bundles

Symfony2 to przede wszystkim ogromne zmiany w architekturze i organizacji kodu aplikacji. Każda aplikacja składa się teraz z pakietów: bundles – coś na wzór modułu z symfony 1.X, z tym że każdy bundle jest teraz dużo bardziej niezależny: posiada odrębną logikę, konfigurację, klasy Entity czy usługi. Dzięki temu nowy mechanizm rozszerzeń Symfony2 jest w całości oparty o bundles – w sieci można znaleźć wiele ciekawie napisanych rozszerzeń: rozbudowany panel administracyjny wzorowany na Django (SonataAdmin) + szereg rozszerzeń, biblioteka do manipulacji/modyfikacji obrazków inspirowana Pythonowym PILem (Imagine), Goutte, biblioteka do budowania scenariuszy, które są następnie wykorzystywane do testowania funkcjonalności (Behat + Mink).

Formularze

Początkowo bardzo toporne – brakuje dobrej dokumentacji. Stworzenie formularza rejestracji, dodanie walidacji (dodanie zależności między polami) stanowi nie lada wyzwanie. Nie podoba mi się przeniesienie walidacji do klasy yml/xml – tak jakbyśmy wracali do symfony 1.0. Na szczęście są annotacje, które można wykorzystać zarówno w klasach Entity, jak i Models. UWAGA na problem z eAcceleratorem – straciłem kilka dobrych godzin przez problem z obcinaniem komentarzy na serwerze produkcyjnym. eAccelerator nie współpracuje poprawnie z nowymi bibliotekami: Symfony2, Doctrine2, Zend Framework, PHP Unit, … . Niestety po kilku godzinach pracy z formularzami miałem odczucie jakby cały mechanizm był teraz znacznie bardziej skomplikowany i trudny do opanowania.

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

Autor wpisu: Tomasz Kowalczyk, dodany: 06.11.2011 15:07, tagi: css, php

Co tu dużo pisać - przed Wami kolejny Linkdump związany z PHP, zapraszam do lektury!       Fotografia: Alexandr Mitriuc @ Fotolia. Linkdump: PHP. I like PHP. I like it too. :) Warto przeczytać, dlaczego można lubić ten język. CSS Crush: PHP-Based CSS Pre-Processor. "Przetwarzacz" CSS w PHP. Open Source PHP Search Engine – [...]

Autor wpisu: Śpiechu, dodany: 06.11.2011 14:10, tagi: mysql, php

Trochę nie pisałem. Mam nadzieję, że dzisiejszy wpis wszystkim wynagrodzi moją nieobecność. Ostatnio stanąłem przed wyzwaniem zrobienia galerii zdjęć, których kolejność dałoby się dowolnie modyfikować za pomocą przeciągania i upuszczania. Dzisiaj opiszę operacje bazodanowe, a na następny raz jQuery. Będę maksymalnie upraszczał aby nie zaciemniać meritum.

1. Przygotowania

Powiedzmy, że mamy 2 tabele relacyjne odpowiedzialne za przechowywanie galerii i obrazów. Np. takie:

CREATE TABLE `galleries` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
  `title` VARCHAR(250) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 ;
 
CREATE TABLE IF NOT EXISTS `images` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `gallery_id` INT(10) UNSIGNED NOT NULL,
  `filename` VARCHAR(50) NOT NULL,
  `ordr` INT(10) UNSIGNED NOT NULL DEFAULT '1',
  `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `image_to_gallery` (`gallery_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 ;

Od razu widać dwa dziwactwa: dlaczego pole nazywa się ordr a nie order? Z czystego lenistwa. Order jest słowem zarezerwowanym w SQL (ORDER BY coś tam). Każdorazowo nazwa pola musiałaby być w nawiasach. Dlaczego pole updated ma domyślną wartość 0000–00-00 00:00:00? Ano dlatego, że CURRENT_TIMESTAMP można użyć tylko raz w tabeli. Wobec tego stworzymy od razu wyzwalacz (trigger), który przed każdym zapytaniem typu UPDATE poprawi wartość na taką jak trzeba.

DELIMITER $$
CREATE TRIGGER `updated_current_timestamp` BEFORE UPDATE ON `galleries`
   FOR EACH ROW BEGIN
      SET NEW.updated = NOW();
END$$

Na koniec trzeba stworzyć relację 1 galeria do wielu zdjęć.

ALTER TABLE `images`
   ADD CONSTRAINT `image_to_gallery` FOREIGN KEY (`gallery_id`) REFERENCES `galleries` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

Oznacza to, że kasując galerię od razu pozbędziemy się również wszystkich powiązanych z nią zdjęć. Pliki z dysku oczywiście nie znikną. Można napisać funkcję, która przed usunięciem galerii z bazy najpierw wyrzuca wszystkie powiązane z nią pliki, a dopiero potem wykonuje polecenie DELETE.

2. Decyzje

Teraz nadszedł czas na poważne decyzje. Chodzi o sposób manipulacji wierszami dotyczącymi zdjęć. Można to zrobić za pomocą PHP. Jest to rozwiązanie prostsze. Powoduje jednak spory narzut komunikacji PHP<—>SQL. W przypadku zwalenia wszystkiego na bazę danych, pchamy logikę wyżej i bliżej modyfikowanych danych. Minusem jest cholerna składnia SQLowa i późniejsze problematyczne utrzymanie kodu. Problem oczywiście nie istnieje gdy robimy galeryjkę na 10 obrazków i przestawimy sobie kolejność ostatniego na przedostatni. Ja raczej podchodzę do rzeczy poważnie i wolę od początku zrobić to tak jak powinno być. Poza tym wyzwalacze i procedury składowane to jest to, co bazodanowe tygryski lubią najbardziej :-)

3. Wykonanie

Każdy nowy rekord tabeli images musi mieć nadany odpowiedni identyfikator pozycji ordr o 1 większy od ostatniego w danej galerii. Mamy trzy rozwiązania: czysty PHP, wyzwalacz wywoływany przed INSERTem lub procedura składowana. Zapytanie w PHP może wyglądać tak:

$q = $pdo->prepare('INSERT INTO images (filename,gallery_id,ordr) (SELECT ?,?,MAX(ordr)+1 FROM images WHERE gallery_id=? LIMIT 1)');
$q->bindValue(1, 'obrazek.jpg', PDO::PARAM_STR);
$q->bindParam(2, $galleryId, PDO::PARAM_INT);
$q->bindParam(3, $galleryId, PDO::PARAM_INT);
$q->execute();

Wspominam o tym rozwiązaniu dlatego, że ma ciekawą konstrukcję INSERT SELECT. Zapewne większość z was po kilkunastokrotnej próbie wywołania polecenia INSERT INTO VALUES i gdzieś tam SELECT dostanie cholery i rozbije zapytanie na 2: pierwsze sprawdza ostatni ordr, a następne doda 1 i umieści INSERTem pozostałe dane. Bazodanowe tygryski wybiorą jednak co innego. Procedury składowane!

DELIMITER $$
CREATE PROCEDURE `insert_image`(IN image_filename VARCHAR(50), IN image_gallery_id INT, OUT last_inserted_id INT)
   MODIFIES SQL DATA
   COMMENT 'Inserts new image at the end of given gallery.'
   BEGIN
      DECLARE max_order INT;
 
      # Zamiast SET zmienna= uzywam SELECT INTO just FOR fun
      SELECT MAX(ordr) INTO max_order FROM images WHERE gallery_id=image_gallery_id LIMIT 1;
 
      # Gdy obrazek jest pierwszy w galerii
      IF max_order IS NULL THEN 
         SET max_order = 1;
      ELSE
         SET max_order = max_order + 1;
      END IF;
      INSERT INTO images (filename, gallery_id, ordr) VALUES (image_filename, image_gallery_id, max_order);
      SELECT LAST_INSERT_ID() INTO last_inserted_id;
END$$

Próba wywołania $pdo->lastInsertId() zakończy się niepowodzeniem (a raczej zerem :-) ). Dlatego potrzebujemy parametru wyjściowego. Poniżej pokazuję jak całość wywołać w PDO:

$q = $pdo->prepare('CALL insert_image(?,?,@lastInsertId)');
$q->bindValue(1, 'obrazek.jpg', PDO::PARAM_STR);
$q->bindParam(2, $galleryId, PDO::PARAM_INT);
$q->execute();
$outputArray = $pdo->query('select @lastInsertId')->fetch(PDO::FETCH_ASSOC);
$lastInsertId = $outputArray['@lastInsertId'];

Ktoś może się zapytać po co te numery ze zmienną wyjściową. PDO i sterownik MySQL w PHP ma szpetny błąd dotyczący obsługi parametrów wyjściowych z procedur składowanych. Podobno w nowszych wersjach jest OK. Trik podany wyżej u mnie działa i oszczędza trochę nerwów.

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

Autor wpisu: Łukasz Socha, dodany: 06.11.2011 10:48, tagi: php

pobierz w .pdf(przeznaczone do wydruku)

PHP jest obecnie bezdyskusyjnie najpopularniejszym językiem programowania używanym w aplikacjach internetowych. Jego główną zaletą jest prostota i łatwość nauki (chociażby brak jawnych typów). Jednak, ma on także znaczne ograniczenia. PHP nie nadaje się do wykonywania bardziej zaawansowanych algorytmów – język nie posiada odpowiednich narzędzi do tworzenia abstrakcyjnych struktur danych. No to jak sam PHP nie ma takich możliwości, to połączmy go z C++…

Jak to zrobić?

Do uruchamiania programów napisanych w innych językach możemy użyć funkcji popen().

Za manualem:

resource popen ( string $command , string $mode )

Funkcja popen() wykonuje polecenie zawarte w $command – może to być np. program w C++ lub polecenie systemowe systemów operacyjnych UNIX. Parametr $mode określa zaś prawa dostępu do procesu. Funkcja zwraca (w przypadku sukcesu) uchwyt do uruchomionego procesu, w przeciwnym wypadku zwróci false.

Przykładowy program

Żeby zobaczyć jak to wygląda w praktyce stwórzmy prosty program do sortowania liczb. Wykorzystamy sortowanie bąbelkowe.

Najpierw stwórzmy kod w C++:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
void boubleSort(int table[], int size) {
	int i, j, temp;
     for (i = 0; i<size; i++) {
		for (j=0; j<size-1; j++) {
			if (table[j] > table[j+1]) {
			 temp = table[j+1];
                table[j+1] = table[j];
                table[j] = temp;
            }
        }
	}
}

int main(int argc, char** argv) {
	int n=argc-1;
	int t[n+1];
	for(int i=0;i<n;i++) {
		stringstream konwersja(argv[i+1]);
		konwersja>>t[i];
	}
	boubleSort(t, n);
	for(int i=0;i<n;i++) {
		cout << t[i]<< " ";
	}
	return 0;
}

W liniach 5-16 zawarty jest algorytm sortujący. W wierszach 21-24 odbieramy i konwertujemy argumenty przekazywane przy uruchamianiu programu do typu int. Właśnie za pomocą tablicy argv będziemy przekazywać dane ze skryptu PHP. Linie 26-28 wyświetlają wynik na standardowym wyjściu (zostanie on przekazany do skryptu PHP).

Teraz stwórzmy skrypt PHP:

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

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.