mysqli_query() expects parameter 1 to be mysqli,

dreggert

Mitglied
Hallo. Ich baue gerade meine Webseite um und versuche grade die DB-Abfrage auf das MySqli anzupassen. Nun bekomme ich aber immer die im Betreff stehende Meldung.

Code Functions.php
Code:
function dbconnect()
{
  $server = "localhost";
  $user = "geral_eggi";
  $pass = "*****";
  $database = "geraldeg_gerald";
 
 
$link = mysqli_connect($server, $user, $pass, $database) or die("Error " . mysqli_error($link));
$link->set_charset("utf8");
}


Im Skript rufe ich dann die Funktion wie folgt auf:

Code:
 require_once('./functions.php');
  dbconnect();  
  echo "<table>";
  $sqlleben="SELECT * FROM lebenslauf ORDER by id DESC";
  //echo  $sqlleben;
  mysqli_query($link,$sqlleben)or die("Error: ".mysqli_error($link));   
  while ($rowleben=mysqli_fetch_array($resleben,MYSQL_ASSOC))   
  {
  $jahr=$rowleben['jahr'];
  $job=$rowleben['job'];
  echo "<tr><td width=\"40%\">".$jahr."</td><td>".$job."</td></tr>";
  echo "<tr><td colspan=\"2\" align=\"center\"><br><hr ></br></td></tr>";
  }
echo "</table>";


Wenn ich nun die Seite aufrufe, kommt die Meldung
Warning: mysqli_query() expects parameter 1 to be mysqli, null given in C:\xampp\htdocs\gerald\uebermich\lebenslauf.php on line 13


Nehme ich den Funktionsaufruf weg und setze den Verbindungsaufbau direkt vor die Datenbankabfrage, funktioniert der Aufbau der Datenbankverbindung.
 

ComFreek

Mod | @comfreek
Moderator
Du erstellst die Variable $link in einer Funktion als lokale Variable. Du kannst außerhalb dieser Funktion darauf nicht zugreifen.

Eine sehr schlechte Notlösung ist, globale Variablen zu nutzen.
Die einzig gute Problemlösung ist es, deinen Spaghetticode in eine MVC-Struktur (o. Ä.) umzuformen. HTML und DB-Abfragen zu mischen, zeugt meist von sehr schlechtem Code.
 

ComFreek

Mod | @comfreek
Moderator
Das hast nichts mit der alten oder neuen MySQL(i)-Erweiterung zu tun. Es geht einfach darum, dass lokale Variablen einer Funktion außerhalb dieser Funktion ohne Weiteres nicht sichtbar sind.

Der Wandel zum MVC-Prinzip ist nicht einfach so in einer Stunde / an einem Tag / in einer Woche vollzogen. Es hängt natürlich von deiner aktuellen Codebasis ab. Ich schätze mal, dass die eher klein ist, da du die DB-Verbindung noch nicht hinbekommen hast.
Zum Informieren kannst du erst einmal Wikipedia konsultieren: Model-view-controller

Ansonsten würde ich dir ein PHP-Framework empfehlen. Die meisten bieten eine fundierte Grundstruktur für das MVC-Prinzip. Natürlich werden dadurch auch einige Dinge hinter den Kulissen versteckt, d. h. der Lerneffekt ist geringer, jedoch dein Code hoffentlich sauberer.

Nehmen wir eine Zeile aus deinem obigen Code:
PHP:
mysqli_query($link,$sqlleben)or die("Error: ".mysqli_error($link));
Schlägt das Query fehl, so bricht das ganze PHP-Skript wegen die() ab! Du hast überhaupt nicht die Möglichkeit den Fehler irgendwo zu behandeln oder zu protokollieren. Stattdessen wird dem Otto Normalverbraucher eine wahrscheinlich kryptische Fehlermeldung präsentiert. Die Lösung wäre es, Exceptions zu benutzen. Doch wo willst du diese abfangen? Hier stößt du an Grenzen deines aktuellen Designs.
 

TheBodo

Erfahrenes Mitglied
Moin,

ja mit mysql_ hat das gut funktioniert, weil er eben intern die Verbindung global gespeichert hat.
Das tut mysqli nicht mehr. Aber das ist jetzt alles auch kein Beinbruch.

Die wichtigere Frage ist doch eher, warum du die DB-Verbindung in einer Funktion aufbaust.
Zum einen gibt es die Funktion ja schon, also warum sie also nochmal mit einer neuen "ummanteln"?
Zum anderen wirst du die Datenbankverbindung pro Seitenaufruf nur einmal benötigen, bei anderen Seiten ggf. sogar gar nicht. Ich würde das einfach in ein kleines Skript auslagern, das du am Anfang deiner Seite einbindest, wenn du es brauchst. Dazu dann ein zweites Skript, das die Verbindung schließt und am Ende der Seite eingebunden wird.

Beispiel:

Datei: dbcon.php (am besten in einem Ordner, der von aussen nicht lesbar ist)
PHP:
<?php
$server = "localhost";
$user = "geral_eggi";
$pass = "*****";
$database = "geraldeg_gerald";

$link = mysqli_connect($server, $user, $pass, $database) or print("Error " . mysqli_error($link));
$link->set_charset("utf8");
?>

Datei: dbclose.php
PHP:
<?php
$link->close();
?>

Datei: seite.php
PHP:
<?php
//starten
require("dbcon.php");

//$link ist jetzt hier benutzbar
$result = $link->query("SELECT * ....");

//schließen
require("dbclose.php");
?>

Solltest du es hingegen unbedingt als Funktion machen wollen, gib die Verbindung zurück.

PHP:
<?php
function db_connect($server, $user, $pass, $db) {
    $link = mysqli_connect($server, $user, $pass, $database) or print("Error " . mysqli_error($link));
    $link->set_charset("utf8");
    return $link;
}

$link = db_connect("localhost", "nutzer", "***", "bank_daten-bank");
$link->query("...");
$link->close();

Ich weiß ja nicht wo du mit deiner Applikation hin willst, aber wenn du schon auf mysqli umstellst, solltest du auch prepared statements betrachten, und nicht nur die Funktionsaufrufe ändern.
Außerdem empfiehlt sich dann gleich auch die Umstellung auf objektorientierte Programmierung.

Zu ComFreeks Kommentar:

Ich hab auch schon oft Projekte angefangen, die erst klein schienen. Einige davon haben mittlerweile über 100 PHP-Skripte. Am Ende ärgert man sich dann, das man das nicht alles vorrauschauender mit Frameworks oder besserer Funktionstrennung entwickelt hat. Sowas lohnt sich schon, und wenn du wirklich mal produktiv in dem Bereich arbeiten willst, kann ein Blick nicht schaden.

Hoffe das hilt soweit.
 

ComFreek

Mod | @comfreek
Moderator
ja mit mysql_ hat das gut funktioniert, weil er eben intern die Verbindung global gespeichert hat.
Das tut mysqli nicht mehr. Aber das ist jetzt alles auch kein Beinbruch.
In der Tat hat die zuletzt geöffnete Verbindung bei der alten MySQL-Erweiterung sozusagen als globale Variable agiert. Das Problem ist allerdings: Globale Variablen sind schlecht!
Wie willst du bei Unit Tests Mocks verwenden, wenn dein ganzer Code auf globalen Variablen basiert? Vor allem noch auf globalen Variablen, die du nicht beeinflussen kannst - wie in dem Fall von MySQL!

Dasselbe Problem wirst du bei dem von dir vorgeschlagenen Code erleben. $link ist eine globale Variable!
Kurzum: Greif zu Frameworks mit einem etablierten Codeaufbau und -strukturierung.
 

TheBodo

Erfahrenes Mitglied
In der Tat hat die zuletzt geöffnete Verbindung bei der alten MySQL-Erweiterung sozusagen als globale Variable agiert. Das Problem ist allerdings: Globale Variablen sind schlecht!
Wie willst du bei Unit Tests Mocks verwenden, wenn dein ganzer Code auf globalen Variablen basiert? Vor allem noch auf globalen Variablen, die du nicht beeinflussen kannst - wie in dem Fall von MySQL!

Dasselbe Problem wirst du bei dem von dir vorgeschlagenen Code erleben. $link ist eine globale Variable!
Kurzum: Greif zu Frameworks mit einem etablierten Codeaufbau und -strukturierung.

Ja, $link ist im globalen Bereich definiert. Wenn er auf objektorientierte Programmierung umsteigt, dann kann er es ja in eine entsprechende Klasse auslagern. Und ja, MVC ist hilfreich und (gute) Frameworks erleichtern die Arbeit und den gesamten Entwicklungsprozess. Ich habe auch schon Leuten bei gewissen Fragen empfohlen, ihr Projekt mal in UML zu planen o. ä.

ABER:

Ich weiß nicht wie weit der / die Fragende in PHP ist. Das er sich mit mysqli statt mysql befasst ist schonmal positiv. Man wird sehen wie das weitergeht, oder auch nicht. Die Hinweise sind auch alle gut gemeint. Aber m. E. kommen sie zum falschen Zeitpunkt. So wie die Funktionen oben benutzt werden, scheint er / sie mir noch nicht objektorientiert zu programmieren. Das halte ich aber für eine wichtige Grundlage, um durch die Frameworks durchzusteigen. Wenn er sich seinen eigenen Controller oder sein eigenes Model bauen muss für seine Daten, dann kommt er da nicht drum herum.
Ihn ohne Lösung zu lassen, so dass die Applikation auf mysql bestehen bleibt und die Einarbeitung in neues aufgeschoben oder abgebrochen wird, halte ich für nicht zielführend.

Also nicht überfordern, sondern den nächsten Schritt zeigen. Ansonsten stimme ich mit dir überein.
 

sheel

I love Asm
@TheBodo: Zum zweiten Absatz: Man könnte vom Fragesteller auch erwarten,
zuerst nötige Grundlagen für ein Vorhaben zu lernen. Einfach bei Bedarf nur schnell
googlen etc., bis man eine irgendwie funktionierende Lösung zusammengefrickelt hat,
bringt auf lange Sicht nichts.
 

TheBodo

Erfahrenes Mitglied
Ich stimme dir vollkommen zu, ich nehme jedoch an, dass das Vorhaben schon umgsetzt wurde, und nun ein Update erhalten soll. Wieviel Mühe man sich dabei macht, bleibt dem jeweiligen Programmierer überlassen. Aber ein bestehendes System auf ein Framework umzustellen ist viel Arbeit. Falls jemand diese Arbeit nicht investieren kann, hilft es wenig ihm die Vorteile von mysqli deswegen vorzuenthalten.

Hier abschlißend ein Link zu einem OOP Tutorial, das auch nochmal kurz erzählt, warum OOP toll und sinnvoll ist:

http://www.peterkropff.de/site/php/oop.htm

Ansonsten allen weiter ein fröhliches hacken.