» »

PHP in objektno programiranje

PHP in objektno programiranje

1
2
»

MrBrdo ::

technolog je izjavil:

spet temelji na security through obscurity.


Ne nunjno slabo. MS se zanaša na to, pa mu nič ne manjka.

To pa ne bo držalo, vsaj ne kar se OS teče. Windows ima veliko bolj advanced security prijeme, kot npr. OS X, mislim pa da sta tudi z Linux nekje tam-tam. Samo zato ker je closed-source še ne pomeni da se zanašajo na obscurty. Imam doma celo knjigo o security, ki naj bi jo morali prebrat vsi programerji ki delajo na MS, pa mislim da ima okoli 600 strani (v glavnem res debela, in kvalitetna knjiga).

To če si pa ti po svojih najboljših močeh napisal svoj FW pa še nič ne pomeni. Tudi vse te FW so ljudje pisali po svojih najboljših močeh, verjetno da nekateri od teh tudi boljši programerji kot ti, pa si med sabo preverjali, pa se še vedno najde kak bug. Se pa strinjam tisto kar si napisal ce je programer slab mu noben FW ne bo pomagal...
MrBrdo

Ziga Dolhar ::

kivi, napišeš lahko:

$this->id = (int) 1;
ali
$this->id = intval(1);
https://dolhar.si/

technolog ::

MrBrdo je izjavil:


To če si pa ti po svojih najboljših močeh napisal svoj FW pa še nič ne pomeni. Tudi vse te FW so ljudje pisali po svojih najboljših močeh, verjetno da nekateri od teh tudi boljši programerji kot ti, pa si med sabo preverjali, pa se še vedno najde kak bug. Se pa strinjam tisto kar si napisal ce je programer slab mu noben FW ne bo pomagal...


Vseeno je, če slabo napišeš FW IN aplikacijo, ali dobiš super FW ina napišeš SLABO aplikacijo. V obeh primerih si "slab" programer in rezultat bo slab. Sledi: če si slab programer, potem bo rezultat slab, če si pa dober programer, lahko napišeš FW sam, ki bo približno enako varen kot tvoja aplikacija.

Jst v lastnem FW vidim predvsem dve slabosti: Slaba kooperabilnost in potrata lastnega časa. Ampak jaz sem se odločil ZA kljub temu.

Zgodovina sprememb…

kivi113 ::

Ziga Dolhar je izjavil:

kivi, napišeš lahko:

$this->id = (int) 1;
ali
$this->id = intval(1);


Lovely. Točno to sem želel. Najlepša hvala.

technolog ::

Sploh ne vem zakaj bi si kdo žežel castat konstanto tipa X na tip X? :)

Ziga Dolhar ::

Ker je PHP loosely-typed jezik, ki programerju omogoča neskončno površnost, zaradi katere pride marsikdaj do težko rešljivih napak. Programer se težko zanese, da bo njegova spremenljivka ohranjala tip oziroma, če želi biti dosleden, mora redno preverjati tip spremenljivke, ki jo dobi kot input.

Zato nekateri vsaj poskušamo imitirati natančne jezike, ki zahtevajo izrecno deklaracijo tipa spremenljivke. Ker hvatanje krivin (veselo transformiranje, mnogokrat nevede, tipa spremenljivke s tem, ko nad njo izvajamo razne operacije) ni zgled dobrega programiranja in vodi v težje lovljenje bugov.

Hkratna eksplicitna definicija tipa spremenljivke (no, tip lahko dodamo še v samo ime spremenljivke - npr. intStarost, strIme) nas na to opominja in psihološko sili k boljši kodi.

PHP je toliko dober jezik, kolikor je dober programer. Je pa tak jezik, ki nudi potuho tudi najbolj obupnemu programerju.
https://dolhar.si/

technolog ::

Čak, čak. Zato ker je PHP losely typed jezik, ima tole spodaj smisel?

$var= (int) 1;

To je zame znak slabega programerja.

Zgodovina sprememb…

Ziga Dolhar ::

$var = (float)1
https://dolhar.si/

technolog ::

$var = 1.;

Hitreje (performančno) in krajše.

Sploh pa je bilo vprašanje, na katerega si odgovorjal tole:

Sploh ne vem zakaj bi si kdo žežel castat konstanto tipa X na tip X?

Zgodovina sprememb…

win64 ::

Zmotilo me je to:
 $query=mysql_query("SELECT * FROM $this->db_name WHERE user_id='" . $this->id . "'");

Nikjer ne preverjaš ali je v $this->id res številka in ne recimo ' and 1==1 ali še hujše '; delete from users

Na splošno se izogibaj sestavljenju sql stavkov v kodi. V phpju žal nimaš druge kot da to delaš, ampak lahko pa vsak parameter prej oviješ z mysql_real_escape(). To je ena osnovnih zaščit pred avtomatskimi napadi.

 $query=mysql_query("SELECT * FROM $this->db_name WHERE user_id='" . mysql_real_escape($this->id) . "'");

atlet ::

Al pa uporabiš prepare() -> glej pod sekcijo "Security" http://net.tutsplus.com/tutorials/php/p...
Enostaven program za fakturiranje -> www.quibi.net

technolog ::

Mene pa to ni zmotilo. Če on že validira $id pri vpisu v spremenljivko, tega ni treba početi še pri izpisu.

Seveda raje dvakrat kot nobenkrat. Vsaj v tem primeru.

technolog ::

Nikjer ne preverjaš ali je v $this->id res številka in ne recimo ' and 1==1 ali še hujše '; delete from users


To ta drugo itak ne bi delalo, ker mysql_query() podpira največ en stavek na klic.

Na splošno se izogibaj sestavljenju sql stavkov v kodi. V phpju žal nimaš druge kot da to delaš,


Kje drugje pa naj sestavi SQL stavek kot v kodi? V časopisu mogoče?
Drugače pa, tudi PHP pozna prepared statements.

Gandalfar ::

> Kje drugje pa naj sestavi SQL stavek kot v kodi? V časopisu mogoče?

Skozi ORM?

technolog ::

ORM pa ni v kodi?

Gandalfar ::

Bistveno tezje je delat glupe napake s SQL injectioni in razmisljat o specifikah tvoje baze.

Zgodovina sprememb…

win64 ::

atlet je izjavil:

Al pa uporabiš prepare() -> glej pod sekcijo "Security" http://net.tutsplus.com/tutorials/php/p...

Sem se narobe izrazil: php+mysqli tega ne podpirata.

kivi113 ::

class usr {

	public $id;
	public $data;
	public $db_name;

	function __construct($id = 0) {    
		
		$c = new config;
		$this->db_name = $c->user_db;	
		
		$def_id = (int) $this->getID();
		
		if (!is_int($id))
		{
			$this->id = $def_id;
		}
		
		$query = mysql_query("SELECT user_id FROM $this->db_name WHERE user_id='$id'");
		$num = mysql_num_rows($query);
		if ($num == 0)
		{
			$this->id = $def_id;
		}
		
		else
		{
			$this->id = $id;
		}
		
		$query=mysql_query("SELECT * FROM $this->db_name WHERE user_id='" . $this->id . "'");
		$data=mysql_fetch_assoc($query);
		$this->data = $data;
        } 
	


technolog je izjavil:


Sploh ne vem zakaj bi si kdo žežel castat konstanto tipa X na tip X?


Upam, da sem prav razumel prejšne vprašanje.

Ko konstruiram razred usr, v vrstici
function __construct($id = 0)

določam default vrednost ($id = 0), če je objekt kreiran brez podanega idja.
$u = new usr();


Če podam $id, ki ni integer, se kreira objekt z default vrednostjo.
Npr.
$u = new usr("Neprimeren string ali nevarna koda");
$u = new usr(0);

producira enak rezultat.

$def_id = (int) $this->getID();

V tej vrstici določim $def_id oz želeno default id vrednost. Ta vrednost se pa prebere preko metode getID(), ki kot argument vrne "current user id", ki je po defaultu integer, poleg tega pa je še eksplicitno določeno, da mora biti $def_id prav tako integer z vrstico, ki jo je prispeval Žiga Dolhar. Ne vem točno, kako bi (vlomilec) prišel čez vse te checke.. :)


Napisal sem tudi metodo, ki sem jo vtaknil v razred developer.
// fint aka force int, validacija integerja	
function fint($var = 0){
		$var = mysql_real_escape_string($var);
		$var = (int) $var;
		return $var;
	}


Ker sem to kodo pisal kasneje, je nisem uporabil pri konstruktu usr metode. Metoda je namenjena predvsem validaciji input integerjev. (int) funkcija v primeru težav (recimo da je vnešen string) vrne 0, kot default vrednost sem določil 0, je pa ta metoda namenjena predvsem escapanju vhodnih podatkov v aplikacijo.

namesto

$id = mysql_real_escape_string($_REQUEST["id"]);

zdaj zadevo dobim z

$dev = new developer;
$id = $dev->fint($_REQUEST["id"]);


Malo hitreje je, pa še spremenljivka je potem za sigurno integer, medtem ko iz forma po defaultu pride spremenljivka kot string. Te stvari so se tekom razvoja php, se mi zdi, celo malček spreminjale, od verzije do verzije.


Hmm. Kar se pa tiče mysql kode. Videl sem nekaj drugačnih načinov pisanja kode, vendar zaenkrat še nisem našel pravega razloga, zakaj bi pisal drugače. Do sedaj se je obneslo.

Bom pa malo preveril, kako se kodo piše skozi ORM, čeprav to malček kasneje? Kaj je bistvena prednost? Kako približno to izgleda?

Hvala za krasen feedback. Aplikacija napreduje, oz sem vedno bolj zadovoljen z delovanjem in s fleksibilnostjo. Trenutno imam 7 razredov:
4 za posamezne tabele (v kratkem bo dodanih še nekaj tabel)
class config
class developer
class display

Če bo potreba, jih bom v prihodnosti povezal z CodeIgniterjem, zendom, cakeom ali katerim drugim, a zaenkrat ni časa za to.

Zgodovina sprememb…

  • spremenil: kivi113 ()

Ziga Dolhar ::

// fint aka force int, validacija integerja
function fint($var = 0){
$var = mysql_real_escape_string($var);
$var = (int) $var;
return $var;
}


Vrstica z mysql_real_escape_string je tu povsem nepotrebna, ker ti bo castanje integerja naredilo razčefuk.
https://dolhar.si/

technolog ::

Nepotrebna in škodljiva - berljivi kodi. Za filtracijo integerja ne rabiš posebne fukcije...

(int)$var

oz. če hočeš uporabnika opozorit:

if ($var!=(int)$var)
echo 'Vpiši številko.';

Zgodovina sprememb…

Ziga Dolhar ::

is_numeric() :))

Oziroma:

is_int()
is_float() itd.
https://dolhar.si/

Zgodovina sprememb…

technolog ::

Edit:

Sem počekiral dokumentacijo in is_numeric čez spusti tud floate, kar moj primer ne.

is_int() pa čekira striktno za INT tip, sepravi string reprezentacijo številke zavrne (recimo to dobiš iz POST).

Če najdeš kako alternetivo za if ($var!=(int)$var), se priporočam.

Zgodovina sprememb…

kivi113 ::

Ziga Dolhar je izjavil:

// fint aka force int, validacija integerja
function fint($var = 0){
$var = mysql_real_escape_string($var);
$var = (int) $var;
return $var;
}


Vrstica z mysql_real_escape_string je tu povsem nepotrebna, ker ti bo castanje integerja naredilo razčefuk.



Oki. Naceloma take metode potem sploh ne potrebujem, ker je enostavno dovolj $var = (int) $var;

Potemtakem bi lahko najbolje prebiral inputane integerje lepo z

$var = (int) $_REQUEST["input"];

in ni treba nobenega mysql_real_escape_string, kot sem delal do sedaj.

Če prečekiram inpute in obenem objekti v __constructu prečekirajo, da so klicani z integerjem, potem bi moralo to zaenkrat zadostovati. Za validacijo stringov pa bom moral pač uporabit mysql_real_escape_string.

Za razlago, 'funkcija' (int) prisili neko zadevo v integer pod določenimi pogoji. Ker pa je to php, omogoča marsikatero telovadbo, npr:
$var = (int) "150x3x"; // $var = 150;
Če pa iz stringa ne more dobiti nobene številke, oz pride do neke težave, pa vrne rezultat 0:
$var = (int) "dsfijdso"; // $var = 0;

Zgodovina sprememb…

  • spremenil: kivi113 ()

technolog ::

Res je.

Vendar pazi - POST data je vedno string. Tako da
is_int($_POST['stevilo'])
bo vrnilo false.

Zgodovina sprememb…

Ziga Dolhar ::

Preverjanje inputa najbolje preverjaš takrat, ko ga "dobiš" oziroma "uporabiš" in se (še) ne moreš zanesti na njegovo legitimnost.

Moje pravilo čez palec:

1. Ko podatek prvič prestrežem iz zahtevka, preverim zgolj njegovo formalno pravilnost: isset() [ali obstaja oziroma je podan], ter strlen(trim()) za nize oziroma ustrezno matematično funkcijo (intval() ipd.) pri številčnih [preverjanje njegovega tipa].

2. Vsebinski preizkus opravim šele takrat, ko podatek podam naprej matičnemu objektu - npr. ali je integer ustrezne velikosti (npr. večji od 0) ...

3. Z "escape" funkcijami se ukvarjam šele, ko gradim SQL stavke (če jih že "na roko", kar jih praviloma ne).

Torej - če preverjanje ustrezno zastaviš, potem ni potrebno na prav vsakem koraku, če le veš, da bo podatek prišel iz zaupanja vredne verige. Na začetku verige formalni test, sredi verige materialni test, ob koncu verige - predaji podatka bazi - escapanje.

Je pa res, da se že vsaj 4 leta s programiranjem ne preživljam več.
https://dolhar.si/

kivi113 ::

Oki.

Kako pa gradiš SQL stavke, če ne "na roko"? Sam sem jih vedno gradil na roko, oz. redko s pomočjo kake aplikacije. Bom tudi sam zastavil, da bom od sedaj escapal stringe z mysql_real_escape_string sele pred samo uporabo queryja.

technolog ::

Na roko se načeloma smatra da skupi zlagaš stringe.

Ne na roko bi bilo pa prepared statements ali pa ORM. Google's your friend.

kivi113 ::

technolog je izjavil:

Na roko se načeloma smatra da skupi zlagaš stringe.

Ne na roko bi bilo pa prepared statements ali pa ORM. Google's your friend.


;)
Hvala.

Kako bi se pa pametno lotil tega, da bo app preprosto prevajati v druge jezike.
Zaenkrat sem kreiral objekt

class languages {
var $s = array(); 
var $si = array(0 => "", "welcome" => "Dobrodošli", "last_visit" => "Zadnji obisk");
var $en = array(0 => "", "welcome" => "Welcome", "last_visit" => "Last time you visited this page");
function __construct($lang = "en"){
	return $this->s = $this->$lang;
	}
}


Potem v templateju oz. v original fajlu zadeve kličem z
$l = new languages('si');
$title = $l->s["welcome"];


Lastnosti (property) $s ima kratko ime, zato, da je zadevo možno čim hitreje napisati.


Pa če še pokomentiram malo. Takole, ko čaram te objekte, sklepam, da so podobne stvari več ali manj že rešene v drugih frameworkih, je pa vsekakor fino, da jih še sam malo sestavljam, ker mi je bistveno bolj jasno sedaj, kaj pričakovati od frameworka. No, pa tudi objekte in sitakso objektov bistveno bolje razumem, kot pred tednom, tako da je tole kar win situacija so far. :)

kivi113 ::

Kar se pa tiče ORM
Object-relational mapping @ Wikipedia

Kar sem na hitro preletel in prebral, nisem uspel zaznati nekih bistvenih prednosti na kratki rok, za uporabo ORM. Na daljši rok verjamem, da bom moral marsikaj pogledati in delati v tej smeri. Po pravici povedano se mi sanja ne o ORM v tem momentu.

Prepared statements pa izgleda že bolj realna rešitev, ki se jo bom verjetno poslužil v kratkem.
http://www.ultramegatech.com/2009/07/us...

technolog ::

ORM tud jst odsvetujem. To je nasploh stvar, o kateri se stroka krega, a ga je vredno uporabljat ali ne. Slabosti je namreč kar nekaj, prednosti pa malo manj.

Gandalfar ::

Please elaborate. Torej, zakaj bi za kupe glupe kode okoli raznih form in validacij sploh razmisljal o svojih strukturah in constraintih.

Tiste tri querye, ki jih je pa treba kao optimizirat, pa bos ze mimo ORM-ja napisal.

Zgodovina sprememb…

technolog ::

Kar hočem povedat je to, da je ORM ena izmed stvari, kjer se programerji ne strinjajo, da je to "univerzalno dobro" in je zaradi tega malo kontroverzna tema. In ni primerno, da kar na lepe učke svetuješ to kar vsakomur. Treba je povedat da ni vse zlato kar se sveti.

Meni osebno izguba kontrole nad delovanjem SQL stavkov ne diši. Že sam SQL je zadost abstrakten, zakaj postavit še en layer na vrh? Za portability skrbi SQL standard, če se ga vendorji ne držijo, ni moj problem.

Ziga Dolhar ::

Ker (oziroma "če") želiš biti kompatibilen še s čim drugim kot z SQL-pogoni :).
https://dolhar.si/

Gandalfar ::

Saj C++ je tudi kontravrzen tistim, ki zagovarjajo, da se z asm pise bolj optimizirano kodo, pa se ta pristop se vedno ne priporca ljudem, ki pisejo poslovne aplikacije.

Nisi pa razlozil zakaj rabis totalni nadzor (vedno in povsod!) nad SQL-ja za vse dolgocasne forme, ki se ti v tipicni web aplikaciji zgodijo. Tipicno ti vsi ORM-ji omogocajo preskocit tisti layer, ce res mislis, da si pametnejsi od njih za tista dva bistvenga querya.

Zgodovina sprememb…

cobrica ::

Da ne odpiram nove teme igram se malo z predelavo CMS-a ki lavfa na Codeigniter. Zanima me na kakšen način bi lahko spremenil sting $config['language'] dinamično preko strani in ne preko notepada. Ima en config file kjer definiraš jezik ima pa tudi spisan cel Language.php file v katerem je sledeča koda:

function load($langfile = '', $idiom = '', $return = FALSE)
	{
		$langfile = str_replace(EXT, '', str_replace('_lang.', '', $langfile)).'_lang'.EXT;

		if (in_array($langfile, $this->is_loaded, TRUE))
		{
			return;
		}

		if ($idiom == '')
		{
			#$CI =& get_instance();
			$deft_lang = $this->session->userdata('selected_language');
			$idiom = ($deft_lang == '') ? 'slovene' : $deft_lang;
		}

		// Determine where the language file is and load it
		if (file_exists(APPPATH.'language/'.$idiom.'/'.$langfile))
		{
			include(APPPATH.'language/'.$idiom.'/'.$langfile);
		}
		else
		{
			if (file_exists(BASEPATH.'language/'.$idiom.'/'.$langfile))
			{
				include(BASEPATH.'language/'.$idiom.'/'.$langfile);
			}
			else
			{
				show_error('Unable to load the requested language file: language/'.$idiom.'/'.$langfile);
			}
		}

		if ( ! isset($lang))
		{
			log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile);
			return;
		}

		if ($return == TRUE)
		{
			return $lang;
		}

		$this->is_loaded[] = $langfile;
		$this->language = array_merge($this->language, $lang);
		unset($lang);

		log_message('debug', 'Language file loaded: language/'.$idiom.'/'.$langfile);
		return TRUE;
	}


Jezik definira na ta način $deft_lang = $CI->config->item('language');, torej prebere ga iz datoteke config.php, rad bi pa da ga prebere ali iz baze ali pa iz sesiona, sicer sem probal iz sesiona na ta način $deft_lang = $this->session->userdata('selected_language');, vendar ne deluje, zgleda da se ne da klicat objekta znotraj drugega objekta,ali pač? Nimam namreč veliko izkušenj še z objektnim programiranjem, zato se še lovim. Ali se da recimo tudi mogoče objekte ki so definirani spreminjati v stilu $deft_lang = $this->session->userdata('selected_language') = 'jezik';? Sicer to ne deluje ampak je kakšna možnost v tej smeri?

kivi113 ::

A lahko pokažeš še v config fileju, kako se kliče ta medota (oz. funkcija?) load(); Pomoje se odgovor na tvoje vprašanje skriva v config.php fajlu in ne v language.php fajlu. Oz. saj ne razumem točno, kaj je problem :) A to funkcijo load() si sam pisal in ne deluje, ali deluje?

v 34. vrstici imaš napisano
if ( ! isset($lang))


Tu preverjaš, če je nastavljena spremenljivka $lang, ki se do takrat v funkciji (metodi?) še ni pojavila. Razen če sem kaj spregledal. Ker meni izgleda, da se ti potem funkcija log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile); kliče vsakič. Lahko, da sem kaj spregledal..

Drugače je pa tudi mene zanimalo, kako se lahko naredi objekt znotraj objekta. Spodaj sem definiral 2 razreda: avtomobil in primer.


class avtomobil {

    public $znamka;
    public $prostornina;
    function __construct(){
        $this->znamka = "BMW";
        $this->prostornina = "2499 ccm";
    }
}
class primer
{
    public $avto;
    function __construct(){
        $objekt = new avtomobil;
        $this->avto=$objekt;
    }
}


Za prikaz potem kreiram variable $var in izpišem znamko avtomobila:

$var = new primer();
echo $var->avto->znamka;

Zgodovina sprememb…

  • spremenil: kivi113 ()
1
2
»


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[UWP] [C#]

Oddelek: Programiranje
423957 (1987) BivšiUser2
»

[C#] Entity Framework

Oddelek: Programiranje
6880 (711) frudi
»

Izšel PHP 5.5

Oddelek: Novice / Ostala programska oprema
114863 (3553) technolog
»

PHP povezava z Mysql

Oddelek: Izdelava spletišč
16842 (687) snooze77
»

[php, mysql] sortiranje izpisa iz baze

Oddelek: Izdelava spletišč
262556 (2075) Binji

Več podobnih tem