NOVINKA: Získej 40 hodin praktických dovedností s AI – ZDARMA ke každému akreditovanému kurzu!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
MichalOškera:17.1.2020 11:44

Zdravím,
učím sa objektovo programovať a mam menší problém a neviem nájsť nikde riešenie, kde robím chybu určite to len zle hladam na internete, ale prosím Vás o radu kde robím chybu alebo či je to celé zle.

Kód mi vypisuje chybu: Uncaught Error: Call to a member function vek() on null in

Zkusil jsem:

class Uzivatel{

        public function meno($meno){
                $this->meno = $meno;
        }

        public function vek($vek){
                $this->vek = $vek;
        }

        public function vaha($vaha){
                $this->vaha = $vaha;
        }

        public function vypis(){
                return $this->meno."-".$this->vek;
        }
        public function VypisVaha(){
                return $this->meno."-".$this->vaha;
        }

}


$Uzivatel= new Uzivatel;
echo $Uzivatel->meno('Jozo')->vek('14')->vypis;
echo $Uzivatel->meno('Tomas')->vaha('85')->VypisVaha;

Chci docílit: Jozo - 14
Tomas - 85

 
Odpovědět
17.1.2020 11:44
Avatar
Odpovídá na MichalOškera
Martin Konečný (pavelco1998):17.1.2020 14:21

Ahoj, abys mohl dělat tzv. fluent interface (zřetězení metod), musíš v těch set() metodách vracet $this, tj.

public function vek($vek){
        $this->vek = $vek;

        return $this;
}

A potom ještě vypis() a VypisVaha() jsou metody, tedy ti chybí závorky, takhle by se to snažilo vypsat atributy $vypis a $VypisVaha a ty pochopitelně neexistují.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
17.1.2020 14:21
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na Martin Konečný (pavelco1998)
MichalOškera:23.1.2020 15:03

Ďakujem za radu... a keby som ešte mohol trošku otravovať skúsil som napisať si kód na login a overenie uživatela... A chcem poprosiť čo je v nom zle kód funguje len myslím ako či je dosť bezpečný....

Data pred tým ako uložim do MySQL 8.0 šifrujem zatial cez base64 ale šifrovanie mam zvlášť v triede, aby som to potom mohol vylepšiť nejaké lepšie šifrovanie.
Trieda Data encode vracia 2 hodnoty jednu šifrovanú, ktorá je aj v DB a druhú bez base64 ale skontrolovanú cez htmlspecialchars

Trieda Miss len vykresluje chyby čo uživatel nesplnil
Trieda Form vykresluje formular
Trieda MySQL pripaja ma cez PDO na databázu udaje vkladam cez bindValue.
Trieda Lang načitáva chybove hlašky adť.

Tu je kód:

class Admin{

        private $Data;
        private $MySQL;
        private $Miss;
        private $Form;
        private $error;


        public function __construct(){
                session_start();

                $this->Data  = new Data;
                $this->MySQL = new MySQL;
                $this->Miss  = new Miss;
                $this->Form  = new Form;
                $this->Email = new Email;
                $this->Lang  = new Lang;

                $this->idUser = $_SESSION['Admin_id'];

                $this->url = $_SERVER['REQUEST_SCHEME']."://".$_SERVER['SERVER_NAME'];
        }




        public function login(){

                if($_SERVER['REQUEST_METHOD'] == 'POST')
                {

                        // ENCODE DATA
                        $email = $this->Data->encode($_POST['email']);
                        $pass  = $this->Data->encode_password($_POST['pass']);


                        /// IF VALIDATE FILTER
                        if(!filter_var($email['decode'], FILTER_VALIDATE_EMAIL)){
                                $error[] = $this->Lang->admin(1);
                        }

                        if(strlen($pass['decode']) < 5){
                                $error[] = $this->Lang->admin(2);
                        }

                        if(count($error) == 0){
                                $user  = $this->MySQL->table('admin')->where('email="'.$email['encode'].'" && pass="'.$pass['encode'].'"')->select()->single();
                        }

                        if(empty($user['id'])){
                                $error[] = $this->Lang->admin(3);
                        }


                        // LOGIN
                        if(count($error) == 0){

                                session_start();

                                $code = md5($user['id'].$this->url.$user['email'].$user['pass'].time());

                                $_SESSION['id_User'] = $this->Data->encode_session($user['id']);
                                $_SESSION['login']       = $this->Data->encode_session(1);


                                setcookie('code_user', $code, time() + 1800, "/");

                                $this->MySQL->table('admin')->where('id='.$user['id'].'')->update($values = array("code" => $code));

                                header("Location:".$this->url."/rs/admin/", true, 301);
                                exit();

                        }else{
                                $news = $this->Miss->error($error);
                                $form = $this->Form->login($input = array("email" => $email['decode']));
                        }

                }else{
                        $news = null;
                        $form = $this->Form->login(null);
                }

         return array($form, $news);
        }



        public function autorizacia(){

                session_start();

                $login   = $this->Data->decode_session($_SESSION['login']);
                $id_User = $this->Data->decode_session($_SESSION['id_User']);

                if(filter_var($login, FILTER_VALIDATE_INT) && $login == 1){

                        $user = $this->MySQL->table('admin')->where('id="'.$id_User.'"')->select()->single();

                        if(filter_var($user['id'], FILTER_VALIDATE_INT) && !empty($user['id'])){

                                if($user['code'] == $_COOKIE['code_user']){

                                        $code = md5($user['id'].$this->url.$user['email'].$user['pass'].time());
                                        $this->MySQL->table('admin')->where('id='.$user['id'].'')->update($values = array("code" => $code));

                                        setcookie('code_user', $code, time() + 1800, "/");

                                        $autorizacia = 1;
                                }else{
                                        $autorizacia = 0;
                                }
                        }else{
                                $autorizacia = 0;
                        }
                }else{
                        $autorizacia = 0;
                }

                if($autorizacia == 0){
                        header("Location:".$this->url."/rs/", true, 301);
                        exit();
                }

        }
}
Editováno 23.1.2020 15:06
 
Nahoru Odpovědět
23.1.2020 15:03
Avatar
Odpovídá na MichalOškera
Martin Konečný (pavelco1998):23.1.2020 18:14

Ahoj, těžko posuzovat takhle z vytrženého kódu celé aplikace, ale na letmý pohled mi některé podmínky přijdou špatně testované, třeba

$user = $this->MySQL->table('admin')->where('id="'.$id_User.'"')->select()->single();

if(filter_var($user['id'], FILTER_VALIDATE_INT) && !empty($user['id'])) {
        ...
}

Nevím, co a jak přesně vrací ta metoda "single()", ale řekl bych, že když to uživatele najde, vrátí to pole s informacemi, a pokud ne, tak to vrátí FALSE nebo NULL. V takovém případě by ta podmínka byla lepší takhle:

if $user !== FALSE) {
        ...
}

ale záleží, co ta metoda vrací :D

Jinak jsou tam věci, které by v té třídě být neměly, jako třeba přesměrování, ale tohle je sporné říkat, jelikož bys takhle postupně stavěl celý webový framework :D Minimálně ale bych z těch tříd jen něco vracel - třeba pole chyb nebo tak něco, a v řídícím skriptu až pak podle toho řešil, jestli se má přesměrovat, něco zobrazit uživateli (chybová hláška, ...) atd.).

Řídící skript je ta část kódu, kde voláš tu metodu login() nebo autorizacia(), tedy např.

$admin = new Admin();

if ($_POST) {
        $result = $admin->login();

        if (empty($result["chyby"])) {
                echo "Přihlášení úspěšné";
        } else {
                echo "Při přihlášení vznikly chyby";
        }
}
Nahoru Odpovědět
23.1.2020 18:14
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Martin Konečný (pavelco1998):23.1.2020 18:24

Ještě co se týká té "bezpečnosti", tak nevím, co přesně děláš za aplikaci, ale zdá se mi zbytečné něco šifrovat a ještě k tomu přes base64, ze kterého snadno zpětně ta reálná data získáš. Data v databázi se obvykle ukládají v surovém stavu, jen hesla se hashují, aby při případném ukradení dat nikdo ta hesla uživatelů nezjistil.

K čemu potřebuješ mít sloupec "code"?

Nahoru Odpovědět
23.1.2020 18:24
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
MichalOškera:23.1.2020 18:37

Ahoj,
Single vracia ak nič nenájde prázdnu premenu. Ked niečo nájde vráti

Array ( [id] => 1 [email] => bWljaGFsb3NrZXJhQGdtYWlsLmNvbQ== [pass] => 27008213f0fbf8e4afe109d27887dc8b
=> a5cba0052a799208113ac519a0c14f29 )

A prečo je lepšia podmienka $user !== FALSE ako keď kontrolujem pomocou filter_var
a zistujem ID či je číslo INT?

Som čítal, že dobre je mať plávajúci kód. Code mám vložený v cookie a v databáze. cookie má platnosť len 30 minut vždy pri obnove stránky sa predlžuje a mení sa code v DB aj cookie.

 
Nahoru Odpovědět
23.1.2020 18:37
Avatar
MichalOškera:23.1.2020 18:44

Viem že base64 neslúži na ochranu dát. Aplikoval som ho kvôli tomu, že dokáže nahradiť špecialne znaky ako ' " toto riešenie som našiel na konkurečnej stránke a keby bolo lepšie riešenie ako toto ošetriť, aby pri zápise napr do DB kód nebol narušený som za... Som samouk a programovanie mam zatiaľ len ako zábavu...

 
Nahoru Odpovědět
23.1.2020 18:44
Avatar
Odpovídá na MichalOškera
Martin Konečný (pavelco1998):23.1.2020 18:44

Ta "prázdná proměnná" znamená konkrétně co? NULL, FALSE, "", ... ? Je to lepší proto, že když to nevrací pole, tak není dobré psát $promenna["neco"], protože to jde psát jen u polí a u řetězců. Tedy tím zbytečně riskuješ nějakou chybu :D a v databázi ID asi nebudeš mít něco jiného než číslo (zvlášť pokud je sloupec INT a AUTO_INCREMENT), takže je ta podmínka na kontrolu čísla zbytečná už z principu.

To "code" se mi zdá zbytečné, jelikož to, že je uživatel přihlášen, řeší session. Tyhle dočasné "tokeny" (code) se používají obvykle spíš jako taková autorizace/au­tentizace, pokud nejde použít session (třeba nemáš registrované uživatele, ale chceš něco zobrazit jen jednomu návštěvníkovi).

Nahoru Odpovědět
23.1.2020 18:44
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na MichalOškera
Martin Konečný (pavelco1998):23.1.2020 18:46

Data do DB je zvykem ukládat v takovém stavu, v jakém přijdou :) tzn. uvozovky, apostrofy a jiné znaky by neměly být problém, ty ošetříš až při výpisu, ne při zápisu. Tedy třeba funkci htmlSpecialChars() použiješ až když ten text na webu vypisuješ, ne už když ukládáš do databáze.

Nahoru Odpovědět
23.1.2020 18:46
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
MichalOškera:23.1.2020 18:57

Vracia hodnotu NULL. Ďakujem idem to zmeniť tie podmienky.

  • Htmlspecialchars používam.
  • Pridávam hodnoty do DB pomocou bindValue
bindValue(':'.$name, $value, $type);

a napr. pri $value bude čiarka tak zrazu vo funkcií budem mať 4 premné nie len 3. Alebo rozmýšlam zle?

 
Nahoru Odpovědět
23.1.2020 18:57
Avatar
Odpovídá na MichalOškera
Martin Konečný (pavelco1998):23.1.2020 19:10

Pokud ve $value bude čárka, tak to nic nezmění na volání funkce - je to stejné, jako kdybys napsal ručně třeba

funkce("hodnota, která, má, čárky")

Stále jde jen o jeden parametr, ne o čtyři, tedy to je v pořádku :)

Nahoru Odpovědět
23.1.2020 19:10
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
MichalOškera:28.1.2020 19:18
$value = "hodnota, ",ktera ma, čarky";

Tak táto hodnota už bude zlá? alebo je jedno že može tam byť hoci jaký špecialny znak a bude to fungovať?

 
Nahoru Odpovědět
28.1.2020 19:18
Avatar
Odpovídá na MichalOškera
Martin Konečný (pavelco1998):28.1.2020 19:30

Tohle ti hodí chybu, řetězec je potřeba obalit do uvozovek nebo apostrofu. Pak je možné řetězce spojovat tečkou nebo čárkou, např.

$value = "hodnota, " , ", která má čárky";

Ale co se stane v příkladu u tebe, tak máš řetězec "hodnota, ", potom spojovací znak (čárku) a pak nějaké "ktera", což se PHP asi pokusí vyhodnotit jako konstantu a hodí ti to chybu :D nebo to prostě hodí chybu, že to nedokáže zpracovat.

Nahoru Odpovědět
28.1.2020 19:30
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na Martin Konečný (pavelco1998)
MichalOškera:29.1.2020 10:57

Je na to nejaká špecialna funckia alebo len str_replace

Editováno 29.1.2020 10:58
 
Nahoru Odpovědět
29.1.2020 10:57
Avatar
Nahoru Odpovědět
29.1.2020 12:30
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:29.1.2020 15:26

Spravne, na co? Ceho presne chces docilit a proc?

$a = '1'; $a = '2'; $a = '3';
$str = $a . $b . $c; echo $str.'<br>'; //123
$str = '123'; echo $str.'<br>';
$str = '1' . '2' . '3'; echo $str.'<br>';
$str = "12$c"; echo $str.'<br>';
$str = '1' . '2' . 3; echo $str.'<br>';  // tohle mozna vypise chybu
$num = 1 + 2 + 3; // 6
$str = "123"; // 123
$str = "1, 2, 3"; // 1, 2 ,3
$str = "\"1\", \"2\", \"3\""; // "1", "2" ,"3"
$str = '"1", "2" ,"3"'; "1", "2" ,"3"
$str = '\'1\', \'2\', \'3\''; // '1', '2' ,'3'
$str = "1
2
3"; // v html: 123, v source code: 1
2
3
$str = "1\n2\n3"; // v html: 123, v source code: 1
2
3 // totez jako prechozi priklad
$str = <<<EOF
"1" '2' 3
EOF; echo $str;
// vypise radek + "1" '2' 3 + radek do source code, html zobrazi mezera + text + mezera

echo '123';
var_dump(123);
var_dump('123');
var_dump('1', '2', '3');
var_dump('1'. '2'. '3');
var_dump($a, $b, $c);

// funkce pro nahrazeni
preg_replace
str_replace
strtr
htmlescapechars - vypis do html kodu
addslashes
nl2br - nahrazeni radkovani \n za <br> pro html
...

Das si

php/net/preg_replace

Podivas se co je pod nadpsem See also. A totez pro ostatni. Spoustu tech funkci nahrazuje ruzne znaky nebo tebou zadane, jakymsi odlisnym zpusobem. A dalse se podivas na ruzne priklady pouziti, co tam online jsou. Po stazeni dokumentace k php mas size zakladni verzi, ale priklady od uzivatelu jsou casto vetsim prinosem nez priklady od autora.

Univerzalni, ale pomalejsi zpusob je preg_replace.

Tve zadani je nejasne, je asi dalsich 300 zpusobu, prikladu, ktere je dobre znat. Neni cas si vsechny vybavit a jeste marnit cas jejich vypisovanim :)

Editováno 29.1.2020 15:26
 
Nahoru Odpovědět
29.1.2020 15:26
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:29.1.2020 15:40
$str = <<<EOF
"1" '2' 3
EOF;

Jo, u tohoto zapisu tam muze byt jakykoliv text. A asi to tam to odradkovani neprida, nejsem si ted jist.
Tam jde o to, ze ten text nahrazuje uzovozky a cely string je ukoncen prave tim textem. cili treba EOF (end of file). Nebo treba jenicek. Zalezi i na velikosti pismen

$str = <<<jenicek
"1" '2' 3
JENICEK
jenicek;

Vyhoda toho zapisu je prave v tom, ze nemusi kvuli php escapovat uvozovky.

Jo, a dalsi vec, kdyz treba pres php vypisujes js kod, tak se tam pouziva jeste escapovani uvozovek, protoze to jsou pravidla html

$str = ' <tag onclick="alert(\"123\");">';
echo $str;
$str = ' <tag onclick="alert(' . preg_quote('"123"'. ');">';
echo $str;
echo htmlescapechars($str);

Ale, jak jsem psal, univerzalne muzes pouzit preg_replace temer na vsechno. Ja osobne jsem si vytvoril vlastni funkce, ktere jsem nazval jednotne escape.
Protoze mne nebavilo stale hledat v manualu a zjistovat, cim se co ma escapovat. Kdyz znam pravidla a vim, co chci videt na vystupu, tak potom s preg_replace je to hracka.

function escapeHtml($str) {return htmlescapechars($str);}
function escapeUrl($url) {return urldecode($url);}
function my_nl2br($str) {return nl2br($str);}
function my_nl2br2($str) {return preg_replace('~\\n~', '<br>', $str);}
 
Nahoru Odpovědět
29.1.2020 15:40
Avatar
MichalOškera:29.1.2020 17:04

Aby som napr. odstranil alebo duplikoval tie apostrofy ono to bude potom aj fungovať

str_replace (' " ', ' """ ' , $text);
Editováno 29.1.2020 17:04
 
Nahoru Odpovědět
29.1.2020 17:04
Avatar
MichalOškera:29.1.2020 17:14

Idem zapisať hodnotu do MySQL pomocou formulára a v inpute bude text + nejaký apostrof tak pri zápisu PDO mi kód to rozdelí nie? PHP bude to rátať ako ďalšiu hodnotu

 
Nahoru Odpovědět
29.1.2020 17:14
Avatar
Odpovídá na MichalOškera
Martin Konečný (pavelco1998):29.1.2020 17:42

PHP to nevadí, vadí to max databázi v momentě, kdy bys to tam strkal přímo do dotazu, např.

$jmeno = "moje jméno s 'apostrofy'";

$pdo->query("INSERT INTO uzivatel VALUES ('{$jmeno}')");

ale pokud používáš parametrizované dotazy, což bys měl, tak to nevadí:

$jmeno = "moje jméno s 'apostrofy'";

$query = $pdo->prepare("INSERT INTO uzivatel VALUES (?)");
$query->execute(array($jmeno));
Nahoru Odpovědět
29.1.2020 17:42
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:29.1.2020 20:41

Viz Martin, pdo ma na to sve mechanizmy. Proto se nepouzivaji starsi ovladace mysql_query.
V pdo mas 2 moznosti. Bud si sql dotaz sestavis sam, jako string. A nebo pouzijes pomocne funkce, jako je prepare, bind, bindValue a pod, ktere maji escapovani vestavene.

$query = "INSERT INTO uzivatel VALUES ('".$jmeno."')";
$pdo->query($query);

Neco takoveho bys mel pouzit jen v pripade, ze vis, co delas. Ze treba uz nejakym filtrem predem z te hodnoty ty apostrofy odstranis nebo to prevadis na integer cislo. Coz je treba muj pripad.
Ale, kdyz potrebuji neco slozitejsiho, tak pouziti podobnou funkci, jako jsi udelal, mam ji nazvanou jako escapeSqlValue (pro data) nebo escapeSqlKey (pro jmena tabulek a sloupcu). jde o to, ze pouzivam casto radu fitrovani a pouzivam to v poli, tak to cyklem escapuji a nemusim resit slozite podminkovani kvuli bindValue. Nektere fitrly treba uzivatel nepouzije a tak.

 
Nahoru Odpovědět
29.1.2020 20:41
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 21 zpráv z 21.