Avatar billede meyer Nybegynder
21. marts 2013 - 11:06 Der er 38 kommentarer og
1 løsning

Fejlmelding når jeg prøver at hente menu med denne Ole har skrevet...

Jeg er ny i det her, så hvis det er et tåbeligt spørgsmål, så bær lige over med mig ;)

Først og fremmest ved jeg godt det IKKE er mysqli, men ville gerne bare ha' en succesoplevelse med at få den til at skriv noget ud på min skærm (helst de rigtige data), så må det laves om og mere sikker bagefter.

Ole har skrevet dette i en anden tråd, så jeg prøvede at tampe det ind og køre det med den fejler..

<?php
$con=mysql_connect("localhost","root","password","database");
// Check connection
if (!$con) {
    die("Database connection failed: " . mysql_error());
}

function getMenu() {
    $sql = 'SELECT * FROM menu ORDER BY parentcategory, id, name';
    $res = mysql_query($sql);
    $menu = array(
        'items' => array(),
        'parents' => array()
    );
    while ($row=mysql_fetch_assoc($res)) {
        $menu['items'][$row['id']] = $row;
        $menu['parents'][$row['parentcategory']][] = $row['id'];
    }
    return buildMenu($menu);
}
function buildMenu($menu, $parent=0) {
    $arrHTML = array();
    $arrHTML[] = '<ul>';
    foreach ($menu['parents'][$parent] as $id) {
        if (!isset($menu['parents'][$id])) {
            $arrHTML[] = '<li>ID: '.$menu['items'][$id]['id'].' :: Name: '.$menu['items'][$id]['name'].'</li>';
        }
        if (isset($menu['parents'][$id])) {
            $arrHTML[] = ' <li>'.$menu['items'][$id]['id'].' :: Name: '.$menu['items'][$id]['name'];
            $arrHTML[] = buildMenu($menu, $id);
            $arrHTML[] = '</li>';
        }
    }
    $arrHTML[] = '</ul>';
    return implode('', $arrHTML);
}

mysql_close($con);
?>
<?php echo getMenu() ?>

Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in C:\xampp\htdocs\tut\hent_menuer2.php on line 15

Notice: Undefined offset: 0 in C:\xampp\htdocs\tut\hent_menuer2.php on line 24

Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\tut\hent_menuer2.php on line 24

Har lavet en menu-tabel med id (int11 auto), name (varchar) og parentcategory (int11) tampet nogle data ind, er der nogen der kan hjælpe mig med at få hul igennem? :)

mvh
Dan
Avatar billede erikjacobsen Ekspert
21. marts 2013 - 11:49 #1
Fortæl hvad der sker hvis du ændrer

    $res = mysql_query($sql);

til

  $res = mysql_query($sql) or die(mysql_error());
Avatar billede meyer Nybegynder
21. marts 2013 - 11:51 #2
Ups... = no database selected.
Avatar billede meyer Nybegynder
21. marts 2013 - 12:18 #3
Burde den ikke spille?
Avatar billede erikjacobsen Ekspert
21. marts 2013 - 12:42 #4
Hvis linien
  $con=mysql_connect("localhost","root","password","database");
ellers indeholder de korrekte oplysninger, så burde det virke, og ikke give lige den fejl. Men er du sikker på, at du har oprettet "database" ?
Avatar billede meyer Nybegynder
21. marts 2013 - 12:48 #5
Ja hvis jeg kører det her så henter den alt:

<?php
$con=mysqli_connect("localhost","root","xxx","xxx");
// Check connection
if (mysqli_connect_errno())
  {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
  }

$result = mysqli_query($con,"SELECT * FROM menu");

echo "<table border='1'>
<tr>
<th>id</th>
<th>navn</th>
</tr>";

while($row = mysqli_fetch_array($result))
  {
  echo "<tr>";
  echo "<td>" . $row['id'] . "</td>";
  echo "<td>" . $row['name'] . "</td>";
  echo "</tr>";
  }
echo "</table>";

mysqli_close($con);
?>
Avatar billede erikjacobsen Ekspert
21. marts 2013 - 12:57 #6
Så har du jo nok skrevet forskelligt de to steder.
Avatar billede meyer Nybegynder
21. marts 2013 - 13:04 #7
Den eneste forskel der er, er at ved den ene står der mysql_connect og mysqli_connect ved den anden. Det her er sgu svært når man er ny i det :D
Avatar billede erikjacobsen Ekspert
21. marts 2013 - 13:41 #8
Okay, så da. Så skyldes det nok at du i det første eksempel får lukket forbindelsen til databasen før du begynder at bruge den.
Avatar billede meyer Nybegynder
21. marts 2013 - 13:54 #9
Næ det ændrede heller ikke noget at slette den linie der lukker den :(
Avatar billede olebole Juniormester
21. marts 2013 - 16:59 #10
<ole>

Din connection i spørgsmålet er forkert. Den håber jeg ikke, du har fra mig! Tjek manualen  *o)

/mvh
</bole>
Avatar billede meyer Nybegynder
21. marts 2013 - 17:13 #11
Nej den har jeg ikke fra dig, KUN functionen ;)
Avatar billede meyer Nybegynder
21. marts 2013 - 17:21 #12
Nu spytter den det ud :) det er sg genialt, var sikker på at jeg skulle lave et loop indeni loopet for at få undermenuerne ud på plads :D

Nu må jeg så se om jeg kan "konvertere" din artikel om mysqli ind her og få det på plads også :)
Avatar billede olebole Juniormester
21. marts 2013 - 17:43 #13
Med det gamle MySQL-API er der ingen tvivl om, at funktionen sparer ret meget ved kun at foretage ét kald til DB'en.

På den anden side afvikler kald med samme prepared statement (men med forskellige værdier), meget hurtigt med MySQLI-API'et. Derfor er forskellen mellem funktionen og DB-kald i en løkke formodentlig ikke nær så stor med MySQLI  =)
Avatar billede meyer Nybegynder
21. marts 2013 - 17:56 #14
Nej ok, men som du ved er jeg ny i det her, så jeg følger bare med stille og roligt og suger til mig :)

Den anden dag da du "sparkede" mig i gang http://www.eksperten.dk/spm/978494#reply_8042210 kunne jeg alligevel ikke få den til at loope inden i loopet, men håber jeg alligevel har fanget noget af det du prøver at fortælle/lære mig :)
Avatar billede olebole Juniormester
21. marts 2013 - 18:21 #15
Fortsæt bare med den, du har gang i her i tråden. Så kan du altid prøve den anden  =)

Om koden i den anden tråd skal dog lige siges, at den 'sparsommelige' måde består i at oprette dit statement nummer to én gang - gerne lige efter det første statement.

Inde i den første løkke binder du så parametre på det andet statement - hvorefter du eksekverer dette og henter de nye data. Noget i stil med:

$stmt_A = $mysqli->prepare( ... );
$stmt_B = $mysqli->prepare( ... );

$stmt_A->bind_param( ... );
$stmt_A->execute();
$stmt_A->bind_result( ... );

while (fetch) {
    echo ... ;
   
    $stmt_B->bind_param( ... );
    $stmt_B->execute();
    $stmt_B->bind_result( ... );
   
    while (fetch) {
        echo ... ;
    }
}

- men som sagt, så prøv først med den, du skriver i spørgsmålet  =)
Avatar billede meyer Nybegynder
21. marts 2013 - 19:06 #16
Tak skal du ha' - det vil jeg gøre :)
Avatar billede meyer Nybegynder
21. marts 2013 - 20:06 #17
Jeg kan få de her til at køre FØR din function, men prøver jeg queryen inde i functionen fejler den.

$mysqli = new mysqli("localhost", "root", "xxx", "db");

/* Tjek, om der opstod en fejl */
if (mysqli_connect_errno()) {
    echo 'Der opstod en fejl ved forbindelsen: ' . mysqli_connect_error();
    exit();
}
$stmt = $mysqli->query('SELECT * FROM menu ORDER BY parentcategory, id, name');

while ($row = $stmt->fetch_object()){
    echo $row->name . "<br>";
    }
Avatar billede olebole Juniormester
21. marts 2013 - 20:29 #18
Ja, for din variabel $mysqli er formodentlig erklæret i det globale scope (udenfor funktionen). Så kan den ikke 'ses' indefra funktionen. Åben forbindelsen i funktionen i stedet  =)
Avatar billede meyer Nybegynder
21. marts 2013 - 20:44 #19
Du er bare en HELT! ;) mange tak :)

Så ser den færdige sådan her ud - er det SÅ med SIKKER kode/forbindelse??

<?php
function getMenu() {
    $mysqli = new mysqli("localhost", "root", "mmgmeyer", "democms");
   
    if (mysqli_connect_errno()) {
      echo 'Der opstod en fejl ved forbindelsen: ' . mysqli_connect_error();
        exit();
    }
    $stmt = $mysqli->query('SELECT * FROM menu ORDER BY parentcategory, id, name');

    $menu = array(
        'items' => array(),
        'parents' => array()
        );
   
  while ($row = $stmt->fetch_assoc()) {
        $menu['items'][$row['id']] = $row;
        $menu['parents'][$row['parentcategory']][] = $row['id'];
    }
    return buildMenu($menu);
    $mysqli->close();
    }

    function buildMenu($menu, $parent=0) {
    $arrHTML = array();
    $arrHTML[] = '<ul>';
    foreach ($menu['parents'][$parent] as $id) {
        if (!isset($menu['parents'][$id])) {
            $arrHTML[] = '<li>ID: '.$menu['items'][$id]['id'].' :: Name: '.$menu['items'][$id]['name'].'</li>';
        }
        if (isset($menu['parents'][$id])) {
            $arrHTML[] = ' <li>'.$menu['items'][$id]['id'].' :: Name: '.$menu['items'][$id]['name'];
            $arrHTML[] = buildMenu($menu, $id);
            $arrHTML[] = '</li>';
        }
    }
    $arrHTML[] = '</ul>';
    return implode('', $arrHTML);
}
?>
<?php echo getMenu(); ?>
Avatar billede olebole Juniormester
21. marts 2013 - 20:49 #20
Alt ser fint ud  =)
Avatar billede meyer Nybegynder
21. marts 2013 - 20:55 #21
DEJLIGT!..endnu engang tusind tak Ole :)
Avatar billede olebole Juniormester
21. marts 2013 - 21:10 #22
You're welcome  =)
Avatar billede meyer Nybegynder
21. marts 2013 - 21:27 #23
Der er dog en lille fejl når den skriver ud som jeg ikke lige kan gennemskue:

    function buildMenu($menu, $parent=0) {
    $arrHTML = array();
    $arrHTML[] = '<ul>';
    foreach ($menu['parents'][$parent] as $id) {
        if (!isset($menu['parents'][$id])) {
            $arrHTML[] = '<li>ID: '.$menu['items'][$id]['id'].' :: Name: '.$menu['items'][$id]['name'].'</li>';
        }
        if (isset($menu['parents'][$id])) {
            $arrHTML[] = ' <li>'.$menu['items'][$id]['id'].' :: Name: '.$menu['items'][$id]['name'];
            $arrHTML[] = buildMenu($menu, $id);
            $arrHTML[] = '</li>';
        }
    }
    $arrHTML[] = '</ul>';
    return implode('', $arrHTML);
}

Hovedmunuerne der ikke har undermenuer skriver den fint, men når hovedmenuen har undermenuer lukker den ikke </li> men </ul>, </li> kommer først efter undermenuerne, her er et udskrift:

<ul>
<li>ID: 1 :: Name: Forside</li>
<li>2 :: Name: Hvem er vi
<ul>
  <li>ID: 5 :: Name: Medarbejdere</li>
  <li>ID: 6 :: Name: Kontoret</li>
</ul></li>
<li>3 :: Name: Løsninger
<ul>
  <li>ID: 7 :: Name: Tryksager</li>
  <li>ID: 8 :: Name: Logoer</li>
  <li>ID: 9 :: Name: Web</li>
</ul></li>
<li>ID: 4 :: Name: Kontakt</li>
</ul>
Avatar billede meyer Nybegynder
21. marts 2013 - 22:17 #24
Bare glem det, taler i febervildelse her, ligger med influenza og høj feber :D
Avatar billede olebole Juniormester
21. marts 2013 - 22:30 #25
Ja, man får zq pip af det der fugleinfluenza!  *D

Hvis du er ved at være der, hvor problemerne er løst, lægger du bare selv et svar og accepterer det, så tråden lukkes. Hverken Erik eller jeg samler point  =)

God bedring! Jeg kan anbefaler te - en god portion sukker - og rigeligt med rom. Det er en elendig medicin - men 'fluen' bliver straks en hel del hyggeligere  *o)
Avatar billede olebole Juniormester
21. marts 2013 - 22:33 #26
PS: Undgå endelig Earl Gray til dén drik. EG får te med rom til at smage, som om det allerede er løbet igennem en kat  :o|
Avatar billede meyer Nybegynder
22. marts 2013 - 08:07 #27
Hahaha.. tak og tak for rådet :D Men hvorfor fanden vil du slå mig ihjel?.. The kan da ikke være sundt for noget som helst ;)

Ja tak, er lige ved at være der, kunne dog f.eks. godt tænke mig at skifte stylesheet på undermenuerne, altså hvis det er en hovedmenu <ul class"hovedmenu">.. er det en undermenu <ul class"undermenu">, kan bare ikke lure hvor jeg skal putte det ind i dit loop :)

Udover det skal jeg nok ha' nogle flere felter med over til de forskellige links, men det tror jeg godt jeg kan klare :)
Avatar billede olebole Juniormester
22. marts 2013 - 15:10 #28
Hehe ... jeg rører ikke selv tørrede blade fra dén busk, når jeg ikke er syg - og god kaffe med rom er en langt mere beskeden fornøjelse  =)

Du kan gøre sådan:

<style type="text/css">
ul {
    background: red;
}
ul ul {
    background: yellow;
}
</style>

- eller du kan gøre sådan:

function buildMenu($menu, $parent=0) {
    $arrHTML = array();
    $class = $parent==0 ? 'hovedmenu' : 'undermenu';
    $arrHTML[] = '<ul class="' . $class . '">';

    foreach ($menu['parents'][$parent] as $id) {
        if (!isset($menu['parents'][$id])) {
            $arrHTML[] = '<li>ID: '.$menu['items'][$id]['id'].' :: Name: '.$menu['items'][$id]['name'].'</li>';
        }
        if (isset($menu['parents'][$id])) {
            $arrHTML[] = ' <li>'.$menu['items'][$id]['id'].' :: Name: '.$menu['items'][$id]['name'];
            $arrHTML[] = buildMenu($menu, $id);
            $arrHTML[] = '</li>';
        }
    }
    $arrHTML[] = '</ul>';
    return implode('', $arrHTML);
}
Avatar billede olebole Juniormester
22. marts 2013 - 15:13 #29
Linjen:

$class = $parent==0 ? 'hovedmenu' : 'undermenu';

- svarer til at skrive:

if ($parent==0) $class = 'hovedmenu';
else $class = 'undermenu';
Avatar billede meyer Nybegynder
22. marts 2013 - 15:33 #30
Haha.. tror bare du har ret, jeg holder mig også til kaffen, men på den anden side efter nogle få kopper er man nok ikke så sart mere :D

Jeg tror bedst jeg kan li' den med $class, kan godt se den anden er nemmere, men den her lærte mig jo noget bedre ;) og den der "sammentrækning" du laver med den if-else, den er sg da genial, hvorfor gøre det sværere end det er :)

Jeg havde prøvet alt inde i den funktion, hentet en variabel fra db hvor hovedmenu var 1 og lavet den if-else, men INTET virkede og kommer du bare og skriver en lille linie, altså! :)

Og endnu endnu endnu. osv...en gang.. tusind tak igen :)
Avatar billede olebole Juniormester
22. marts 2013 - 15:49 #31
Den laveste ID, du har i databasen er 1 - og $parent i funktionen er den ID, som den pågældende menu skal lægge sig under. Når $parent er 0, må vi derfor være ude i roden (= 'hovedmenuen')
Avatar billede meyer Nybegynder
22. marts 2013 - 15:53 #32
Jeps, den har jeg luret :) men i databasen lavede  jeg et 1 tal når det er en hovedmenu, det var det jeg prøvede at tjekke den op imod uden held :) Men alle de sidespring er jo spild af tid har jeg nu lært, hvorfor gøre det mere besværligt end det er.
Avatar billede olebole Juniormester
22. marts 2013 - 16:01 #33
Præcis  *o)
Avatar billede erikjacobsen Ekspert
22. marts 2013 - 20:16 #34
Som man siger: Tee trinkt der Wiener nur, wenn er krank ist.

Jeg tror jeg skal ændre strategi på eksperten.dk - sådan noget i retning af at læse og forstå hele spørgsmålet, inden jeg svarer. Sædvanligvis finder jeg eet ømt punkt, og kigger ikke på resten - der er jo også det nemmeste.

Til hr. Meyer, en lille anbefaling: hvis din menu ikke ændrer sig tit, kan du med fordel generere den een gang for alle, og gemme den som tekstfil, eller i et databasefelt. Dermed nedbringes det arbejde, der skal laves for hver sidevisning, mod at du ved ændringer af menuen genererer denne "cache" een gang til.
Avatar billede olebole Juniormester
22. marts 2013 - 20:46 #35
- og lad mig i den forbindelse udtale de senere så berømte ord:

"Ich bin ein Wiener!"
- Ole Bole


Derudover er jeg helt enig med Erik. Har man skrevet et lille CMS til at oprette/rette/slette sider i, kunne man kalde funktionen i slutningen af hver rettelse. Så vil menuen altid være cached i aktuel version
Avatar billede meyer Nybegynder
22. marts 2013 - 21:59 #36
Tak for rådet :) den er lavet :D

file_put_contents('menu.php',getMenu());

Og ja Ole, den smider jeg ind til sidst i admin-menudelen af cms'et, kan godt se ideen i det Erik kom med der, vi må ha' faaart og spare på kræfterne :D
Avatar billede olebole Juniormester
22. marts 2013 - 22:04 #37
Ja, sålænge han er rask og ikke i Wiener-mode, er det nogle helt fornuftige og ædruelige forslag, Erik bidrager med  *o)
Avatar billede olebole Juniormester
22. marts 2013 - 22:06 #38
- men, selvom det ikke er roskildesyge, så pas på med ikke at få for meget 'fart' på!  *D

Arrrhhhhh ... arrhhhh ... det kan man ikke sige, Ole!
Avatar billede meyer Nybegynder
22. marts 2013 - 22:11 #39
haha, hold ham endelig fra theen så, jeg har brug for hjælpen ;)

Men seriøst, jeg har haft en super god uge her, syg eller ej, så føler jeg at jeg er kommet rigtigt langt med det her php på så kort tid, det giver sgu da blod på tanden :)

(og JA Erik ved godt jeg skulle ha' gjort det for mange år siden)

.. men havde det jo godt der som Palle alene i ASPverdenen :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester