[php] Databaseclass

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik wil een database class maken zodat alle foutafhandelingen etc... automatisch gebeuren.

De class maken en de foutafhandeling & debug modus maken is geen probleem wel hoe ik de class moet gebruiken.

Moet ik nu elke class die gebruik wil maken van een database deze database class laten include en een object aanmaken van database?
Eerder stelde iemand mij voor om elke klas extends database te doen maar dit lijkt mij een slecht idee want dan verlies ik ongeveer elk voordeel met het gebruik van classen...

Acties:
  • 0 Henk 'm!

  • DEiE
  • Registratie: November 2006
  • Laatst online: 16-08 19:21
Wellicht kan je eens kijken naar het Singleton design pattern: http://en.wikipedia.org/wiki/Singleton_pattern

Acties:
  • 0 Henk 'm!

  • _JGC_
  • Registratie: Juli 2000
  • Laatst online: 10:00
Sowieso zou ik van je database object een singleton maken, dus slechts 1 instantie van laten bestaan. Je wilt nml niet per class een nieuwe databaseconnectie maken.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Als je zo een singleton designpattern gebruik voor de databaseclass. Moet je dan nog steeds in elke class-file de database-file include maar alleen geen object meer van maken?

Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 07:04

Saven

Administrator

PDO? :) Zit ook een leuke exception handler bij

Acties:
  • 0 Henk 'm!

  • DEiE
  • Registratie: November 2006
  • Laatst online: 16-08 19:21
Je moet zorgen dat je class bij de database-class kan inderdaad, door de singleton hoef je alleen niet in elke class een instantie te maken.
Saven schreef op zaterdag 19 december 2009 @ 14:15:
PDO? :) Zit ook een leuke exception handler bij
PDO werkt ook mooi, dan hoef je ook niet al je invoer te escapen maar dat kan PDO doen dmv prepared statements :)

[ Voor 49% gewijzigd door DEiE op 19-12-2009 14:18 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Maar als de claas elke keer opnieuw wordt geïnclude, maak ik dan ook niet telkemaal opnieuw een database verbinding?

Acties:
  • 0 Henk 'm!

Verwijderd

Hou toch eens op over singletons als het om database objecten gaat! Je kunt makkelijk behoefte hebben om meerdere databases te gebruiken voor een request. Leer gewoon goed programmeren in plaats van slechte ideeën om te zetten in slechte oplossingen.
Verwijderd schreef op zaterdag 19 december 2009 @ 14:19:
Maar als de claas elke keer opnieuw wordt geïnclude, maak ik dan ook niet telkemaal opnieuw een database verbinding?
Ga het eens gewoon proberen? Het helpt als je zelf begrijpt wat er gebeurt in plaats van het aan anderen moeten vragen.

[ Voor 41% gewijzigd door Verwijderd op 19-12-2009 14:20 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Waarom krijg ik hier geen getallen terug van connectioncount en querycount?

test1.php
PHP:
1
2
3
4
5
6
7
8
9
10
11
<?php
session_start();
$_SESSION['connectioncount'] = 0;
$_SESSION['querycount'] = 0;
include('test2.php');
include('Database.php');
$pDatabase = Database::getInstance();
$pDatabase->query();
echo $_SESSION['connectioncount'];
echo $_SESSION['querycount'];
?>


test2.php
PHP:
1
2
3
4
5
6
<?php
session_start();
include('Database.php');
$pDatabase = Database::getInstance();
$pDatabase->query();
?>


database.php
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
session_start();
class Database
{
    // Store the single instance of Database
    private static $m_pInstance;

    // Private constructor to limit object instantiation to within the class
    private function __construct()
    {
        echo "Constructor called<br />\n";
                $_SESSION['connectioncount']++;
    }

    // Getter method for creating/returning the single instance of this class
    public static function getInstance()
    {
        if (!self::$m_pInstance)
        {
            self::$m_pInstance = new Database();
        }

        return self::$m_pInstance;
    }

    // Test function to simulate a query
    public function query()
    {
                $_SESSION['querycount']++;
        echo "Running query on database conenction...<br />\n";
    }

}
?>

Acties:
  • 0 Henk 'm!

  • DEiE
  • Registratie: November 2006
  • Laatst online: 16-08 19:21
Waarschijnlijk omdat je 2x hetzelfde bestand include (ook al is het uit een ander bestand). include_once gebruiken ipv include lost dit op.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Inderdaad dat was het probleem en de test setup geeft ook meteen antwoord op mijn vraag.

Acties:
  • 0 Henk 'm!

  • Manuel
  • Registratie: Maart 2008
  • Laatst online: 14-09 14:15
Verwijderd schreef op zaterdag 19 december 2009 @ 15:00:
Inderdaad dat was het probleem en de test setup geeft ook meteen antwoord op mijn vraag.
Dit kan je voorkomen door error_reporting(E_ALL); bovenaan te zetten of de server instellingen aanpassen zodat je de waarschuwingen zelf ook ziet. Graag wel zelf wat proberen voordat je om help gaat roepen. ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Het probleem was vooral de session_start in Database.php. Of eigenlijk een totaal gebrek aan ervaring en inzicht, en het feit dat je door mensen die alles singletons willen maken de verkeerde kant op wordt gestuurd.

Waarom gebruik je hier in godsnaam sessions voor variabelen die eigenlijk properties van de Database class hadden moeten zijn? Hoe interessant is het hoeveel queries iemand per session doet? Het aantal queries per request is veel boeiender.

Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 10-09 22:45
Wat je wel kan doen is 1 database klasse maken, maar daarnaast nog een Query klasse.

Die DB klasse is dan een singleton, en die Query klasse kan je dan meerdere keren gebruiken in je framework zonder dat je meerdere DB sessies opent.

Acties:
  • 0 Henk 'm!

  • DEiE
  • Registratie: November 2006
  • Laatst online: 16-08 19:21
Megamind schreef op zaterdag 19 december 2009 @ 15:08:
Wat je wel kan doen is 1 database klasse maken, maar daarnaast nog een Query klasse.

Die DB klasse is dan een singleton, en die Query klasse kan je dan meerdere keren gebruiken in je framework zonder dat je meerdere DB sessies opent.
Cheatah doelde er juist op om van de Databaseklasse géén singleton te maken, omdat je zo meerdere databases kan gebruiken, dit is met een singleton niet mogelijk (ook al zijn meerdere databases hoogstwaarschijnlijk niet van toepassing op het probleem van de TS)

Acties:
  • 0 Henk 'm!

  • Ssander
  • Registratie: December 2009
  • Laatst online: 12-06-2023
Verwijderd schreef op zaterdag 19 december 2009 @ 15:05:
Het probleem was vooral de session_start in Database.php. Of eigenlijk een totaal gebrek aan ervaring en inzicht, en het feit dat je door mensen die alles singletons willen maken de verkeerde kant op wordt gestuurd.

Waarom gebruik je hier in godsnaam sessions voor variabelen die eigenlijk properties van de Database class hadden moeten zijn? Hoe interessant is het hoeveel queries iemand per session doet? Het aantal queries per request is veel boeiender.
Ervaring en inzicht kun je niet verwachten van iemand die net begint te programmeren, beetje een nutteloze reactie. Daarbij zeg je nu al twee keer dat je het niet eens bent met de Singleton oplossing zonder zelf met een beter alternatief te komen, dus vandaar mijn vraag: wat stel jij dan voor?

En het lijkt mij dat die $_SESSION variabelen gewoon gebruikt worden om even te testen.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
In mijn geval ga ik maar gebruik maken van 1 database dus is het niet zo een probleem. En dat vuile gedoe met sessies was maar even een setup om te kijken wat het nu zou doen. Of het elke keer dat ik het include een nieuwe connectie zou openen enz. Nu weet ik daar het antwoord op :)

Echter nog even een vraagje:
Moet ik nu elke variable in Database static maken? Of is dit enkel vereist voor Instance?

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
class Database {
    //Instance van Database
    private static $Instance;

    // Private constructor, kan niet worden geinstancieerd.
    private function __construct(){ }

    //Getter method for creating/returning the single instance of this class
    public static function getInstance()
    {
        if (!self::$Instance)
        {
            self::$Instance = new Database();
        }
        return self::$Instance;
    }

    //Query
    public function query()
    {
    
    }
}
?>

Acties:
  • 0 Henk 'm!

  • DEiE
  • Registratie: November 2006
  • Laatst online: 16-08 19:21
Alleen de instance en de getinstance, maar dit kon je ook lezen bij de link die ik gaf in mijn eerste post. Lees deze nog eens door, dan snap je ook waarom!

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Ssander schreef op zaterdag 19 december 2009 @ 15:13:
[...]


Ervaring en inzicht kun je niet verwachten van iemand die net begint te programmeren, beetje een nutteloze reactie. Daarbij zeg je nu al twee keer dat je het niet eens bent met de Singleton oplossing zonder zelf met een beter alternatief te komen, dus vandaar mijn vraag: wat stel jij dan voor?
Moet je perse met een alternatief komen voor iets wat inherent gewoon slecht opgezet is? Singletons zij gewoon niet handig als je met meerdere dbases werkt.

En als je echt zonodig een alternatief zoekt en het zelf niet kan bedenken dan verwijs ik je graag naar de vele dbase classes die er gewoon al zijn en die dit al getackeled hebben ipv enkel alles wat je zelf gemaakt hebt te vertrouwen.

Acties:
  • 0 Henk 'm!

  • Manuel
  • Registratie: Maart 2008
  • Laatst online: 14-09 14:15
Zoals Cheetah ook al reeds heeft gezegd, probeer het eens uit en kijk welke foutmeldingen je krijgt indien je een fout maakt. Niet vragen maar doen is het magische antwoord bij het leren programmeren.

Verder om antwoord te geven op je vraag, het hangt er vanaf waar je die variabelen later weer wilt voor gebruiken en natuurlijk op wat voor manier. Ik zou zeggen, neem de PHP handleiding eens goed door en dan voornamelijk dit gedeelte wat over OOP gaat.

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Nu online
De singleton is een stom idee omdat er geen enkele reden is om af te dwingen dat er maar 1 instance is van de klasse. Het voorstel wordt gedaan omdat een singleton het mogelijk maakt om makkelijk bij je ene instance te komen. Daarvoor zijn echter veel geschikter methoden. In zijn eenvoudigste vorm kan dat gewoon een functietje zijn:
PHP:
1
2
3
4
5
function DB() {
  static $DB;
  if(is_null($DB)) { $DB = new Database($a,$b,$c); }
  return $DB;
}

Als je het wat flexibeler wil maken dan kun je eens kijken naar het Registry-pattern. Dat kun je ook gebruiken voor andere zaken die je globaal beschikbaar wil maken (een sessie-object bijvoorbeeld).

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 10:02

MueR

Admin Tweakers Discord

is niet lief

Even iets totaal ongerelateerd aan het feitelijke probleem. Ik zie een hoop mensen include(_once) gebruiken voor dingen als database classes en andere vitale delen. Include heeft echter een nadeel hierin; het gaat niet stuk als het bestand niet bestaat. Voor vitale onderdelen wil je over het algemeen gebruik maken van de require_once construct. Als het bestand niet gevonden/gelezen kan worden, gaat dat namelijk wat harder stuk.
PHP:
1
2
3
4
5
6
7
8
// Niet bestaand bestand config.php (toch vrij nuttig) includen:
include_once '/absoluut/pad/naar/config.php';
// Niet aanbevolen voor kritieke bestanden, want bij een fout:
// E_WARNING, script blijft doorlopen, waardoor alle andere scripts ineens geen config waarden krijgen.

require_once '/absoluut/pad/naar/config.php';
// Aanbevolen voor kritieke bestanden, want bij een fout:
// E_ERROR, script stopt direct met een niet subtiele foutmelding

Gebruik voor database classes, configuraties en andere belangrijke zaken dus altijd require_once. Gebruik overigens altijd require_once of include_once, tenzij je de inhoud van $bestand meerdere keren wil (kunnen) laten uitvoeren (templates bijvoorbeeld). Het is ook aan te raden altijd absolute paden in plaats van relatieve paden te gebruiken. Dit kan namelijk hoofdpijn kostten bij dingen als crons of andere command line aanroepen.

[ Voor 10% gewijzigd door MueR op 19-12-2009 18:07 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

Verwijderd

@MueR:
Voor iets als het includen van een database klasse test je natuurlijk de instance met de instanceof operator. Want als gebruiker kan het je namelijk helemaal niet schelen hoe die klasse is geladen en of dat nou include of requiren_once of __autoload was moet ook helemaal niet uitmaken natuurlijk. Goed OOP programmeren is vooral ook het scheiden van verantwoordelijkheden en probleem gebieden.

En uitvoerbare code in includes?!? Nog nooit van functies gehoord zeker. Bij mij is alle code die wordt uitgevoerd een functie of method. Een include_once of require_once hoort niets te uittevoeren behalve mischien templates zoals je al aangaf. Het hoort iets te beschikbaar te stellen aan de gebruiker.

@Ontopic:
Hoewel een single-ton aardig werkt kent het wel 2 grote beperkingen. Je kunt maar met 1 database tegelijk verbinden en waarom zou je je instance altijd via een static constructor moeten ophalen. In veel gevallen is een database klasse vaak een dunne abstractie laag om de database extensie of PDO heen. Het is in zo'n geval veel logischer om een static class variable te gebruiken. Op die manier kun je gewoon de constructor blijven gebruiken en als je van de static class variable een array maakt waarin je je PDO classes stopt waarmee je werkt kun je door 1 extra argument in de normale constructor ook met meerdere databases tegelijk praten.

De performance die je met zo'n oplossing zou verliezen in een C++ applicatie is voor PHP toch al niet van toepassing door de JIT en run-time overhead. En dan nog heb je het over een tiental bytes per instance.

Even een voorbeeld, zo even uit mijn hoofd. Niet test en zonder sanity checks!! voeg die altijd zelf toe!!
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class DBAL
{
 private $conn_id;
 static private $conn_count;
 static private $conn_list;

 public function __construct($conn_id)
 {
  if((is_array(self::$conn_list) !== true) OR (is_array(self::$conn_count) !== true)){
   self::$conn_list = array();
   self::$conn_count = array();
  }

  $this->conn_id = $conn_id;
  if(isset(self::$conn_list[$this->conn_id]) === true){
   self::$conn_count[$this->conn_id]++;
  }
 }

 public function __destruct()
 {
  self::$conn_count[$this->conn_id]--;
 }

}

$dbA = new DBAL(1);
$dbB = new DBAL(2);
$dbC = new DBAL(1);


simpel en eigenlijk veel logischer zeker wanneer je ipv nummers bijvoorbeeld het database adres gebruikt.

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 10:02

MueR

Admin Tweakers Discord

is niet lief

Verwijderd schreef op zaterdag 19 december 2009 @ 18:49:
Voor iets als het includen van een database klasse test je natuurlijk de instance met de instanceof operator. Want als gebruiker kan het je namelijk helemaal niet schelen hoe die klasse is geladen en of dat nou include of requiren_once of __autoload was moet ook helemaal niet uitmaken natuurlijk. Goed OOP programmeren is vooral ook het scheiden van verantwoordelijkheden en probleem gebieden.
Allereerst, OOP programmeren heeft er niks mee te maken. Dit gaat om het beschikbaar maken van functies en/of classes. Daarnaast heeft ook de gebruiker er geen donder mee te maken. Het enige wat de gebruiker wil is dat de boel werkt. Dan kan je beter 1 harde foutmelding hebben "kan $bestand niet laden" dan tientallen of zelfs honderden failures omdat $bestand niet geladen kon worden. Je verlegt hiermee je point of failure en sluit daarmee meteen een hoop andere mogelijke "fouten" uit. Tenzij je met gebruiker de programmeur bedoelt, maar dat lijkt me niet.

Testen met instanceof? Why? Daarvoor zijn Exceptions uitgevonden. Bij het starten van de DB connectie hoor je gewoon een Exception te gooien als er iets niet goed gaat.
En uitvoerbare code in includes?!? Nog nooit van functies gehoord zeker. Bij mij is alle code die wordt uitgevoerd een functie of method. Een include_once of require_once hoort niets te uittevoeren behalve mischien templates zoals je al aangaf.
Zeg wijsneus, ik loop al even mee, uiterhaard heb ik gehoord van functies. Ik zei toch ook niet dat herhaald uitvoeren van code in bestanden op die manier een goede methode is? Ik wil er voornamelijk het o zo belangrijke verschil tussen de twee varianten require en require_once mee aanwijzen. De hint naar templates is zo ongeveer het enige excuus wat ik me er voor kan bedenken. Je hoeft niet meteen te reageren alsof ik heiligschennis pleeg.

[ Voor 4% gewijzigd door MueR op 19-12-2009 19:29 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

Verwijderd

Volgensmij hebben we een misverstand hoor.

Je hoeft je niet meteen zo aangevallen te voelen hoor. Ik probeer ook alleen maar behulpzaam te zijn vooral naar de TS zodat deze niet het hele single-ton concept en OOP in het algemeen verkeerd begrijpt.

En nee ik beschuldig je niet van heiligschennis. Ik denk dat jij ook wel begrijpt dat als je veel tijd hebt gestoken in een goeie database- sessie-beheer en login klassen dat je niet je forum code als een stuk losse code in een include stopt maar netjes in een klasse of een stel functies/methods. OOP is vooral een programmeer en denk stijl waarin elk deeltje van de 'machine' in een eigen klasse/functie/method met eigen verantwoordelijkheden wordt geplaatst. Zo verdeel je het 'probleem' en is elk stuk code verantwoordelijk voor zich zelf en niets anders.

Met gebruiker in deze context bedoel ik dus de code welke de single-ton of klasse instance gaat gebruiken.

De reden waarom ik tijdens debuggen nog wel eens een vaste header file gebruik met alle include_once is juist omdat include doorgaat na een error. Zo kan ik meerdere fouten tegelijk opsporen en hoef ik dit niet voor elke typo opnieuw te doen. Een goeie include is dus eigenlijk reentrant en kent geen bijwerkingen. Zeker nu vaste include's en require's worden ingehaald met het __autoload principe waarin een klasse on-demand wordt geladen.

Daarnaast is het soms ook wel beter om in een __autoload functie include te gebruiken zodat je zelf een exceptie kunt gooien van je eigen type en je de bezoeker/gebruiker van je applicatie een duidelijkere error-pagina kunt laten zien en extra debug informatie kunt dumpen. Met de standaard E_FATAL van require kan dat niet.

Maar ik wil nogmaals benadrukken dat ik weet net zoals jij dat er niet 1 'heilige' manier is om programma's/website's in PHP of welke programmeer taal dan ook te maken en het laatste wat ik hier wil beginnen is een flamewar over hoe een database klasse te schrijven. Dit zijn gewoon een aantal tips over hoe ik het zou aanpakken en wat daar de voor en nadelen van zijn. Laten we dus vooral constructief zijn naar de TS.

En nee ik ben niet lid van de Vi noch de Emacs kerk en of een mono of micro kernel beter is begin ik niet aan.

Acties:
  • 0 Henk 'm!

  • Alex
  • Registratie: Juli 2001
  • Laatst online: 20-08 21:38
In elk geval is de topic starter volgens mij alles behalve gebaat bij de bovenstaande discussies, gezien dat de TS echt dat niveau niet lijkt te hebben. Graag een constructieve discussie ipv de 'ik weet het beter' mentaliteit.

Topicstarter: Het maakt totaal niet uit in dit geval of je met Singletons of niet gaat werken. Je gaat kijken wat je wilt doen: wil je naar 1 database connecten of meerdere? Voer je 1 of meerdere queries uit?
Bouw eerst eens een klasse die de verbinding afhandeld en queries. Wil je dan vervolgens dat er altijd maar 1 object van deze klasse mag bestaan(zodat je resources kunt hergebruiken) zet dan het singleton pattern in.
Maar nog veel verstandiger vind ik het om te kijken naar een bestaande library die dit allemaal voor je doet en dergelijke problemen al opgelost heeft.
Dit is een typisch geval waarbij het wiel al 25000x is uitgevonden en jij enkel de kar nog hoeft te bouwen. Zoek op Google naar [google]PHP Database Object[/google] of [google]PHP Database Class[/google]. Ook Zend heeft haar varianten.

[ Voor 6% gewijzigd door Alex op 20-12-2009 10:58 ]

Deze post is bestemd voor hen die een tegenwoordige tijd kunnen onderscheiden van een toekomstige halfvoorwaardelijke bepaalde subinverte plagiale aanvoegend intentioneel verleden tijd.
- Giphart


Acties:
  • 0 Henk 'm!

  • wackmaniac
  • Registratie: Februari 2004
  • Laatst online: 10:24
T-MOB schreef op zaterdag 19 december 2009 @ 16:19:
De singleton is een stom idee omdat er geen enkele reden is om af te dwingen dat er maar 1 instance is van de klasse. Het voorstel wordt gedaan omdat een singleton het mogelijk maakt om makkelijk bij je ene instance te komen. Daarvoor zijn echter veel geschikter methoden. In zijn eenvoudigste vorm kan dat gewoon een functietje zijn:
PHP:
1
2
3
4
5
function DB() {
  static $DB;
  if(is_null($DB)) { $DB = new Database($a,$b,$c); }
  return $DB;
}

Als je het wat flexibeler wil maken dan kun je eens kijken naar het Registry-pattern. Dat kun je ook gebruiken voor andere zaken die je globaal beschikbaar wil maken (een sessie-object bijvoorbeeld).
Offtopic; dit is in mijn ogen een andere methode om een singleton pattern te implementeren; hiermee dwing je nog steeds af dat er maar een enkele instantie van de DB aanwezig is.

Read the code, write the code, be the code!


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Sowieso vindt ik de benaming (semantiek, ik weet) 'database class' al fout per definitie - het is geen class dat een database is, maar een class die verbindingen en communicatie met een database beheert. Met andere woorden, ik zie liever praat over een DatabaseConnection class, een Query class, een QueryExecuter, etcetera.

PHP:
1
2
3
4
$connection = new MySQLDatabaseConnection($config);
$query = new Query()->select('*')->from('mijntabel')->where('conditie = waarde')->and('andereconditie = anderewaarde');
$result = new QueryExecuter()->executeSelect($query, $connection);
$connection->close();


En wat betreft het hele singleton verhaal: singleton is een luie manier om niet aan dependency management te doen. Bij een singleton stop je iets in de global scope (wat niet slecht per sé is, maar toch niet optimaal), en wat belangrijker is, je voegt de verantwoordelijkheid van het krijgen van een verbinding toe aan alle objecten die een databaseverbinding nodig hebben. Hierdoor zul je bij grotere scripts (en scripts die door meerdere mensen gemaakt worden) het overzicht verliezen van waar overal de databaseverbinding gebruikt wordt.

Het is beter om dit centraal te houden, dwz één centrale plaats waar een databaseverbinding 'uitgedeeld' wordt aan de objecten die het gebruiken. MVC-actig:

PHP:
1
2
3
4
5
6
7
8
$connection = new MSSQLDatabaseConnection($config);
// eventueel stukje code om te controleren of de PersonDao ook daadwerkelijk gebruikt moet worden
// hier heb ik nog geen leuke oplossing voor gevonden, maar ik ben ook meer gewend aan Java
$personDao = new PersonDao($connection);
$henkDao = new HenkDao($connection);

$personController = new PersonController($personDao, $henkDao);
// etc


Zo weet je precies wie wanneer je databaseverbinding krijgt, waardoor je dit snel aan kunt passen. Je kunt ook makkelijk je HenkDao een andere verbinding geven (niet dat er veel PHP apps zijn die meerdere databases gebruiken, maar je weet maar nooit). En natuurlijk bespaar je weer de regels code in je classes die een verbinding moeten opzoeken, alsmede de verantwoordelijkheid daarvoor. En een regel van nette code is dat je classes zo weinig mogelijk verantwoordelijkheid hebben.

/rant

Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 09:27

Creepy

Tactical Espionage Splatterer

Leuk, een rant, maar op jou rant zouden andere mensen weer kunnen ranten ;) O.a. over het gebruik van een totaal afwijkende syntax om een query samen te stellen
code:
1
New Query()->select('*')->from('mijntabel')->where('conditie = waarde')->and('andereconditie = anderewaarde');

Voegt wat mij betreft niks toe t.o.v. van een
code:
1
$query = "SELECT * FROM mijntabel WHERE ... AND ... "

en dan is bij de query direct duidelijk wat er nu precies mee wordt bedoelt. Bij jou query class moet je maar hopen dat de methodes where, and, or, in etc. ook 1 op 1 doen wat je zou willen. Er is al ergens een topic geweest waar daar ook flink op werd ingegaan waarbij de 1 een oplossing als de jouwe geweldig vond maar er ook anderen waren doe het niks vonden om o.a. de redenen die ik nu aandraag.

En bij je DAO voorbeeld plaats ik dan weer vraagtekens bij de HenkDAO, aangezien ik zelf denk dat Henk een persoon is die die PersonDao zou moeten opleveren.

@TS: Anyway, om niet nog veel verder offtopic te gaan: nu heb je misschien maar 1 database en voor de "Test" zet je variabelen maar op een bepaalde plek neer maar je zou niet de eerste zijn die alles maar gewoon zo laat omdat het werkt en later mischien wel in de problemen komt omdat je ineens wel een tweede database nodig hebt. Sla dan ook niet zomaar de gegeven adviezen hier in de wind, of kijk er in elk geval kritisch naar.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor al die informatie!

Echter heb ik nog een probleempje met singleton...
Ik gebruik $database = Database::getInstance(); echter voert hij niets uit en geeft geen foutmeldingen... (E_ALL gebruikt).
Hoe komt het dat hij niets doet?

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private function __construct()
    {
        //Begintijd
        $this->ExcecutionTime = microtime(TRUE);
        
        try
        {
            //Verbinding maken
            if(!mysql_connect($this->DbHost, $this->DbUser, $this->DbPass))
            {
                throw new Exception("[ERROR] Couldn't connect!<BR>[ERROR] " . mysql_error() . "<HR>");
            }

            //Database selecteren
            if(!mysql_select_db($this->DbName))
            {
                throw new Exception("[ERROR] Couldn't select the database!<BR>[ERROR] " . mysql_error() . "<HR>");
            }
        }
        catch (Exception $e)
        {
            debugger($e);
        }
    }

    //Getter method for creating/returning the single instance of this class
    public static function getInstance()
    {
        if (!self::$Instance)
        {
            self::$Instance = new Database();
        }
        echo 'instance started';
        return self::$Instance;
    }

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Door stukjes weg te halen ben ik erachter gekomen dat dit de boosdoener is:

PHP:
1
2
3
4
5
 //Database selecteren
            if(!mysql_select_db($this->DbName))
            {
                throw new Exception("[ERROR] Couldn't select the database!<BR>[ERROR] " . mysql_error() . "<HR>");
            }


Ik begrijp echter niet wat er fout is aan die throw new Exception... Krijg geen foutmelding en hij voert de constructer niet verder uit.

Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 14-09 08:25
Er is al genoeg gerant in dit topic over nutteloze persoonlijke voorkeuren, dus ik ga niet zeuren over het feit dat ik het niet zo zou doen (Ik ben sowieso geen fan van Singletons, al begrijp ik dat ze makkelijk kunnen zijn).

Maar het zou het wel gewoon moeten werken. Ik heb nu dit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
class Database {
    static $Instance;
    private $DbHost = 'localhost';
    private $DbUser = 'user';
    private $DbPass = 'pass';
    private $DbName = 'db';

    private function __construct()
    {
        //Begintijd
        $this->ExcecutionTime = microtime(TRUE);

        try
        {
            //Verbinding maken
            if(!mysql_connect($this->DbHost, $this->DbUser, $this->DbPass))
            {
                throw new Exception("[ERROR] Couldn't connect!<BR>[ERROR] " . mysql_error() . "<HR>");
            }

            //Database selecteren
            if(!mysql_select_db($this->DbName))
            {
                throw new Exception("[ERROR] Couldn't select the database!<BR>[ERROR] " . mysql_error() . "<HR>");
            }
        }
        catch (Exception $e)
        {
            die($e);
        }
    }

    //Getter method for creating/returning the single instance of this class
    public static function getInstance()
    {
        if (!self::$Instance)
        {
            self::$Instance = new Database();
        }
        echo 'instance started';
        return self::$Instance;
    }
}

$db = Database::getInstance();
?>


Vrijwel hetzelfde behalve mijn super elegante die() ipv. die debugger functie. Maar ik krijg hier gewoon foutmeldingen en 'instance started' e.d. Staat display_errors wel aan? :P

[edit:]
Toch nog maar even een disclaimer, want er is nog wel genoeg aan te merken op deze code, maar ik hoop dat het gewoon een beginnetje is. Zo zou ik die db instellingen niet zo in de klassedefinitie instellen zoals ik het nu makkelijk deed, maar in een soort van ini file die je kan parsen. Verder is het misschien handig om de connection identifier die je terug krijgt ergens in je object op te slaan en zou ik denken aan een duidelijke foutafhandeling etc.

[ Voor 66% gewijzigd door Shagura op 20-12-2009 14:59 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Geweldig, mijn error reporting staat blijkbaar uit in mamp (eerste keer dat ik programmeer op mac).

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hoe kan ik een fout van mysql_fetch_assoc opvangen?
Bij mysql_real_escape_string(), mysql_query() etc heb ik het zo gedaan:

PHP:
1
2
3
4
5
6
7
8
9
10
11
// (201) Quote
    public function quote($inp){
        try{
            if(!$ret = mysql_real_escape_string($inp)){
                throw new Exception(mysql_error(), 201);
            }
        }catch (Exception $e){
            $this->debugger($e-getMessage(), $e->getCode());
        }
        return $ret;
    }


Ik heb dan dit geprobeerd bij mysql_fetch_assoc(), echter wanneer ik een fout opzettelijk veroorzaak door bv de variable in mysql_fetch_assoc(--hier--) even verkeerd te schrijven, echter geen error door mijn foutafhandeling enkel als ik de @ weghaal maar dan is het een error die weergeven wordt waar mijn debugger niets mee te maken heeft.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
   // (202) Fetch
    public function fetch($query){
        $queryRes = $this->query($query);
        while($ret[] = @mysql_fetch_assoc($queryRes));
        try{
            if(!is_array($ret)){
                throw new Exception(mysql_error(), 202);
            }
        }catch (Exception $e){
            $this->debugger($e->getMessage(), $e->getCode());
        }
        return $ret;
    }

Acties:
  • 0 Henk 'm!

  • WouZz
  • Registratie: Mei 2000
  • Niet online

WouZz

Elvis is alive!

Ik heb dan dit geprobeerd bij mysql_fetch_assoc(), echter wanneer ik een fout opzettelijk veroorzaak door bv de variable in mysql_fetch_assoc(--hier--) even verkeerd te schrijven, echter geen error door mijn foutafhandeling enkel als ik de @ weghaal maar dan is het een error die weergeven wordt waar mijn debugger niets mee te maken heeft.
set_error_handler of pdo gebruiken.

On track


Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Geen @ gebruiken. En zet die mysql_fetch_assoc binnen de try.

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 10:02

MueR

Admin Tweakers Discord

is niet lief

PHP:
1
while($ret[] = @mysql_fetch_assoc($queryRes));

Behalve de eerder aangehaalde @, lijkt het me niet dat je ineens alle records wil teruggeven? Dat wil je toch gewoon net zoals de huidige mysql_fetch_*() kunnen doen, een per keer?

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedoeling is dat ik het dan buiten de class met foreach(* as *) kan gebruiken. Probleem is hoe vang ik nu een fout op... als ik de @ weghaal geeft hij de fout maar hoe kan ik ervoor zorgen ipv die fout te weergeven dat hij een exception throwed?

Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Verwijderd schreef op maandag 21 december 2009 @ 19:30:
Bedoeling is dat ik het dan buiten de class met foreach(* as *) kan gebruiken. Probleem is hoe vang ik nu een fout op... als ik de @ weghaal geeft hij de fout maar hoe kan ik ervoor zorgen ipv die fout te weergeven dat hij een exception throwed?
Je mysql_fetch_assoc moet geen Exception throwen, dat moet je $this->query() al doen op het moment dat de query mislukt.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dus mysql_num_rows, mysql_fetch_assoc enz hoeven niet gecontroleerd worden op fouten? Dus enkel de query functie moet gecontroleerd worden en eventueel een exception throwen?

En mysql_real_escape_string moet die gecontroleerd worden?

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Serieus is het zo ondertussen geen tijd om gewoon een bestaande class te pakken?

Je begon het topic met :
De class maken en de foutafhandeling & debug modus maken is geen probleem wel hoe ik de class moet gebruiken.
...

Maar om je laatste vraag te proberen te beantwoorden : Als je query functie fout gaat dan volgt daarna gewoon niets meer.

Je kan aan mysql_num_rows wel een fout afhandeling hangen, alleen moet je dan goed begrijpen wat de fout is ( 9 vd 10 keer een mysql server die tussentijds onbereikbaar is geworden ).
In theorie ( en als je het als onderdeel van een framework zou maken ) zou je mysql_num_rows / mysql_fetch_assoc etc wel moeten controleren op fouten enkel niet via exceptions ( want de standaard error_handler pakt hem dan eerder op ) maar door de error_handler te overrulen ( of pdo zoals HuHu zei )

In praktijk ( en als je het maar voor 1 of 2 kleine projectjes gebruikt ) zie je vaak dat het gelijk na de query komt en dat 99,9999999% vd fouten in de query zitten.

Zelfde met mysql_real_escape_string, die moet je in theorie ook checken, maar in de praktijk ken ik geen enkel voorbeeld waarop die fout zou kunnen gaan.

Als je echt een framework wilt maken moet je gewoon de docs op php.net volgen en alles wat een error kan opleveren netjes afhandelen

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor de info, als ik bestaande classes zou gebruiken ga ik er nooit wat van verstaan. Dit is gewoon een soort oefening/ funprojectje die database class waar ik tot nu toe al veel van heb geleerd: singleton, try-throw-catch, ...

Acties:
  • 0 Henk 'm!

  • kokx
  • Registratie: Augustus 2006
  • Laatst online: 13-09 20:30

kokx

WIN

Even een iets andere vraag kwitter, wat wil je precies bereiken met jouw foutafhandeling? Naar mijn mening is het altijd het beste dat de gebruiker de foutafhandeling uitvoert. Of wil je gewoon Exceptions gaan gooien bij elke error ipv de standaardfoutmeldingen van MySQL?

En nog iets anders: de mysql_fetch_array() functie geeft alleen een array als de ingegeven resultset fout is (dus als er eerder een fout is voorgekomen).

Eigenlijk een betere aanrader blijft PDO, veel database classes die ik gebzien heb, zijn eigenlijk niet meer dan een vervanger voor iets als PDO. Tenzij je echt meerwaarde aanbied, heeft het weinig zin iets anders te gebruiken. Ook heeft PDO bijvoorbeeld ondersteuning voor prepared statements, wat qua veiligheid toch een stuk beter is dan de standaard mysql_* functies.

[ Voor 2% gewijzigd door kokx op 22-12-2009 21:22 . Reden: eindgebruiker veranderd in gebruiker ]


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
kokx schreef op dinsdag 22 december 2009 @ 18:34:
Naar mijn mening is het altijd het beste dat de eindgebruiker de foutafhandeling uitvoert.
Niet iedereen laat z'n gebruikers db fouten herstellen. 8)7

{signature}


Acties:
  • 0 Henk 'm!

  • kokx
  • Registratie: Augustus 2006
  • Laatst online: 13-09 20:30

kokx

WIN

Voutloos schreef op dinsdag 22 december 2009 @ 21:14:
[...]
Niet iedereen laat z'n gebruikers db fouten herstellen. 8)7
Heb je gelijk in, ik bedoel gebruiker van de class, niet eindgebruiker, sorry 8)7.
Pagina: 1