Avatar billede Slettet bruger
10. august 2017 - 16:13 Der er 13 kommentarer og
1 løsning

Tilpasning af kode

Hej eksperter,

Jeg har følgende kode til beregning af aldersgruppe;
$ages = array();
if ($result = $conn->query("SELECT name, age_from, age_to FROM tbl_age ORDER BY id")){
      while ($row = $result->fetch_object()){
        $age = array(
          'name' => $row->name,
          'from' => $row->age_from,
          'to' => $row->age_to
        );
        $ages[] = $age;
      }
      $result->close();
    }
    $dates_id = array();
    $members_id = array();

Jeg vil dog gerne have koden til at skifte aldersgruppe pr. 1. juli (og ikke ved fødselsdato). Nedenfor ses inddelingen.
- U9 må ikke den 31. december være fyldt 9 år
- U11 må ikke den 31. december være fyldt 11 år, men skal være fyldt 9 år.
- U13 må ikke den 31. december være fyldt 13 år, men skal være fyldt 11 år.
- U15 må ikke den 31. december være fyldt 15 år, men skal være fyldt 13 år.
- U17 må ikke den 31. december være fyldt 17 år, men skal være fyldt 15 år.
- U19 må ikke den 31. december være fyldt 19 år, men skal være fyldt 17 år.

Nogen der kan hjælpe?
Avatar billede jakobdo Ekspert
10. august 2017 - 16:33 #1
Du skal jo "bare" rette databasen.
Jeg mener du har:
date_from og date_to
Hvis du laver:

name: U9
date_from: NOW/EMPTY/Whatever...
date_to: 2008-12-31

name: U11
date_from: 2009-01-01
date_to: 2006-12-31

osv...

Er det ikke løsningen?
Den kan jo evt. laves dynamisk, så den selv tager højde for når vi skifter år...
Avatar billede Slettet bruger
10. august 2017 - 16:59 #2
Jo det tænkte jeg også, men så skal jeg i hvert fald ændre lidt på strukturen i tabellen der indeholder date_from og date_to.

Lige nu har de typen INT. De skal vel have typen Date eller Datetime?
Avatar billede Slettet bruger
10. august 2017 - 17:11 #3
Måske type YEAR er den rigtige at bruge, da jeg egentligt "bare" skal regne på om de er en bestemt årgang.

Hvilken tilpasning skal jeg lave i koden, hvis jeg ændrer typen i databasen?
Avatar billede olsensweb.dk Ekspert
10. august 2017 - 18:04 #4
#3 kunne være en simpel løsning, du har jo brugerens fødselsdato i tbl_medlem.dob, så er det jo bare at udtrække året

ala
SELECT YEAR(dob)

eller med
select DATEPART(year,dob)

og så slette dette i din php
// $ar=$row;
// $from = new DateTime('1970-02-01');
$from = new DateTime($row['dob']);
$to = new DateTime('today');
$ar['age'] = $from->diff($to)->y;

alternativt til sql løsningen rette ovenstående php til
$ar['year'] = new DateTime($row['dob'])->format("Y");

nb det er utested
Avatar billede Slettet bruger
10. august 2017 - 18:14 #5
Jeg forstår udemærket tanken, og jeg tænker også at det nemmest bare vil være at arbejde YEAR, men det du skriver kan jeg ikke lige omsætte til noget der giver mening for mig?
Avatar billede olsensweb.dk Ekspert
10. august 2017 - 18:58 #6
slet tabellen tbl_age_interval
opret tabellen tbl_year_interval


$ar['year'] = new DateTime($row['dob'])->format("Y");
skal være
$dob = new DateTime($row['dob']);
$ar['year'] = $dob->format("Y");


burde kunne laves sådan

din index.php har jeg ikke rørt ved.


tbl_year_interval
CREATE TABLE `tbl_year_interval` (
  `id` int(11) NOT NULL,
  `name` varchar(50) COLLATE utf8_danish_ci NOT NULL,
  `year_to` year(4) NOT NULL,
  `year_from` year(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_danish_ci;


INSERT INTO `tbl_year_interval` (`id`, `name`, `year_to`, `year_from`) VALUES
(1, 'U09', 2017, 2008),
(2, 'U11', 2009, 2006),
(3, 'U13', 2005, 2004),
(4, 'U15', 2003, 2002),
(5, 'U17', 2001, 2000),
(6, 'U19', 1999, 1997);

ALTER TABLE `tbl_year_interval`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `tbl_year_interval`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;



min request_medlemmer.php fra
https://www.computerworld.dk/eksperten/spm/1018253?k=8264351
rettelser fremhævet

request_medlemmer.php
<?php
require("connect.php");
$arr = array();
$id = (int) $_GET['hold'];

$sql = "SELECT DISTINCT tbl_medlem.id, tbl_medlem.fornavn, tbl_medlem.efternavn, tbl_medlem.dob FROM tbl_map_medlem_hold_traeninger JOIN tbl_medlem ON tbl_medlem.id = tbl_map_medlem_hold_traeninger.medlem_id WHERE tbl_map_medlem_hold_traeninger.hold_id =" . $id;
$rs = $conn->query($sql);
while ($row = $rs->fetch_assoc()) {
    $ar = array();
    $ar['id'] = $row['id'];
    $ar['fornavn'] = $row['fornavn'];
    $ar['efternavn'] = $row['efternavn'];
    $dob = new DateTime($row['dob']);
    $ar['year'] = $dob->format("Y");   
    $sql1 = "SELECT name FROM tbl_year_interval WHERE " . $ar['year'] . " BETWEEN year_from AND year_to";
    $rs1 = $conn->query($sql1);
    if ($rs1) {
        $row1 = $rs1->fetch_assoc();
        $ar['age_group'] = $row1['name'];
    } else {
        $ar['age_group'] = "unknown";
    }

    // bør nok joine tbl_traeninger så det kun er træninger i år / inden for de sidste 12 måneder
    $sql2 = "SELECT count(id) AS antal FROM tbl_map_medlem_hold_traeninger where hold_id = ".$id." and medlem_id = ".$ar['id'];
    $rs2 = $conn->query($sql2);
    $row2 = $rs2->fetch_assoc();
    $ar['antal'] = $row2['antal'];   
    $arr[] = $ar;
}
echo json_encode($arr);
?>
Avatar billede olsensweb.dk Ekspert
10. august 2017 - 19:09 #7
du udskriver jo også alder for fanden.
indsæt de fremhøvet linjer

$ar = array();
$ar['id'] = $row['id'];
$ar['fornavn'] = $row['fornavn'];
$ar['efternavn'] = $row['efternavn'];
$dob = new DateTime($row['dob']);   
$to = new DateTime('today');
$ar['age'] = $dob->diff($to)->y;

$ar['year'] = $dob->format("Y");   
Avatar billede jakobdo Ekspert
10. august 2017 - 19:18 #8
I stedet for at køre i år, ville det så ikke give mere mening af regne i ÅR?

U9 skal jo netop være børn der ikke er fyldt eller fylder 9 år i år.
U11 skal være ældre end 9 men ikke fyldt 11 eller fylder 11 i år.
osv...
Avatar billede olsensweb.dk Ekspert
10. august 2017 - 19:57 #9
>I stedet for at køre i år, ville det så ikke give mere mening af regne i ÅR?
det var det den oprindeligt vertion af request_medlemmer.php gjorde, den kiggede så ikke på resten af året, men det er op til spørgeren

det vil da gøre det nemmere at vedligeholde, istedet for årstal der skal opdateret dynamisk, som man skal i tbl_year_interval

så hvis man går tilbage til den gamle må der "bare" laves noget logik der kigger på måned år, og tælle år 1 op, hvis man fylder senere på året
Avatar billede jakobdo Ekspert
12. august 2017 - 11:14 #10
Kig på noget ala dette:

$now = new DateTime('NOW');
$now->setDate($now->format("Y"), 12, 31);

$dob = new Datetime('YYYY-MM-DD'); <== DATE FROM USER / DATABASE
$interval = $dob->diff($now);
echo $interval->format('%y');
Avatar billede olsensweb.dk Ekspert
12. august 2017 - 11:48 #11
start med at slette tbl_year_interval og gå tilbage til den oprindelige, tbl_age_interval
og tæl brugerens aktuelle år 1 op, hvis denne fylder senere på året.

iden med at lave tbl_year_interval der dynamisk skal opdateres, burde være skudt ned med det sammen.

nedenstående code er ikke gennemtested, eller helt tænk igennem, men prøv at lege med den.


CREATE TABLE `tbl_age_interval` (
  `id` int(11) NOT NULL,
  `name` varchar(50) COLLATE utf8_danish_ci NOT NULL,
  `age_from` int(11) NOT NULL,
  `age_to` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_danish_ci;

INSERT INTO `tbl_age_interval` (`id`, `name`, `age_from`, `age_to`) VALUES
(1, 'U09', 0, 9),
(2, 'U11', 10, 11),
(3, 'U13', 12, 13),
(4, 'U15', 14, 15),
(5, 'U17', 16, 17),
(6, 'U19', 18, 19);


request_medlemmer.php
<?php
require("connect.php");
$arr = array();
$id = (int) $_GET['hold'];
$sql = "SELECT DISTINCT tbl_medlem.id, tbl_medlem.fornavn, tbl_medlem.efternavn, tbl_medlem.dob FROM tbl_map_medlem_hold_traeninger JOIN tbl_medlem ON tbl_medlem.id = tbl_map_medlem_hold_traeninger.medlem_id WHERE tbl_map_medlem_hold_traeninger.hold_id =" . $id;
$rs = $conn->query($sql);
while ($row = $rs->fetch_assoc()) {
    $ar = array();
    $ar['id'] = $row['id'];
    $ar['fornavn'] = $row['fornavn'];
    $ar['efternavn'] = $row['efternavn'];     
    $today = new DateTime('today');   
   
    $today_month = $today->format("m");
    $dob = new DateTime($row['dob']);
    $dob_month = $dob->format("m");               
    $age = $dob->diff($today)->y;
    $ar['age'] = $age; // den aktuelle alder   
   
    // skifte aldersgruppe pr. 1. juli
    // her mangler lige en if sætning
   
   
    if($dob_month > $today_month ){
        $age++; // fylder senere på året
    }
    else{
        if($dob_month == $today_month ){
            if($dob->format("d") > $today->format("d") ){
                $age++; // fylder senere på månedet
            }
        }   
    }   
    $sql1 = "SELECT name FROM tbl_age_interval WHERE " . $age . " BETWEEN age_from AND age_to";

   
    $rs1 = $conn->query($sql1);
    if ($rs1) {
        $row1 = $rs1->fetch_assoc();
        $ar['age_group'] = $row1['name'];
    } else {
        $ar['age_group'] = "unknown";
    }

    // bør nok joine tbl_traeninger så det kun er træninger i år / inden for de sidste 12 måneder
    $sql2 = "SELECT count(id) AS antal FROM tbl_map_medlem_hold_traeninger where hold_id = ".$id." and medlem_id = ".$ar['id'];
    $rs2 = $conn->query($sql2);
    $row2 = $rs2->fetch_assoc();
    $ar['antal'] = $row2['antal'];   
   
    $arr[] = $ar;
}
echo json_encode($arr);
?>
Avatar billede jakobdo Ekspert
12. august 2017 - 12:40 #12
Han kan jo også bare bruge min kode...
Det interessante er jo at vide hvor gammel er personen 31. december nuværende år...
Når man ved dette, kan de til en hver tid sammenlignes med tabellen.

U9 < 9 år
U11 > 9år og < 11år
osv...

Det bliver jo ikke mere simpelt.
Avatar billede jakobdo Ekspert
13. august 2017 - 12:10 #13
Brug tabel tbl_age_interval fra #11

Brug denne kode:

$now = new DateTime('NOW');
$now->setDate($now->format("Y"), 12, 31);

$dob = new Datetime('YYYY-MM-DD'); <== DATE FROM USER / DATABASE
$year = $dob->diff($now)->y;
lav en query mod tabel fra #11:

select name from tbl_age_interval where age_from <= YEAR and age_to >= YEAR

Så har du alt du behøver...

og du kan jo evt. trække alle intervaller ud og lave tjekket "manuelt" så du ikke skal skyde en sql ved hvert medlem.
Avatar billede Slettet bruger
13. august 2017 - 18:32 #14
Tusind tak begge to :-)
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

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