Debugging Jekyll
Have you ever wondered what's inside Jekyll variables?
So far I’ve faced it at least twice, so keeping my work DRY it’s time to document this.
Have you ever wondered what’s inside Jekyll’s variables? So did I! And don’t get me wrong it is in the official Jekyll documentation, but I don’t know how many people will get into such a detail. How many are aware of things like that so they can google it.
So here it is, a way to see what sits inside any variable in your blog, really useful if you want to create some features.
{{ variable | inspect }}
Just replace variable
with the actual variable you want to inspect.
Example
For example, this page, if you run
{{ page | inspect }}
You will get:
{ "output": null, "previous": { "output": "<!DOCTYPE html>\n<html>\n\n <head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <meta name=\"author\" content=\"WojciechNowicki\">\n\n <title>Polska Trudny Język - Google Home</title>\n <meta name=\"description\" content=\"Długie pisanie postów nie ma sensu… ten post jest tego przykładem. Należy zacząć pisać i skończyć możliwie szybko!\">\n <meta name=\"keywords\" content=\"IT, PHP, agile, oop, Raspberry Pi, photography, scrum, software development, software architecture, e-commerce, git, opensource\">\n <meta property=\"og:title\" content=\"Polska Trudny Język - Google Home\" />\n <meta property=\"og:type\" content=\"website\" />\n <meta property=\"og:url\" content=\"https://wojciechnowicki.com/2018/06/10/polska-trudny-jezyk\" />\n <meta property=\"og:image\" content=\"https://wojciechnowicki.com/assets/img/post-bg/2018-06-10.jpg\">\n <meta property=\"og:description\" content=\"Długie pisanie postów nie ma sensu… ten post jest tego przykładem. Należy zacząć pisać i skończyć możliwie szybko!\">\n\n <link rel=\"canonical\" href=\"https://wojciechnowicki.com/2018/06/10/polska-trudny-jezyk\">\n <link rel=\"alternate\" type=\"application/rss+xml\" title=\"Wojciech Nowicki\" href=\"https://wojciechnowicki.com/feed.xml\" />\n\n <!-- Bootstrap Core CSS -->\n <link href=\"/assets/css/bootstrap.min.css\" rel=\"stylesheet\">\n\n <!-- Custom CSS -->\n <link href=\"/assets/css/clean-blog.css\" rel=\"stylesheet\">\n\n <link href=\"/assets/css/syntax.css\" rel=\"stylesheet\">\n <link href=\"/assets/flags/flags.min.css\" rel=stylesheet type=\"text/css\">\n\n <!-- Custom Fonts -->\n <link href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.6.0/css/font-awesome.min.css\" rel=\"stylesheet\" type=\"text/css\">\n <link href='https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>\n <link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>\n\n <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->\n <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->\n <!--[if lt IE 9]>\n <script src=\"https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js\"></script>\n <script src=\"https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js\"></script>\n <![endif]-->\n</head>\n\n\n <body>\n\n <!-- Navigation -->\n<nav class=\"navbar navbar-default navbar-custom navbar-fixed-top\">\n <div class=\"container-fluid\">\n <!-- Brand and toggle get grouped for better mobile display -->\n <div class=\"navbar-header page-scroll\">\n <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\"#bs-example-navbar-collapse-1\">\n <span class=\"sr-only\">Toggle navigation</span>\n <span class=\"icon-bar\"></span>\n <span class=\"icon-bar\"></span>\n <span class=\"icon-bar\"></span>\n </button>\n \n <a class=\"navbar-brand\" href=\"/\">Wojciech Nowicki</a>\n \n </div>\n\n <!-- Collect the nav links, forms, and other content for toggling -->\n <div class=\"collapse navbar-collapse\" id=\"bs-example-navbar-collapse-1\">\n <ul class=\"nav navbar-nav navbar-right\">\n <!-- <li>\n <a href=\"/\">Home</a>\n </li> -->\n <li>\n <a href=\"/about\">About</a>\n </li>\n <li>\n <a href=\"/projects\">Projects</a>\n </li>\n <li>\n <a href=\"/blog\">Blog</a>\n </li>\n <li>\n <a href=\"/contact\">Contact</a>\n </li>\n </ul>\n </div>\n <!-- /.navbar-collapse -->\n </div>\n <!-- /.container -->\n</nav>\n\n\n <div class=\"page-content\">\n <div class=\"wrapper\">\n <!-- Post Header -->\n<header class=\"intro-header\" style=\"background-image: url('/assets/img/post-bg/2018-06-10.jpg')\">\n <div class=\"container\">\n <div class=\"row\">\n <div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n <div class=\"post-heading\">\n <h1>Polska Trudny Język - Google Home</h1>\n \n <h2 class=\"subheading\">Dostępność czy cena, co wpływa na małą popularność takich urządzeń?</h2>\n \n <span class=\"meta\">Posted by wojtek on June 10, 2018 in Default</span>\n </div>\n </div>\n </div>\n </div>\n</header>\n\n<!-- Post Content -->\n<article>\n <div class=\"container\">\n <div class=\"row\">\n <div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n \n <p>Długie pisanie postów nie ma sensu… ten post jest tego przykładem. Należy zacząć pisać i skończyć możliwie szybko!</p>\n\n<p>Gdy zaczynałam go pisać na początku kwietnia nawet nie przypuszczałem, że <em>LG</em> sprawi nam taką niespodziankę… <a href=\"https://www.radiozet.pl/Nauka-i-Technologia/Technologia/Sztuczna-inteligencja-w-telewizorach-LG-rozumie-po-polsku\">Sztuczna inteligencja w telewizorach LG rozumie po polsku</a>. Krótko mówiąc <em>Google Home</em> (o którym miał być ten post) został w tyle. Dobrze, może jednak wykorzystam trochę z tego co już napisałem.</p>\n\n<h3 id=\"polski-na-3-miejscu\">Polski na 3 miejscu!</h3>\n<p>Tak, nie pomyliłem się nie <em>Polska</em> a <em>Polski Język</em>. Czy próbowaliście kiedyś nauczyć znajomych z zagranicy kilku słów po polsku? Jakiegość <em>cześć</em> czy <em>dziękuję</em>? A jak to jest z waszym imieniem, czy obcokrajowcy używają formy ze swojego własnego języka czy tak jak w przypadku mojego imienia po prostu nie są w stanie? Nic dziwnego, według tego rankingu <em>Polityki</em> <a href=\"https://www.polityka.pl/galerie/1690846,1,13-najtrudniejszych-jezykow-swiata.read\">13 najtrudniejszych języków świata</a> polski jest na 3 miejscu!</p>\n\n<p><strong>Nie tylko trudny ale też mało popularny.</strong> Niestety liczba osób mówiących po polsku nie jest też duża w porównaniu do innych języków, takich jak Angielski, Chiński czy Hiszpański. Oczywiście na popularność Angielskiego wpływa też siła nabywcza rynków na których używa się tego języka. Co za tym idzie producenci nie chcą inwestować w rozwój rozpoznawania języka, który obszarem jest też ograniczony tylko do jednego kraju. Do tego kraju w którym wspomniana siła nabywcza jest jedną z najmniejszych w Europie. Wystarczy zacytować chociażby <a href=\"https://businessinsider.com.pl/twoje-pieniadze/budzet-domowy/sila-nabywcza-konsumentow-w-europie-polska-na-29-miejscu/c5l1lyp\">Siła nabywcza Polaków dramatycznie niska</a>. Ale nie tylko nasze zarobki są tutaj problemem jak się okazuje sprzęty elektroniczne są u nas droższe w porównaniu z innymi krajami:</p>\n\n<blockquote>\n <h4 id=\"cena-iphonea-7\">Cena iPhone’a 7:</h4>\n <ul>\n <li>USA $815</li>\n <li>Hong Kong $821</li>\n <li><strong>Polska $1005</strong></li>\n <li>Rosja $1086</li>\n <li>Brazylia $1115</li>\n <li>Turcja $1200</li>\n </ul>\n\n <p><em>źródło: <a href=\"https://www.bankier.pl/wiadomosc/Polska-kraj-taniej-Coca-Coli-i-drogiego-iPhone-a-7593582.html\">Polska-kraj-taniej-Coca-Coli-i-drogiego-iPhone</a></em></p>\n</blockquote>\n\n<p>Tym bardziej ciekawa jest decyzja <em>LG</em> o wyprodukowania TV rozumiejącego polecenia po polsku. Ciekaw jestem jak to działa w praktyce… Jednakże jedyny taki model na rynku na pewno znajdzie nabywców.</p>\n\n<h2 id=\"asystent-dla-każdego\">Asystent dla każdego!</h2>\n<p>Jeśli macie telefon z <em>Androidem</em> to zapewne macie w nim też osobistego asystenta. Jak Wam się to podoba? Ja wiem, że to przegląda Waszą pocztę itd. Oczywiście wszystko w zakresie uprawnień które mu sami nadaliśmy. Jednak czy nie jest to wygodne, że wszystkie nasze loty samolotem czy podróże pociągiem automatycznie lądują w naszym kalendarzu. Czy też codzienne powroty do domu z pracy nie stały się trochę inne kiedy wiemy, że nie musimy się spieszyć i lepiej iść na jakieś małe zakupy koło biura ponieważ nasza droga do domu jest obecnie o 30 minut wolniejsza niż zwykle przez wypadek. Lub w drugą stronę, wstajemy rano i od razu wiemy, że musimy wyjść z domu wcześniej bo zą większe niż zwykle korki. I nawet nie musimy o to pytać, nasz asystent sam wyświetli nam informacje w obszarze powiadomień. Czy życie nie stało się trochę wygodniejsze? Jesteście za czy przeciw?</p>\n\n<h4 id=\"bezpieczeńśtwo-i-prywatność\">Bezpieczeńśtwo i Prywatność</h4>\n<p>Wspomniane już wcześniej kwestie prywatności i uprawnień a co za tym idzie zagrożenia które ze sobą niosą poruszałem ostatnio na <a href=\"https://twitter.com/wonowicki/status/1002821632929484801\">Twitter</a>, przy okazji artykułu <em>Tygodnika Powszechnego</em>:</p>\n\n<blockquote class=\"twitter-tweet .center-bloc\" data-lang=\"en-gb\"><p lang=\"pl\" dir=\"ltr\">Dzięki <a href=\"https://twitter.com/hashtag/BigData?src=hash&ref_src=twsrc%5Etfw\">#BigData</a> i <a href=\"https://twitter.com/hashtag/AI?src=hash&ref_src=twsrc%5Etfw\">#AI</a> poziom inwigilacji w Chinach osiągnął porażającą wysokość. Komputery oceniają koncentrację uczniów w szkole, obywatele dostają (lub tracą) punkty za swoją obywatelską postawę, a algorytm na tej podstawie może np. zabronić im podróży.<a href=\"https://t.co/9EgKdlrQkb\">https://t.co/9EgKdlrQkb</a></p>— Tygodnik Powszechny (@tygodnik) <a href=\"https://twitter.com/tygodnik/status/1002808826108764160?ref_src=twsrc%5Etfw\">2 June 2018</a></blockquote>\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n\n<p>Ważne jest budowanie świadomości zagrożeń jakie niesie ze sobą <em>AI</em> i <em>BigData</em>. Ale na pewno nie można siać paniki, bo to nigdy nie jest dobre. Pewne rzeczy już się dzieją i musimy przywyknąć trochę do czasów w jakich żyjemy. Wiele zależy od nas samych, co udostępniamy! I nie mam tu na myśli dawania uprawnień dla aplikacji a przede wszystkim tego co sami przesadnie wrzucamy na <em>Facebook</em> i <em>Instagram</em>. Z tego wiele można wyczytać i nie trzeba być tajną rządową agencją czy mega korporacją. Jeśli chodzi o kradzież danych których nie udostępniliśmy, racjonalnie myśląc jeśli nie jesteśmy osobą publiczną to raczej nie powinniśmy się takich rzeczy obawiać.</p>\n\n<h3 id=\"ok-google\">“OK Google”</h3>\n<p>Inteligentne głośniki idą dalej, nie potrzebujemy już trzymać telefonu przy sobie, wystarczy się o coś zapytać lub poprosić o włączenie świateł. Nasze domy stają się naprawdę coraz bardziej “inteligentne”, to co mogliśmy oglądać na filmach science fiction kilka lat temu teraz jest rzeczywistością.</p>\n\n<p>Moim zdaniem najważniejszym aspektem jest to, że wszystko jest ze sobą zintegrowane. Kupujemy głośnik o jednego producenta i żarówki od innego i wszystko działa. Nie ma żadnego niepotrzebnego utrudniania nam życia, różnych rodzajów złączy nie pasujących do innych producentów, wszystko komunikuje się ze sobą bezprzewodowo.</p>\n\n<p>Osobiście jeszcze nie dorosłem do tego żeby zainstalować tego typu żarówki, jednak cieszy mnie możliwość rozszerzania mojego zestawu. Na tym początkowym etapie głośnik jest głównie używany do słuchania polskiego radia poprzez <em>TuneIn</em> oraz sporadycznie zadawania pytań jeśli jakimś dziwnym zbiegiem okoliczności nie mam pod ręką żadnego urządzenia (brzmi mało realnie co nie). W moim przypadku język nie stanowił bariery, jednak wiem że nie każdego użytkownika który tylko uczył się w szkole urządzenie rozpozna bez problemu. Wydaje mi się, że jednak ta bariera językowa będzie dość mocno spowalniała popularyzację tego typu sprzętu w Polsce</p>\n\n<h3 id=\"widoki-na-przyszłość\">Widoki na przyszłość</h3>\n<p>Wiadomo <em>nie odrazu Rzym zbudowano</em> więc dostępne obecnie urządzenia należy uznać za świetne podwaliny pod dalszy rozwój. Google miało wprowadzić do swoich głośników tryb ciągłej rozmowy, czyli nie za każdym razem będziemy musieli używać wywołania <em>OK Google</em> tylko będziemy mogli kontynuować rozmowę po uzyskaniu odpowiedzi. Jeśli zamieszczone poniżej artykuły mają rację to należy się spodziewać języka polskiego jeszcze w tym roku!</p>\n\n<ul>\n <li><a href=\"https://www.androidpolice.com/2018/02/15/google-assistant-may-support-38-countries-17-languages-2018/\">Google Assistant may support 38 more countries and 17 more languages in 2018</a></li>\n <li><a href=\"https://www.theverge.com/2018/2/23/17041920/google-assistant-languages-multilingual-detection\">Google Assistant languages multilingual detection</a></li>\n</ul>\n\n\n <hr>\n <ul class=\"list-inline\"><li>Category:</li><li><a href=\"/blog/categories#default\"><strong>Default</strong></a></li></ul>\n \n <ul class=\"list-inline\">\n <li>Tags:</li>\n \n <li><span class=\"label label-default\"><a href=\"/blog/tags#recenzja\">#recenzja (2)</a></span></li>\n <!-- <li><a href=\"/blog/tags#recenzja\" class=\"btn btn-default btn-xs\">recenzja <span class=\"badge\">2</span></a></li> -->\n \n <li><span class=\"label label-default\"><a href=\"/blog/tags#google\">#google (1)</a></span></li>\n <!-- <li><a href=\"/blog/tags#google\" class=\"btn btn-default btn-xs\">google <span class=\"badge\">1</span></a></li> -->\n \n <li><span class=\"label label-default\"><a href=\"/blog/tags#ai\">#ai (1)</a></span></li>\n <!-- <li><a href=\"/blog/tags#ai\" class=\"btn btn-default btn-xs\">ai <span class=\"badge\">1</span></a></li> -->\n \n </ul>\n \n\n <ul class=\"pager hidden-print\">\n \n <li class=\"previous\">\n <a href=\"/2018/03/10/rozszerzamy-serwer-mysql\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Rozszerzamy serwer - MySQL\">← Previous Post</a>\n </li>\n \n \n <li class=\"next\">\n <a href=\"/2018/09/02/debugging-jekyll\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Debugging Jekyll\">Next Post →</a>\n </li>\n \n </ul>\n\n </div>\n\n \n <div class=\"well col-sm-12\">\n NOTE!</br>\n Comments suspended as this is not production environment!\n </div>\n \n </div>\n </div>\n</article>\n\n<hr>\n\n </div>\n </div>\n\n <!-- Footer -->\n<footer>\n <div class=\"container\">\n <div class=\"row\">\n <div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n <ul class=\"list-inline text-center hidden-print\">\n <li>\n <a href=\"https://twitter.com/wonowicki\">\n <span class=\"fa-stack fa-lg\">\n <i class=\"fa fa-circle fa-stack-2x\"></i>\n <i class=\"fa fa-twitter fa-stack-1x fa-inverse\"></i>\n </span>\n </a>\n </li>\n <li>\n <a href=\"https://linkedin.com/in/wonowicki\">\n <span class=\"fa-stack fa-lg\">\n <i class=\"fa fa-circle fa-stack-2x\"></i>\n <i class=\"fa fa-linkedin fa-stack-1x fa-inverse\"></i>\n </span>\n </a>\n </li>\n <li>\n <a href=\"https://github.com/wnowicki\">\n <span class=\"fa-stack fa-lg\">\n <i class=\"fa fa-circle fa-stack-2x\"></i>\n <i class=\"fa fa-github fa-stack-1x fa-inverse\"></i>\n </span>\n </a>\n </li>\n </ul>\n <p class=\"copyright text-muted\">Copyright © WojciechNowicki.com 2013-2024, <a href=\"/credits\">credits</a></p>\n </div>\n </div>\n </div>\n</footer>\n\n<!-- jQuery -->\n<script src=\"/assets/js/jquery.js\"></script>\n\n<!-- Bootstrap Core JavaScript -->\n<script src=\"/assets/js/bootstrap.min.js\"></script>\n\n<!-- Custom Theme JavaScript -->\n<script src=\"/assets/js/clean-blog.min.js\"></script>\n\n\n </body>\n\n</html>\n", "previous": { "output": "<!DOCTYPE html>\n<html>\n\n <head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <meta name=\"author\" content=\"WojciechNowicki\">\n\n <title>Rozszerzamy serwer - MySQL</title>\n <meta name=\"description\" content=\"Jakiś czas temu zrobiłem pierwszy odcinek kursu PHP w Praktyce w którym to pokazałem jak zrobić własny lokalny serwer na którym możecie budować aplikacje z u...\">\n <meta name=\"keywords\" content=\"IT, PHP, agile, oop, Raspberry Pi, photography, scrum, software development, software architecture, e-commerce, git, opensource\">\n <meta property=\"og:title\" content=\"Rozszerzamy serwer - MySQL\" />\n <meta property=\"og:type\" content=\"website\" />\n <meta property=\"og:url\" content=\"https://wojciechnowicki.com/2018/03/10/rozszerzamy-serwer-mysql\" />\n <meta property=\"og:image\" content=\"https://wojciechnowicki.com/assets/img/bg/blog.jpg\">\n <meta property=\"og:description\" content=\"Jakiś czas temu zrobiłem pierwszy odcinek kursu PHP w Praktyce w którym to pokazałem jak zrobić własny lokalny serwer na którym możecie budować aplikacje z u...\">\n\n <link rel=\"canonical\" href=\"https://wojciechnowicki.com/2018/03/10/rozszerzamy-serwer-mysql\">\n <link rel=\"alternate\" type=\"application/rss+xml\" title=\"Wojciech Nowicki\" href=\"https://wojciechnowicki.com/feed.xml\" />\n\n <!-- Bootstrap Core CSS -->\n <link href=\"/assets/css/bootstrap.min.css\" rel=\"stylesheet\">\n\n <!-- Custom CSS -->\n <link href=\"/assets/css/clean-blog.css\" rel=\"stylesheet\">\n\n <link href=\"/assets/css/syntax.css\" rel=\"stylesheet\">\n <link href=\"/assets/flags/flags.min.css\" rel=stylesheet type=\"text/css\">\n\n <!-- Custom Fonts -->\n <link href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.6.0/css/font-awesome.min.css\" rel=\"stylesheet\" type=\"text/css\">\n <link href='https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>\n <link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>\n\n <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->\n <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->\n <!--[if lt IE 9]>\n <script src=\"https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js\"></script>\n <script src=\"https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js\"></script>\n <![endif]-->\n</head>\n\n\n <body>\n\n <!-- Navigation -->\n<nav class=\"navbar navbar-default navbar-custom navbar-fixed-top\">\n <div class=\"container-fluid\">\n <!-- Brand and toggle get grouped for better mobile display -->\n <div class=\"navbar-header page-scroll\">\n <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\"#bs-example-navbar-collapse-1\">\n <span class=\"sr-only\">Toggle navigation</span>\n <span class=\"icon-bar\"></span>\n <span class=\"icon-bar\"></span>\n <span class=\"icon-bar\"></span>\n </button>\n \n <a class=\"navbar-brand\" href=\"/\">Wojciech Nowicki</a>\n \n </div>\n\n <!-- Collect the nav links, forms, and other content for toggling -->\n <div class=\"collapse navbar-collapse\" id=\"bs-example-navbar-collapse-1\">\n <ul class=\"nav navbar-nav navbar-right\">\n <!-- <li>\n <a href=\"/\">Home</a>\n </li> -->\n <li>\n <a href=\"/about\">About</a>\n </li>\n <li>\n <a href=\"/projects\">Projects</a>\n </li>\n <li>\n <a href=\"/blog\">Blog</a>\n </li>\n <li>\n <a href=\"/contact\">Contact</a>\n </li>\n </ul>\n </div>\n <!-- /.navbar-collapse -->\n </div>\n <!-- /.container -->\n</nav>\n\n\n <div class=\"page-content\">\n <div class=\"wrapper\">\n <!-- Post Header -->\n<header class=\"intro-header\" style=\"background-image: url('/assets/img/post-bg/default.jpg')\">\n <div class=\"container\">\n <div class=\"row\">\n <div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n <div class=\"post-heading\">\n <h1>Rozszerzamy serwer - MySQL</h1>\n \n <h2 class=\"subheading\">Czym jest aplikacja która nie może przechowywać danych</h2>\n \n <span class=\"meta\">Posted by wojtek on March 10, 2018 in Development</span>\n </div>\n </div>\n </div>\n </div>\n</header>\n\n<!-- Post Content -->\n<article>\n <div class=\"container\">\n <div class=\"row\">\n <div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n \n <p>Jakiś czas temu zrobiłem pierwszy odcinek kursu <a href=\"/php\"><em>PHP w Praktyce</em></a> w którym to pokazałem jak zrobić własny lokalny serwer na którym możecie budować aplikacje z użyciem PHP. Sensownie jest rozpocząć taki kurs od narzędzia umożliwiającego uruchamianie wszystkiego tego o czym będzie w dalszych odcinkach. Żeby uprościć sprawę na tak zwanego maksa a dodatkowo jeszcze wprowadzać dobre standardy zamiast udostępnić serwer do pobrania z własnej strony stworzyłem repozytorium <a href=\"https://github.com/wpraktyce/server\"><code class=\"language-plaintext highlighter-rouge\">wpraktyce/server</code></a> z które to można sobie pobrać zrobić <a href=\"https://pl.wikipedia.org/wiki/Fork\">fork</a>. Oczywiście projekt był prosty adekwatnie do potrzeb kursu. Co prawda kurs nie doczekał się jeszcze odcinka w którym potrzebowalibyśmy baz danych jednak chcąc sobie odświeżyć trochę wiedzę z zakresu <code class=\"language-plaintext highlighter-rouge\">bash</code> postanowiłem rozszerzyć trochę funkcjonalność tego serwera. Co opisze w tym poście.<br />\n<em>Oryginalny odcinek kursu można znaleźć tutaj: <a href=\"/php/00/01\">Lokalny Server PHP</a>.</em></p>\n\n<h2 id=\"obsługa-błędów\">Obsługa błędów</h2>\n<p>Najpierw jednak muszę się przyznać do pewnego przeoczenia, mógłbym wręcz powiedzieć, że błędu. Zapomniałem prawidłowo skonfigurować wyświetlanie błędów więc bardzo trudne było rozwiązywanie jakichkolwiek pomyłek w kodzie PHP. Zamiast czytelnego błędu wyświetlała nam się pusta strona ponieważ serwer był w konfiguracji produkcyjnej. Oczywiście wystarczyło zajrzeć do notatek sprzed lat i wprowadzić kilka dodatkowych linijek do naszego skryptu. Przede wszystkim chodziło o włączenie następujących dyrektyw:</p>\n\n<div class=\"language-sh highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>display_errors <span class=\"o\">=</span> On\nerror_reporting <span class=\"o\">=</span> E_ALL\n</code></pre></div></div>\n\n<p>Zrobiłem to z użyciem komendy <a href=\"https://pl.wikipedia.org/wiki/Sed_(program)\"><code class=\"language-plaintext highlighter-rouge\">sed</code></a> całość zmian znajdziecie tutaj: <a href=\"https://github.com/wpraktyce/server/commit/72b2fd5659a510dbbd978be3e8f5c161594c83cf\">72b2fd5</a></p>\n\n<h2 id=\"reorganizacja-skryptu\">Reorganizacja skryptu</h2>\n<p>Jako kolejny element ulepszeń postanowiłem podzielić skrypt który znajduje się w jednym pliku na funkcje zajmujące się poszczególnymi sekcjami naszego serwera. Skrypt lada moment będzie rozszerzony o kolejne n linijek odpowiedzialnych za serwer bazy danych, jego konfigurację i użytkowników, czyli moment wprowadzenia modułowości jest idealny. Pozwoli nam to łatwiej zarządzać wszystkim w przyszłości.</p>\n\n<p>Stworzyłem folder <code class=\"language-plaintext highlighter-rouge\">src</code> w którym będę przechowywał funkcje <code class=\"language-plaintext highlighter-rouge\">bash</code>. Oczywiście pierwszym krokiem musi być załadowanie tych wszystkich funkcji do naszego głównego skryptu, jeśli wszystkie interesujące nas funkcje znajdują się w jednym katalogu i są tam tylko pliki z funkcjami możemy to zrobić za pomocą jednej pętli:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">for </span>THIS_FILE <span class=\"k\">in </span>src/<span class=\"k\">*</span>\n<span class=\"k\">do\n </span><span class=\"nb\">source</span> <span class=\"nv\">$THIS_FILE</span>\n<span class=\"k\">done</span>\n</code></pre></div></div>\n\n<p>Jeśli w przyszłości potrzebowalibyśmy dodać jakiś plik z innej lokalizacji możemy to zrobić z użyciem komendy <code class=\"language-plaintext highlighter-rouge\">source</code> podając ścieżkę do tego pliku. Funkcje definiujemy bardzo prosto bo:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">function </span>nazwa_funkcji<span class=\"o\">()</span>\n<span class=\"o\">{</span>\n <span class=\"c\"># kod funkcji</span>\n<span class=\"o\">}</span>\n</code></pre></div></div>\n\n<blockquote>\n <p><strong>Uwaga!</strong>\nNależy pamiętać żeby wszystkie kody umieścić w funkcjach dzięki czemu wykonają się one dopiero w momencie wywołania przez nas funkcji, ze wszystkimi wymaganymi parametrami. W przeciwnym wypadku skrypty wykonają się w momencie ich załadowania.</p>\n</blockquote>\n\n<p>Następnie należy już tylko w odpowiedniej kolejności wywołać nasze funkcje:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>base_setup\ninstall_apache\ninstall_composer\n</code></pre></div></div>\n\n<p>Całość zmian znajdziecie tutaj: <a href=\"https://github.com/wpraktyce/server/commit/512cad3f53b0f6048bfdeacc769d98c901f24cbb\">512cad3</a></p>\n\n<h2 id=\"mysql\">MySQL</h2>\n<p>Przejdźmy do właściwego tematu tego wpisu, chcemy dodać zarówno sam serwer MySQL jak i jego obsługę w PHP, więc zacznijmy od tego pierwszego. W tym celu dodałem jedną dodatkową bibliotekę <code class=\"language-plaintext highlighter-rouge\">php5-mysql</code> do skryptu <code class=\"language-plaintext highlighter-rouge\">install_apache</code> instalującego nam PHP. Podstawowa instalacja PHP wygląda teraz tak:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>apt-get <span class=\"nt\">-y</span> <span class=\"nb\">install </span>php5 php5-mysql\n</code></pre></div></div>\n\n<p>Kolejnym krokiem jest instalacja samego serwera, jako że to zadanie jest dość duże samo w sobie stworzyłem mu osobną funkcję <code class=\"language-plaintext highlighter-rouge\">install_mysql</code>. W skrócie funkcja instaluje nam sam serwer oraz przeprowadza podstawową konfigurację taką jak:</p>\n<ul>\n <li>ustawienie hasła dla użytkownika <code class=\"language-plaintext highlighter-rouge\">root</code> które można podać jako pierwszy parametr funkcji</li>\n <li>umożliwienie dostępu publicznego do bazy</li>\n <li>kopiujemy domyślny plik konfiguracji <code class=\"language-plaintext highlighter-rouge\">local.cnf</code></li>\n <li>utworzenie pierwszej bazy danych której nazwa może być opcjonalnie ustawiona jako drugi parametr</li>\n</ul>\n\n<h3 id=\"dodawanie-użytkowników\">Dodawanie użytkowników</h3>\n<p>Kolejnym krokiem będzie dodanie użytkownika którego będziemy używać do połączenia z naszą bazą danych, w tym celu stworzyłem funkcję <code class=\"language-plaintext highlighter-rouge\">mysql_add_user</code>. Pierwszym parametrem jest nazwa użytkownika drugim jego hasło. Funkcja nie tylko dodaje użytkownika ale również przyznaje mu wszystkie uprawnienia do tej bazy danych. W skrypcie domyślnie dodajemy jednego użytkownika na start.</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>mysql_add_user user pass <span class=\"o\">[</span>root_pass] <span class=\"o\">[</span>db_name]\n</code></pre></div></div>\n\n<h3 id=\"konfiguracja-połączenia\">Konfiguracja połączenia</h3>\n<p>Teraz pozostało nam tylko użyć klienta MySQL żeby połączyć się z naszą bazą danych. Ja osobiście używam <a href=\"https://www.sequelpro.com/\">Sequel Pro</a>\njeśli chodzi o coś na inne platformy to <a href=\"https://www.mysql.com/products/workbench/\">MySQL Workbench</a> lub pobawić się w instalację webowego <a href=\"https://www.phpmyadmin.net/\">phpMyAdmin</a>. Bez różnicy jakiego klienta użyjemy nasze dane do logowania na początek będą takie:</p>\n\n<table>\n <thead>\n <tr>\n <th>Host</th>\n <th><code class=\"language-plaintext highlighter-rouge\">172.11.1.111</code></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>User</td>\n <td><code class=\"language-plaintext highlighter-rouge\">user</code></td>\n </tr>\n <tr>\n <td>Password</td>\n <td><code class=\"language-plaintext highlighter-rouge\">pass</code></td>\n </tr>\n <tr>\n <td>Database</td>\n <td><code class=\"language-plaintext highlighter-rouge\">develop</code></td>\n </tr>\n <tr>\n <td>Port</td>\n <td><code class=\"language-plaintext highlighter-rouge\">3306</code></td>\n </tr>\n </tbody>\n</table>\n\n<p>Zmiany w kodzie możecie oczwyiście znaleźć tutaj: <a href=\"https://github.com/wpraktyce/server/commit/175c0a55728ca777e05f65f699a7fd230668a596\">175c0a5</a></p>\n\n<h2 id=\"konfiguracja\">Konfiguracja</h2>\n<p>Oczywiście opisanie wszystkiego dokładnie zajęło by mi znacznie więcej czasu. Myślę, że wyjaśniłem najważniejsze elementy teraz czas na ostatni konfigurację modułów. Obecnie komenda <code class=\"language-plaintext highlighter-rouge\">vagrant up</code> zainstaluje nam wszystko zarówno PHP jak i MySQL ale nie zawsze jest nam potrzebna pełna konfiguracja. Wygląda to tak:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>base_setup\n\n<span class=\"c\">## Configuration:</span>\n\ninstall_apache\ninstall_composer\ninstall_mysql\nmysql_add_user user pass\ninstall_tools\n</code></pre></div></div>\n\n<p>Jeśli któryś z elementów nie będzie nam potrzebny wystarczy daną linijkę zakomentować używając <code class=\"language-plaintext highlighter-rouge\">#</code>. Oczywiście nie polecam usuwania <code class=\"language-plaintext highlighter-rouge\">base_setup</code>. Dla przykładu jeśli nie chcemy instalować bazy danych:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>base_setup\n\n<span class=\"c\">## Configuration:</span>\n\ninstall_apache\ninstall_composer\ninstall_mysql\n<span class=\"c\"># mysql_add_user user pass</span>\n<span class=\"c\"># install_tools</span>\n</code></pre></div></div>\n\n<p>Cały pull request dostępny jest tutaj <a href=\"https://github.com/wpraktyce/server/pull/1\">PR#1</a>.</p>\n\n<h2 id=\"inne-dostępne-narzędzia\">Inne dostępne narzędzia</h2>\n<p>Ważne jest to żeby wspomnieć o tym, że w przypadku serwerów PHP istnieją również inne gotowe narzędzia. Bo czy tworząc ten mały projekt nie powieliłem już istniejących dobrze wspieranych projektów? Oczywiście, że tak! Ale zrobiłem to w celach edukacyjnych, łatwiej zrozumieć działanie pewnych rzeczy na prostszych przykładach. Jeśli chodzi o użytkowanie komercyjne to oczywiście polecam użycie bardziej profesjonalnych narzędzi.</p>\n\n<p>Tak jak już wspominałem od tych bardziej ogólnych przechodzimy do tych bardziej wyspecjalizowanych. <em>VirtualBox</em> jest ogólnie platformą do tworzenia maszyn wirtualnych, <em>Vagrant</em> wspomaga automatyczne i powtarzalne tworzenie maszyn wirtualnych a <a href=\"https://laravel.com/docs/5.6/homestead\">Homestead</a> zbiera to wszystko razem do kupy i tworzy nam gotowe do działania środowisko PHP przystosowane do współpracy z framework’iem <em>Laravel</em>. Jest to oczywiście narzędzie znacznie bardziej rozbudowane od przedstawionego przeze mnie serwera i jeśli interesuje nas tylko korzystanie to czemu nie użyć czegoś co w szybki sposób pozwala nam stworzyć wiele lokalnych stron.</p>\n\n<p>Innym rozwiązaniem o którym tutaj tylko wspomnę jest <a href=\"https://www.docker.com/\">Docker</a> czyli inny rodzaj wirtualizacji. Można go określić liderem przyszłości a dokładniejsze opisy zostawię specjalistom z dziedziny.</p>\n\n<h2 id=\"co-dalej\">Co dalej?</h2>\n<p>Jeśli chodzi o następne etapy to:</p>\n<ul>\n <li>koniecznie trzeba przenieść serwer na <strong>PHP7</strong></li>\n <li>wprowadzić obsługę <em>SQLite</em> oraz <em>MongoDB</em> żeby poszerzyć możliwości edukacyjne, ale to też może dopiero z odcinkami kursu</li>\n <li>może zmiana architektury w celu łatwiejszego importowania serwera do innych projektów lub lepszy mechanizm do zarządzania <code class=\"language-plaintext highlighter-rouge\">vhost</code> z różnych lokalizacji</li>\n</ul>\n\n<blockquote>\n <p><strong>Wersja do której się odnosi ten wpis to <a href=\"https://github.com/wpraktyce/server/releases/tag/2.0.0\">v2.0.0</a></strong></p>\n</blockquote>\n\n\n <hr>\n <ul class=\"list-inline\"><li>Category:</li><li><a href=\"/blog/categories#development\"><strong>Development</strong></a></li></ul>\n \n <ul class=\"list-inline\">\n <li>Tags:</li>\n \n <li><span class=\"label label-default\"><a href=\"/blog/tags#vagrant\">#vagrant (1)</a></span></li>\n <!-- <li><a href=\"/blog/tags#vagrant\" class=\"btn btn-default btn-xs\">vagrant <span class=\"badge\">1</span></a></li> -->\n \n <li><span class=\"label label-default\"><a href=\"/blog/tags#php\">#php (3)</a></span></li>\n <!-- <li><a href=\"/blog/tags#php\" class=\"btn btn-default btn-xs\">php <span class=\"badge\">3</span></a></li> -->\n \n <li><span class=\"label label-default\"><a href=\"/blog/tags#mysql\">#mysql (2)</a></span></li>\n <!-- <li><a href=\"/blog/tags#mysql\" class=\"btn btn-default btn-xs\">mysql <span class=\"badge\">2</span></a></li> -->\n \n <li><span class=\"label label-default\"><a href=\"/blog/tags#bash\">#bash (2)</a></span></li>\n <!-- <li><a href=\"/blog/tags#bash\" class=\"btn btn-default btn-xs\">bash <span class=\"badge\">2</span></a></li> -->\n \n <li><span class=\"label label-default\"><a href=\"/blog/tags#sql\">#sql (1)</a></span></li>\n <!-- <li><a href=\"/blog/tags#sql\" class=\"btn btn-default btn-xs\">sql <span class=\"badge\">1</span></a></li> -->\n \n </ul>\n \n\n <ul class=\"pager hidden-print\">\n \n <li class=\"previous\">\n <a href=\"/2018/02/26/tab-s3-recenzja-nietechniczna\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Tab S3 recenzja nietechniczna\">← Previous Post</a>\n </li>\n \n \n <li class=\"next\">\n <a href=\"/2018/06/10/polska-trudny-jezyk\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Polska Trudny Język - Google Home\">Next Post →</a>\n </li>\n \n </ul>\n\n </div>\n\n \n <div class=\"well col-sm-12\">\n NOTE!</br>\n Comments suspended as this is not production environment!\n </div>\n \n </div>\n </div>\n</article>\n\n<hr>\n\n </div>\n </div>\n\n <!-- Footer -->\n<footer>\n <div class=\"container\">\n <div class=\"row\">\n <div class=\"col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1\">\n <ul class=\"list-inline text-center hidden-print\">\n <li>\n <a href=\"https://twitter.com/wonowicki\">\n <span class=\"fa-stack fa-lg\">\n <i class=\"fa fa-circle fa-stack-2x\"></i>\n <i class=\"fa fa-twitter fa-stack-1x fa-inverse\"></i>\n </span>\n </a>\n </li>\n <li>\n <a href=\"https://linkedin.com/in/wonowicki\">\n <span class=\"fa-stack fa-lg\">\n <i class=\"fa fa-circle fa-stack-2x\"></i>\n <i class=\"fa fa-linkedin fa-stack-1x fa-inverse\"></i>\n </span>\n </a>\n </li>\n <li>\n <a href=\"https://github.com/wnowicki\">\n <span class=\"fa-stack fa-lg\">\n <i class=\"fa fa-circle fa-stack-2x\"></i>\n <i class=\"fa fa-github fa-stack-1x fa-inverse\"></i>\n </span>\n </a>\n </li>\n </ul>\n <p class=\"copyright text-muted\">Copyright © WojciechNowicki.com 2013-2024, <a href=\"/credits\">credits</a></p>\n </div>\n </div>\n </div>\n</footer>\n\n<!-- jQuery -->\n<script src=\"/assets/js/jquery.js\"></script>\n\n<!-- Bootstrap Core JavaScript -->\n<script src=\"/assets/js/bootstrap.min.js\"></script>\n\n<!-- Custom Theme JavaScript -->\n<script src=\"/assets/js/clean-blog.min.js\"></script>\n\n\n </body>\n\n</html>\n", "previous": { "relative_path": "_posts/2018-02-26-tab-s3-recenzja-nietechniczna.md", "url": "/2018/02/26/tab-s3-recenzja-nietechniczna", "id": "/2018/02/26/tab-s3-recenzja-nietechniczna", "categories": [ "default" ], "tags": [ "samsung", "tablet", "android", "recenzja" ], "title": "Tab S3 recenzja nietechniczna", "collection": "posts", "date": "2018-02-26 10:40:00 +0100", "path": "_posts/2018-02-26-tab-s3-recenzja-nietechniczna.md", "draft": false, "layout": "post", "subtitle": "Gadżet czy potencjalny następca tradycyjnego notesu?", "author": "wojtek", "post_id": "9984d1c688a54de88248147baacc71fa", "heading_image": "2018-02-26-tab.jpg", "language": "pl", "slug": "tab-s3-recenzja-nietechniczna", "ext": ".md" }, "relative_path": "_posts/2018-03-10-rozszerzamy-serwer-mysql.md", "excerpt": "<p>Jakiś czas temu zrobiłem pierwszy odcinek kursu <a href=\"/php\"><em>PHP w Praktyce</em></a> w którym to pokazałem jak zrobić własny lokalny serwer na którym możecie budować aplikacje z użyciem PHP. Sensownie jest rozpocząć taki kurs od narzędzia umożliwiającego uruchamianie wszystkiego tego o czym będzie w dalszych odcinkach. Żeby uprościć sprawę na tak zwanego maksa a dodatkowo jeszcze wprowadzać dobre standardy zamiast udostępnić serwer do pobrania z własnej strony stworzyłem repozytorium <a href=\"https://github.com/wpraktyce/server\"><code class=\"language-plaintext highlighter-rouge\">wpraktyce/server</code></a> z które to można sobie pobrać zrobić <a href=\"https://pl.wikipedia.org/wiki/Fork\">fork</a>. Oczywiście projekt był prosty adekwatnie do potrzeb kursu. Co prawda kurs nie doczekał się jeszcze odcinka w którym potrzebowalibyśmy baz danych jednak chcąc sobie odświeżyć trochę wiedzę z zakresu <code class=\"language-plaintext highlighter-rouge\">bash</code> postanowiłem rozszerzyć trochę funkcjonalność tego serwera. Co opisze w tym poście.<br />\n<em>Oryginalny odcinek kursu można znaleźć tutaj: <a href=\"/php/00/01\">Lokalny Server PHP</a>.</em></p>\n", "url": "/2018/03/10/rozszerzamy-serwer-mysql", "id": "/2018/03/10/rozszerzamy-serwer-mysql", "categories": [ "development" ], "tags": [ "vagrant", "php", "mysql", "bash", "sql" ], "title": "Rozszerzamy serwer - MySQL", "collection": "posts", "date": "2018-03-10 11:06:00 +0100", "next": { "relative_path": "_posts/2018-06-10-polska-trudny-jezyk.md", "url": "/2018/06/10/polska-trudny-jezyk", "id": "/2018/06/10/polska-trudny-jezyk", "categories": [ "default" ], "tags": [ "recenzja", "google", "ai" ], "title": "Polska Trudny Język - Google Home", "collection": "posts", "date": "2018-06-10 21:10:00 +0200", "path": "_posts/2018-06-10-polska-trudny-jezyk.md", "draft": false, "layout": "post", "subtitle": "Dostępność czy cena, co wpływa na małą popularność takich urządzeń?", "author": "wojtek", "post_id": "7e41f5cccf604941ba4ffa0f2dad4120", "heading_image": "2018-06-10.jpg", "language": "pl", "slug": "polska-trudny-jezyk", "ext": ".md" }, "path": "_posts/2018-03-10-rozszerzamy-serwer-mysql.md", "content": "<p>Jakiś czas temu zrobiłem pierwszy odcinek kursu <a href=\"/php\"><em>PHP w Praktyce</em></a> w którym to pokazałem jak zrobić własny lokalny serwer na którym możecie budować aplikacje z użyciem PHP. Sensownie jest rozpocząć taki kurs od narzędzia umożliwiającego uruchamianie wszystkiego tego o czym będzie w dalszych odcinkach. Żeby uprościć sprawę na tak zwanego maksa a dodatkowo jeszcze wprowadzać dobre standardy zamiast udostępnić serwer do pobrania z własnej strony stworzyłem repozytorium <a href=\"https://github.com/wpraktyce/server\"><code class=\"language-plaintext highlighter-rouge\">wpraktyce/server</code></a> z które to można sobie pobrać zrobić <a href=\"https://pl.wikipedia.org/wiki/Fork\">fork</a>. Oczywiście projekt był prosty adekwatnie do potrzeb kursu. Co prawda kurs nie doczekał się jeszcze odcinka w którym potrzebowalibyśmy baz danych jednak chcąc sobie odświeżyć trochę wiedzę z zakresu <code class=\"language-plaintext highlighter-rouge\">bash</code> postanowiłem rozszerzyć trochę funkcjonalność tego serwera. Co opisze w tym poście.<br />\n<em>Oryginalny odcinek kursu można znaleźć tutaj: <a href=\"/php/00/01\">Lokalny Server PHP</a>.</em></p>\n\n<h2 id=\"obsługa-błędów\">Obsługa błędów</h2>\n<p>Najpierw jednak muszę się przyznać do pewnego przeoczenia, mógłbym wręcz powiedzieć, że błędu. Zapomniałem prawidłowo skonfigurować wyświetlanie błędów więc bardzo trudne było rozwiązywanie jakichkolwiek pomyłek w kodzie PHP. Zamiast czytelnego błędu wyświetlała nam się pusta strona ponieważ serwer był w konfiguracji produkcyjnej. Oczywiście wystarczyło zajrzeć do notatek sprzed lat i wprowadzić kilka dodatkowych linijek do naszego skryptu. Przede wszystkim chodziło o włączenie następujących dyrektyw:</p>\n\n<div class=\"language-sh highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>display_errors <span class=\"o\">=</span> On\nerror_reporting <span class=\"o\">=</span> E_ALL\n</code></pre></div></div>\n\n<p>Zrobiłem to z użyciem komendy <a href=\"https://pl.wikipedia.org/wiki/Sed_(program)\"><code class=\"language-plaintext highlighter-rouge\">sed</code></a> całość zmian znajdziecie tutaj: <a href=\"https://github.com/wpraktyce/server/commit/72b2fd5659a510dbbd978be3e8f5c161594c83cf\">72b2fd5</a></p>\n\n<h2 id=\"reorganizacja-skryptu\">Reorganizacja skryptu</h2>\n<p>Jako kolejny element ulepszeń postanowiłem podzielić skrypt który znajduje się w jednym pliku na funkcje zajmujące się poszczególnymi sekcjami naszego serwera. Skrypt lada moment będzie rozszerzony o kolejne n linijek odpowiedzialnych za serwer bazy danych, jego konfigurację i użytkowników, czyli moment wprowadzenia modułowości jest idealny. Pozwoli nam to łatwiej zarządzać wszystkim w przyszłości.</p>\n\n<p>Stworzyłem folder <code class=\"language-plaintext highlighter-rouge\">src</code> w którym będę przechowywał funkcje <code class=\"language-plaintext highlighter-rouge\">bash</code>. Oczywiście pierwszym krokiem musi być załadowanie tych wszystkich funkcji do naszego głównego skryptu, jeśli wszystkie interesujące nas funkcje znajdują się w jednym katalogu i są tam tylko pliki z funkcjami możemy to zrobić za pomocą jednej pętli:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">for </span>THIS_FILE <span class=\"k\">in </span>src/<span class=\"k\">*</span>\n<span class=\"k\">do\n </span><span class=\"nb\">source</span> <span class=\"nv\">$THIS_FILE</span>\n<span class=\"k\">done</span>\n</code></pre></div></div>\n\n<p>Jeśli w przyszłości potrzebowalibyśmy dodać jakiś plik z innej lokalizacji możemy to zrobić z użyciem komendy <code class=\"language-plaintext highlighter-rouge\">source</code> podając ścieżkę do tego pliku. Funkcje definiujemy bardzo prosto bo:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">function </span>nazwa_funkcji<span class=\"o\">()</span>\n<span class=\"o\">{</span>\n <span class=\"c\"># kod funkcji</span>\n<span class=\"o\">}</span>\n</code></pre></div></div>\n\n<blockquote>\n <p><strong>Uwaga!</strong>\nNależy pamiętać żeby wszystkie kody umieścić w funkcjach dzięki czemu wykonają się one dopiero w momencie wywołania przez nas funkcji, ze wszystkimi wymaganymi parametrami. W przeciwnym wypadku skrypty wykonają się w momencie ich załadowania.</p>\n</blockquote>\n\n<p>Następnie należy już tylko w odpowiedniej kolejności wywołać nasze funkcje:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>base_setup\ninstall_apache\ninstall_composer\n</code></pre></div></div>\n\n<p>Całość zmian znajdziecie tutaj: <a href=\"https://github.com/wpraktyce/server/commit/512cad3f53b0f6048bfdeacc769d98c901f24cbb\">512cad3</a></p>\n\n<h2 id=\"mysql\">MySQL</h2>\n<p>Przejdźmy do właściwego tematu tego wpisu, chcemy dodać zarówno sam serwer MySQL jak i jego obsługę w PHP, więc zacznijmy od tego pierwszego. W tym celu dodałem jedną dodatkową bibliotekę <code class=\"language-plaintext highlighter-rouge\">php5-mysql</code> do skryptu <code class=\"language-plaintext highlighter-rouge\">install_apache</code> instalującego nam PHP. Podstawowa instalacja PHP wygląda teraz tak:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>apt-get <span class=\"nt\">-y</span> <span class=\"nb\">install </span>php5 php5-mysql\n</code></pre></div></div>\n\n<p>Kolejnym krokiem jest instalacja samego serwera, jako że to zadanie jest dość duże samo w sobie stworzyłem mu osobną funkcję <code class=\"language-plaintext highlighter-rouge\">install_mysql</code>. W skrócie funkcja instaluje nam sam serwer oraz przeprowadza podstawową konfigurację taką jak:</p>\n<ul>\n <li>ustawienie hasła dla użytkownika <code class=\"language-plaintext highlighter-rouge\">root</code> które można podać jako pierwszy parametr funkcji</li>\n <li>umożliwienie dostępu publicznego do bazy</li>\n <li>kopiujemy domyślny plik konfiguracji <code class=\"language-plaintext highlighter-rouge\">local.cnf</code></li>\n <li>utworzenie pierwszej bazy danych której nazwa może być opcjonalnie ustawiona jako drugi parametr</li>\n</ul>\n\n<h3 id=\"dodawanie-użytkowników\">Dodawanie użytkowników</h3>\n<p>Kolejnym krokiem będzie dodanie użytkownika którego będziemy używać do połączenia z naszą bazą danych, w tym celu stworzyłem funkcję <code class=\"language-plaintext highlighter-rouge\">mysql_add_user</code>. Pierwszym parametrem jest nazwa użytkownika drugim jego hasło. Funkcja nie tylko dodaje użytkownika ale również przyznaje mu wszystkie uprawnienia do tej bazy danych. W skrypcie domyślnie dodajemy jednego użytkownika na start.</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>mysql_add_user user pass <span class=\"o\">[</span>root_pass] <span class=\"o\">[</span>db_name]\n</code></pre></div></div>\n\n<h3 id=\"konfiguracja-połączenia\">Konfiguracja połączenia</h3>\n<p>Teraz pozostało nam tylko użyć klienta MySQL żeby połączyć się z naszą bazą danych. Ja osobiście używam <a href=\"https://www.sequelpro.com/\">Sequel Pro</a>\njeśli chodzi o coś na inne platformy to <a href=\"https://www.mysql.com/products/workbench/\">MySQL Workbench</a> lub pobawić się w instalację webowego <a href=\"https://www.phpmyadmin.net/\">phpMyAdmin</a>. Bez różnicy jakiego klienta użyjemy nasze dane do logowania na początek będą takie:</p>\n\n<table>\n <thead>\n <tr>\n <th>Host</th>\n <th><code class=\"language-plaintext highlighter-rouge\">172.11.1.111</code></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>User</td>\n <td><code class=\"language-plaintext highlighter-rouge\">user</code></td>\n </tr>\n <tr>\n <td>Password</td>\n <td><code class=\"language-plaintext highlighter-rouge\">pass</code></td>\n </tr>\n <tr>\n <td>Database</td>\n <td><code class=\"language-plaintext highlighter-rouge\">develop</code></td>\n </tr>\n <tr>\n <td>Port</td>\n <td><code class=\"language-plaintext highlighter-rouge\">3306</code></td>\n </tr>\n </tbody>\n</table>\n\n<p>Zmiany w kodzie możecie oczwyiście znaleźć tutaj: <a href=\"https://github.com/wpraktyce/server/commit/175c0a55728ca777e05f65f699a7fd230668a596\">175c0a5</a></p>\n\n<h2 id=\"konfiguracja\">Konfiguracja</h2>\n<p>Oczywiście opisanie wszystkiego dokładnie zajęło by mi znacznie więcej czasu. Myślę, że wyjaśniłem najważniejsze elementy teraz czas na ostatni konfigurację modułów. Obecnie komenda <code class=\"language-plaintext highlighter-rouge\">vagrant up</code> zainstaluje nam wszystko zarówno PHP jak i MySQL ale nie zawsze jest nam potrzebna pełna konfiguracja. Wygląda to tak:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>base_setup\n\n<span class=\"c\">## Configuration:</span>\n\ninstall_apache\ninstall_composer\ninstall_mysql\nmysql_add_user user pass\ninstall_tools\n</code></pre></div></div>\n\n<p>Jeśli któryś z elementów nie będzie nam potrzebny wystarczy daną linijkę zakomentować używając <code class=\"language-plaintext highlighter-rouge\">#</code>. Oczywiście nie polecam usuwania <code class=\"language-plaintext highlighter-rouge\">base_setup</code>. Dla przykładu jeśli nie chcemy instalować bazy danych:</p>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>base_setup\n\n<span class=\"c\">## Configuration:</span>\n\ninstall_apache\ninstall_composer\ninstall_mysql\n<span class=\"c\"># mysql_add_user user pass</span>\n<span class=\"c\"># install_tools</span>\n</code></pre></div></div>\n\n<p>Cały pull request dostępny jest tutaj <a href=\"https://github.com/wpraktyce/server/pull/1\">PR#1</a>.</p>\n\n<h2 id=\"inne-dostępne-narzędzia\">Inne dostępne narzędzia</h2>\n<p>Ważne jest to żeby wspomnieć o tym, że w przypadku serwerów PHP istnieją również inne gotowe narzędzia. Bo czy tworząc ten mały projekt nie powieliłem już istniejących dobrze wspieranych projektów? Oczywiście, że tak! Ale zrobiłem to w celach edukacyjnych, łatwiej zrozumieć działanie pewnych rzeczy na prostszych przykładach. Jeśli chodzi o użytkowanie komercyjne to oczywiście polecam użycie bardziej profesjonalnych narzędzi.</p>\n\n<p>Tak jak już wspominałem od tych bardziej ogólnych przechodzimy do tych bardziej wyspecjalizowanych. <em>VirtualBox</em> jest ogólnie platformą do tworzenia maszyn wirtualnych, <em>Vagrant</em> wspomaga automatyczne i powtarzalne tworzenie maszyn wirtualnych a <a href=\"https://laravel.com/docs/5.6/homestead\">Homestead</a> zbiera to wszystko razem do kupy i tworzy nam gotowe do działania środowisko PHP przystosowane do współpracy z framework’iem <em>Laravel</em>. Jest to oczywiście narzędzie znacznie bardziej rozbudowane od przedstawionego przeze mnie serwera i jeśli interesuje nas tylko korzystanie to czemu nie użyć czegoś co w szybki sposób pozwala nam stworzyć wiele lokalnych stron.</p>\n\n<p>Innym rozwiązaniem o którym tutaj tylko wspomnę jest <a href=\"https://www.docker.com/\">Docker</a> czyli inny rodzaj wirtualizacji. Można go określić liderem przyszłości a dokładniejsze opisy zostawię specjalistom z dziedziny.</p>\n\n<h2 id=\"co-dalej\">Co dalej?</h2>\n<p>Jeśli chodzi o następne etapy to:</p>\n<ul>\n <li>koniecznie trzeba przenieść serwer na <strong>PHP7</strong></li>\n <li>wprowadzić obsługę <em>SQLite</em> oraz <em>MongoDB</em> żeby poszerzyć możliwości edukacyjne, ale to też może dopiero z odcinkami kursu</li>\n <li>może zmiana architektury w celu łatwiejszego importowania serwera do innych projektów lub lepszy mechanizm do zarządzania <code class=\"language-plaintext highlighter-rouge\">vhost</code> z różnych lokalizacji</li>\n</ul>\n\n<blockquote>\n <p><strong>Wersja do której się odnosi ten wpis to <a href=\"https://github.com/wpraktyce/server/releases/tag/2.0.0\">v2.0.0</a></strong></p>\n</blockquote>\n", "draft": false, "layout": "post", "subtitle": "Czym jest aplikacja która nie może przechowywać danych", "author": "wojtek", "post_id": "7368d2377b894e9b8e0e447f9e28f803", "heading_image": null, "language": "pl", "slug": "rozszerzamy-serwer-mysql", "ext": ".md" }, "relative_path": "_posts/2018-06-10-polska-trudny-jezyk.md", "excerpt": "<p>Długie pisanie postów nie ma sensu… ten post jest tego przykładem. Należy zacząć pisać i skończyć możliwie szybko!</p>\n", "url": "/2018/06/10/polska-trudny-jezyk", "id": "/2018/06/10/polska-trudny-jezyk", "categories": [ "default" ], "tags": [ "recenzja", "google", "ai" ], "title": "Polska Trudny Język - Google Home", "collection": "posts", "date": "2018-06-10 21:10:00 +0200", "next": { "output": null, "previous": { "relative_path": "_posts/2018-06-10-polska-trudny-jezyk.md", "url": "/2018/06/10/polska-trudny-jezyk", "id": "/2018/06/10/polska-trudny-jezyk", "categories": [ "default" ], "tags": [ "recenzja", "google", "ai" ], "title": "Polska Trudny Język - Google Home", "collection": "posts", "date": "2018-06-10 21:10:00 +0200", "path": "_posts/2018-06-10-polska-trudny-jezyk.md", "draft": false, "layout": "post", "subtitle": "Dostępność czy cena, co wpływa na małą popularność takich urządzeń?", "author": "wojtek", "post_id": "7e41f5cccf604941ba4ffa0f2dad4120", "heading_image": "2018-06-10.jpg", "language": "pl", "slug": "polska-trudny-jezyk", "ext": ".md" }, "relative_path": "_posts/2018-09-02-debugging-jekyll.md", "excerpt": "<p>So far I’ve faced it at least twice, so keeping my work <a href=\"https://en.wikipedia.org/wiki/Don%27t_repeat_yourself\">DRY</a> it’s time to document this.</p>\n", "url": "/2018/09/02/debugging-jekyll", "id": "/2018/09/02/debugging-jekyll", "categories": [ "development" ], "tags": [ "jekyll", "debugging", "troubleshooting", "blog" ], "title": "Debugging Jekyll", "collection": "posts", "date": "2018-09-02 11:25:00 +0200", "next": { "relative_path": "_posts/2018-09-04-python-wprowadzenie.md", "url": "/2018/09/04/python-wprowadzenie", "id": "/2018/09/04/python-wprowadzenie", "categories": [ "development" ], "tags": [ "python", "programowanie", "oop", "aws", "jupyter", "anaconda", "raspberrypi", "kodi" ], "title": "Python: Wprowadzenie", "collection": "posts", "date": "2018-09-04 17:50:00 +0200", "path": "_posts/2018-09-04-python-wprowadzenie.md", "draft": false, "layout": "post", "subtitle": "Dlaczego warto się go uczyć?", "author": "wojtek", "post_id": "0d4b96b2776842b5b2a8d05b78379ea7", "heading_image": "2018-09-python.png", "language": "pl", "slug": "python-wprowadzenie", "ext": ".md" }, "path": "_posts/2018-09-02-debugging-jekyll.md", "content": "So far I've faced it at least twice, so keeping my work [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) it's time to document this.\n\nHave you ever wondered what's inside Jekyll's variables? So did I! And don't get me wrong it is in the [official Jekyll documentation](https://jekyllrb.com/docs/liquid/filters/), but I don't know how many people will get into such a detail. How many are aware of things like that so they can google it.\n\nSo here it is, a way to see what sits inside any variable in your blog, really useful if you want to create some features.\n\n```liquid\n{% raw %}\n{{ variable | inspect }}\n{% endraw %}\n```\n\nJust replace `variable` with the actual variable you want to inspect.\n\n### Example\n\nFor example, this page, if you run\n\n```liquid\n{% raw %}\n{{ page | inspect }}\n{% endraw %}\n```\n\nYou will get:\n\n<pre>\n{{ page | inspect }}\n</pre>\n\nEnjoy!\n", "draft": false, "layout": "post", "subtitle": "Have you ever wondered what's inside Jekyll variables?", "author": "wojtek", "post_id": "5432ef209c2449508ecacab0a9f49504", "language": "en", "slug": "debugging-jekyll", "ext": ".md" }, "path": "_posts/2018-06-10-polska-trudny-jezyk.md", "content": "<p>Długie pisanie postów nie ma sensu… ten post jest tego przykładem. Należy zacząć pisać i skończyć możliwie szybko!</p>\n\n<p>Gdy zaczynałam go pisać na początku kwietnia nawet nie przypuszczałem, że <em>LG</em> sprawi nam taką niespodziankę… <a href=\"https://www.radiozet.pl/Nauka-i-Technologia/Technologia/Sztuczna-inteligencja-w-telewizorach-LG-rozumie-po-polsku\">Sztuczna inteligencja w telewizorach LG rozumie po polsku</a>. Krótko mówiąc <em>Google Home</em> (o którym miał być ten post) został w tyle. Dobrze, może jednak wykorzystam trochę z tego co już napisałem.</p>\n\n<h3 id=\"polski-na-3-miejscu\">Polski na 3 miejscu!</h3>\n<p>Tak, nie pomyliłem się nie <em>Polska</em> a <em>Polski Język</em>. Czy próbowaliście kiedyś nauczyć znajomych z zagranicy kilku słów po polsku? Jakiegość <em>cześć</em> czy <em>dziękuję</em>? A jak to jest z waszym imieniem, czy obcokrajowcy używają formy ze swojego własnego języka czy tak jak w przypadku mojego imienia po prostu nie są w stanie? Nic dziwnego, według tego rankingu <em>Polityki</em> <a href=\"https://www.polityka.pl/galerie/1690846,1,13-najtrudniejszych-jezykow-swiata.read\">13 najtrudniejszych języków świata</a> polski jest na 3 miejscu!</p>\n\n<p><strong>Nie tylko trudny ale też mało popularny.</strong> Niestety liczba osób mówiących po polsku nie jest też duża w porównaniu do innych języków, takich jak Angielski, Chiński czy Hiszpański. Oczywiście na popularność Angielskiego wpływa też siła nabywcza rynków na których używa się tego języka. Co za tym idzie producenci nie chcą inwestować w rozwój rozpoznawania języka, który obszarem jest też ograniczony tylko do jednego kraju. Do tego kraju w którym wspomniana siła nabywcza jest jedną z najmniejszych w Europie. Wystarczy zacytować chociażby <a href=\"https://businessinsider.com.pl/twoje-pieniadze/budzet-domowy/sila-nabywcza-konsumentow-w-europie-polska-na-29-miejscu/c5l1lyp\">Siła nabywcza Polaków dramatycznie niska</a>. Ale nie tylko nasze zarobki są tutaj problemem jak się okazuje sprzęty elektroniczne są u nas droższe w porównaniu z innymi krajami:</p>\n\n<blockquote>\n <h4 id=\"cena-iphonea-7\">Cena iPhone’a 7:</h4>\n <ul>\n <li>USA $815</li>\n <li>Hong Kong $821</li>\n <li><strong>Polska $1005</strong></li>\n <li>Rosja $1086</li>\n <li>Brazylia $1115</li>\n <li>Turcja $1200</li>\n </ul>\n\n <p><em>źródło: <a href=\"https://www.bankier.pl/wiadomosc/Polska-kraj-taniej-Coca-Coli-i-drogiego-iPhone-a-7593582.html\">Polska-kraj-taniej-Coca-Coli-i-drogiego-iPhone</a></em></p>\n</blockquote>\n\n<p>Tym bardziej ciekawa jest decyzja <em>LG</em> o wyprodukowania TV rozumiejącego polecenia po polsku. Ciekaw jestem jak to działa w praktyce… Jednakże jedyny taki model na rynku na pewno znajdzie nabywców.</p>\n\n<h2 id=\"asystent-dla-każdego\">Asystent dla każdego!</h2>\n<p>Jeśli macie telefon z <em>Androidem</em> to zapewne macie w nim też osobistego asystenta. Jak Wam się to podoba? Ja wiem, że to przegląda Waszą pocztę itd. Oczywiście wszystko w zakresie uprawnień które mu sami nadaliśmy. Jednak czy nie jest to wygodne, że wszystkie nasze loty samolotem czy podróże pociągiem automatycznie lądują w naszym kalendarzu. Czy też codzienne powroty do domu z pracy nie stały się trochę inne kiedy wiemy, że nie musimy się spieszyć i lepiej iść na jakieś małe zakupy koło biura ponieważ nasza droga do domu jest obecnie o 30 minut wolniejsza niż zwykle przez wypadek. Lub w drugą stronę, wstajemy rano i od razu wiemy, że musimy wyjść z domu wcześniej bo zą większe niż zwykle korki. I nawet nie musimy o to pytać, nasz asystent sam wyświetli nam informacje w obszarze powiadomień. Czy życie nie stało się trochę wygodniejsze? Jesteście za czy przeciw?</p>\n\n<h4 id=\"bezpieczeńśtwo-i-prywatność\">Bezpieczeńśtwo i Prywatność</h4>\n<p>Wspomniane już wcześniej kwestie prywatności i uprawnień a co za tym idzie zagrożenia które ze sobą niosą poruszałem ostatnio na <a href=\"https://twitter.com/wonowicki/status/1002821632929484801\">Twitter</a>, przy okazji artykułu <em>Tygodnika Powszechnego</em>:</p>\n\n<blockquote class=\"twitter-tweet .center-bloc\" data-lang=\"en-gb\"><p lang=\"pl\" dir=\"ltr\">Dzięki <a href=\"https://twitter.com/hashtag/BigData?src=hash&ref_src=twsrc%5Etfw\">#BigData</a> i <a href=\"https://twitter.com/hashtag/AI?src=hash&ref_src=twsrc%5Etfw\">#AI</a> poziom inwigilacji w Chinach osiągnął porażającą wysokość. Komputery oceniają koncentrację uczniów w szkole, obywatele dostają (lub tracą) punkty za swoją obywatelską postawę, a algorytm na tej podstawie może np. zabronić im podróży.<a href=\"https://t.co/9EgKdlrQkb\">https://t.co/9EgKdlrQkb</a></p>— Tygodnik Powszechny (@tygodnik) <a href=\"https://twitter.com/tygodnik/status/1002808826108764160?ref_src=twsrc%5Etfw\">2 June 2018</a></blockquote>\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n\n<p>Ważne jest budowanie świadomości zagrożeń jakie niesie ze sobą <em>AI</em> i <em>BigData</em>. Ale na pewno nie można siać paniki, bo to nigdy nie jest dobre. Pewne rzeczy już się dzieją i musimy przywyknąć trochę do czasów w jakich żyjemy. Wiele zależy od nas samych, co udostępniamy! I nie mam tu na myśli dawania uprawnień dla aplikacji a przede wszystkim tego co sami przesadnie wrzucamy na <em>Facebook</em> i <em>Instagram</em>. Z tego wiele można wyczytać i nie trzeba być tajną rządową agencją czy mega korporacją. Jeśli chodzi o kradzież danych których nie udostępniliśmy, racjonalnie myśląc jeśli nie jesteśmy osobą publiczną to raczej nie powinniśmy się takich rzeczy obawiać.</p>\n\n<h3 id=\"ok-google\">“OK Google”</h3>\n<p>Inteligentne głośniki idą dalej, nie potrzebujemy już trzymać telefonu przy sobie, wystarczy się o coś zapytać lub poprosić o włączenie świateł. Nasze domy stają się naprawdę coraz bardziej “inteligentne”, to co mogliśmy oglądać na filmach science fiction kilka lat temu teraz jest rzeczywistością.</p>\n\n<p>Moim zdaniem najważniejszym aspektem jest to, że wszystko jest ze sobą zintegrowane. Kupujemy głośnik o jednego producenta i żarówki od innego i wszystko działa. Nie ma żadnego niepotrzebnego utrudniania nam życia, różnych rodzajów złączy nie pasujących do innych producentów, wszystko komunikuje się ze sobą bezprzewodowo.</p>\n\n<p>Osobiście jeszcze nie dorosłem do tego żeby zainstalować tego typu żarówki, jednak cieszy mnie możliwość rozszerzania mojego zestawu. Na tym początkowym etapie głośnik jest głównie używany do słuchania polskiego radia poprzez <em>TuneIn</em> oraz sporadycznie zadawania pytań jeśli jakimś dziwnym zbiegiem okoliczności nie mam pod ręką żadnego urządzenia (brzmi mało realnie co nie). W moim przypadku język nie stanowił bariery, jednak wiem że nie każdego użytkownika który tylko uczył się w szkole urządzenie rozpozna bez problemu. Wydaje mi się, że jednak ta bariera językowa będzie dość mocno spowalniała popularyzację tego typu sprzętu w Polsce</p>\n\n<h3 id=\"widoki-na-przyszłość\">Widoki na przyszłość</h3>\n<p>Wiadomo <em>nie odrazu Rzym zbudowano</em> więc dostępne obecnie urządzenia należy uznać za świetne podwaliny pod dalszy rozwój. Google miało wprowadzić do swoich głośników tryb ciągłej rozmowy, czyli nie za każdym razem będziemy musieli używać wywołania <em>OK Google</em> tylko będziemy mogli kontynuować rozmowę po uzyskaniu odpowiedzi. Jeśli zamieszczone poniżej artykuły mają rację to należy się spodziewać języka polskiego jeszcze w tym roku!</p>\n\n<ul>\n <li><a href=\"https://www.androidpolice.com/2018/02/15/google-assistant-may-support-38-countries-17-languages-2018/\">Google Assistant may support 38 more countries and 17 more languages in 2018</a></li>\n <li><a href=\"https://www.theverge.com/2018/2/23/17041920/google-assistant-languages-multilingual-detection\">Google Assistant languages multilingual detection</a></li>\n</ul>\n", "draft": false, "layout": "post", "subtitle": "Dostępność czy cena, co wpływa na małą popularność takich urządzeń?", "author": "wojtek", "post_id": "7e41f5cccf604941ba4ffa0f2dad4120", "heading_image": "2018-06-10.jpg", "language": "pl", "slug": "polska-trudny-jezyk", "ext": ".md" }, "relative_path": "_posts/2018-09-02-debugging-jekyll.md", "excerpt": "<p>So far I’ve faced it at least twice, so keeping my work <a href=\"https://en.wikipedia.org/wiki/Don%27t_repeat_yourself\">DRY</a> it’s time to document this.</p>\n", "url": "/2018/09/02/debugging-jekyll", "id": "/2018/09/02/debugging-jekyll", "categories": [ "development" ], "tags": [ "jekyll", "debugging", "troubleshooting", "blog" ], "title": "Debugging Jekyll", "collection": "posts", "date": "2018-09-02 11:25:00 +0200", "next": { "output": null, "previous": { "output": null, "previous": { "relative_path": "_posts/2018-06-10-polska-trudny-jezyk.md", "url": "/2018/06/10/polska-trudny-jezyk", "id": "/2018/06/10/polska-trudny-jezyk", "categories": [ "default" ], "tags": [ "recenzja", "google", "ai" ], "title": "Polska Trudny Język - Google Home", "collection": "posts", "date": "2018-06-10 21:10:00 +0200", "path": "_posts/2018-06-10-polska-trudny-jezyk.md", "draft": false, "layout": "post", "subtitle": "Dostępność czy cena, co wpływa na małą popularność takich urządzeń?", "author": "wojtek", "post_id": "7e41f5cccf604941ba4ffa0f2dad4120", "heading_image": "2018-06-10.jpg", "language": "pl", "slug": "polska-trudny-jezyk", "ext": ".md" }, "relative_path": "_posts/2018-09-02-debugging-jekyll.md", "excerpt": "<p>So far I’ve faced it at least twice, so keeping my work <a href=\"https://en.wikipedia.org/wiki/Don%27t_repeat_yourself\">DRY</a> it’s time to document this.</p>\n", "url": "/2018/09/02/debugging-jekyll", "id": "/2018/09/02/debugging-jekyll", "categories": [ "development" ], "tags": [ "jekyll", "debugging", "troubleshooting", "blog" ], "title": "Debugging Jekyll", "collection": "posts", "date": "2018-09-02 11:25:00 +0200", "next": { "relative_path": "_posts/2018-09-04-python-wprowadzenie.md", "url": "/2018/09/04/python-wprowadzenie", "id": "/2018/09/04/python-wprowadzenie", "categories": [ "development" ], "tags": [ "python", "programowanie", "oop", "aws", "jupyter", "anaconda", "raspberrypi", "kodi" ], "title": "Python: Wprowadzenie", "collection": "posts", "date": "2018-09-04 17:50:00 +0200", "path": "_posts/2018-09-04-python-wprowadzenie.md", "draft": false, "layout": "post", "subtitle": "Dlaczego warto się go uczyć?", "author": "wojtek", "post_id": "0d4b96b2776842b5b2a8d05b78379ea7", "heading_image": "2018-09-python.png", "language": "pl", "slug": "python-wprowadzenie", "ext": ".md" }, "path": "_posts/2018-09-02-debugging-jekyll.md", "content": "So far I've faced it at least twice, so keeping my work [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) it's time to document this.\n\nHave you ever wondered what's inside Jekyll's variables? So did I! And don't get me wrong it is in the [official Jekyll documentation](https://jekyllrb.com/docs/liquid/filters/), but I don't know how many people will get into such a detail. How many are aware of things like that so they can google it.\n\nSo here it is, a way to see what sits inside any variable in your blog, really useful if you want to create some features.\n\n```liquid\n{% raw %}\n{{ variable | inspect }}\n{% endraw %}\n```\n\nJust replace `variable` with the actual variable you want to inspect.\n\n### Example\n\nFor example, this page, if you run\n\n```liquid\n{% raw %}\n{{ page | inspect }}\n{% endraw %}\n```\n\nYou will get:\n\n<pre>\n{{ page | inspect }}\n</pre>\n\nEnjoy!\n", "draft": false, "layout": "post", "subtitle": "Have you ever wondered what's inside Jekyll variables?", "author": "wojtek", "post_id": "5432ef209c2449508ecacab0a9f49504", "language": "en", "slug": "debugging-jekyll", "ext": ".md" }, "relative_path": "_posts/2018-09-04-python-wprowadzenie.md", "excerpt": "<blockquote>\n <p>“Kto nie idzie do przodu, ten się cofa.” ~Johann Wolfgang von Goethe</p>\n</blockquote>\n", "url": "/2018/09/04/python-wprowadzenie", "id": "/2018/09/04/python-wprowadzenie", "categories": [ "development" ], "tags": [ "python", "programowanie", "oop", "aws", "jupyter", "anaconda", "raspberrypi", "kodi" ], "title": "Python: Wprowadzenie", "collection": "posts", "date": "2018-09-04 17:50:00 +0200", "next": { "output": null, "previous": { "relative_path": "_posts/2018-09-04-python-wprowadzenie.md", "url": "/2018/09/04/python-wprowadzenie", "id": "/2018/09/04/python-wprowadzenie", "categories": [ "development" ], "tags": [ "python", "programowanie", "oop", "aws", "jupyter", "anaconda", "raspberrypi", "kodi" ], "title": "Python: Wprowadzenie", "collection": "posts", "date": "2018-09-04 17:50:00 +0200", "path": "_posts/2018-09-04-python-wprowadzenie.md", "draft": false, "layout": "post", "subtitle": "Dlaczego warto się go uczyć?", "author": "wojtek", "post_id": "0d4b96b2776842b5b2a8d05b78379ea7", "heading_image": "2018-09-python.png", "language": "pl", "slug": "python-wprowadzenie", "ext": ".md" }, "relative_path": "_posts/2019-09-09-prep-your-ticket.md", "excerpt": "<p><a href=\"https://en.wikipedia.org/wiki/Agile_software_development\">Agile</a> ticket flow usually sounds easy, as a dev you are getting a ticket with all business requirements defined by a product owner, business analyst etc. Then you just have to deliver it, submit it for a review, pass QA and UAT and then it finally lands in the live environment.</p>\n", "url": "/2018/09/09/prep-your-ticket", "id": "/2018/09/09/prep-your-ticket", "categories": [ "development" ], "tags": [ "agile", "scrum", "documentation" ], "title": "Prep your ticket", "collection": "posts", "date": "2018-09-09 17:45:00 +0200", "next": { "relative_path": "_posts/2019-09-16-language-flags.md", "url": "/2018/09/16/language-flags", "id": "/2018/09/16/language-flags", "categories": [ "development" ], "tags": [ "jekyll", "blog", "webdev" ], "title": "Language flags", "collection": "posts", "date": "2018-09-16 17:25:00 +0200", "path": "_posts/2019-09-16-language-flags.md", "draft": false, "layout": "post", "subtitle": "How to add language flags to Jekyll?", "author": "wojtek", "post_id": "71c087c57e004f89af19fb02cf2862b6", "language": "en", "slug": "language-flags", "ext": ".md" }, "path": "_posts/2019-09-09-prep-your-ticket.md", "content": "[Agile](https://en.wikipedia.org/wiki/Agile_software_development) ticket flow usually sounds easy, as a dev you are getting a ticket with all business requirements defined by a product owner, business analyst etc. Then you just have to deliver it, submit it for a review, pass QA and UAT and then it finally lands in the live environment.\n\nWait... just deliver... here comes the difficult element and something that can generate an unnecessary cost. Of course, there is the technical side which can be done wrong, inefficient and low in quality. But this article is more about the soft side of your ticket. And this soft side can cause the same negative effects as bad technical implementation or can lead you to bad implementation.\n\nTo avoid failing you have to answer those questions:\n\n- How to organise your work?\n- What things should you check?\n- And what questions you should ask?\n\n## Before you start\n\nIn order to get things right you have to sort out things from the list below:\n\n1. **Can I start it?**\n\n Yes, do you have all the information you need on the ticket? In an ideal world, you would get what you need. But we are not living there. Even more to that, there may be no business analysis in your company or anyone with the skills to write a good business case. So before moving forward check if you have all the information you need. If not ask relevant people. Remember now you are the owner of this ticket and you have to deliver it. So you need to do everything which is required to complete it.\n\n2. **Do I understand the problem I’m solving?**\n\n That’s a fair question. No yet from a technical point but from a business point, do you understand what problem you are trying to solve? What process will this feature improve? A decent level of understanding will be good to make sure you are solving right thin in right way.\n\n3. **What parts of the system am I touching?**\n\n The first step into a technical element of your ticket. Just check what parts of the system you need to work in to be able to complete your story. First, it will help you to better understand the scope of the task. And as well it will allow you to check if you have access to all relevant parts. A small suggestion here each separate part of the system is either a task or even separate ticket.\n\n4. **Do I have clear acceptance criteria?**\n\n Or do you have any at all? Will be good to know what positive completion looks like.\n\n5. **Is anything big enough to be split out?**\n\n It’s always better to play smaller tickets. As well it will allow to share them in between your team, so it gets delivered faster.\n\n> ### Write what you don’t know!\n> \n> And your prep will become getting those questions answered.\n\nRemember about some key principles. Timebox everything, make sure you are not spinning on anything. If you get stuck ask for help.\n\nDon’t be worried too much, remember that you are not alone there. You are working as a part of a team of a company. So I’m guessing there is a senior developer, architect, business analyst, product owner to help you with your prep.\n\n## Do your prep\n\nNow it’s time to start doing some technical preparation. Assuming that you know everything you need from the previous stage. Now there are a few more questions to be answered.\n\nRemember that in this stage it’s really important to write down key things. As in this stage, you will be creating actual tasks or even additional tickets. Anyone who will pick this after you should be able to complete it without repeating what you’ve done already. Creating **clear tasks is important as well from a visibility point** of view so [SCRUM](https://en.wikipedia.org/wiki/Scrum_(software_development)) Master, iteration manager or event the rest of a business can see progress.\n\n0. **What documentation I need to write?**\n\n Documentation is really important part of the software, although clean code should explain itself some higher level description is key. Especially with API’s, another developer to work with this code needs to know where to start. So check what documentation you need to update or create.\n\n0. **Is this affect the external world?**\n\n For example, am I changing public API? If so, then the previous point becomes even more important. Remember to be really careful in this area. Other people are using it so you can’t introduce any breaking changes or remove any functionality. And don’t forget to apply some standards like paginations, limits, filters where applicable.\n\n0. **What is the architecture?**\n\n How do I design it? Should I introduce a new service? Or add this as a part of the existing one? How might this thing evolve in the future? Is it extendable? Don’t forget to align your solution with the overall architecture of your system. And use some best practices ex. [SOLID design principles](https://stackify.com/solid-design-principles/).\n\n0. **What technologies I need to use?**\n\n Do I need to introduce any new technologies? If so what technologies? Is what you have at the moment available insufficient? Or introducing new will make things a lot easier? But then what additional implications would it bring? And management overhead for future? Potentially second difficult question here.\n\n0. **Do I need to change any data structures?**\n\n If things are already abstracted properly then you almost shouldn’t care about it. But if they are not then you must check if your changes won’t break anything in other parts of the system or even out of it like reporting.\n\n0. **How I will be testing it?**\n\n Last but not the least. Good testing is priceless. Current tests should make sure that you are not breaking anything in the system. That’s why so far there wasn’t much about making sure you are not breaking anything. So don’t break current… but as well to maintain coverage and your safe sleep in future you have to write some good tests. Prepare a plan for it and validate it with your QA.\n\nAnd you feel like you still haven’t to write any code. Absolutely not! What is the point of theoretical prep? Especially in cases like new technology architecture and so on. There should be some base code created already. How you want to start doing final step without checking first if your ideas will work.\n\n## Before you start...\n\nJust make sure\n\n1. The ticket is updated with your solution\n2. All relevant tickets and tasks are created\n3. Everything has size estimated\n4. And you’ve not missed anything from previous sections!\n\nDepending on the rules in your team this is the time you want to have a quick chat with your senior developer and check if he is happy with what you’ve done so far. Potentially this person will be reviewing your work later so better to make sure you have the same things in your minds.\n\nAlthough this whole \"process\" may look like it's time-consuming and decreasing your productivity. Nothing more wrong than that! These steps are just a suggestion of how you can perform something which must be done anyway. You don't need to use them but you should get into the similar result. Looking on it from a delivery perspective even if there is a little bit more of work to do upfront it will benefit later. And the whole process will be more efficient. Because now you should know everything you need and it’s just a case of converting your knowledge into code.\n\n**Good luck!**\n", "draft": false, "layout": "post", "subtitle": "How to perform technical inception of business requirements?", "author": "wojtek", "post_id": "8b808f7667f141bab8e9def097be161b", "heading_image": "2018-09-scrum.jpg", "language": "en", "slug": "prep-your-ticket", "ext": ".md" }, "path": "_posts/2018-09-04-python-wprowadzenie.md", "content": "> \"Kto nie idzie do przodu, ten się cofa.\" ~Johann Wolfgang von Goethe\n\nRozwój osobisty jeszcze nigdy nie był tak ważny jak jest teraz. Zwłaszcza w IT, gdzie prawie codziennie powstają nowe projekty i technologie. Dlatego też osoby pracujące w tej branży są bardziej niż inni narażeni na swego rodzaju przedawnienie. Konkluzja jest prosta, trzeba się rozwijać i o konkretnym rozwoju jest ten wpis.\n\n## Dlaczego Python?\nDobry inżynier oprogramowania poza szlifowaniem aktualnego języka czy pojęć ogólnych powinien poznawać nowe technologie i języki. Mój wybór padł na Python’a, który wcale taki nowy nie jest bo powstał w latach dziewięćdziesiątych ubiegłego wieku. Jednakże w raporcie [2018 Developer Skills Report](https://research.hackerrank.com/developer-skills/2018/) Python zajmuje czołowe miejsce.\n\nDlaczego konkretnie? Oto kilka podstawowych cech/zalet tego języka\n- język wysokiego poziomu - czyli stosunkowo prosty do opanowania\n- ogólnego przeznaczenia - czyli zrobimy w nim dużo\n- rozbudowany pakiet bibliotek - tu drzemie potęga tego języka którą dopiero poznacie\n- mówi się że jest czytelny i klarowny - ja osobiście jestem bardziej przyzwyczajony do składni PHP, C++ czy Java\n- dynamiczny system typów - tu można polemizować czy to zaleta\n- wspiera paradygmat obiektowy (OOP)\n- wszystko jest obiektem - nawet zwykły string, co w praktyce okazuje się ciekawą zaletą\n- wieloplatformowy\n- open source\n\nPython jest językiem skryptowym interpretowalnym (nie kompilowalnym) co bez wątpienia dla wielu nie będzie uznawane za jego zaletę. Jednak jest to język pozwalający mniej zaawansowanym programistom na tworzenie prostych skryptów na różnego rodzaju platformach. Stąd jego popularność i możliwość użycia w takich narzędziach jak [AWS Lambda](https://aws.amazon.com/free/webapps) czy AWS Glue.\n\nZ innych ciekawych zastosowań należałoby wymienić to że jest głównym językiem używanym do nauki programowania w projekcie [Raspberry Pi](https://www.raspberrypi.org/). Czyli jednym z najtańszych dostępnych obecnie na rynku komputerów.\n\nUmożliwia pisanie wtyczek na platformę [Kodi](https://kodi.tv/article/attention-addon-developers-migration-python-3).\n\n### Data Science\nJednym z ważniejszych zastosowań Python’a obecnie jest analiza i przetwarzanie danych. Prostota i wsparcie technologii pozwala naukowcom (nie będącym zaawansowanymi programistami) przeprowadzanie różnych doświadczeń i analiz w sposób zautomatyzowany. Ważną rolę tutaj odgrywają narzędzia takie jak [jupyter](http://jupyter.org/) pozwalający na tworzenie tak zwanych notesów w których mieszamy skrypty z dokumentacją metod które wykorzystujemy do rozwiązania naszych skomplikowanych problemów. Czy idąc jeszcze dalej, zintegrowane środowiska takie jak [Anaconda](https://anaconda.org/) ułątwiające nam instalacje i przygotowanie narzędzi i bibliotek.\n\n## Prostota\nPython’a cechuje prostota samego używania jak również prostota na starcie, ale o tym dokładnie jak zacząć napiszę następnym razem. Ważne jest to, że nie potrzebujemy żadnych specjalnych serwerów, płatnych narzędzi itd. Wystarczy zainstalować Pythona najlepiej z użyciem jakiegoś narzędzia i po prostu zacząć kodować.\n", "draft": false, "layout": "post", "subtitle": "Dlaczego warto się go uczyć?", "author": "wojtek", "post_id": "0d4b96b2776842b5b2a8d05b78379ea7", "heading_image": "2018-09-python.png", "language": "pl", "slug": "python-wprowadzenie", "ext": ".md" }, "path": "_posts/2018-09-02-debugging-jekyll.md", "content": "So far I've faced it at least twice, so keeping my work [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) it's time to document this.\n\nHave you ever wondered what's inside Jekyll's variables? So did I! And don't get me wrong it is in the [official Jekyll documentation](https://jekyllrb.com/docs/liquid/filters/), but I don't know how many people will get into such a detail. How many are aware of things like that so they can google it.\n\nSo here it is, a way to see what sits inside any variable in your blog, really useful if you want to create some features.\n\n```liquid\n{% raw %}\n{{ variable | inspect }}\n{% endraw %}\n```\n\nJust replace `variable` with the actual variable you want to inspect.\n\n### Example\n\nFor example, this page, if you run\n\n```liquid\n{% raw %}\n{{ page | inspect }}\n{% endraw %}\n```\n\nYou will get:\n\n<pre>\n{{ page | inspect }}\n</pre>\n\nEnjoy!\n", "draft": false, "layout": "post", "subtitle": "Have you ever wondered what's inside Jekyll variables?", "author": "wojtek", "post_id": "5432ef209c2449508ecacab0a9f49504", "language": "en", "slug": "debugging-jekyll", "ext": ".md" }
Enjoy!
- Category:
- Development
NOTE!
Comments suspended as this is not production environment!