Pokazywanie postów oznaczonych etykietą php. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą php. Pokaż wszystkie posty

2015-11-27

Z underscore na CamelCase

Jak zamienić w PHP string z this_is_test na ThisIsTest? Poniżej znajduje się linijeczka kodu, która robi taką fajną rzecz.

preg_replace('/(?:^|_)(.?)/e', "strtoupper('$1')", "this_is_test");

źródło: devops.zone

Umieściłem to polecenie w bibliotece tools dostępnej w serwisie GitHub.

2015-10-13

PHP DateTime: Pierwszy i ostatni dzień poprzedniego miesiąca

Od PHP 5.3 pierwszy i ostatni dzień miesiąca można wybrać w bardzo prosty sposób:
$dataod = new \DateTime('first day of previous month');
$datado = new \DateTime('first day of previous month');
Można w ten sposób w prosty sposób przypisać domyślne wartości w formularzu:
$command = new EksportSwiadczenDoCsvCommand();
$command->setDataod(new \DateTime('first day of previous month'));
$command->setDatado(new \DateTime('last day of previous month'));

$form = $this->createForm('platne_eksport_zlecen_do_csv', $command);

$form->handleRequest($request);

if($form->isValid()){
    //...
}
W ten sam sposób możemy wybrać również pierwszy i ostatni dzień aktualnego miesiąca - odpowiadają za to zmienne 'first day of this month' oraz 'last day of this month'.

2015-08-25

Symfony2 - debugowanie skryptów uruchamianych z konsoli

Istnieje możliwość debugowania kodu odpalanego z konsoli (app/console). Aby móc cieszyć się takim dobrodziejstwem wystarczy:

w php.ini (dla cli) wpisać:

xdebug.remote_enable=1

przed poleceniem app/console wpisać:

SERVER_PORT=9000 SERVER_NAME='PHPSTORM' php -dxdebug.remote_autostart=On app/console test

2015-08-06

Symfony2 - FOSJsRoutingBundle

Za pomocą bundla FOSJsRoutingBundle można korzystać z routingu Symfony w javascriptowym kodzie. Poniżej krótki przykład:

PHP:

 /**
  * @Route("/ks", options={"expose" = true}, name="nfz.raport_wykbadpoz_kolumny_standardowe")
  * @Template("raport/kolumny_standardowe.html.twig")
  *
  * @return array
  */
 public function kolumnyStandardoweAction()
 {
  $ar_kolumny_standardowe = $this->raportWykbadpozManager->getKolumnyStandardowe();
  return compact('ar_kolumny_standardowe');
 }

JavaScript:

$.wczytajKolumnyStandardowe = function(url){
    var kolumny_standardowe = $("#kolumny_standardowe");

    $.post(Routing.generate("nfz.raport_wykbadpoz_kolumny_standardowe"), {}, function(data){
        kolumny_standardowe.html(data);
    });
};
Należy pamiętać o options={"expose" = true} w annotacjach. Więcej informacji na githubie.

2015-08-05

Symfony2 form - wynik w innej akcji i w nowym oknie

W Symfony po submicie formularza wracamy do tej samej akcji (w naszym przypadku do indexAction()). Aby to zmienić wystarczy dodać odpowiednią opcję przy tworzeniu obiektu formularza (form). Istnieje również możliwość otworzenia wyniku w nowym oknie. Całość można zobaczyć w poniższym kodzie:

 /**
  * @Route("/", name="nfz.raport_wykbapoz")
  * @Template()
  *
  * @return array
  */
 public function indexAction()
 {
  //...
  $form = $this->createForm('nfz_raport_wykbadpoz', $object, [
   'action' => $this->generateUrl('nfz.raport_wykbadpoz_wynik'),
   'attr' => [
    'target' => '_blank'
   ]
  ]);

  return [
   'form' => $form->createView()
  ];
 }

 /**
  * @Route("/wynik", name="nfz.raport_wykbadpoz_wynik")
  * @Template()
  *
  * @param Request $request
  * @return array
  */
 public function wynikAction(Request $request)
 {
  //zabezpieczenie malutkie
  if($request->getMethod() != 'POST') {
   return new RedirectResponse($this->generateUrl('nfz.raport_wykbapoz'));
  }

  //utworzenie obiektu formularza
  $form = $this->createForm('nfz_raport_wykbadpoz');
  //pobranie danych z submitowanego formularza
  $form->handleRequest($request);

  //walidacja formularza
  if($form->isValid()){
   //pobranie danych z formularza
   $data = $form->getData();
  }
  //...
  return [];
 }

Widać tutaj, że funkcja kontrolera wynikAction() przchwytuje dane z submitowanego w indexAction() formularza.

2015-06-19

Instalacja Nginx zamiast Apache2

Nadszedł czas na coś nowego - zrezygnowałem z Apache2 na rzecz Nginx'a. Z Nginxem dobrze działa PHP FPM, który daje kilka ciekawych opcji - np: możliwość użycia eventu Symfony o nazwie kernel.terminate.


Jak zainstalować Nginx'a i PHP FPM pod Mintem (lub Ubuntu)?

# zatrzymujemy apache'a
sudo service apache2 stop

# usuwamy apache'a z autostartu
sudo update-rc.d apache2 disable

# instalujemy nginx'a
sudo apt-get update
sudo apt-get install nginx
sudo service nginx start
sudo service nginx status

# instalujemy PHP FPM
sudo apt-get install php5-fpm

# zmieniamy cgi.fix_pathinfo z 1 na 0
sudo mc -e /etc/php5/fpm/php.ini -> cgi.fix_pathinfo=0

# restartujemy PHP FPM
sudo service php5-fpm restart

Po kilku tygodniach pracy z lokalnie zainstalowanym Nginx'em mam nieodparte wrażenie, że jest on szybszy i lżejszy niż Apache2.

2015-05-22

Debuggowanie aplikacji webowych za pomocą Xdebug i PhpStorm

PhpStorm umożliwia debuggowanie kodu, który wyświetlany jest aktualnie przez przeglądarkę internetową. Aby móc cieszyć się tym dobrodziejstwem musimy przejść kilka kroków opisanych poniżej (instrukcja dla dystrybucji linuksa Ubuntu/Mint).

Instalacja Xdebug

sudo apt-get install php5-xdebug
Do php.ini dodajemy:
zend_extension="/usr/lib/php5/20121212/xdebug.so"
xdebug.remote_enable=1
xdebug.remote_handler=dbgp 
xdebug.remote_mode=req
xdebug.remote_host=127.0.0.1 
xdebug.remote_port=9000
xdebug.max_nesting_level=300

Restartujemy Apache'a:
sudo service apache2 restart

Utworzenie przycisków odpalających debuggera

Aby uruchomić i zatrzymać debuggera w przeglądarce trzeba podać jej specjalne parametry. Można to zrobić ręcznie lub utworzyć sobie do tego odpowiednie przyciski - np. na pasku zakładek (ja używam właśnie takiego rozwiązania). Pod adresem https://www.jetbrains.com/phpstorm/marklets/ można wygenerować potrzebny kod. 

Start debugger:
javascript:(/** @version 0.5.2 */function() {document.cookie='XDEBUG_SESSION='+'PHPSTORM'+';path=/;';})()

Stop debugger:
javascript:(/** @version 0.5.2 */function() {document.cookie='XDEBUG_SESSION='+''+';expires=Mon, 05 Jul 2000 00:00:00 GMT;path=/;';})()

Uruchomienie debuggera

W przeglądarce uruchamiamy debuggera (np. przyciskiem start debugger), przechodzimy do PhpStorma i tam również włączamy debuggowanie (po wcześniejszym ustawieniu breakpointów oczywiście). Wracamy do przeglądarki, uruchamiamy badaną aplikację PHP i po napotkaniu breakpointa powinno nas przenieść automatycznie do PhpStorma w zaznaczone miejsce.

Więcej na ten temat znaleźć można tutaj.

2015-04-27

PHP Deprecated - comment starting with '#'

PHP Deprecated:  Comments starting with '#' are deprecated in /etc/php5/cli/conf.d/imap.ini on line 1 in Unknown on line 0

W przypadku powyższego błędu wchodzimy w plik imap.ini i zastępujemy znak '#' znakiem ';'.

2015-04-03

Symfony2 i generowanie plików PDF

KnpSnappyBundle

Do generowania plików PDF w Symfony2 wiele osób poleca bundla o nazwie KnpSnappyBundle. Wykorzystuje on jednak wkhtmltopdf (open source'owe konsolowe narzędzie do tworzenia plików PDF na podstawie HTML), które trzeba dodatkowo zainstalować na serwerze produkcyjnym (wraz z wieloma innymi bibliotekami). To według mnie spora wada tego bundla ale jeszcze do przeskoczenia. Większym minusem wkhtmltopdf jest to, że PDF'y na różnych maszynach generują różne pliki PDF. Różnice są niby niewielkie ale przy mojej pracy zupełnie dyskwalifikujące to rozwiązanie.

PdfBundle

PdfBundle autorstwa Piotra Śliwy eliminuje wady wcześniej omówionego bundla. Nie trzeba na serwerze instalować osobnych  systemowych narzędzi i na każdej maszynie wydruk wygląda identycznie. PdfBundle korzysta z biblioteki PHPPfd tego samego autora. PHPPfd tworzy pliki PDF (lub pliki graficzne) na podstawie plików XML co może być to istotną wadą dla niektórych użytkowników. Dla mnie jednak jest to rozwiązanie niemal idealne.

PdfBundle - problem z img

Podczas pracy trafiłem na problem, który zawieszał całego Apache'a przy próbie wygenerowania pliku PDF z dużym plikiem jgp:

    
        
    

Aby pozbyć się problemu wystarczy element dynamic-page zmienić na page - czyli:

    
        
    

2015-01-28

Firefox - przekroczono limit czasu połączenia

Jeśli pojawia Ci się taki komunikat po ok. 300 sekundach (mimo wszelkich zmian w php.ini) to być może odpowiada za to zmienna network.http.response.timeout. Firefox domyślnie ma przy tej zmiennej wartość 300 sekund - aby to zmienić wystarczy wejść w opcje (about:config), zwiększyć odpowiednio wartość zmiennej i zrestartować przeglądarkę.

2015-01-14

Doctrine i Symfony - wyświetlenie SQL'a z parametrami

Wyświetlić utworzonego SQL'a możemy za pomocą polecenia:
$qb->getQuery()->getSQL();

a parametry tegoż zapytania za pomocą polecenia:
$qb->getParameters();

Wcześniej oczywiście tworzymy obiekt $qb oraz zapytanie - np:
$qb = $this->createQueryBuilder('l')
 ->where('l.del = :del')
 ->andWhere('l.wysw = :wysw')
 ->andWhere('lower(l.nazwisko) LIKE lower(:szukana) OR lower(l.nrpwz) LIKE lower(:szukana)')
 ->orderBy('l.nazwisko')
 ->setParameters(array(
  'del' => 'false',
  'wysw' => 'true',
  'szukana' => '%' . $szukana . '%'
 ));

Wynik zapytania pobieramy w poniższy sposób:
$qb->getQuery()->getResult();

2015-01-13

Doctrine Symfony PostgreSQL - LIKE i OR

Przykład zapytania SQL z klauzulą LIKE:
$qb = $this->createQueryBuilder('k')
 ->where('k.kod_res_8 = :kod_res_8')
 ->andWhere('lower(k.ulica) LIKE lower(:ulica)')
 ->setParameter('kod_res_8', $kod_res_8)
 ->setParameter('ulica', $ulica . '%')
 ->setMaxResults(1);

Przykład zapytania SQL z klauzulą LIKE i OR:
$qb = $this->createQueryBuilder('j')
 ->where('j.del = :del')
 ->andWhere('j.wysw = :wysw')
 ->andWhere('lower(j.nazw) LIKE lower(:szukana) OR lower(j.regon) LIKE lower(:szukana)')
 ->orderBy('j.nazw')
 ->setParameters(array(
  'del' => 'false',
  'wysw' => 'true',
  'szukana' => '%' . $szukana . '%'
 ));

return $qb->getQuery()->getResult();

2014-05-30

[php][symfony] FOSUserBundle - modyfikacja routingu

Cel


Zmienić ścieżkę logowania z:

moja_witryna.lh/login
na:

moja_witryna.lh/xyz_login

Rozwiązanie


Aby tego dokonać wystarczą dwa proste kroki przedstawione poniżej.

Usuwamy domyślny routing fos_user_security i dajemy własny


W pliku routing.yml modyfikujemy zapis

fos_user_security:
    resource: "@FOSUserBundle/Resources/config/routing/security.xml"

na:

fos_user_security_login:
    pattern: /xyz_login
    defaults: { _controller: FOSUserBundle:Security:login }

fos_user_security_check:
    pattern: /xyz_login_check
    defaults: { _controller: FOSUserBundle:Security:check }

fos_user_security_logout:
    pattern: /xyz_logout
    defaults: { _controller: FOSUserBundle:Security:logout }

Modyfikujemy security.yml


Zmieniamy:

firewalls:
        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            logout:       true
            anonymous:    true

na:

firewalls:
        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
                login_path: fos_user_security_login
                check_path: fos_user_security_check
            logout:
                path: fos_user_security_logout
            anonymous:    true

2014-02-21

[php][kohana] Instalacja tumblr.php za pomocą Composer'a

Instalacja biblioteki tumblr.php w projekcie opartym na frameworku Kohana za pomocą Composera:
  1. Tworzymy katalog tumblr w application/vendor
  2. Instalujemy Composera (będąc w katalogu tumblr)
    curl -sS https://getcomposer.org/installer | php
  3. Instalujemy biblioteki, z których korzysta tumblr.php
    php composer.phar install
  4. Wykorzystujemy w naszym projekcie nowo powstały autoloader
    require_once(APPPATH.'vendor/tumblr/vendor/autoload.php');

2014-02-18

[kohana] Korzystanie z zewnętrznych bibliotek

Dobrym zwyczajem jest instalowanie zewnętrznych bibliotek w katalogu application/vendor. Np w przypadku klienta Tumblr API (tumblr.php) będzie to katalog application/vendor/tumblr.
Kohana nie wczytuje automatycznie zewnętrznych bibliotek - trzeba je wczytać samodzielnie np za pomocą:
include Kohana::find_file('vendor/library', 'file_name');

2013-02-24

[kohana][php] Upgrade z wersji 3.1 do 3.3

Oczywiście jak to przy zmianie wersji frameworka kohana (po dłuższym czasie) jest niezła zabawa z dostosowaniem aplikacji. Zmian jest sporo - poniżej przedstawiam te, które udało mi się zarejestrować szybko przerabiając swoją własną stronkę, która wcześniej stała na wersji 3.1:

Zmiana wielkości liter


Zmienia się wielkość liter katalogów i plików w aplikacji. Na przykład zamiast
application/classes/model/flickr.php
musi być
application/classes/Model/Flickr.php

Brak modułu kohana_cache


Jeśli ktoś używał odpalał ten moduł w bootstrap.php to musi z tego zrezygnować.

Cookie salt


Należy w bootstrap.php (np po i18n) wpisać coś takiego:
Cookie::$salt = 'Your-Salt-Goes-Here';
źródło: http://forum.kohanaframework.org/discussion/8873/cookie-salt-problem/p1

Konfiguracja MySQL


Trzeba zmienić w pliku konfiguracyjnym 'type' z 'mysql' na 'MySQL'.
źródło: http://stackoverflow.com/questions/13043412/error-when-using-auth-with-orm-driver-kohana-3-3-0

Odczyt danych z pliku konfiguracyjnego


Przestaje istnieć - teraz zamiast dawnego:
$config = Kohana::config('nazwa_pliku_konfiguracyjnego');
plik konfiguracyjny odpalamy następująco:
$config = Kohana::$config->load('nazwa_pliku_konfiguracyjnego');

Main request


Wygląda teraz mniej więcej tak u mnie:
$request = Request::factory();
$response = $request->execute()->send_headers(TRUE);

if($response->body()){
    $total = array(
        '{memory_usage}' => number_format((memory_get_peak_usage() - KOHANA_START_MEMORY) / 1024, 2).'KB',
        '{execution_time}' => number_format(microtime(TRUE) - KOHANA_START_TIME, 2).' s.'
    );
    
    echo $response->body(strtr((string) $response, $total));
}

Redirect


Zamiast:
$this->request->redirect(Url::base(FALSE, FALSE).'start');
mamy teraz:
$this->redirect(URL::base(FALSE, FALSE) . 'start');
źródło: http://stackoverflow.com/questions/13088601/kohana-errorexception-fatal-error-call-to-undefined-method-requestredirec

Query builder


Zamiast:
$count = $q_count->select('count("*") AS ilosc')->group_by('tytul','tresc')->execute()->get('ilosc');
mamy teraz:
$count = $q_count->select(array(DB::expr('COUNT(*)'),'ilosc'))->group_by('tytul','tresc')->execute()->get('ilosc');
źródło: http://kohanaframework.org/3.3/guide/database/query/builder

Parametry funkcji action


Zamiast:
public function action_index($kod=''){}
mamy teraz:
public function action_index(){ $kod = $this->request->param('kod'); }

To tyle w mocno telegraficznym skrócie... wg mnie są to dobre zmiany! :)

Więcej informacji: http://kohanaframework.org/3.3/guide/kohana/upgradingguide/kohana/upgrading

2012-03-29

NetBeans IDE dla PHP

Dziś postanowiłem odpocząć od Eclipse i poszukać alternatywnego IDE dla PHP - padło na NetBeans.
Pierwsze testy przeszły bardzo pomyślnie - założenie projektu z istniejącego źródła poszło bezboleśnie, svn działa bez żadnych problemów bez konieczności kombinowania w ustawieniach. NetBeans poza obsługą MySql umożliwia również podpięcie się do bazy PostgreSQL - wystarczy jedynie podać parametry - żadnych dodatkowych "szpagatów". To dla mnie fantastyczna sprawa... :-)
Jak na razie problem miałem jedynie z zaznaczaniem bloku tekstu (Block Selection Mode), który w Eclipse dla PHP jest dostępny po wciśnięciu kombinacji klawiszy Ctrl+Shift+A. W NetBeans trzeba ściągnąć i zainstalować plugin, który umożliwia tego typu zaznaczanie tekstu. Plugin nazywa się Rectangular Edit Tools i można go znaleźć pod adresem: http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=33497

Już po chwili gotów jestem zaryzykować stwierdzenie, że NetBeans IDE w wersji 7.1.1 jest naprawdę godny uwagi... :)

2011-07-28

[jQuery] Tablica z wynikami wyciągnięta za pomocą $.post

$.post umożliwia (oprócz zwykłych ciągów znaków) odebranie całej tablicy z danymi - bardzo fajna sprawa dzięki której dziś zrobiło mi się lżej na sercu. :) Żeby odebrać taki "array" a nie tylko "string" wystarczy po argumentach funkcji $.post dodać znacznik "json":

$.post("test.php", { "func": "getNameAndTime" },
function(data){
console.log(data.name); // John
console.log(data.time); // 2pm
}, "json");

W pliku test.php z którego pobieramy dane wystarczy zamiast zwykłego

echo "zwykly ciag znakow";
dać

echo json_encode(array("name"=>"John","time"=>"2pm"));

Żródło: http://api.jquery.com/jQuery.post/

2011-06-01

[php] rawurlencode() i [js] decodeURIComponent()

Chcąc zakodować jakiś string w PHP i poprawnie go odkodować przy użyciu JavaScriptu proponuję zastosować wbudowane funkcje: rawurlencode() i decodeURIComponent().
urlencode() nie do końca mi wystarczyło - funkcja zmienia na przykład spację na "+" zamiast na %20 (przez co trudniej taki string odkodować wbudowanymi funkcjami w js). decodeURI natomiast nie odkodowało np. znaków %21 (!) czy %40 (@).
Tak więc rawurlencode() i decodeURIComponent() to dobre połączenie - przynajmniej dla mnie. :-)

2011-04-20

[Kohana] Upgrade z 3.0.x na 3.1.x

Upgrade mojej strony (marceen.pl) opartej na Kohanej nie obył się bezboleśnie niestety. Framework cały czas mocno się rozwija a ja - przyznaję się bez bicia - ostatnio nie śledziłem zmian jakie w nim zaszły. :-)
Dziś postanowiłem na własnej skórze zbadać jak mocno się zmieniło to środowisko. I jak się okazuje jest kilka zmian:

Wywołanie widoku

//3.0
$this->request->response = $view;
//3.1
$this->response->body($view);

Wyłapywanie błędu 404


W wersji 3.0 obsługa wyjątku odbywała się w bootstrap.php i wyglądała mniej więcej tak:
try {
    $request->execute();
} catch (Exception $e) { // if its not valid, it gets caught here
    $request->status = 404;
    $request->response = View::factory('errors/404');
}

W wersji 3.1 wygląda to zupełnie inaczej. W bootstrap.php dodajemy jedynie jedną linijkę kodu (koniecznie za Kohana::init()):
set_exception_handler(array('Kruzar_Exception_Handler', 'handle'));
oraz tworzymy klasę Kruzar_Exception_Handler:
class Kruzar_Exception_Handler
{
    public static function handle(Exception $e)
    {
        switch (get_class($e))
        {
            case 'HTTP_Exception_404':
                $response = new Response;
                $response->status(404);
                $view = View::factory('errors/404');
                $view->title = 'ERROR 404 - nie ma takiej strony';
                $view->message  = $view->title;
                $view->message .= $e->getMessage();
                echo $response->body($view)->send_headers()->body();
                return TRUE;
                break;
            default:
                return Kohana_Exception::handler($e);
                break;
        }
    }
}
i umieszczamy w /application/classes/kruzar/exception/handler.php

Odchudzony bootstrap.php


Już na przykładzie powyżej widać optymalizację kodu w bootstrap. Zmiany w tym pliku są większe - część kodu związana z uruchomieniem została przeniesiona do pliku index.php. W bootstrap tylko konfigurujemy śrosowisko - podejście bardzo fajne. :-)

Execution Time


W wersji 3.0 miałem informację (pod zdjęciami) o tym jaki jest czas generowania strony. W związku ze zmianami kawałek kodu który za to odpowiadał nieco trzeba było zmienić i przenieść do pliku index.php:
//zamiast
echo Request::factory()
   ->execute()
   ->send_headers()
   ->body();

//piszemy coś takiego:
$request = Request::factory();
$request->execute();

if ($request->response()->body())
{
   $total = array(
      '{memory_usage}'   => number_format((memory_get_peak_usage() - KOHANA_START_MEMORY) / 1024, 2).'KB',
      '{execution_time}' => number_format(microtime(TRUE) - KOHANA_START_TIME, 2).' s.');
   $request->response()->body(strtr((string) $request->response(), $total));
}

echo $request->response()->send_headers()->body();

To zmiany, przez które dziś przebrnąłem - szerszą informację o zmianach można znaleźć tutaj.