Posts by FangorN

    @MOnkNL ik denk dat we ongeveer hetzelfde bedoelen, je schrijft "wikkels" (wrappers, what's in a name eh?) om de mysqli en mysql_result classes.


    Echter, het uitgangspunt wordt gevormd (of zou gevormf moeten worden) door abstracte classes/interfaces die omschrijven wat de wrappers zouden moeten implementeren om zo te komen tot een soort van semi-uniforme implementatie. Een beetje wat PDO doet dus (je schrijft in wezen een DAAL - Data Access Abstraction Layer).


    Deze wrappers moeten wel een zekere toegevoegde waarde hebben. Dit zijn dus niet enkel aliassen van een mysqli-functie of -methode, dat zou nogal loos zijn (maar wel een stap in de goede richting als het gaat om het tegengaan van "hardcoding van de database-oplossing").


    Wat je bijvoorbeeld zou kunnen doen bij je publieke methode query():
    - nagaan of de query geslaagd was, en
    - zoja, een object van een afgeleide klasse van mysqli_result retourneren (deze kun je ook extenden)
    - de query loggen
    - het aantal queries tellen (+1)
    - zonee, een exception kunnen throwen


    Dit voert dus veel verder dan simpelweg een alias van een mysqli-methode.

    ik had ergens gelezen dat ze helpen tegen sql injection doordat ze laten zien wat het begin en einde is van een value maar blijkbaar is dat dan toch iets dat ik beter niet toepas of niet klopte.

    Accolades voorkomen SQL injection niet. Deze maken het hooguit (iets) lastiger om dit te doen maar uiteindelijk biedt dit onvoldoende bescherming.


    Het enige wat failsafe is is het gebruik van (single) quotes (om de te escapen waarde) in combinatie met een escape-functie (voor het escapen van de waarde zelf). Het een zonder het ander is niet veilig.


    Ook is het een goede gewoonte om je invoer te filteren. Als je bijvoorbeeld een numerieke waarde verwacht: controleer hier dan ook op.


    Wat @MOnkNL doet is consequent de object georiënteerde schrijfwijze toepassen. Dit is niet per definitie beter, maar anders. En zeker wat korter. En waarschijnlijk meer in lijn met hoe MySQLi werkt (met klassen en objecten). In het algemeen beweegt programmeren (in PHP) weg van procedureel en naar object georiënteerd toe. Je kunt je eigen voorkeur hebben, maar wat handig/verstandig is lijkt mij duidelijk.


    Wat naar mijn mening niet/minder handig is is het volgende: hetgeen je gebruikt zijn nog steeds specifieke MySQL(i)-functies en -methoden. Hierbij bedien je je min of meer van "hardcoding van de database-oplossing". De SQL-code is ook nog steeds "MySQL specifiek", daar kom je ook niet omheen tenzij je een Database Abstraction Layer hebt, maar dat terzijde.


    Sommigen van jullie zijn nu bezig met een omzetting van functies van de oorspronkelijke MySQL-driver naar MySQLi-functies en methoden, maar in zekere zin bega je opnieuw dezelfde fout door alle hardcoded instanties van mysql_-functies te vervangen door hardcoded instanties van het MySQLi-equivalent. Dit is een hoop (foutgevoelig) ge-search en replace in je code. Maar wat nu als je een wrapper had gebruikt voor deze functies? Dan hoefde je (idealiter) enkel de implementatie van deze wrapper aan te passen indien je van de oorspronkelijke MySQL-driver naar MySQLi overstapte. Er zijn andere voordelen van het gebruik van een wrapper: je kunt hier je eigen foutafhandeling en logging in stoppen en ook bewerkingen bundelen (met name bij gebruikmaking van transacties). Ook kun je methode(name)n korter maken zodat communicatie met je database eenvoudiger wordt. En tot slot heb je één plek waar je een uniforme definitie hebt van hoe je met je database communiceert die niet verspreid is over je hele codebase maar is gevangen in één of enkele klassen.


    Het eenmalig schrijven van een wrapper bespaart je op termijn vele malen meer tijd.

    Heb je meerdere omgevingen waar deze code en database op staat, bijvoorbeeld een test/ontwikkelomgeving en een live-omgeving? Gebeuren hier soortgelijke/dezelfde dingen? Oftewel, zit dit echt in code onafhankelijk van omgeving of komt dit alleen voor op een specifieke webserver?


    Het enige wat ik nog kan bedenken is dat je een specifiek geval van dit "gedrag" isoleert, oftewel, kom tot een of ander scenario van door jouw site heenklikken die elke keer tot dit reproduceerbare gedrag leidt en sla daar dan aan het debuggen. Het klinkt allemaal alsof dit alles (vele malen) dieper in je systeem zit op een of andere manier.


    Het zal een soort samenloop van omstandigheden zijn waarvan het (blijkbaar) niet direct duidelijk is waar dit vandaan komt.


    Met de informatie die je geeft is het duidelijk wat er gebeurt, maar dit is waarschijnlijk onvoldoende om het oorspronkelijke probleem (wat blijkbaar wijder verspreid is in jouw site) op te lossen.


    (kort samengevat: heb eigenlijk geen idee wat er misgaat :))


    EDIT: heb je ergens een online voorbeeld?

    Je query heeft waarschijnlijk geen resultaten. Die { accoladen } zijn een PHP-ding, in die zin dat ik die vaak in PHP-code zie, terwijl die eigenlijk daar ook al weinig/niets toevoegen.


    Ze horen niet thuis in SQL, tenzij je een e-mailadres echt hebt opgeslagen als {[email protected]}, wat ik betwijfel.


    Oftewel: accolades weghalen. Dan heb je waarschijnlijk wel / meer resultaat.


    EDIT: enne, na een header('Location: ...'); hoort bijna altijd een exit te staan zoals ik al vaker heb toegelicht.

    Het vrijgeven van een resultset is niet hetzelfde als het sluiten van de connectie.


    Indien je klaar bent met (het gebruiken van) een resultset is het altijd een goed idee om de resultaten hiervan direct vrij te geven omdat dit het verbruik van resources tijdens de uitvoering van een script beperkt.


    Nu lijkt dit triviaal omdat een script meestal in enkele milliseconden klaar is, waarna toch alle resources (al het geheugen) worden vrijgegeven.


    Maar als je een drukbezochte site hebt dan duren requests mogelijk wat langer, waarmee dus eenzelfde script mogelijk op eenzelfde moment door meerdere gebruikers (of liever gezegd threads van de webserver) wordt uitgevoerd. Als je dan niet tussentijds resources vrijgeeft dan kun je dus af en toe enorme pieken in je (totale) geheugenverbruik krijgen. Je krijgt dan dus een soort van zelfversterkend (sneeuwbal)effect.


    Het expliciet verbreken van een database-connectie is niet nodig en ook, zoals we in een andere thread zagen, onverstandig. Wanneer al je scripts klaar zijn wordt de connectie impliciet verbroken.


    Ik zou trouwens nog steeds onderzoeken of (en wanneer) $db om wat voor reden dan ook "soms" ongedefinieerd is. Dit lijkt mij vooralsnog de enige reden / verklaring voor de "the connection was reset" meldingen die jij krijgt. Kan het zijn dat het pad van je include soms niet klopt ofzo? Als een include mislukt gaat je script gewoon verder, dit in tegenstelling tot een require. Heb je al geprobeerd om het melden en weergeven van foutmeldingen aan te zetten (zoals volgens mij al eerder is voorgesteld)?


    EDIT: meh, wss al geprobeerd. Kijk anders eens in je errorlogs?

    welke PHP versie gebruik je op de webserver waar je die meldingen krijgt

    Als je zoekt naar "connection was reset" meldingen zit het vaak in de hoek van een (knetter) oude versie van PHP, of iets anders dat uit de pas loopt als je gebruik maakt van MySQLi. Dit alles klinkt als een webserver aangelegenheid, en hoeft niet per se iets met MySQLi te maken te hebben, tenzij er misconfiguratie is of alles gewoon te oud is.


    Vandaar mijn vraag over (PHP) versies. Kijk ook gelijk naar de MySQL(i) versies er gebruikt worden en welke Client API (library) version gebruikt wordt? Idealiter is dit de native driver (nd), en niet een of andere externe MySQL module.


    Ook kan het helpen (is in ieder geval beter voor performance) om op IP-basis een connectie te maken. Gebruik dus bij voorkeur '127.0.0.1' in plaats van 'localhost'.

    @MOnkNL strict genomen zou dat niet uit moeten maken omdat MySQLi enkel met objecten werkt. Dit in tegenstelling tot de oorspronkelijke MySQL-driver, die zich bediende van resources. Neemt niet weg dat het inderdaad beter zou zijn als je één schrijf/werkwijze hanteert (ofwel de procedurele, ofwel de object georiënteerde stijl waarbij laatstgenoemde waarschijnlijk de voorkeur heeft, of zou moeten hebben).


    @Opium welke PHP versie gebruik je op de webserver waar je die meldingen krijgt, en wat is de exacte melding - is deze echt in het nederlands? :P


    Vermoeden: $db is onbekend wanneer je bovenstaande aanroep van mysqli_query() doet. Staat deze code in een functie of methode waar $db niet bekend is / je $db niet aan meegegeven hebt? Dump $db eens? Grote kans dat deze dan NULL is ofzo?


    In zekere zin klinkt dit plausibel, want bij een aanroep van mysql_query() (oude stijl) werd standaard uitgegaan van de laatst gemaakte verbinding. Hierbij hoefde je niet expliciet de connectie-parameter mee te geven, dit in tegenstelling tot mysqli_query() (nieuwe stijl), waar dit wel moet.


    Waarschijnlijk gaat er dus iets fout met $db. Mogelijk wordt deze ergens overschreven? Hoe refereer je aan $db?

    Niet closed, lees de zin opnieuw. Ze gaven toe dat ze het overgenomen hebben, niet dat ze het hebben AFgehaald.

    Ik bedoelde meer dat het duidelijk is hoe dat logo tot stand is gekomen en dat dat duidelijk niet de bedoeling is en dus ook dat het duidelijk is wat er (zou) moet(en) gebeuren. Theoretisch is dat dus een "afgeronde zaak" maar er moet natuurlijk nog wel het een en ander gebeuren... :)

    Zelfs gokken met virtueel geld uit een spel kan in strijd zijn met de EULA uit dat spel wat mogelijk tot gevolg kan hebben dat je gebanned wordt uit het betreffende spel.

    Je kan 't best sluiten na je alle query's hebt voltooid.

    Dit moment staat niet altijd vantevoren vast.


    Er is zelden tot nooit zoiets als "het beste". Het beste wat je kunt doen is de voors en tegens tegen elkaar afwegen. Op het moment dat alle code is uitgevoerd wordt de connectie sowieso impliciet gesloten. Dit is vaak een kwestie van milliseconden, dus waarom zou je dit moment nog verder naar voren willen halen?


    Overigens zul je volgens mij meer "performance" winst (in termen van resources) boeken als je tussentijds query-resultaten vrijgeeft.


    Ik ben eigenlijk nog nooit een situatie tegengekomen dat het nodig was dat je een connectie expliciet (en mogelijk voortijdig?) sluit.


    Als je gebruik gaat maken van transacties dan is het trouwens overduidelijk niet de bedoeling dat je de connectie tussentijds sluit omdat dat dan de "ondeelbaarheid" van opeenvolgende queries (in de transactie) niet gegarandeerd kan worden.


    TL;DR het tussentijds sluiten van een connectie na het uitvoeren van een query is onzinnig en zou vermeden moeten worden.

    Ik zou zeggen, dump je sessie-data eens naar je scherm:

    isset() retourneert ook false als de waarde van de variabele NULL IS. Let er op dat er een NOT-operator (het uitroepteken) voor je isset() statement staat.


    Voor de leesbaarheid zou je ook kunnen overwegen om ofwel het volgende te gebruiken:

    PHP
    <?php
    if (isset($a) === false) {
        echo '$a is not set';
    } else {
        echo '$a is set';
    ?>

    Of je draait de delen om:

    PHP
    <?php
    if (isset($a)) {
        echo '$a is set';
    } else {
        echo '$a is not set';
    ?>

    Misschien is dat nog beter: gebruik zo min mogelijk operators waardoor je je mogelijk kunt vergissen.


    Of gebruik te maken van empty, maar je moet dan ook goed opletten dat de variabele ook als "leeg" wordt beschouwd als de waarde van de variabele een "lege" waarde heeft (de lege string, het cijfer 0 (al dan niet tussen quotes), false of NULL).

    PHP
    <?php
    if (empty($a)) {
        echo '$a is empty';
    } else {
        echo '$a is not empty';
    }
    ?>

    Verwijder of comment de voorkomens van mysql_close() en kijk dan of het probleem nog speelt.


    En nee, het is niet de bedoeling dat je na elke query de connectie verbreekt en weer opnieuw opbouwt als je een andere query wilt uitvoeren. Waar heb je dat gehoord? :)


    Idealiter maak je ook één keer een connectie gedurende de uitvoer van je scripts. Dus een eenmalige aanroep van een connect-functie aan het begin van je script zou voldoende moeten zijn. Indien al je scripts klaar zijn met hun executie wordt de connectie automatisch (en impliciet) verbroken. Dit hoef je eigenlijk zelden of nooit expliciet (door middel van een close-functie) te doen eigenlijk.


    Voor het probleem wat je ondervindt maakt het volgens mij niet uit dat je meerdere keren een connectie maakt omdat PHP zelf wel zo slim is dat als de parameters waarmee je een connectie maakt (host, username, password, database) hetzelfde zijn, PHP een bestaande connectie met dezelfde parameters hergebruikt. Tenzij je dus expliciet elke keer de verbinding verbreekt met behulp van mysql_close(); je connectie is dan echt weg. Het opbouwen van een connectie is een vrij dure operatie, dus dit doe je idealiter zo min mogelijk.


    Ook lijkt het mij verstandig dat je overstapt naar MySQLi of PDO, want de oorspronkelijke MySQL-driver (dit zijn effectief alle mysql_...-functies) is al ~10 jaar verouderd en is verdwenen in PHP 7.

    :)


    Headers zijn onderdeel van output. Deze worden pas verstuurd op het moment dat er output wordt geproduceerd.


    Er ontbreekt een exit in dat if-statement. ALLE code die daarna nog volgt wordt dus gewoon uitgevoerd. Zoals ik al eerder heb beschreven: header('Location: ...') transporteert je niet direct automagisch naar een nieuwe locatie.


    Ik denk dat het de moeite loont als je je code controleert op dit soort constructies. Wat mogelijk nog beter is is dat je een redirect-functie of methode maakt, zodat je de "exit" nooit meer vergeet. Daarbij wordt je code ook nog eens een stuk korter:

    PHP
    <?php
    function redirect($link) {
        header('HTTP/1.1 303 See Other');
        header('Location: '.$link);
        exit;
    }
    ?>

    ik kan dit ook niet vaak genoeg zeggen en benadrukken: het verschil tussen het plaatsen of ontbreken van een exit-statement kan het verschil betekenen tussen een veilige of onveilige applicatie.

    mysqli is opgebouwd in oop style dus hier kan je direct gebruik van maken zonder dat zelf een class voor te bouwen.

    Er valt weliswaar inderdaad iets voor te zeggen om van de OOP variant van mysqli gebruik te maken, maar dat neemt niet weg dat het handig kan zijn om een (eenvoudige) wrapper om de mysqli class zelf te bouwen, dit kan je het werk nog makkelijker maken.


    @futur3 wellicht is het handig om een aantal misverstanden op te helderen.


    Allereerst heb je bij mysqli, in tegenstelling tot de oorspronkelijke mysql-functies, de mogelijkheid om direct een database te selecteren op hetzelfde moment als het maken van een connectie, bij de originele mysql-extensie had je hier twee functies voor nodig (mysql_connect() en mysql_select_db()). Dit doe je ook op regel 9 van je eerste codefragment (4e parameter bevat de naam van de database). Dit hoef je dus niet nogmaals te doen in login.php.


    Als je toch een rechtvaardiging hebt om het selecteren van een database uit te stellen zul je eerst de 4e parameter uit de aanroep van mysqli_connect() in connection.php moeten verwijderen. Daarbij is het dus wellicht nog beter om helemaal over te stappen naar de OOP variant van mysqli. Vervolgens zou je de getInfo() methode in login.php moeten uitbreiden met een aanroep van de connect() methode uit de parent class voordat je een database selecteert, anders bestaat $this->con simpelweg niet! Dit had je waarschijnlijk direct kunnen constateren als je het melden + weergeven van fouten had aangezet voor ontwikkeling. Dit soort instellingen verdienen zeker een plaats in je configuratie...


    Daarnaast de volgende observatie: een "login" class is geen logisch voortborduursel van een "database" class als je het mij vraagt. Een "login" class zou hooguit gebruik moeten maken van een "database" class. Dit zou je ook kunnen bereiken door een instantie van een database-class-object door te geven aan de login class op het moment van creatie. Je geeft daarmee dus in feite de login class al het gereedschap om acties die gerelateerd zijn aan het in- en uitloggen uit te kunnen voeren. Maar een login class is iets heel anders dan een database class, dus het ene in het verlengde plaatsen van het ander is nogal vreemd.


    Tot slot is de configuratie-functionaliteit enkel bedoeld om op een eenduidige manier instellingen vast te leggen (of zou dit moeten zijn). Het staat dus ter discussie of het ook de taak van configuratie-functionaliteit is om (direct, dan en daar) een database connectie te maken. Als je dit dan toch doet loont het wellicht de moeite om dit database-object weer onder te brengen onder een aparte configuratie-variabele of -array die (referenties van) objecten of (handles van) resources bevat. Op die manier zou je ook via een "getter methode" de referentie naar je database-object uit je configuratie-variabelen kunnen trekken.


    Doorgaans hebben klassen één duidelijk omschreven set taken/verantwoordelijkheden. Als je dingen gaat doen die hier (erg) van afwijken (niet echt passen in de set) is dat een signaal dat je wellicht een of meer aparte klassen mist en/of dat er een kronkel zit in je ontwerp.

    De query "gaat goed" omdat deze qua syntax (vorm) goed is.


    Alhoewel de volgende query "correct" is:

    SQL
    UPDATE klant
    SET online=NOW()
    WHERE id_klant=''
    LIMIT 1

    levert deze (waarschijnlijk) nooit een resultaat op. Ook zie ik niet helemaal waarom die LIMIT 1 er bij moet. Het kan geen kwaad, maar op deze manier krijg ik de indruk dat je er niet van uit kan gaan dat het goed gaat als je dit weglaat :). Dat zou inhouden dat je de informatie in je sessie niet helemaal kan vertrouwen, en als dat aan de orde is heb je andere problemen :).


    En je krijgt de notice omdat $_SESSION['id'] niet bestaat. Ofwel omdat je sessie niet gestart is ten tijde van het uitvoeren van de query, of dat $_SESSION['id'] niet geinitieerd is. Dit laatste kan weer verschillende redenen hebben als:
    - een gebruiker was niet ingelogd op het moment van uitvoeren van de query
    - de sessie was verlopen bij het (opnieuw) opvragen van een pagina


    Je zou dit inderdaad op kunnen lossen door op het bestaan van $_SESSION['id'] te controleren, maar die controle zelf hoort waarschijnlijk op een andere plaats thuis, en niet direct voor de uitvoer van de query... Bijvoorbeeld bij het laden van de pagina - daar had je waarschijnlijk al ingelogd moeten zijn om de pagina te mogen zien, dat (bij het opvragen van de pagina) zou dan ook een geschiktere plaats moeten zijn als je het mij vraagt.

    maar je moet toch ook php files hebben met de opdrachten daarin voor de cronjobs of is dat niet altijd nodig ?

    Uiteraard. Een cronjob is niets meer dan een geautomatiseerde aanroep van bijvoorbeeld een PHP-script.


    Het hangt van de werking van de code (verdeeld over een of meer scripts) af wat er moet gebeuren. Het kan zijn dat verschillende scripts verschillende cronjobs met verschillende momenten (tijdsintervallen) van aanroep vereisen.


    Of het systeem heeft een eigen scheduler, zodat je deze scheduler alleen maar om de X minuten hoeft aan te roepen, en deze scheduler bepaalt verder welke taken uitgevoerd dienen te worden (delegeert het werk naar individuele routines).


    Ik zou verwachten dat je deze informatie zou moeten kunnen halen uit documentatie of een installatiehandleiding, of, in een minder optimaal geval, uit commentaar in code die aangeeft wat de werking / bedoeling is. Wat er ingesteld moet worden zal anders moeilijk te herleiden zijn tenzij je het systeem van binnen en van buiten kent.