[PHP Basics - Exercises] - 09. Object to JSON String
Задача: [PHP Basics - Exercises] - 09. Object to JSON String
Линк в Judge: https://judge.softuni.bg/Contests/Practice/Index/240#8
Моят код: http://pastebin.com/9xVcUfxw
Проблем: Използвам $inputLines = array_map('trim',$inputLines); уж се ползва 'trim', но накрая при преобразуване в JSON се появява един празен ред ("":null ), т.е. {"name":"Angel","surname":"Georgiev","age":20,"grade":6,"date":"23/05/1995","town":"Sofia","":null}
ВЪПРОС: Защо се получава този проблем и какъв е начинът да се избегне?
Благодаря много за изчерпателния отговор!
Беше доста полезен!
Иначе бих могъл да реализирам варианта с последователни операции, но мислех, че има кратък вариант с готова функция, като същевременно мислех, че trim() премахва и празните редове в получения стринг/масив, но всъщност ми се изясни, че тя действа сами върху определения стринг/елемент от масива. И в реда на тези си мисли, реших, че вероятно не ползвам функцията array_map() коректно и че може като първи параметър да се постави условие от рода на
което да премахва и празните редове.
Сега ми е ясно вече действието на array_map(), и trim(), за което благодаря!
Ако бих могъл да попитам и още нещо:
Защо проверката
винаги дава TRUE след натискане на submit, дори и ПРИ ПРАЗНИ, НЕПОПЪЛНЕНИ данни в полетата?!
Примерно независимо дали съм въвел или не някаква стойност в полето, натискайки submit, isset($_GET['delimiter']) да речем, винаги ми дава TRUE, което малко обезсмисля тази проверка?!
Дали нещо друго влияе в случая или isset() има друга идея?
isset() проверява дали дадена променлива/стойност присъства в текущия scope. Променливи, които са празни стрингове, все пак съществуват.
Направи си следния експеримент.
въведи нещо само в едното поле или не въвеждай нищо и кликни бутона Submit Query. Погледни резултата в URL-a (Address bar-a):
Както се забелязва и lastName и delimiter са там, но са с празни стойности.
Всъщност използването на isset() е крайно обезкуражени от добрите практики. Би трябвало на един endpoint (страница, метод...) да си абсолютно убеден за данните, които ще получиш и да няма нужда да проверяваш там ли са или не са. Т.е. само на едно централно място да се прави проверка за request method-а и после данните да се разпращат на определени методи, които ги очакват със сигурност. Но това е друга бира и няма да я засягам повече в темата.
Идеята в случая с $_GET/$_POST е, че евентуално може да има два или повече формуляра, които изпращат заявка до страницата ти.
Ако кликна бутона на първия, ще се изпратят lastName и delimiter. Ако кликна на втория - firstName и delimiter. Респективно на третия - username и password.
Тогава мога да проверя кой формуляр точно е изпратен, проверявайки нещо уникално от формуляра дали е set-нато. Например delimiter само не върши работа, защото той присъства и в първия и във втория формуляр. Така, че ще трябва да проверява и двете.
Естествено, ако имаш повече от две полета, става крайно неподдържано това да изреждаш всичките в isset() (един от проблемите на тази практика). Тогава по-логично би било да сложиш уникален елемент във всеки формуляр и да проверяваш него. Например бутонът за изпращане на формуляра.
Сега, това което ти се опитваш да направиш е да разбереш не просто дали е изпратен даден формуляр, а дали стойностите в него отговарят на някакво условие. Нека го кажем - валидация. В конкретния случай е да не са празни, така че се връщаме на вторто изречение от предния пост за функцията empty()
Що се отнася до хитрия начин за филтриране на празните елементи в масив, можем да опрем до това как работят нетипизираните езици като РНР. При тях има type-juggling. Когато се опитваш да провериш нещо от един тип дали има стойност от друг тип, то това нещо тихичко се каства до втория тип. Така например условието на if() блок трябва да бъде булево, но ако бъде подадена друга стойност, тя ще се кастне до булева.
Празен стринг и нула са FALSE by nature, ако бъдат кастнати към булева стойност. В такъв случай, ако имаме в един масив празни стрингове, нули или други falsy стойности (разбирай под falsy всичко, което като го кастнеш към булева стойност връща FALSE).
Така, че нека си представим, че имаме масива:
И искаме да махнем всички falsy стойности, а именно: "", 0, false, null;
Ще използваме array_filter() като функцията, която ще подадем ще провери дали кастнатия към boolean елемент от масива връща true и ще върнем true, в противен случай false. Само когато функцията върне true тогава елементът ще се запази.
Резултат:
Нека опростим функцията. if (el) return true може да се свете до просто return el, тъй като в условието на иф-а се крие и return-a:
А сега нека прочетем документацията на функцията array_filter. Вариант е ако ползваш сносно IDE да я кликнеш (CTRL+click при PHPStorm). Другият вариант е да я отвориш в php.net. Нека видим какво пише над функцията когато е CTRL+click-на
Т.е. можем да пропуснем втория аргумент на функцията, който е нашата функция какво да остане в масива. Ако го направим, всички falsy елементи така или иначе ще изчезнат.
Резултатът отново е същият!
В крайна сметка ако се озовем с масива от първия случай:
Трябва да сведем всички whitespaces до празен стринг, за да мине горният номер. Тук идва твоят array_map. Ще тримнем всеки елемент и после ще го филтрираме.
Резултат:
Иии разбира се, ако сме мазачи, можем и на един ред да го напишем :-))
И резултатът отново е този, който желаем ;-)
Благодаря отново за изчерпателния отговор!
Беше ми много полезен.
Съжалявам само че под отговора нямаше този път бутон <Best answer>