Visualizzazione risultati 1 fino 17 di 17
Like Tree1Likes
  • 1 Post By mzanella

Discussione: Script PHP con MySQL

  1. #1
    kittbobba non è connesso Neofita
    Data registrazione
    01-08-2014
    Messaggi
    11

    Question Script PHP con MySQL

    Salve, ho scaricato un template Bootstrap e vorrei inserire al suo interno uno script MySQL
    id | day | time
    1 | 2 | 17
    2 | 2 | 18
    3 | 3 | 20
    5 | 2 | 12
    5 | 2 | 13

    day sarebbe il giorno della settimana, quindi 5 = venerdi mentre time l'ora del giorno.

    Vorrei che qui: http://kittbobba.altervista.org/sito/
    dove c'è Event Schedule mi stampi il seguente risultato:
    http://kittbobba.altervista.org/risultato.png
    Si può fare? Non ho idea da dove partire, immagino serva più di un ciclo

    Ricapitolando:
    Se non c'è nessun evento in quel giorno della settimana non stampa neanche il giorno mentre se c'è qualcosa stampa il giorno più gli eventi

  2. #2
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Come primo passo, scomponi il problema in componenti più piccole.

    Da quanto ho capito hai un insieme di eventi non in relazione tra loro dei quali è noto il momento (giorno e ora) di inizio, e vuoi mostrare il programma degli eventi all'interno di un intervallo di date specifico (dall'esempio sembra una settimana), ordinati per momento di inizio.

    Avrai bisogno di memorizzare le informazioni in una base di dati, se non l'hai già fatto. Dall'esempio che hai mostrato, sembra che tu abbia un entità event con almeno questi attributi: id, name, description, start_time. I primi tre sono autoesplicativi mentre il quarto, di tipo DATETIME o analogo, rappresenta giorno e ora di inizio dell'evento.

    Quindi avrai bisogno di funzioni (PHP) per interagire con la base di dati. A seconda dell'architettura che stai adottando questo potrebbe tradursi in classi e metodi o in funzioni. Senza perdita di generalità assumiamo che si tratti di funzioni, e che gli eventi siano rappresentati da vettori associativi. Oltre al classico CRUD (Create - Read - Update - Delete) ti servirà una funzione che restituisca la lista degli eventi programmati in un intervallo di date:
    Codice PHP:
    event_search_by_date($from = null, $to = null)
    la quale restituisce gli eventi la cui data di inizio è successiva a $from (o non vincolata se $from è null) ed antecedente a $to (o non vincolata se $to è null). Dovrai scegliere un formato per i parametri $from e $to, ad esempio un timestamp (intero) o una data testuale. In ogni caso è possibile passare da un formato all'altro al bisogno. Con queste informazioni puoi costruire una query analoga a:
    Codice:
    SELECT id, name, description, start_time FROM event
    WHERE start_time >= from AND start_time <= to
    ORDER BY start_time ASC
    avendo cura di convertire from e to nello stesso formato che hai usato nella base di dati, e di gestire i casi in cui almeno uno dei due è null. Gli eventi saranno restituiti sotto forma di vettore contenente vettori associativi, ad esempio:
    Codice:
    [
        [
            "id" => 3,
            "name" => "Evento 1",
            "description" => "...",
            "start_time" => "...",
        ],
        [
            "id" => 4,
            "name" => "Evento 2",
            "description" => "...",
            "start_time" => "...",
        ],
        ...
        [
            "id" => 42,
            "name" => "Evento N",
            "description" => "...",
            "start_time" => "...",
        ]
    ]
    Ulteriori dettagli dipendono strettamente dall'ambiente che hai creato, ad esempio l'uso di mysqli o PDO per interrogare la base di dati. Non mysql, poiché deprecato.

    Avendo a disposizione questa funzione puoi invocarla nella pagina PHP passandole i parametri $from e $to relativi ad un dato giorno. Per come è strutturata la funzione ed in relazione a ciò che intendi ottenere, essi dovranno "puntare" rispettivamente alla mezzanotte del primo giorno della settimana di interesse ed alle 23:59 dell'ultimo giorno della settimana di interesse, ad esempio:
    Codice PHP:
    $events = event_search_by_date("2018-06-09 00:00:00", "2018-06-15 23:59:00")
    Fatto ciò, all'interno del vettore $events avrai a disposizione tutti i dati di cui hai bisogno.

    Se $events è vuoto, non mostrerai nulla. Altrimenti, ti basterà scorrerlo e stamparne il contenuto in maniera opportuna. Per ottenere un effetto simile all'esempio che hai mostrato, potrebbe essere utile raggruppare preventivamente gli eventi in base al giorno:
    Codice PHP:
    $grouped_events = [];
    foreach (
    $events as $event) {
    // Legge il giorno in cui l'evento comincia.
    // L'implementazione dipende da come hai deciso di rappresentare il giorno.
    $day = event_get_day($event);
    $grouped_events[$day][] = $event;
    }
    Così facendo avrai a disposizione un vettore associativo raggruppato per giorno:
    Codice:
    [
        "2018-06-09" => [
            ["id" => 3, "name" => "Evento 1", description => "...", start_time => "2018-06-09 08:30:00"],
            ["id" => 7, "name" => "Evento 2", description => "...", start_time => "2018-06-09 12:30:00"]
        ],
        ...,
        "2018-06-14" => [
            ["id" => 42, "name" => "Evento N", description => "...", start_time => "2018-06-14 22:00:00"]
        ],
    In questo caso potrai avvalerti di due cicli innestati per mostrare gli eventi raggruppati per giorno:
    Codice PHP:
    foreach ($grouped_events as $day => $events) {
    echo
    "Events on: $day\n";
    echo
    "<ul>";
    foreach (
    $events as $event) {
    echo
    "<li>" . $event['start_time'] . ": " . $event['name'] . "</li>";
    }
    echo
    "</ul>";
    }
    L'ultimo passo è ottenere l'effetto grafico che hai mostrato. Essendo una questione di resa grafica dovresti capire come usare HTML e CSS per ottenere ciò che cerchi. A prima vista un'idea potrebbe essere realizzare due colonne, una con i nomi dei giorni della settimana ed una con gli eventi. Quella con gli eventi è relativamente semplice. Quella con i nomi dei giorni va resa, tramite CSS, in modo che ogni riga con un giorno mostri il nome del giorno dentro un cerchio, mentre le righe senza nome mostrino un cerchio più piccolo, il tutto con una linea verticale. Ma questo è, appunto, l'ultimo passo.

    Questo è lo schema generale, molti punti sono lasciati indefiniti perché dipendono dalle scelte implementative che hai fatto o che farai.
    Ultima modifica di mzanella : 12-07-2018 alle ore 22.54.16

    I suggerimenti che do più spesso:


  3. #3
    kittbobba non è connesso Neofita
    Data registrazione
    01-08-2014
    Messaggi
    11

    Predefinito

    Grazie mille per la risposta @mzanella !
    Ho creato la tabella eventi con le colonne id (primario), day(int), time(int).
    Considerando che ogni evento dura un'ora precisa ho pensato che inserire il dato "datatime" non mi servisse, perchè appunto vorrei che se nella colonna time è presente ad esempio il dato 16 sulla pagina mostri 16:00 - 17:00 e questo ho pensato di farlo ad esempio così:
    Codice PHP:
    $link = mysqli_connect('localhost','root','','');
    $query = mysqli_query($link, "SELECT * FROM eventi");
    $array = mysqli_fetch_assoc($query);
    $ora = $array['time'];
    echo
    "Ora: $ora:00 - " . $ora=$ora+1 . ":00";
    Fare la parte di CSS per me non è un problema ma sono abbastanza negato in linguaggio lato server e non so bene come fare questa funzione.

    Ogni domenica resetto la tabella quindi non ho bisogno neanche di un controllo /giorno/mese/anno ecc.
    Lasciando perdere la parte grafica il risultato che vorrei ottenere è il seguente
    Codice:
    Tabella eventi:
    id  | day  | time
    1   |  1   |  10
    2   |  1   |  11
    3   |  1   |  17
    4   |  3   |  11
    5   |  4   |  10
    6   |  4   |  15
    7   |  4   |  18
    8   |  4   |  21
    9   |  6   |  12
    10  |  7   |  09
    
    Pagina di output:
    Lunedi
    10:00 - 11:00
    11:00 - 12:00
    17:00 - 18:00
    
    Mercoledi
    11:00 - 12:00
    
    Giovedi
    10:00 - 11:00
    15:00 - 16:00
    18:00 - 19:00
    21:00 - 22:00
    
    Sabato:
    12:00 - 13:00
    
    Domenica
    09:00 - 10:00
    Purtroppo non posso modificare la disposizione della tabella perchè è collegata ad un pannello fatto in php che mi gestisce tutto
    Ultima modifica di kittbobba : 13-07-2018 alle ore 02.57.07

  4. #4
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Ogni domenica resetto la tabella quindi non ho bisogno neanche di un controllo /giorno/mese/anno ecc.
    E' un modo quantomeno... bizzarro di usare una base di dati!

    Sotto queste premesse puo' certamente funzionare, ma un'architettura di questo tipo non e' molto buona. In primo luogo, ti stai vincolando per l'eternita' a poter gestire solo eventi che iniziano alle ore X e zero minuti. Questo vincolo ora puo' sembrare ragionevole, ma lo sara' anche fra 5 o 10 anni?
    Analogamente costringi gli eventi a durare un'ora esatta.
    La parte su cui ho dubbi maggiori e' il fatto di svuotare e ripopolare la base di dati ogni settimana: supponiamo che io sia un utente interessato agli eventi che gestisci, e vorrei organizzarmi per seguirne uno... la prossima settimana. Con l'impostazione che hai adottato questo non e' possibile, perche' hai scelto di mostrarmi solo gli eventi nella settimana corrente, da lunedi' a domenica.
    Peggio ancora, se ora fosse domenica sera e volessi vedere quali eventi hai in programma per domani mattina (lunedi') non avrei accesso a questa informazione.
    Un'altra limitazione e' che rinunci alla possibilita' di avere un archivio degli eventi passati, funzionalita' non indispensabile ma comunque interessante.
    Infine c'e' da dire che, se decidi di usare INT per giorno e ora, accetti la possibilita' di avere eventi il "giorno 348 alle ore 3500:00". Per tutelarti devi spostare i controlli di integrita' nel codice PHP, quindi devi scriverteli a mano. Sarebbe molto piu' semplice delegare questo a MySQL usando il tipo di dato pensato apposta per quello che stai facendo, ovvero DATETIME e simili.

    Complessivamente ci sono diversi problemi che potrebbero essere risolti molto facilmente migliorando la struttura della tabella.

    Se decidi ugualmente di non seguire queste indicazioni puoi comunque realizzare cio' di cui hai bisogno con una funzione analoga a quella di cui parlavo nel messaggio precedente:
    Codice PHP:
    function event_get_all() {
    $link = mysqli_connect('localhost','root','','');

    $query = " SELECT * FROM eventi ORDER BY day ASC, time ASC");
    $result = mysqli_query($link, $query);
    if (
    $result === false) {
    die(
    mysqli_error($link));
    }

    $events = [];
    while ((
    $row = mysqli_fetch_assoc($result)) !== false) {
    $events[] = [
    'id' => $row['id'],
    'day' => $row['day'],
    'time' => $row['time']
    ];
    }

    return
    $events;
    }


    // Converte un giorno da numero (1, 2, ...) a testo.
    // Per covnenzione, 1 rappresenta il lunedi', 2 il martedi', ecc.
    function day_to_text($day) {
    $lookup_table = ["lunedi", "martedi", "mercoledi", "giovedi", "venerdi", "sabato", "domenica"];

    return
    $lookup_table[($day - 1) % 7];
    }

    ...

    $events = event_get_all();
    $grouped_events = [];
    foreach (
    $events as $event) {
    $grouped_events[$event['day']][] = $event;
    }


    foreach (
    $grouped_events as $day => $events) {
    echo
    "<div>";
    echo
    day_to_text($day);
    echo
    "<ul>";
    foreach (
    $events as $event) {
    echo
    "<li>" . $event['time'] . ":00 - " . ($event['time'] + 1) . ":00</li>";
    }
    echo
    "</ul>";
    echo
    "</div>";
    }
    Ultima modifica di mzanella : 13-07-2018 alle ore 09.26.33

    I suggerimenti che do più spesso:


  5. #5
    kittbobba non è connesso Neofita
    Data registrazione
    01-08-2014
    Messaggi
    11

    Predefinito

    Citazione Originalmente inviato da mzanella Visualizza messaggio
    Infine c'e' da dire che, se decidi di usare INT per giorno e ora, accetti la possibilita' di avere eventi il "giorno 348 alle ore 3500:00". Per tutelarti devi spostare i controlli di integrita' nel codice PHP, quindi devi scriverteli a mano. Sarebbe molto piu' semplice delegare questo a MySQL usando il tipo di dato pensato apposta per quello che stai facendo, ovvero DATETIME e simili.
    Con questo metodo settimanale non dovrò mettere dati più alti di 7 su "day".

    Ho provato il codice e mi stampa l'errore
    Parse error: syntax error, unexpected ')' in /membri/kittbobba/test/index.php on line 5
    Codice PHP:
    $query = " SELECT * FROM eventi ORDER BY day ASC, time ASC");
    Ho pensato l'errore possa essere la parentesi chiusa, l'ho tolta e mi da questo errore:
    Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 72 bytes) in /membri/kittbobba/test/index.php on line 12
    quindi in questa riga:
    Codice PHP:
    while (($row = mysqli_fetch_assoc($result)) !== false) {

  6. #6
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Con questo metodo settimanale non dovrò mettere dati più alti di 7 su "day".
    Esatto, non dovrai, il che significa che dovrai implementare a mano nel codice PHP dei controlli sul valore di day.
    Ripeto: si puo' certamente fare, ma non e' un buon approccio.

    Hai fatto bene a togliere la parentesi, era un errore di battitura.

    La riga che causa il problema va modifica togliendo il confronto:
    Codice PHP:
    while ($row = mysqli_fetch_assoc($result)) {
    poiche' mysqli_fetch_assoc non restituisce false, bensi' null, quando la lettura termina.

    I suggerimenti che do più spesso:


  7. #7
    kittbobba non è connesso Neofita
    Data registrazione
    01-08-2014
    Messaggi
    11

    Predefinito

    Grazie mille!! Funziona alla grande!

  8. #8
    kittbobba non è connesso Neofita
    Data registrazione
    01-08-2014
    Messaggi
    11

    Predefinito

    Ciao mzanella! Ho riprovato il codice con calma e ho notato che con questi valori:
    id | day | time
    1 | 1 | 17
    2 | 1 | 9

    Stampa prima 17:00 - 18:00 e poi 9:00 - 10:00, come si potrebbe risolvere?

  9. #9
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Devi specificare l'ordine dei risultati come indicato qualche messaggio fa:
    Codice:
    SELECT * FROM eventi ORDER BY day ASC, time ASC

    I suggerimenti che do più spesso:


  10. #10
    kittbobba non è connesso Neofita
    Data registrazione
    01-08-2014
    Messaggi
    11

    Predefinito

    Si la query è proprio questa:
    Codice:
    $query = " SELECT * FROM eventi ORDER BY day ASC, time ASC");
    Ho notato che gli orari sotto 10 non li mette in ordine..

  11. #11
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Il tipo della colonna time è INT o testuale?

  12. #12
    kittbobba non è connesso Neofita
    Data registrazione
    01-08-2014
    Messaggi
    11

    Predefinito

    Era VARCHAR ho risolto mettendo INT, grazie ancora
    Ho provato a collegare il tutto nell'HTML e ho notato una cosa: prima della modifica la pagina era strutturata cosi:

    Codice per il nuovo giorno:
    Codice HTML:
    <div class="event">
    <div class="event-day">
    <div>
    <span class="day">15</span>
    <span class="year">Feb, 2018</span>
    </div>
    </div>
    <div class="event-content">
    <p class="event-time">
    <i class="fa fa-clock-o"></i> 8 : 00 AM - 11 : 00 AM</p>
    <h3 class="event-title">His id altera fabellas facilisis. Has eros assueverit cu</h3>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    </div>
    </div>
    Se noti c'è prima il codice del giorno e poi un evento per le 8 am.
    Il codice dell'evento singolo invece è questo:
    Codice HTML:
    <div class="event">
    <div class="event-hour"></div>
    <div class="event-content">
    <p class="event-time"><i class="fa fa-clock-o"></i> 8 : 00 AM - 11 : 00 AM</p>
    <h3 class="event-title">Perpetua consectetuer definitiones id sea, mei utinam eripuit ne</h3>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    <p>By <a href="#">John Doe</a></p>
    </div>
    </div>
    Ho scritto quindi questo codice:
    Codice PHP:
    <?php
    foreach ($grouped_events as $day => $events) {
    ?>
    <div class="event">
    <div class="event-day">
    <div>
    <span class="day"><?php echo day_to_text($day); ?></span>
    </div>
    </div>
    <div class="event-content">
    </div>
    </div>
    <?php foreach ($events as $event) { ?>
    <div class="event">
    <div class="event-hour"></div>
    <div class="event-content">
    <p class="event-time"><i class="fa fa-clock-o"></i> <?php echo $event['time'] . " : 00 -" . ($event['time'] + 1) . ": 00"; ?></p>
    <h3 class="event-title"></h3>
    </div>
    </div>
    <?php }
    }
    ?>
    Si potrebbe inserire subito dopo il giorno solo il primo evento e dopo con il secondo foreach mettere tutti gli eventi di quel giorno tranne il primo? Perchè quella pagina è fatta per avere di fianco al giorno il primo evento.
    Grazie
    Ultima modifica di kittbobba : 14-07-2018 alle ore 13.00.54

  13. #13
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Attento a ciò che desideri!

    No, guardando il sorgente della pagina kittbobba.altervista.org/sito sembra che l'organizzazione sia leggermente diversa:
    Codice:
    events-wrapper = [
      event = {
        event_day = {}
        event_content = {}
      }
      event = {
        event_hour = {}
        event_content = {}
      }
      ...
      event = {
        event_hour = {}
        event_content = {}
      }
      
    
      event = {
        event_day = {}
        event_content = {}
      }
      event = {
        event_hour = {}
        event_content = {}
      }
      ...
      event = {
        event_hour = {}
        event_content = {}
      }
    
      ...
    
      
      event = {
        event_day = {}
        event_content = {}
      }
      event = {
        event_hour = {}
        event_content = {}
      }
      ...
      event = {
        event_hour = {}
        event_content = {}
      }
    ]
    Ovvero si tratta di un'unica lista di eventi in cui il primo di ciascuna giornata ha un figlio con classe event_day, tutti gli altri hanno invece un figlio con classe event_hour. Credo che questo sia un ottimo esempio di come non impostare una pagina, in quanto si va a modificare la struttura in funzione della resa grafica, quando in realtà dovrebbe essere il contrario.

    Ad ogni modo la soluzione c'è, e consiste nel creare un figlio con classe event_day o event_hour a seconda del fatto che si stia mostrando il primo evento di una giornata:
    Codice PHP:
    <?php foreach ($grouped_events as $day => $events) : ?>
    <?php for ($i = 0; $i < count($events); ++$i): ?>
    <?php $event = $events[$i]; ?>
    <div class="event">

    <?php if ($i === 0): ?>
    <div class="event-day">
    <div>
    <span class="day"><?php echo day_to_text($day); ?></span>
    </div>
    </div>
    <?php else: ?>
    <div class="event-hour"></div>
    <?php endif; ?>

    <div class="event-content">
    <p class="event-time">
    <i class="fa fa-clock-o"></i>
    <?php echo $event['time'] . " : 00 -" . ($event['time'] + 1) . ": 00"; ?>
    </p>

    <h3 class="event-title"></h3>
    </div>
    </div>
    <?php endfor; ?>
    <?php
    endforeach; ?>

    I suggerimenti che do più spesso:


  14. #14
    kittbobba non è connesso Neofita
    Data registrazione
    01-08-2014
    Messaggi
    11

    Predefinito

    Funziona perfettamente!
    Stavo pensando di inserire una colonna su "eventi" chiamata 'descrizione' per inserire una breve descrizione sull'evento.
    Quale funzione devo modificare per poterla visualizzare?
    Grazie

  15. #15
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    La events_get_all, aggiungendo la lettura della nuova colonna:
    Codice PHP:
    function event_get_all() {
    $link = mysqli_connect('localhost','root','','');

    $query = " SELECT * FROM eventi ORDER BY day ASC, time ASC");
    $result = mysqli_query($link, $query);
    if (
    $result === false) {
    die(
    mysqli_error($link));
    }

    $events = [];
    while ((
    $row = mysqli_fetch_assoc($result)) !== false) {
    $events[] = [
    'id' => $row['id'],
    'day' => $row['day'],
    'time' => $row['time'],
    'descrizione' => $row['descrizione']
    ];
    }

    return
    $events;
    }

    I suggerimenti che do più spesso:


  16. #16
    kittbobba non è connesso Neofita
    Data registrazione
    01-08-2014
    Messaggi
    11

    Predefinito

    Grazie, funziona tutto alla perfezione!

    Riguardo il sito in generale ho notato che da mobile premendo il bottone del menu e cliccando su una sezione il menù non si nasconde automaticamente.
    Hai idee su come risolvere?

  17. #17
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Immagino si possa aggiungere un event listener ai pulsanti del menù tramite JavaScript che, al click, nasconda il menù.

    Ho qualche vago ricordo sul funzionamento di Bootstrap, bisogna aggiungere dinamicamente una classe da qualche parte, qualcosa come collapse.
    kittbobba likes this.

    I suggerimenti che do più spesso:


Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •