login  Naam:   Wachtwoord: 
Registreer je!
 Forum

Fout bij mysqli update

Offline pascalbianca - 30/06/2016 01:35
Avatar van pascalbiancaNieuw lid Ik wil een user updaten met de volgende code.:
  1. if(isset($_POST['add'])) {
  2. include_once ('config.php');
  3. //Output any connection error
  4. if ($con->connect_error) {
  5. die('Error : ('. $con->connect_errno .') '. $con->connect_error);
  6. }
  7.  
  8. $statement = $con->prepare("UPDATE leden SET BGRangImage='imagesgge/'".$_POST['nfbgrang']."'.png', BGRang='".$_POST['NRang']."' WHERE GGEName='".$_POST['GGEName']."'");
  9.  
  10. $results = $statement->execute();
  11. if($results){
  12. print 'Gebruiker is met succes met status aangepast!';
  13. }else{
  14. print 'Fout : ('. $con->errno .') '. $con->error;
  15. }}
  16. ?>


De gegevens wat moeten aangepast komen uit een dropdown die ik in mijn post van 23-06 heb gesteld.

Alleen nu krijg ik de volgende melding.:
Fatal error: Call to a member function execute() on a non-object in xxxxxxxxx.php on line 34

De fout waar hij aangeeft met regelnummer 34 is in mijn bovenste php code.:
  1. $results = $statement->execute();


Wat doe ik fout of wat zie ik over het hoofd?

10 antwoorden

Gesponsorde links
Offline advertentiep - 30/06/2016 09:41
Avatar van advertentiep PHP interesse Krijg je meer info te zien als je dit onder de PHP open-tag zet:
  1. ini_set('display_errors', 1);


Ik weet niet of de functie prepare of execure ook een foutmelding afhandelen ? Je voert namelijk wel de controle of er een connectie is gemaakt met de DB, maar gebeurt dit ook op de query ?

Wat ik wel weet is dat je beter:
  1. if ($_SERVER['REQUEST_METHOD'] == 'POST')

dan een IsSet() op je submit button.

Je kan na de POST check (eerste statment) print_r($_POST); doen om te kijken of alle velden wel een waarde vast houden ? (daar is de foutmelding niet echt naar).

PS; $results = $statement->execute(); moet niet toevallig $con->execute(); zijn ?

Offline Thomas - 30/06/2016 13:59
Avatar van Thomas Moderator
Citaat:
PS; $results = $statement->execute(); moet niet toevallig $con->execute(); zijn ?

Nee, normaal gesproken retourneert prepare() een object van de klasse mysqli_statement, waar je vervolgens een execute() op kunt toepassen.

Ik zeg normaal gesproken, want dit is wat er waarschijnlijk fout gaat: het querysjabloon klopt niet, kijk maar eens naar de enkele quotes. Als het preparen mislukt retourneert prepare() de waarde false in plaats van een object. false is geen object. Dit is precies wat de foutmelding zegt.

Los daarvan is dit een verkeerd gebruik van prepared statements @pascalbianca. Bij prepared statements plak je de in te vullen vakjes niet rechtstreeks in de query... en al helemaal niet zonder de juiste escaping .

Ook zou je je kunnen afvragen waarom je hier prepared statements gebruikt. Wat is de meerwaarde hiervan?

Verder ben ik het wel eens met de opmerkingen van @advertentiep. Maak code voor jezelf inzichtelijk door eens wat informatie naar je scherm te dumpen en te werken in "debug modus" zodat alle fouten worden gemeld.

Eerst zul je jezelf een bepaalde werkwijze moeten aanleren anders zul je je blijven verwonderen over dingen die er fout gaan maar geen enkel idee hebt over hoe je deze moet gaan oplossen.
Offline pascalbianca - 01/07/2016 01:22 (laatste wijziging 01/07/2016 01:54)
Avatar van pascalbianca Nieuw lid Deze code om de fouten weer te geven werk niet of ik doe iets fout.
  1. ini_set('display_errors', 1);


Ik ben er dus wel achter gekomen dat in deze regel.:
  1. $statement = $con->prepare("UPDATE leden SET BGRangImage=?, BGRang=? WHERE GGEName=?");
  2. $statement->bind_param('ssi',"imagesgge/".$_POST["nfbgrang"], $_POST["NRang"], $_POST["GGEName"]);
  3. $results = $statement->execute();


dat
  1. "imagesgge/".$_POST["nfbgrang"]

de fout veroorzaakt.
Want als ik het zo doe.: (buiten dat het met alle gebruikers volledig de mist in gaat dan)

  1. $statement->bind_param('ssi',$_POST["nfbgrang"], $_POST["NRang"], $_POST["GGEName"]);


Gaat het wel.

Maar dan kom ik bij het volgende geval wat dan gebeurd, als het wel lukt is dat dan alle gebruikers worden aangepast, terwijl ik maar 1 soort van beide opvang.

Dus aub wat hulp want ik begin er langzaam grijze haren van te krijgen.  
Offline advertentiep - 01/07/2016 09:34
Avatar van advertentiep PHP interesse Voordat je gaat updaten eerst kijken of er wel een overeenkomst is met een record in de je DB.

- dus een select query met de WHERE-clause = (je GGEName veld), het bijbehordende user-id opvragen.
- Controle of er een rij is opgehaald, zo niet foutmelding.
- Data updaten WHERE user-id = (je opgehaalde id van je select query).

Voordat je begint te typen in een nieuw / bestaand bestand is het wellicht makkelijk om alvast een plannetje te hebben wat de volgorde is (offtopic):

- Waarom je include pas als er gesubmit wordt ? (gezien de naam 'config' is dit denk ik redelijk algemeen en zou ik het persoonlijk overzichtelijker vinden om dit onder de PHP-tag te includen).

- DB connectie check uitvoeren op elke pagina ? waarom niet in de config.

- Als je code werkt, betekend dit niet dat dit geheel veilig is, er is denk ik geen controle op de input (ik heb niet de hele code gezien), en de data wordt rauw in je DB gezet. Als je dit nog lastig vind zou ik je aanraden om in je config.php de suberglobals $_GET & $_POST te voorzien van standaard php functionaliteiten.

Je hebt er veel profijt van om is op onderzoek te gaan naar: mysqli_real_escape_string(); addslashes(); stripslashes(); htmlentities();
Offline Thomas - 01/07/2016 14:50 (laatste wijziging 01/07/2016 14:57)
Avatar van Thomas Moderator
Citaat:
Voordat je gaat updaten eerst kijken of er wel een overeenkomst is met een record in de je DB.

Ik denk persoonlijk dat het veel belangrijker is dat je op een of andere manier controleert of de persoon die de wijziging wil uitvoeren dit ook mag doen. Het maakt dan namelijk niet uit of het record wat je (al dan niet door manipulatie verandert) wilt aanpassen bestaat of niet.

Citaat:
Waarom je include pas als er gesubmit wordt ? (gezien de naam 'config' is dit denk ik redelijk algemeen en zou ik het persoonlijk overzichtelijker vinden om dit onder de PHP-tag te includen).

Mee eens.

Citaat:
DB connectie check uitvoeren op elke pagina ? waarom niet in de config.

Niet mee eens. Dit is niet de taak van configuratie. Configuratie definieert, maar voert niet uit. Het opzetten van een databaseverbinding lijkt mij onderdeel van initialisatie van de applicatie.

Citaat:
Als je code werkt, betekend dit niet dat dit geheel veilig is, er is denk ik geen controle op de input (ik heb niet de hele code gezien), en de data wordt rauw in je DB gezet.

Dit laatste is niet per se een probleem, zolang je maar tot op zekere hoogte je input filtert of controleert (EDIT: en niet te vergeten: altijd output escaping voor die context gebruikt, tenzij je een zeer speciale, en gedocumenteerde, reden hebt waarom je dat niet doet). Het onverstandigste wat je echter kunt doen is aannemen dat (als) de informatie (eenmaal) in je database (zit dat deze) betrouwbaar is. Dit is nog steeds user data. Vertrouw nooit user data.

Citaat:
Als je dit nog lastig vind zou ik je aanraden om in je config.php de suberglobals $_GET & $_POST te voorzien van standaard php functionaliteiten.

Ik kan mij hier weinig bij voorstellen eigenlijk. Als je bedoelt dat je op voorhand allerlei sanitizers en escaping hier op loslaat: ik zou dat niet (op voorhand) doen.

Citaat:
Je hebt er veel profijt van om is op onderzoek te gaan naar: mysqli_real_escape_string(); addslashes(); stripslashes(); htmlentities();

Ik denk dat als je nog addslashes en stripslashes in je (security) oplossingen gebruikt dat deze (zwaar) verouderd zijn. De functionaliteit die automatisch backslashes toevoegt (concreet: magic_quotes_gpc) in superglobal arrays ($_GET, $_POST etc.) is vanaf PHP 5.3.0 deprecated en vanaf 5.4.0 verwijderd. Los daarvan, het is verstandiger om deze instelling expliciet uit te zetten zodat je altijd hetzelfde uitgangspunt hebt en alvast forward compatible bent voor als deze functionaliteit niet meer in jouw PHP versie wordt ondersteund.

Nog meer profijt dan het doen van onderzoek naar deze functionaliteit heb je bij een juist gebruik van deze functionaliteit. Dit is namelijk het punt waarbij meestal veel te wensen over laat: mensen hebben er geen idee van hoe ze deze concepten op een juiste wijze moeten toepassen...

@pascalbianca: wat is er op tegen om geen prepared statements te gebruiken? Dit is namelijk niet verplicht in MySQLi en in jouw geval mogelijk ook (stukken) makkelijker. Los daarvan: prepared statements in MySQLi zijn nogal bagger (onhandig in het gebruik) als je het mij vraagt.

Ook komt het volgende mij vreemd over: je zegt WHERE GGEName=? en vervolgens bind je deze parameter als getal. Hoe is een Name een getal? Is dit gewoon slechte naamgeving voor een getal of was dit daadwerkelijk een naam in welk geval dat niet zo'n fantastisch selectiecriterium is en het binden mislukt omdat een string nu eenmaal geen integer is; in het ergste geval wordt er iets getypecast zodat dit WHERE GGEName=0 wordt ofzo, je zou dit dan uit je querylogs moeten vissen of de returnwaarden van prepare(), bind_param() en/of execute() controleren om te zien waar het mis gaat. Wat je ook niet doet, daarom zie je ook niet waar het precies fout gaat, dat maakt het oplossen van je probleem niet makkelijker.
Offline pascalbianca - 02/07/2016 00:56
Avatar van pascalbianca Nieuw lid @Thomas.
Waar haal jij uit dat ik een getal gebruik?
Citaat:
Ook komt het volgende mij vreemd over: je zegt WHERE GGEName=? en vervolgens bind je deze parameter als getal.

Haal dit nergens uit mijn code code op.

De rest van jullie beide uitleggen zeer mooi uitgelegd, alleen loopt het mij door elkaar en voor dat klein stukje code waar ik het maar voor nodig heb.

De code werkt , alleen doet hij mij alle namen wijzigen met een en dezelfde titel en dat was mijn vraag hoe dit kan en waar het aan ligt.

Dat mijn manier van code niet correct is , oke dat snap ik, daar wil ik mij later zeer goed in verdiepen , maar wilde alleen dat klein stukje werkend hebben zodat de site door kan lopen.
Offline Thomas - 02/07/2016 12:53 (laatste wijziging 02/07/2016 13:24)
Avatar van Thomas Moderator
Citaat:
Haal dit nergens uit mijn code code op.

Nou, dat doe je hier:
  1. <?php
  2. $statement->bind_param('ssi',$_POST["nfbgrang"], $_POST["NRang"], $_POST["GGEName"]);
  3. ?>

Hier zeg je: behandel het eerste argument (nfbgrang) als string, het tweede argument (NRang) als string en het derde argument (GGEName) als integer. De "typehints" zet je in het eerste argument: ssi.

Citaat:
De code werkt , alleen doet hij mij alle namen wijzigen met een en dezelfde titel en dat was mijn vraag hoe dit kan en waar het aan ligt.

Hoe luidt de uiteindelijk uitgevoerde query? Heb je een ontwikkelomgeving waar je deze code schrijft en test? De uiteindelijke query zul je waarschijnlijk uit je logs moeten vissen. Dit is een ander "nadeel" aan prepared statements: je ziet niet (direct) welke query nu concreet wordt uitgevoerd.

Citaat:
Dat mijn manier van code niet correct is , oke dat snap ik, daar wil ik mij later zeer goed in verdiepen , maar wilde alleen dat klein stukje werkend hebben zodat de site door kan lopen.

Wellicht, maar het probleem is vaak niet het probleem, maar de benadering ervan. De strekking van een probleem is meestal zoiets als "Ik weet niet waarom X niet werkt". Dat X niet doet wat deze zou moeten doen kan doorgaans makkelijk vastgesteld worden. Maar het probleem is niet zozeer "waarom X niet werkt" maar meer "ik weet niet waarom". Daar zit hem de kneep: men heeft geen handvaten om meer informatie in te winnen over X die hun mogelijk naar de oorzaak van het probleem leidt (waaruit de oplossing meestal eenvoudig volgt) en ook weet men niet hoe men zelf deze handvaten zou moeten creëren. Oftewel: het analyseren en debuggen van code, daar wringt de schoen.

Concreet in jouw geval: je query doet niet wat deze zou moeten doen. Mijn eerste (logische) vraag is dan: hoe ziet jouw query er concreet uit? Je gebruikt prepared statements. Je kunt dan niet de uiteindelijk uit te voeren query bij zijn kladden pakken. Dus zul je deze moeten loggen terwijl deze wordt uitgevoerd. Hiervoor heb je ook zekere instrumentatie nodig (een ontwikkelomgeving waarvan je ongeveer weet hoe je hiermee om moet gaan en dingen kunt configureren). En vervolgens zul je je log na moeten kijken.

Of je gebruikt een variant waarbij je geen gebruik maakt van prepared statements. Je kunt dan wat makkelijker debuggen.

Om een probleem op te lossen moet je eerst snappen wat er gebeurt.
Offline pascalbianca - 02/07/2016 18:17
Avatar van pascalbianca Nieuw lid
Citaat:
Nou, dat doe je hier:
php code - Bekijk de code zonder highlighting - Klap code in
<?php
$statement->bind_param('ssi',$_POST["nfbgrang"], $_POST["NRang"], $_POST["GGEName"]);
?>

Hier zeg je: behandel het eerste argument (nfbgrang) als string, het tweede argument (NRang) als string en het derde argument (GGEName) als integer. De "typehints" zet je in het eerste argument: ssi.


Kan ik die typehints ergens achterhalen?
Want het moeten 3 strings zijn en geen 2 , dus zal die 'ssi' anders benaamd moeten worden denk ik.
Offline Thomas - 02/07/2016 19:28
Avatar van Thomas Moderator -_-

Maak er dan "sss" van... Ik denk dat je niet snapt hoe bind_param() werkt.
Offline pascalbianca - 03/07/2016 00:51 (laatste wijziging 03/07/2016 09:04)
Avatar van pascalbianca Nieuw lid ssi= string, string, integer

en

sss = 3 maal string

btw.: heb het script aan de praat eindelijk  
Nu kan ik mij verder verdiepen in die mysqli.
Gesponsorde links
Je moet ingelogd zijn om een reactie te kunnen posten.
Actieve forumberichten
© 2002-2024 Sitemasters.be - Regels - Laadtijd: 0.417s