Beste

Ik ben bezig met adresboek te ontwikkelen. Daarin zit database met een tabel contacts. Deze tabel bevat enkele basisgegevens: naam, adres, telefoonnummer en email. Nu wil de klant dat de mogelijkheid er is om velden toe te voegen (dat meldde hij later). Daardoor ontstaat een volledig dynamische tabel.

Nu is mijn vraag: is het mogelijk om zo'n dynamic table te fetchen, zodat ik hem toch volledig kan weergeven, inclusief de custom informatie?

De code die ik al heb, ziet er als volgt uit:


<?php
class Contacts
{
    public getAll()
    {
        // Select all data from contacts
        $query = $db->query('select * from contacts');
        // create table
        echo '<table>';
        // create table header
        echo '<theader><tr>';
        for($counter=0; $counter < $query->columnCount(); $counter++) {
            $meta = $query->getColumnMeta($counter); // get column meta data
            echo '<th>'.$meta['name'].'</th>'; // print the column name from the meta data
        }
        echo '</tr></theader>';
        
        // create table body
        echo '<tbody>';
        foreach($query as $row) {
            // hier weet ik niet wat gedaan moet worden
        }
        echo '</tbody></table>';
    }
}


Zoals je kunt zien, heb ik wel al de tabelhoofding goed, maar ik weet niet hoe ik de tabelinhoud goed kan zetten.

Is er iemand die me een tip zou kunnen geven waar ik uitleg kan krijgen over hoe dit moet, of iemand die me wellicht wat op weg kan helpen?

Alvast bedankt :)
Je kan de database relationeel maken door alle velden in een aparte tabel (Fields) op te slaan. Dan kan je dus velden aanmaken voor Facebook, Twitter, Instagram, Steam, Nood-telefoonnummer etc...

In een koppeltabel Velden_Personen koppel je dan de velden met de juiste personen, en bij het ophalen gebruik je een JOIN. Het voordeel is dat je onbeperkt aantal velden kan gebruiken bij een persoon zonder je structuur steeds aan te passen.
Ik zie niet echt wat je bedoelt... zou je eens een mini-voorbeeldje kunnen geven?
Ik zou sowieso niet alles weergeven? Niet alles is interessant voor de gebruiker?
Maak bijvoorbeeld een whitelist van kolomnamen? Hardcoded of schrijf een klein beheerscherm waarin je aan kunt vinken wat iemand ziet?

En anders draai je gewoon alles af wat in de $row zit met nog een foreach?

Enne, co[color=#ff0000]tn[/color]acts? :p
@Thomas hahaha ja dat laatste was een typefoutje. Whoops :p
Maar daar gaat het juist over: ik ken de keys in de array, of toch niet allemaal. Hoe kan ik dat dan oplossen?
Je vraagt toch alle kolommen op met SELECT * ?

Dat lijkt mij dan irrelevant?

Je weet ook hoeveel kolommen het zijn (columnCount()) en hoe deze heten (getColumnMeta()).

Waar loop je dan precies vast? Je kunt $row gewoon uitdraaien met een foreach()?
@Thomas
Werkt dit dan?:


<?php
foreach($query as $row) {
echo '<tr>';
for($counter=0; $counter < $query->columnCount(); counter++) {
$meta = $query->getColumMeta($counter);
echo '<td>'.$row[$meta['name']].'</td>';
}
echo '</tr>';
}


@AdoptiveSolution Ja, bedankt. Was even vergeten hoe dat zat. Zal dit ook aanpassen.
Uhh, of je pakt meteen de value?
<?php
foreach ($row as $value) {
    // whee
}
?>

Je hebt de kolomnamen daar niet nodig?

EDIT: op een soortgelijke wijze kun je on the fly de kolomnamen ophalen als je de eerste rij uitdraait.

<?php
// @todo check of er uberhaupt iets weer te geven valt?
?><table><?php
    $printHeader = true;
    foreach ($query as $row) {
        if ($printHeader) {
            ?><thead><tr><?php
                foreach ($row as $name => $whatever) {
                    ?><td><?php echo $name; ?></td><?php
                }
            ?></tr></thead>
            <tbody><?php
            $printHeader = false;
        }
        ?><tr><?php
            foreach ($row as $value) {
              ?><td><?php echo $value; ?></td><?php
            }
        ?></tr><?php
    }
    ?></tbody>
</table><?php
// @todo check of er uberhaupt iets weer te geven valt afsluithaak
?>

Daarbij doe je er verstandig aan om output ($name, $value) te escapen.
Zelf zou ik de gebruiker de tabel niet uit laten breiden. Dan komen ze weer met allemaal "kolomnamen" die problemen opleveren (spaties, leestekens, enz). Je kunt beter met een aparte tabel met "extra velden" werken (dat is volgens mij ook wat Ariën bedoelt).


contacts: //je bestaande tabel
- id //pri.key
- naam
- adres
- telefoonnummer
- email

contact_meta //deze moet "de klant" dus ergens kunnen beheren
- id //auto-inc pri.key
- naam //naam voor de "extra kolom"
- seq //sorteer volgorde (int)

contact_meta_data
- contact_id //ref naar contacts.id
- meta_id //ref naar contact_meta.id
- value //waarde

Als je nou je data op wilt halen doe je (pseudo code):
[code]<?php

$metas = $db->record('select id,naam from contact_meta order by seq');
//retourneert een assoc.array met id => naam voor "extra kolommen" paren
//bijvoorbeeld [1 => 'Facebook', 2 => 'Twitter', ...]

//query opbouwen, incl meta data
$sql = 'select c.*';
foreach($metas as $id => $name) $sql .= ",
(select value from contact_meta_data where contact_id = c.id and meta_id = $id) as meta$id";
$sql .= "\n from contacts c";
//alle meta data zit dus per record als meta? (? = id) in hetzelfde record als de basisgegevens
//evt die($sql) en dan in phpMyAdmin uitvoeren om te zien hoe & wat

//tabel header (basis + meta)
print('<table><thead><th> {basisgegevens} </th>');
foreach($metas as $name) print('<th>' . htmlspecialchars($name) . '</th>');
print('</tr></thead><tbody>');

//tabel data (basis + meta)
foreach($db->all($sql) as $record){
print('<tr><td> {basisgegevens} </td>');
foreach($metas as $id => name) print('<td>' . htmlspecialchars($record['meta' . $id]) . '</td>');
print('</tr>');
}

//tabel sluiten
print('</tbody></table>');
?>
Het voorstel van @Rob is wellicht geschikter voor wat je probeert te doen.

Waar je wel over na moet denken is het volgende: de bovestaande manier beschrijft enkel hoe je je data organiseert en IN je database krijgt. Misschien moet je ook even nadenken hoe je deze er weer UIT haalt, vooral als je wilt kunnen zoeken in deze data, met zoekvelden en filters enzo.

Reageren