• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

filter_input a pobieranie zmiennej z tablicy $_POST

VPS Starter Arubacloud
0 głosów
1,183 wizyt
pytanie zadane 12 stycznia 2018 w PHP przez kevin Mądrala (5,010 p.)

Witam!

Po co się używa: $in_adres = filter_input(INPUT_POST, 'adres');

Skoro można pobrać zmienną $in_adres = $_POST['adres'] ?

Co wprowadza mi filter_input ?

komentarz 12 stycznia 2018 przez efiku Szeryf (75,160 p.)
edycja 12 stycznia 2018 przez efiku
Dokumentacja Twoim przyjacielem, spróbuj zrozumieć i pomyśleć jak to wykorzystać.

http://php.net/manual/en/function.filter-input.php
komentarz 13 stycznia 2018 przez kevin Mądrala (5,010 p.)
Na moim etapie nauki ciężko będzie wymyślić praktyczne zastosowanie.

1 odpowiedź

+2 głosów
odpowiedź 12 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)
Gdy ten element nie będzie istniał w tablicy $_POST (nie zostanie przesłany) to odwołanie przez $_POST[] spowoduje ostrzeżenie. filter_input() automatycznie sprawdza czy dany element jest - jeśli tak to odczytuje i zwraca jego wartość, jeśli nie to zwraca nulla.

Dodatkowo można również dołożyć 3 argument z jakimś filtrem, dzięki którym możesz np. od razu wykonać sanityzację czy walidację. Cała lista filtrów: http://php.net/manual/en/filter.filters.php
komentarz 12 stycznia 2018 przez kevin Mądrala (5,010 p.)

Ostrzeżenie wystąpi nawet dla instrukcji if( isset( $_POST['zmiena_xyz']); ?

komentarz 12 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)
Oczywiście nie, jeśli wykonasz tylko sprawdzenie czy istnieje i jeśli istniał nie będzie to się do niego nie odwołasz, to ostrzeżenia nie będzie. Ale jeśli masz w formularzu np. 10 pól, to każde wypadałoby sprawdzić przez taki isset czy tam ??, a tak można po prostu użyć od razu filter_input().
komentarz 12 stycznia 2018 przez kevin Mądrala (5,010 p.)

Dobra, ale dla 10 pól użyję filter_input() i skąd będę wiedział czy wszystkie pola zostały wypełnione ? filter_input zwróci mi null ale ifem będę musiał sprawdzać czy zmienne są null ?

komentarz 12 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)
Zakładając że robisz to po prostu na warunkach i musisz sprawdzić czy te pola są wypełnione no to tak, będziesz musiał i tak to zapisać na to jakieś warunki.
komentarz 12 stycznia 2018 przez kevin Mądrala (5,010 p.)

A można inaczej niż na warunkach ? issetem sprawdzam czy istnieje taka zmienna ( $in_zmiennaZPost != null ) później na tej zmiennej wykonuję funkcję empty() sprawdzając czy coś zawiera.

$in_con = null;
if (( isset( $_POST['con'] ) && empty( $_POST['con']) {

        $in_con = filter_input(INPUT_POST, 'con');
}

Funkcja ta jest tylko do filtracji danych, jeżeli chcę aby dane w poście zawierały tylko znaki alfanumeryczne to mogę  sprawdzić to funkcją ctype_alnum i dzięki temu mam wynik true/false a filter_input usunie mi niechciane znaki z stringu. Nie mogę sobie wyobrazić praktycznego zastosowania... Pobieranie danych z tablicy $_POST dalej jest poprawne bez użycia filter_input() ?

komentarz 12 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)
Przez inne miałem na myśli rzeczy trochę bardziej rozbudowane - teraz jak się domyślam masz po prostu kod, który wykonuje się od dołu do góry i tyle (bez urazy oczywiście). Docelowo można to napisać lepiej, np. przy użyciu funkcji, albo obiektowo.

Ale ok, może za daleko odchodzę. Jeśli przed odwołaniem się do danego elementu tablicy $_GET czy $_POST sprawdzisz czy taki element istnieje i nie chcesz używać od razu takich filtrów to nie widzę problemu, możesz robić to tak "po staremu". Mi osobiście bardziej podoba się jednak sposób z filter_input(), bo jest łatwo rozszerzalny no i nie operuję tak wprost na tablicy superglobalnej.
1
komentarz 12 stycznia 2018 przez efiku Szeryf (75,160 p.)
komentarz 13 stycznia 2018 przez kevin Mądrala (5,010 p.)

@Arkadiusz Waluk,
A może być taki który nie wykonuje się od góry do dołu ? Dla przykładu tutaj mam funkcję która zwraca indeks w tablicy asocjacyjnej string'u który zawiera tłumaczenie błędu dla niepoprawnego hasła:

 	function validate_password ( $password )
 	{
		if( !isset( $password ))
			return 'e_validate_password_does_not_exist';
 		
                $pass_length = strlen($password);
		
               if($pass_length == 0)
			return 'e_validate_password_does_not_exist';
		
		else if (ctype_alnum($password) == false)
			return 'e_validate_password_has_incorrect_chars';

		else if ($pass_length < 5)
			return 'e_validate_password_is_too_short';

		else if ($pass_length > 22)
			return 'e_validate_password_is_too_long';

 		return null; // no error
 	}

 

Używam:

$pass_err = validate_password( $_POST['pass'] );

if( isset($pass_err) ) {
         
         echo $lang->translate( $pass_err );
}

 

I takie coś działa, czy jest poprawnie napisane względem pewnych wytycznych o których mówicie ? Nie wiem...

komentarz 13 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)

No, funkcje to już jest coś, co trochę ten kod rozbudowuje. Tyle że u Ciebie nie ma sprawdzenia czy ten element tablicy istnieje przed odwołaniem.

validate_password( $_POST['pass'] );

Odwołanie jest już tutaj.

 if( !isset( $password ))

A ten warunek nie ma sensu bo $password zawsze będzie istniało, przychodzi w końcu z argumentu, który musi tam być. Z kolei samo zwracanie treści błędu jakoś gdzieś musi nastąpić, ale warto też pamiętać że są wyjątki, typowo do obsługi błędów.

Poza tym warto zwrócić uwagę, że strlen źle liczy m.in. polskie znaki, lepiej użyć mb_strlen. No i polecałbym też poznać standard wyglądu kodu o nazwie PSR-2, nie jest to co prawda oficjalny standard, ale bardzo wielu programistów PHP się do niego stosuje.

komentarz 13 stycznia 2018 przez kevin Mądrala (5,010 p.)
edycja 13 stycznia 2018 przez kevin

Czyli że przekazanie $_POST['xyz'] do funkcji i w niej sprawdzenie czy zmienna istnieje isset'em nie ma sensu i wywoła ostrzeżenie w przypadku gdy w tablicy POST nic nie istnieje ? Jeżeli sprawdzam poprawność kilku pól to nie ma sensu raczej rzucać wyjątek dla jednego pola.

$pass_err = validate_password($_POST['pass']);
$email_err = validate_email($_POST['email']);
$rules_err = validate_accept_rules($_POST['rules']);

try
{
    if( ( !isset($pass_err) ) || ( !isset($email_err) ) || ( !isset($rules_err) )
       throw new ValidateException("");

}
catch(ValidateException $e)
{
      $lang_pack = array();

      if( isset($pass_err) )
         $lang_pack[] = $pass_err;

      if( isset($email_err) )
         $lang_pack[] = $email_err;

      if( isset($rules_err) )
         $lang_pack[] = $rules_err;

      $lang = new Language();
      if($lang->load_language($_SESSION['language'], $lang_pack) == false)
     {
         echo json_encode(array("success"=>false,
         "error_type"=>"fatal", "msg"=>"Can't load language !");
 
         exit();
      }

       echo json_encode(array("success"=>false,
         "error_type"=>"validate",
         "password"=>    (isset($pass_err))   ? $lang->translate($pass_err)  : null,
         "email"=>        (isset($email_err))       ? $lang->translate($email_err)      : null,
         "rules"=>    (isset($rules_err))   ? $lang->translate($rules_err)  : null);

      exit();   
}

Jest pełno tych samych ifów ale nie przerwie mi to działania po wykryciu jednego błędu tylko sprawdzi wszystkie. Jest jeszcze ten błąd o którym mówiłeś przy przekazaniu tablicy POST do funkcji. I Czy jest tutaj coś w czym filter_input() może mi pomóc/usprawnić rozbudować ? Bo ja muszę zobaczyć zastosowanie na przykładnie bo tak to tego nie widzę.

 

Edycja posta: A przekazanie argumentu przez referencje nie załatwi problemu ?

komentarz 13 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)
Nie załatwi, jeśli chcesz tak zrobić musiałbyś przekazać całą tablicę $_POST. A to z kolei ma mało sensu, bo do tej tablicy możesz się odwołać z dowolnego miejsca kodu (superglobalna).

Zrobienie tak jak robiłeś do tej pory spowoduje ostrzeżenie, zobacz sam: https://3v4l.org/Urumc

Jak już mówiłem, to wszystko zależy jak bardzo chcesz rozbudować taki kod. Mógłbyś np. działać tak, że podajesz tablicę gdzie kluczem jest nazwa pola, a wartością są reguły walidacji. Nie musiałbyś wtedy przekazywać danych do takiej funkcji, bo ona sama by sobie takowe odczytała mając tylko nazwę pola. Tylko no to jest trochę pisania i zabawy, zależy co i jak chcemy uzyskać.

Inny sposób: możesz wziąć coś gotowego, np. bibliotekę do walidacji albo cały framework. Tyle że to sugeruję bardzo ostrożnie, bo skoro masz problem z napisaniem czegoś takiego samemu, to średnio chciałbym podsuwać gotowca.
komentarz 14 stycznia 2018 przez kevin Mądrala (5,010 p.)

Czyli że filter_input ma w środku odwołanie do tablicy POST i po to jest pierwszy parametr. Trochę sam pomyślałem i filter_input jest dobre np. do sprawdzenia czy w przesłanej zmiennej jest tylko tekst bądź to jest liczba etc. Ale w moim przypadku skoro potrzebuję mieć w kodzie określony rodzaj błędu jaki wystąpił prz sprawdzeniu poprawności danych to filter_input mi chyba nie pomoże. O ile się nie mylę.

Co do tego o czym mówisz to chodzi Ci o coś takiego ?

	define("VAL_PASSWORD_DOS_NOT_EXIST",     		"e_validate_password_does_not_exist");
	define("VAL_PASSWORD_HAS_INCORRECT_CHARS",	"e_validate_password_has_incorrect_chars");
	define("VAL_PASSWORD_IS_TOO_SHORT",     		"e_validate_password_is_too_short");
	define("VAL_PASSWORD_IS_TOO_LONG",     		"e_validate_password_is_too_long");
	
	function validate_password( $key ) {

		$error_tag = null;
		
		if(( !isset($_POST[$key]) ) || ( empty($_POST[$key]) ) {

			$error_tag = VAL_PASSWORD_DOS_NOT_EXIST;
		} else {

			$pass_length = strlen($_POST[$key]);

			if ( !ctype_alnum($_POST[$key]) )
				$error_tag = VAL_PASSWORD_HAS_INCORRECT_CHARS;

			else if ( $pass_length < 5 )
				$error_tag = VAL_PASSWORD_IS_TOO_SHORT;

			else if ( $pass_length > 22 )
				$error_tag = VAL_PASSWORD_IS_TOO_LONG;
		}

		if( $error_tag ) // $error_tag != null
			return Array('success' => false, 'error_lang_tag' => $error_tag);

		return Array('success' => true, 'error_lang_tag' => null);
	}

Bez podawania reguł bo to umieszczę jako stałą bo aktualnie nie widzę sensu abym jakoś dynamicznie zmieniał długość hasła w trakcie działania strony.

Nie chcę żadnej biblioteki. Studiuję, pracuję ( ale nie w zawodzie programisty/informatyka ) i jak za pewien czas będę szukał pracy jako junior to chcę coś rozumieć i umieć a nie powiedzieć wykorzystałem framework do sprawdzania poprawności hasła i jestem PRO z tego powodu.

PS: Swoją drogą to nie wiem czemu ale boje się jakoś ładować do skryptu rzeczy które nie będą mu potrzebne ale tak chyba przesadnie. Funkcje sprawdzające poprawność danych np. ta którą przedstawiłem jest globalna, funkcja sprawdzająca poprawność email też jest globalna są też inne funkcje i też są globalne i każda jest w osobnym pliku. Dołączane do skryptu są tylko te które są mu potrzebne. Tak czytam Twoją wypowiedz i zastanawia mnie czy nie lepiej już to opakować w klasę w której będą te funkcje i wyglądać miałoby to tak:

class Validator {

	private $error_table = Array();

	public function have_error() {
		
		if(count($this->error_table) == 0)
			return false;		

		return true;
	}

	public function get_errors() { return $this->error_table; }
	public function throw_exception() {}
	public function clear_errors() { $this->error_table = Array(); }
	
	public validate_email( $email_key ) {

		// w przypadku błędu dodanie do $error_table z opisem błędu
		 $this->error_table['$email_key'] = 'Zły adres email !';
	}

	public validate_password( $password_key ) {

		// w przypadku błędu dodanie do $error_table z opisem błędu
		 $this->error_table[$password_key] = 'Podaj hasło !';
	}

	public validate_confirm_password ( $password_key, $confirm_password_key ) {

		// w przypadku błędu dodanie do $error_table z opisem błędu
		 $this->error_table[$confirm_password_key] = 'Różne hasła !';
	}
}

Użycie:

$valid = new Validator();

$valid->validate_email('email'); // key in $_POST[]
$valid->validate_password('pass'); // key in $_POST[]

if($valid->have_error()) {
	$errors = $valid->get_errors();

	//
}

 

komentarz 15 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)

Co do tego o czym mówisz to chodzi Ci o coś takiego ?

Akurat miałem na myśli coś na wzór:

$validator = [
    'name' => 'required|min:10|max:30',
    'email' => 'required|email',
    'postal_code' => 'required|regex:[\d{2}-\d{3}]'
];

To jest na przykładzie Laravela. Jako klucz jest nazwa pola do odczytania, jako wartość reguły walidacji oddzielone |. Na pewno z napisaniem czegoś takiego będzie znacznie więcej zabawy niż z prostą walidacją na warunkach, a więc jeśli piszesz coś małego to nie wiem czy ma to sens.

Nie chcę żadnej biblioteki. Studiuję, pracuję ( ale nie w zawodzie programisty/informatyka ) i jak za pewien czas będę szukał pracy jako junior to chcę coś rozumieć i umieć a nie powiedzieć wykorzystałem framework do sprawdzania poprawności hasła i jestem PRO z tego powodu

Wydaje mi się, że myślisz i dobrze i jednocześnie źle. Jak najbardziej, trzeba wiedzieć co jak działa i to rozumieć. Ale gdzie nie będziesz szukał pracy to zobaczysz w wymaganiach znajomość frameworka X, biblioteki Y i narzędzia Z. Jak już do tej pracy trafisz to nikt tam nie pisze wszystkiego od zera (chyba że faktycznie coś tego wymaga) tylko korzysta z dostępnych narzędzi. A więc należy wiedzieć co jak działa i o co chodzi, ale znajomość frameworka też jest potrzebna i na plus.

Przerobienie tego obiektowo jest spoko, już chyba gdzieś wyżej o tym wspomniałem. Tyle że nie wiem, czy akurat tak jak to zrobiłeś będzie ok - gdy pojawi się jeszcze 20 innych reguł walidacji to zrobisz je wszystkie w jednej klasie? To będzie słabe. Musiałbyś pomyśleć jak dalej to rozbudować. Tylko tu znów pytanie czy to ma sens - zależy jak dużą aplikację robisz, a jeśli dużą to czy ma sens pisanie tego od zera :)

komentarz 16 stycznia 2018 przez kevin Mądrala (5,010 p.)
$validator = [
    'name' => 'required|min:10|max:30',
    'email' => 'required|email',
    'postal_code' => 'required|regex:[\d{2}-\d{3}]'
];

Czyli tutaj widzę pętlę pobierającą klucz z tablicy $validator która jest argumentem funkcji. Po pobraniu klucz należy sprawdzić if'em jakiego typu powinny być danem if($current_key == 'email') validate_email($current_value);

Aby sprawdzić wymagania walidacji należy rozbić wartość którą przechowuje klucz funkcją explode('|', $current_value); ( to jest w pętli ) następnie rozbić jeszcze raz aby oddzielić parametr od wartości explode(':', $current_value); I mam coś na wzór tego.

Czy warto ? Zawsze to jakieś doświadczenie :) Ja potrzebuję sprawdzania poprawności adresu e-mail, hasła, powtórzenia hasła, akceptacji regulaminu (checkbox), mechanizmu captcha. Więc coś prostego mi wystarczy ponieważ najwięcej dylematów mam typu: Czy brnąć dalej w udoskonalanie kodu poprzez  dodanie reguł sprawdzania poprawności danych poprzez tablice (Twój przykład) czy zostawić funkcję w klasie tak jak przedstawiłem i wywoływać to co mi jest potrzebne.

Jeżeli miałbym n reguł to masz racje to nie było by poręczne. Więc dodał bym kolejną klasę z tymi regułami. Bądź osobną dla odpowiedniego typu danych do sprawdzenia i wywoływał bym z klasy głównej. Tego typu klasa powinna być Singletonem. Zgadza się ?

Masz rację, znajomość frameworków jest potrzebna. Aktualnie piszę rzeczy które mi się przydadzą ale chcę to tak napisać że jak pójdę na rozmowę o pracę to żebym miał z głową poukładane to i owo a nie wykrzaczył się na błędach typu ten o których mi powiedziałeś bo to nie sztuka byle jak zrobić i speca zgrywać.

komentarz 16 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)
No dokładnie tak, trzeba by przeiterować się po tej tablicy i np. przez explode wydzielić sobie reguły i odpowiednio walidować. Jeśli ma być to tak mała walidacja to również jestem zdania, że nie ma tu sensu nie wiadomo jak rozbudowany mechanizm. Czym powinna być tego typu klasa to pewnie zależy od szczegółów implementacji, akurat tutaj nie widzę konieczności użycia singletona. Pewnie nic się nie stanie, ale gdybyś stworzył nową klasę też by się nic nie stało moim zdaniem. A z singletonów bym po prostu nie nadużywał - stosował, gdy potrzebne.
komentarz 16 stycznia 2018 przez kevin Mądrala (5,010 p.)

Racja z tym singletonem.

Wracając do filter_input, są funkcje pochodne typu filter_var które bez problemu mogę wykorzystać do sprawdzenia poprawności adresu email. Tylko czy dobrze rozumiem ? Najpierw powinienem z takiego adresu usunąć wszystkie niedozwolone znaki za pomocą filter_var($email, FILTER_SANITIZE_EMAIL); później powinienem sprawdzić czy to co zwróci ta funkcja jest adresem email za pomocą if(filter_var($rezult_email, FILTER_VALIDATE_EMAIL) i porównać to z tym adresem z którego usuwałem niedozwolone znaki ponieważ w przesłanych danych jako adres email mogą znajdować się niedozwolone znaki pierwszy filtr zwróci string z dozwolonymi znakami jakie mogą być dla adresu email a niedozwolone znaki zostaną usunięte. Kolejny filtr sprawdza czy to co zostaje przekazane po usunięciu znaków jest adresem email jeżeli tak to zwróci true a ostatni if sprawdza czy z przesłanych danych nie zostały usunięte znaki tzn czy adres który trafił metodą POST/GET jest prawidłowy.

 

$result_email = filter_var($email, FILTER_SANITIZE_EMAIL); // Usuwa niedozwolone dla email znaki
		
if ( (filter_var($result_email, FILTER_VALIDATE_EMAIL) == false ) || ($email != $result_email) )
{
	return 'e_validate_incorrect_email';
}

 

komentarz 17 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)

Nie rozumiem po co tak kombinować. Dlaczego nie możesz zrobić po prostu tak: https://3v4l.org/3ZSOX? Po co usuwać niedozwolone dla emaila znaki? Jeśli ktoś tam takowe wpisze to jak dla mnie nie powinno to po prostu przejść walidacji, a nie pomagać (że jednak coś się samo usunie i jakoś przejdzie). 

komentarz 18 stycznia 2018 przez kevin Mądrala (5,010 p.)

Pan Misrosław Zelent w jednym odcinku prezentował takie rozwiązanie i ja sam do końca nie rozumiałem dlaczego tak przeprowadza walidację danych. Skoro znajdują się jakieś niedozwolone znaki to jasne jest to że nie przejdzie pozytywnie testu z filter_var.

komentarz 18 stycznia 2018 przez Arkadiusz Waluk Ekspert (287,550 p.)
No właśnie. I skoro po prostu nie przejdzie walidacji to jak dla mnie nie ma po co dodatkowo się zabezpieczać i modyfikować tego, co wprowadził użytkownik.

Podobne pytania

0 głosów
0 odpowiedzi 260 wizyt
pytanie zadane 26 października 2019 w PHP przez JSJerry Początkujący (260 p.)
0 głosów
1 odpowiedź 148 wizyt
pytanie zadane 30 stycznia 2019 w PHP przez zerakot Obywatel (1,870 p.)
0 głosów
1 odpowiedź 191 wizyt
pytanie zadane 18 czerwca 2018 w PHP przez Piotr Szramowski Użytkownik (860 p.)

92,455 zapytań

141,263 odpowiedzi

319,099 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...