Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: CSV-tiedoston luvuilla laskeminen

Sivun loppuun

latenleffahylly [15.08.2012 14:22:50]

#

Hei,

Osaatteko neuvoa miten voi kertoa tuloksen 100:lla?

<?php
$csvFile = "valuuttakurssit.csv";

$array = file($csvFile);

  foreach ($array as $arrayValue) {

  $merkkijono = $arrayValue;

  $break = explode('"',$merkkijono);

  echo $break[1] . "<br>";

  }
?>

Tulostus:

1,1661
2,4772
1,9558
0,78610

- Luvut ovat euroja, jotka haluaisin kertoa 100:lla, jotta ne muuttuisivat senteiksi. (pilkut pois)

- Eli kohta joka pitää kertoa 100 olisi kaiketi tämä:

$break tai $break[1] <-Mutta ei onnistu arrayn kertominen * ?? Kiitos jos ehditte taas auttaa.

Lebe80 [15.08.2012 14:29:38]

#

Korvaa merkkijonosta php:lla ensiksi pilkku pisteellä ja kokeile uudelleen.

latenleffahylly [15.08.2012 14:51:35]

#

Okei ehkä selitin hieman väärin, yritän jotain tällaista:

<?php
$csvFile = "valuuttakurssit.csv";

$array = file($csvFile);

  foreach ($array as $arrayValue) {

  $merkkijono = $arrayValue;

  $break = explode('"',$merkkijono);



  $luku = $break;
  $kerroin = 100;

  $tulos = $break * $kerroin;
  echo "Eurot sentteinä: {$tulos}";


  }
?>

Lebe80 [15.08.2012 14:59:58]

#

Taisin selittää liian selvästi:

Muuta ensiksi sen merkkijonon ($break) sisältämät pilkut (,) pisteiksi (.), jotta php pystyy muuntamaan merkkijonon luvuksi.

Tällöin tosiaan laskutoimituksen pitäisi toimia. Eli pilkkuahan ei käytetä ohjelmoinnissa desimaalierottimena, vaan desimaalierottimena käytetään pistettä.

Eli tuloste ei saa näyttää tältä ennen kertolaskua:
1,1661
2,4772
1,9558
0,78610

vaan pitää näyttää tältä:
1.1661
2.4772
1.9558
0.78610

latenleffahylly [15.08.2012 15:02:59]

#

Jaahas.. Juu sorry kokeilen, pahoittelut.

Lisäys:

Ajattelin kokeilla jotain tällaista:

$a = new NumberFormatter('fi_FI', NumberFormatter::CURRENCY);
echo $a->format($luvut) . "<br>";

- Pitää kuitenkin ensin osata luoda oma luokka.

dartvaneri [15.08.2012 20:24:27]

#

Sulla on tuossa koodissa([15.08.2012 14:51:35]) muutama ylimääräinen muuttuja, lisäksi muista, että explode-funktio palauttaa arrayn, jotenka et voi kertoa sitä suoraan 100:lla, joudut käyttämään $break[0], jotta se onnistuu.

latenleffahylly [15.08.2012 21:15:06]

#

Kiitos jälleen avusta dartvaneri. Alkuperäinen idea oli nimen omaan kertoa tuo Array sadalla? Mietin että miten se tehdään... mutta ensin luvuista pitää poistaa välit (space) ja pilkut (comma) muuttaa pisteiksi (dot)

..jokatapauksessa yritän itse selvittää nyt tätä ongelmaa. Eli en voi ennen laskea, kunnes array/ tai string muutettu luettavaan muotoon.

<?php

$csvFile = "valuuttakurssit.csv";

$array = file($csvFile);


  foreach ($array as $arrayValue) {

  $merkkijono = $arrayValue;

  $break = explode('"',$merkkijono);


  // echo $break[0] . "<br>";
  // echo $break[1] . "<br>";
  }
?>

Valuuttakursseissa on ensin valuutan nimi sitten arvo:

Japanin jeni,JPY,10.08.2012,
96,12

groovyb [15.08.2012 21:40:42]

#

En tiedä ymmärsinkö nyt väärin, mutta sulla on csv filu jota splittaat heittomerkillä? (explode('"'))

koska rivilläsi ei ole yhtään heittomerkkiä, on palautuvassa arrayssä vain yksi solu joka on koko rivisi.

splittaa käyttämällä pilkkua. Näin break array sisältää arvot eriteltyinä soluihin.

Tämän jälkeen voit kasata tietosi näistä soluista.

plus että et oikein noita valuuttakursseja voi sadalla kertoa, jos euroja haluat.

kurssisi ovat päinvastoin, eli kuinka montaa yksikköä kyseistä valuuttaa yksi euro vastaa. (jos jpy:n kurssi on 96.12, vastaa yksi euro kyseistä määrää jenejä.)
Jos taasen jaat 1 / 96.12, saat yhden jenin arvon euroissa, eli 0.01040366 jne.

latenleffahylly [15.08.2012 22:18:04]

#

Hmm.. Eli tarkoitus on kertoa euro määrät 100:lla jotta ne muuttuvat senteiksi.

Alla hieman kuvaa CSV-tiedostosta:

Title,CURRENCY_CodelistValue,txtb_day,txtb_value
Australian dollari,AUD,10.08.2012,"1,1661"
Brasilian real,BRL,10.08.2012,"2,4772"
Bulgarian uusi lev,BGN,10.08.2012,"1,9558"


Koodi tähän saakka, huom!! en halua valmiita vastauksia, sillä yritän itse selvittää miten saan pilkut pisteiksi ja välit pois euroarvoista.

<?php

$CSVtiedosto = "valuuttakurssit.csv";

$arrayRivit = file($CSVtiedosto);

foreach ($arrayRivit as $arrayArvo) {

  $kokoRivi = $arrayArvo;

  $jaaKahtia = explode('"',$kokoRivi);

  echo $jaaKahtia[1] . "<br><br>";
  }


  /*
   * print_r($array);
   * break;
   *
   *
   * $results = print_r($b, true);
   *
   * echo $muuttuja . "<br>";
   * break;
  */

?>

Yritän nyt tehdä jotain tuolle -> $jaaKahtia[1]

96,12

1,2192

7,7989

11 632,35


- Elikkä: pilkut -> pisteiksi ja välit pois :) Huom! en halua mitään valmista, yritän jotenkin käsitellä tuota array:ta ??? Manipuloida merkkijonoa.. sitten kerron luvut sadalla, ja tallennan tietokantaan.

Myöhemmin luvuilla voi laskea: esim. viimeinen luku: 11 632,35 -> 116323500 senttiä! luulisin, kiitos kuitenkin kaikille mielenkiinnosta.

tgunner [15.08.2012 22:53:39]

#

Tutustu funktioon str_replace ja kokeile miettiä, miten voisit käyttää sitä hyväksesi.

latenleffahylly [15.08.2012 23:10:46]

#

Kiitos t"gunner" tutustun samantien.

punppis [16.08.2012 01:21:32]

#

<?php
	$number = "0,99";
	echo str_replace(",", ".", $number) * 100;
?>

Merri [16.08.2012 07:18:47]

#

CSV-tiedostojen lukemiseen on oma funktionsa:
https://www.php.net/manual/en/function.fgetcsv.php

latenleffahylly [16.08.2012 08:30:02]

#

fgetcsv on hyvä, mutta myös file toimii. Punppikselle tiedoksi että en nyt etsi valmiita koodipätkiä vaan yritän itse selvittää asiat.

Eli tgunner auttoi ja punppis päätti sitten ratkaista koko homman, kiitos joka tapauksessa. Haluan itse sisäistää homman koska muuten en voi oppia.

dartvaneri [16.08.2012 09:32:42]

#

Kannattanee myös kokeilla säännöllisiä lausekkeita(SL-haaste!). Ja sieltä etenkin preg_replace komentoa.

latenleffahylly [16.08.2012 10:02:55]

#

Juu.. tuo haaste pitäisi muutenkin käydä läpi kun taidot kunnossa. Koodi nyt:

<?php

 $CSVtiedosto = "valuuttakurssit.csv";

 $arrayRivit = file($CSVtiedosto);

 foreach ($arrayRivit as $arrayArvo) {

 $kokoRivi = $arrayArvo;

 $jaaKahtia = explode('"',$kokoRivi);

 $osat = $jaaKahtia;

 $merkit = $osat[0];
 $luvut = $osat[1];

 $luvut = str_replace(',', '.', $luvut);


 // ONGELMA!!! ...eli ongelma on juurikin tässä kohtaa.

 // luku: 1 386,66

 // pilkkujen muuttaminen pisteiksi onnistuu mutta välien poistaminen ei:

 $luvut = str_replace(' ', '', $luvut);

 // ...eli luku pitäisi saada muotoon 1386.66

 // VÄLILYÖNTIEN (SPACE) POISTAMINEN EI ONNISTU MILLÄÄN!!!


 // Näitä olen kokeillut:

 // $luvut = preg_replace('/\s+/','',$luvut);
 // $luvut = str_replace(' ','',$luvut);
 // $luvut = str_replace(',', '.', $luvut);










 echo $luvut . "<br><br>";

 // echo $tulos[0] . "<br><br>";
 // echo $tulos . "<br><br>";

 }

Lisäys:

Noniin sen verran olen selvittänyt että ongelma on UTF-8 eli kun tulostan:

1Â 386.66

51.261

9.5121

11Â 632.35


...Eli nuo merkit -> (Â ) ongelma luvuissa.

punppis [16.08.2012 10:54:25]

#

Välilyönnit pitäisi lähteä tuolla koodilla. Voipi olla että kyseessä ei olekaan välilyönti, vaan jotain muuta.

ord-funktiolla voit tarkastaa, mikä merkki on kyseessä.

dartvaneri [16.08.2012 11:06:49]

#

preg_replace("/ /", "", $muuttuja) pitäisi toimia,jos se on väli. lisäksi tuo muuttuja $kokoRivi on turha.

latenleffahylly [16.08.2012 12:47:52]

#

Miten tuolla ordilla voisi tutkia mitä merkkejä CSV-tiedosto sisältää. Itse tiedostossa näyttäisi olevan vain väli.

CSV: 1 386,66
Tulostus: 1Â 386,66

Lisäys:

..no ..yksi tapa on poistaa välit CSV-tiedostosta, mutta tämä ei tietenkään ole kiva eikä hyvä asia.

..juu kiitoksia.

dartvaneri [16.08.2012 13:27:04]

#

En ole kokeillu, mutta nopeesti vilkasin manuskaa, niin laitat sen merkin ton ord funktion sisään, niin se palauttaa merkkiä vastaavan numeron.

latenleffahylly [16.08.2012 13:36:31]

#

$luvut = (ord($luvut);
  echo $luvut;

- tuolla sitä ainakaan ei voi tehdä... syntax error, unexpected ';'

Jaska [16.08.2012 13:38:09]

#

Tuossahan on sulut pielessä.

latenleffahylly [16.08.2012 13:46:07]

#

Siinä on kaikki pielessä, antaa olla. En osaa tuota ordia käyttää omassa koodissa jotta saisin tiedon mitä lukee kohdassa ---> $luvut

$luvut = str_replace(',', '.', $luvut);

Tuon jälkeen luvut tulostuvat näin:

1Â 386.66
51.261
9.5121
11Â 632.35

Lisäys:

SANOOKO TÄLLAINEN JOTAIN, ELI KÄYTTÄISI:

NUMBER_FORMAT ???

-----

An array will always be converted into 1, so, if you have:

<?php
$my_array = array(55);
echo number_format($my_array,0,',','.');
// 1

var_dump(number_format($my_array,2,',','.'));
// string(4) "1,00"
?>

tgunner [16.08.2012 17:44:06]

#

En tiedä, mistä tuo mörkömerkki oikein ilmestyy, mutta jos haluat vain eliminoida sen, käytä vaikkapa allaolevaa koodia.

$L = "1Â 386.66";
# korvataan kaikki paitsi numerot ja piste
# tulostus on 1386.66
echo ereg_replace("[^\.0-9]", "", $L);

latenleffahylly [16.08.2012 19:43:03]

#

EREG_REPLACE

Warning
This function has been DEPRECATED as of PHP 5.3.0. Relying on this feature is highly discouraged.

...

Tuota, tuota.. Olen saanut neuvon tutkia funktiota NUMBER_FORMAT , joten yritän oppia käyttämään sitä seuraavaksi.

Macro [16.08.2012 20:14:40]

#

Kuten virheilmoitus sanoo, niin uusimmissa PHP:n versioissa ei kuulu enään käyttää tollasta funktiota. preg_replace toimii uudemmissa.

tgunner [16.08.2012 20:25:40]

#

latenleffahylly kirjoitti:

EREG_REPLACE
Warning

This function has been DEPRECATED as of PHP 5.3.0. Relying on this feature is highly discouraged.

Jahas, olen ajastani jäljessä. Korvaaja näyttää kuitenkin toimivan samalla tavalla.

latenleffahylly [16.08.2012 20:44:10]

#

number_format ei tunnu auttavan ongelmassani eli miten saada:

tällainen luku: 1 386,66 -> 1386.66 ja sitten myöhemmin eurot senteiksi.. 13866600 tai jotain sellaista. Kokeilen tuota:


-----------------------------------------------------------------
preg_replace — Perform a regular expression search and replace

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

Searches subject for matches to pattern and replaces them with replacement.

Jaska [16.08.2012 21:00:57]

#

Koodi

echo str_replace(array(' ', ','), array('', '.'), '1 232 322,45');

tulostaa 1232322.45. Tosin nyt esim. 1 232 322,0 jää muotoon 1232322.0. Haittaako loppunolla?

Hmm. Tuossa pitäisi kai ensiksi muuttaa luku merkkijonoksi (strval), suorittaa koodi ja muuttaa merkkijono luvuksi (floatval).

latenleffahylly [16.08.2012 21:41:12]

#

Nyt tilanne tämä:

<?php
$CSVtiedosto = "valuuttakurssit.csv";


$arrayRivit = file($CSVtiedosto);

foreach ($arrayRivit as $kokoRivi) {

  $jaaKahtia = explode('"',$kokoRivi);

  $osat = $jaaKahtia;

  $merkit = $osat[0];
  $luvut = $osat[1];

  $tulos = preg_replace('/\,/', '.', $luvut);
  $tulos = preg_replace('/\s/', '', $tulos);

  echo $tulos . "<br><br>";
}
?>

Tulostaa näin:

1.9558

0.78610

9.9772

1Â 386.66


...Eli ei edelleenkään osaa poistaa tuota väliä?

Tämä toimii: Mutta HUOM! tässä itse tekemä välilyönti luvussa: 11 632,35

<p>testi</p>

<?php
$x = "11 632,35";
$tulos = preg_replace('/\,/', '.', $x);
$tulos = preg_replace('/\s/', '', $tulos);
echo $tulos;
?>

Tulostaa oikein: 11632.35

Lisäys: .........Okei eli Jaska, olet varmasti oikeassa. Array -> merkkijonoksi ja sitten merkkijono arrayksi?

Jaska [16.08.2012 21:53:50]

#

latenleffahylly kirjoitti:

Lisäys: .........Okei eli Jaska, olet varmasti oikeassa. Array -> merkkijonoksi ja sitten merkkijono arrayksi?

Kannattaa muistaa, että olen varsin aloittelija ja harrastelija. En tosiaan tiedä PHP:stä paljoa enkä sitä, onko suoraa tapaa olemassa. Netistä löysin nuo funktiot ja PHP.netin perusteella voisin olettaa ratkaisun toimivan.

dartvaneri [16.08.2012 22:31:09]

#

tgunner kirjoitti:

$L = "1Â 386.66";
# korvataan kaikki paitsi numerot ja piste
# tulostus on 1386.66
echo ereg_replace("[^\.0-9]", "", $L);

Kuten tgunner jo sanoi, saat ne "välit" pois tuon tyylisellä lausekkeella. Ja Macron korjauksen avulla päästään seuraavaan koodiin:

preg_replace("[^\.0-9]", "", $L);

Kokeile tuota.

latenleffahylly [16.08.2012 22:38:10]

#

Eli alimmalle riville ereg_replace tilalle preg_replace

dartvaneri [16.08.2012 22:47:53]

#

$tulos = preg_replace('/\,/', '.', $luvut);
$tulos = preg_replace('/\s/', '', $tulos);
$tulos = preg_replace("[^\.0-9]", "", $tulos);

Kokeiles vaikka tuota.

The Alchemist [16.08.2012 23:09:01]

#

Lopettakee nyt jo se räpeltäminen, sattuu!

<?php
function parse_csv($string) {
    $csv = array();
    $data = explode(PHP_EOL, trim($string));

    foreach ($data as $row) {
        $csv[] = str_getcsv($row);
    }

    return $csv;
}

$data = file_get_contents('data.csv');
$csv = parse_csv($data);

array_shift($csv);

foreach ($csv as $row) {
    $rate = str_replace(',', '.', $row[3]);
    $cents = $rate * 100;

    print "{$row[0]}: {$cents} cents\n";
}

Metabolix [16.08.2012 23:42:08]

#

Joo, on aika surullista katsoa, miten näin yksinkertaisesta asiasta saadaan näin valtava soppa, vaikka auttajia on jo monta.

Myös The Alchemistin koodissa on eräitä puutteita, jotka hän ehkä korjaakin tämän luettuaan.

Suurin puute on, että koodi ei poista tässä toisena ongelmana ollutta UTF-8-muotoista non-breaking space -merkkiä ("\xC2\xA0", Windows-1252-muodossa tulkittuna  ja NBSP). Jälkimmäisen foreach-silmukan ensimmäisen rivin pitäisi siis olla esimerkiksi jompikumpi näistä:

$rate = str_replace(array(",", "\xC2\xA0"), array(".", ""), $row[3]);
$rate = preg_replace(array("/,/", "/[^0-9.]/"), array(".", ""), $row[3]);

En myöskään ymmärrä, mitä hyötyä on muuttaa tämän jälkeen eurot senteiksi, kun monilla valuuttakurssitaulukon (ks. CSV) riveillä on joka tapauksessa myös senttien osia (esimerkiksi 2,4817 euroa = 248,17 senttiä) eli kurssista ei edelleenkään tule kokonaislukua. Ehkäpä latenleffahyllyllä on tähän jokin hyvä perustelu – tai ehkä ei.

Toinen puute on, että koodi toimii väärin, jos jonkin kentän arvo sisältää rivinvaihtoja. Tällä ei tietenkään ole merkitystä, jos missään kentässä ei ole rivinvaihtoja. Jos ongelma kuitenkin ilmenee, voi kokeilla, osaisiko vaikka fgetcsv-funktio käsitellä myös rivinvaihdot.

latenleffahylly [17.08.2012 07:47:41]

#

Kiitos, kiitos. Olen kokeillut useita tapoja purkaa csv-tiedosto. Jäin jumiin tuohon (space, väli) kohtaan. Vaikka tämä foorumi on myös aloittelijoille, ymmärrän turhautumisenne.

Jos rookiet neuvovat keltanokkia ? Mitä siitä seuraa? Mietin vielä tuota valuutta juttua, kannattaako muttaa senteiksi. Idea on että tuloksilla voisi laskea myöhemmin.

Lisäys:

-----

No niin no.. eli Alkemistille suur kiitos hienosta koodista. Opettelen sen tämän tehtävän jälkeen. Nyt teen kuitenkin tavalla, joka sopii aloittelijalle. Yritän ymmärtää jokaisen rivin eli mitä tapahtuu.

Suurkiitokset myös Metabolixille, joka tuntuu olevan aina oikeassa. Koodi tällä hetkellä alla ja tulostus toimii oikein.

<?php
$CSVtiedosto = "valuuttakurssit.csv";

$arrayRivit = file($CSVtiedosto);

foreach ($arrayRivit as $kokoRivi) {

  $jaaKahtia = explode('"',$kokoRivi);

  $osat = $jaaKahtia;

  $merkit = $osat[0];
  $luvut = $osat[1];

  $tulos = str_replace(array(",", "\xC2\xA0"), array(".", ""), $luvut);

  echo $tulos . "<br><br>";
}
?>

Tulostaa:

1.1661

2.4772

1.9558

0.78610

9.9772

1386.66

1.2262

jne.

- Pitää vielä miettiä tallennanko luvut tuollaisena tietokantaan vai muunnanko. Luvuilla pitäisi pystyä laskemaan. 1 € = 1.2262 Yhdysvaltain dollaria.

latenleffahylly [17.08.2012 12:54:12]

#

.....

Nyt olen päässyt siihen pisteeseen että alan tallentamaan tietoa tietokantaan. On vain 1 ongelma!

- id, ok
- valuutan nimi, ok
- lyhenne, ok
- pvm <--------------------------- ongelma!
- valuutta, ok

Eli merkit ovat tällaisia

Dollari
DOL
10.08.2012
1.222

Nyt kun tallennan MySQL -tietokantaan pitäisi saada DATE ensin muotoon 2012-08-10

Tässäpä se ongelma onkin. Olen tutkinut Googlen kautta DATE funktion toimintaa, mutta turhaan. Mihin suuntaan tämän ongelman kanssa...?

Lebe80 [17.08.2012 13:26:15]

#

Mitäpä jos vaikka kokeilisit pilkkoa päivämäärän pisteiden perusteella ja tehdä siitä sitä kautta päivämäärän, jonka tietokanta ymmärtää?

latenleffahylly [17.08.2012 13:45:04]

#

Niin tätä mietin myös itse, mutta ajattelin että täytyy olla jokin siistimpi keino.

Lisäys:

...

// Convert the timestamp
$date = date("D, d M Y", $timestamp);

Tällä lähdetään..

latenleffahylly [20.08.2012 14:54:51]

#

Hei,

kysyisin vielä tällaista. Eli kun CSV-tiedosto tällainen:

---tyhjä rivi---
Title,CURRENCY_CodelistValue,txtb_day,txtb_value
Australian dollari,AUD,10.08.2012,"1,1661"
Brasilian real,BRL,10.08.2012,"2,4772"
Bulgarian uusi lev,BGN,10.08.2012,"1,9558"
---tyhjä rivi---
---tyhjä rivi---

- Miten voisin järkevimmin tallentaa muuttujaan vain sellaiset rivit, jossa (Valuutan nimi, lyhenne, pvm, kurssi). Ja jättää pois tyhjät rivit ja otsikko rivin.

$CSVtiedosto = "valuuttakurssit.csv";

$arrayRivit = file($CSVtiedosto);

  foreach ($arrayRivit as $YksiKokonainenRivi) {

  $JaaRiviKahtia = explode('"',$YksiKokonainenRivi);

  jne...

jalski [20.08.2012 15:48:42]

#

latenleffahylly kirjoitti:

- Miten voisin järkevimmin tallentaa muuttujaan vain sellaiset rivit, jossa (Valuutan nimi, lyhenne, pvm, kurssi). Ja jättää pois tyhjät rivit ja otsikko rivin.

1. Miten olisi, että syöttäisit rivin trim() funktion läpi ja vertaisit trimmatun rivin pituutta tyhjän merkkijonon pituuteen karsiaksesi tyhjän rivin pois?

2. Sitten splittaat rivin pilkun mukaan ja tarkistat onko ensimmäinen komponentti Title ja toinen tuo CURRENCY merkintä.

3. Tästä eteenpäin tulevat rivit ovatkin sitten haluttuja valuuttakurssirivejä...

dartvaneri [20.08.2012 22:39:10]

#

latenleffahylly kirjoitti:

Niin tätä mietin myös itse, mutta ajattelin että täytyy olla jokin siistimpi keino.

Lisäys:
...

// Convert the timestamp
$date = date("D, d M Y", $timestamp);

Tällä lähdetään..

Eikai se nyt niin rumakaan ole?

<?php
    $date = explode(".", $dateTime); //Pilkotaan aika osiin '.' kohdalta.
    $dateTime = $date[2]."-".$date[1]."-".$date[0]; //Ja järjestellään uudelleen.
?>

Muuttujien nimet, ei nyt varmaan ihan parhaat ole.

tuutti [21.08.2012 00:39:55]

#

Voit käyttää mysql daten sijasta myös unixtimestamppeja:

$date = strtotime('10.8.2012');

The Alchemist [21.08.2012 06:10:28]

#

tuutti kirjoitti:

Voit käyttää mysql daten sijasta myös unixtimestamppeja:

$date = strtotime('10.8.2012');

Joka tapauksessa aikojen muotoilu on järkevämpää tehdä muuttamalla annettu merkkijono timestampiksi ja siitä haluttuun muotoon. Samalla saa validoinnin sille, että aika on oikeasti kelvollinen. Ja sitten se tärkein asia eli kirjoitettu koodi on kertaluokkaa siistimpää.

latenleffahylly [21.08.2012 13:12:58]

#

Hmm.. No tavallaan naurettavaa että saan päivämäärän muodossa pp.kk.vvvv ja joudun muuttamaan sen muotoon vvvv-kk-pp ennen tietokantaan tallentamista. Sitten haen tiedon ja muutan muotoon pp.kk.vvvv

No niin, mutta nyt suurin ongelma tuo CSV-tiedosto. Eli en halua tallentaa tyhjiä riviä tietokantaan. En myöskään otsikko riviä. Tämä tuntuu aika vaikealta, joten jalskin neuvot tulevat tarpeeseen.

dartvaneri [21.08.2012 13:17:20]

#

Voit toki tallentaa sen ajan text(tai vastaava) tyyppisenä, mutta en näe siinä mitään järkeä, kun kerran siellä on valmiiksi date ja datetime.

Lebe80 [21.08.2012 13:24:48]

#

latenleffahylly kirjoitti:

Hmm.. No tavallaan naurettavaa että saan päivämäärän muodossa pp.kk.vvvv ja joudun muuttamaan sen muotoon vvvv-kk-pp ennen tietokantaan tallentamista. Sitten haen tiedon ja muutan muotoon pp.kk.vvvv

No niin, mutta nyt suurin ongelma tuo CSV-tiedosto. Eli en halua tallentaa tyhjiä riviä tietokantaan. En myöskään otsikko riviä. Tämä tuntuu aika vaikealta, joten jalskin neuvot tulevat tarpeeseen.

Ei siinä mitään naurettavaa ole. Aikaisemmista koodeista taas saa sen kuvan, että et ole käsittänyt, että muuttujia kannattaa käsitellä niiden "luonnollisessa" muodossa, ja tulostusvaiheessa muuntaa ne "ihmiselle luettavaan" muotoon.

Eli anna niiden päivämäärien yms. olla siellä tietokannassa niille tarkoitetussa muodossa (yyyy-mm-dd hh:mm:ss), jolloin ne on koodatessakin automaagisesti oikeassa muodossa ja voit rajata tietokantahakuja ihan päivämäärien mukaankin.

Myös valuutat kannattaa tosiaan käsitellä ihan desimaalilukuina, jolloin ei missään vaiheessa käy niin, että et ole varma onko määrässä nyt kyseessä sitten eurot vaiko sentit.

Yritä siis opetella ohjelmoimaan niin, että on käytössä aina järkevät muodot luvuista. Tee vaikka omat funktiot tulostuksille, jolloin voit tulostaa automaattisesti 100e sentteinä sekoittamatta lukua myöhemmässä koodissasi.

Sama päivämäärille, tee vaikka oma funktio joka parsii pp.kk.vvvv -muodossa olevat päivämäärät tietokannalle sopivaan muotoon.


Voit myös opetella nimeämään muuttujat nimillä, joista selviää, missä muodossa muuttujan sisältö on:

$date ====> $dateUnixTimestamp;

$tulos ===> $currencyInEuros;

tms.

The Alchemist [21.08.2012 16:22:49]

#

En pitäisi lainkaan liioiteltuna lukea päivämääriä tietokannasta DateTime-olioon ja sitä käyttäen muokata haluttuun näyttömuotoon aina tarvittaessa. Toinen vaihtoehto on käyttää juuri tuota standardia muotoa, jossa ne tietokannassakin ovat.

Tuota nimeämiskäytäntöä en allekirjoita. Liikaa redundanttia tietoa, mikä tekee muuttujista hankalia kirjoittaa. "$euros" ja "$stamp" ovat minulle tutumpia.

latenleffahylly [22.08.2012 20:53:08]

#

Teillä on jälleen paljon hyviä pointteja ja ideologiaa, jota aion hyödyntää. MUTTA ette halua ymmärtää että minulle tuottaa kaikista eniten vaivaa tuo alku.

- Eli miten saada CSV-tiedostosta jo alkuvaiheessa pois tyhjät rivit, siis miten koodata se.

// luodaan muuttuja jossa tallennettuna csv-tiedoston nimi
$CSVtiedosto = "valuuttakurssit.csv";


// tuodaan csv-tiedoston sisältö file-komennolla ja tallennetaan muuttujaan $arrayRivit
$arrayRivit = file($CSVtiedosto);


var_dump($arrayRivit); // <--- täysi mysteeri miten käsitellä tuota kasaa merkkejä

Tämänkin voi tehdä eri tavoin, mutta en ymmärrä täysin mitä $arrayRivit sisältää ja miten sitä lähdetään muokkaamaan. Onko kyse merkkijonosta vai taulukosta?? (string,array) ..huoh

TULOSTUS:

array(36) { [0]=> string(2) " " [1]=> string(50) "Title,CURRENCY_CodelistValue,txtb_day,txtb_value " [2]=> string(44) "Australian dollari,AUD,10.08.2012,"1,1661" " [3]=> string(40) "Brasilian real,BRL,10.08.2012,"2,4772" " [4]=> string(44) "Bulgarian uusi lev,BGN,10.08.2012,"1,9558" " [5]=> string(42) "Englannin punta,GBP,10.08.2012,"0,78610" " [6]=> string(46) "Etelä-Afrikan randi,ZAR,10.08.2012,"9,9772" " [7]=> string(46) "Etelä-Korean won,KRW,10.08.2012,"1 386,66" " [8]=> string(43) "Filippiinien peso,PHP,10.08.2012,"51,261" " [9]=> string(44) "Hongkongin dollari,HKD,10.08.2012,"9,5121" " [10]=> string(46) "Indonesian rupia,IDR,10.08.2012,"11 632,35" " [11]=> string(39) "Intian rupia,INR,10.08.2012,"67,7900" " [12]=> string(46) "Israelin uusi sekeli,ILS,10.08.2012,"4,9051" " [13]=> string(37) "Japanin jeni,JPY,10.08.2012,"96,12" " [14]=> string(41) "Kanadan dollari,CAD,10.08.2012,"1,2192" " [15]=> string(46) "Kiinan juan renminbi,CNY,10.08.2012,"7,7989" " [16]=> string(39) "Kroatian kuna,HRK,10.08.2012,"7,4865" " [17]=> string(38) "Latvian lati,LVL,10.08.2012,"0,6962" " [18]=> string(39) "Liettuan liti,LTL,10.08.2012,"3,4528" " [19]=> string(42) "Malesian ringgit,MYR,10.08.2012,"3,8222" " [20]=> string(40) "Meksikon peso,MXN,10.08.2012,"16,1368" " [21]=> string(39) "Norjan kruunu,NOK,10.08.2012,"7,2700" " [22]=> string(38) "Puolan zloty,PLN,10.08.2012,"4,0961" " [23]=> string(43) "Romanian uusi leu,RON,10.08.2012,"4,5345" " [24]=> string(40) "Ruotsin kruunu,SEK,10.08.2012,"8,2077" " [25]=> string(44) "Singaporen dollari,SGD,10.08.2012,"1,5296" " [26]=> string(41) "Sveitsin frangi,CHF,10.08.2012,"1,2009" " [27]=> string(40) "Tanskan kruunu,DKK,10.08.2012,"7,4427" " [28]=> string(39) "Thaimaan baht,THB,10.08.2012,"38,589" " [29]=> string(40) "Tšekin koruna,CZK,10.08.2012,"25,205" " [30]=> string(38) "Turkin liira,TRY,10.08.2012,"2,1942" " [31]=> string(42) "Unkarin forintti,HUF,10.08.2012,"278,90" " [32]=> string(49) "Uuden-Seelannin dollari,NZD,10.08.2012,"1,5162" " [33]=> string(42) "Venäjän rupla,RUB,10.08.2012,"39,1440" " [34]=> string(46) "Yhdysvaltain dollari,USD,10.08.2012,"1,2262" " [35]=> string(2) " " }

Lebe80 [22.08.2012 21:17:58]

#

latenleffahylly kirjoitti:

Onko kyse merkkijonosta vai taulukosta?? (string,array) ..huoh

No nopeasti katsottuna kyse on molemmista.

Eli se on taulukko, jonka jokaisessa "solussa" on merkkijono.

latenleffahylly [22.08.2012 21:41:12]

#

Hmm.. Jotenkin tuntuu siltä että esim $arrayRivit[0] pitäisi muuttaa merkkijonoksi, jota verrataan esim. Lukuun 10.

Jos ekassa rivissä yli 10 merkkiä tallenna tieto taulukkomuuttujaan muuten poista! Mutta miten hemmetissä tällainen perusasia koodataan :/ ...jos jotakin helpottaa niin hommasin uuteen iPadiin PHP FOR DUMMIES, painoskin oli jotain 2011 ja käsittää MySQL jutut myös. (iBook kirjakauppa, englanniksi).

Lebe80 [22.08.2012 22:01:54]

#

latenleffahylly kirjoitti:

Hmm.. Jotenkin tuntuu siltä että esim $arrayRivit[0] pitäisi muuttaa merkkijonoksi, jota verrataan esim. Lukuun 10.

Jos ekassa rivissä yli 10 merkkiä tallenna tieto taulukkomuuttujaan muuten poista!

You're waaaaaaaaay off.

dartvaneri [22.08.2012 23:09:57]

#

Merkkijonon pituuden voit selvittää strlen()-funktiolla. Eli perus if-lauseella onnistuu.

<?php
    $string = "example";
    $stringLength = strlen($string);
    echo "String length:".$stringLength; // 7


/**********************************************/


   if(strlen($string) > 10){
       //Do something..
   }
   else{
       //Do something else.
   }
?>

Lisäys:

latenleffahylly kirjoitti:

Hmm.. Jotenkin tuntuu siltä että esim $arrayRivit[0] pitäisi muuttaa merkkijonoksi, jota verrataan esim. Lukuun 10.

Ei tarvi. Taulukon solua(?) voit verrata muuttujaan ihan samoin, kun muuttujaa muuttujaan, mutta taulukkoa et voi verrata muuttujaan.

<?php
    $array = array(2,"example");
    $array2 = array(array(2, "example"),"example");
    $string = "example";
    $number = 2;

   if($array[0] == 2){
       //Success
   }

   if($array[1] == "example"){
       //Success
   }

   if($array[1] == $string){
       //Success
   }

   if($array[0] == $number){
       //Success
   }

   if($array == "example"){
       //Failed
   }

   if($array2[0][1] == "example"){
       //Success
   }
?>

Lisäys:

Voit laittaa myös näin:

<?php
    if($row != "\n"){
        //Do something..
    }
?>

Eli siis tuon if-lauseen sisään tulee koodi, joka halutaan suorittaa silloin, jos rivillä ei ole pelkkä rivin vaihto. Jos taasen haluat poistaa kaikki rivinvaihdot, se käy kätevästi säännöllisillä lausekkeilla.

preg_replace("/\n/","<br>","Example text")

jalski [23.08.2012 00:00:38]

#

dartvaneri kirjoitti:

Eli siis tuon if-lauseen sisään tulee koodi, joka halutaan suorittaa silloin, jos rivillä ei ole pelkkä rivin vaihto.

Tuo ei kuitenkaan poista kaikkia tyhjiä rivejä, eihän? Tyhjä rivihän voi tässä tapauksessa sisältää lisäksi myös välilyöntejä...

The Alchemist [23.08.2012 07:08:51]

#

dartvaneri kirjoitti:

Eli siis tuon if-lauseen sisään tulee koodi, joka halutaan suorittaa silloin, jos rivillä ei ole pelkkä rivin vaihto. Jos taasen haluat poistaa kaikki rivinvaihdot, se käy kätevästi säännöllisillä lausekkeilla.

preg_replace("/\n/","<br>","Example text")

Ei käy. Regexit ovat huonoin mahdollinen vaihtoehto, koska ne ovat hitaampia kuin staattisia merkkijonoja vertailevat funktiot. Jos korvattava merkkijono on vakio, niin silloin kannattaa aina käyttää str_replace()-funktiota. Whitespacen poistamiseen rivien lopusta on silti parempi käyttää funktiota trim() tai rtrim().

dartvaneri [23.08.2012 07:51:17]

#

jalski kirjoitti:

dartvaneri kirjoitti:

Eli siis tuon if-lauseen sisään tulee koodi, joka halutaan suorittaa silloin, jos rivillä ei ole pelkkä rivin vaihto.

Tuo ei kuitenkaan poista kaikkia tyhjiä rivejä, eihän? Tyhjä rivihän voi tässäu tapauksessa sisältää lisäksi myös välilyöntejä...

Enpä ottanut tuota huomioon. Ei taida poistaa,kuin ne rivit, joissa on pelkästään rivin vaihto.

latenleffahylly [23.08.2012 08:45:27]

#

Aloitetaan tästä:

<?php
    $string = "example";
    $stringLength = strlen($string);
    echo "String length:".$stringLength; // 7
?>

Nyt kun laitan "example" tilalle valuuttakurssi-tiedoston sisällön:

<?php
$CSVtiedosto = "valuuttakurssit.csv";

$arrayRivit = file($CSVtiedosto);

$string = $arrayRivit;
    $stringLength = strlen($string);
    echo "String length:".$stringLength;
?>

Tietenkin tulee varoitus: "Warning: strlen() expects parameter 1 to be string, array given"

Eli juurikin tätä kysyin aikaisemmin. Eli mitä sieltä CSV-tiedostosta tulee ja miten se pitää käsitellä?

- Array
- jaa Array riveihin
- parsi osa riveistä pois
- halutut rivit yhteen muuttuja-arrayhin
- hmm..

Lisäys:

$stringLength = count($string);

COUNT -funktiolla, tulokseksi tulee 36. Eli koodi laskee arrayn kaikki rivit. Voiko strlen -funktiota edes käyttää arrayn kohdalla.

Lebe80 [23.08.2012 09:52:21]

#

Et voi verrata edelleenkään merkkijonon pituusfunktiota taulukkoon.

Eli ei:

$string = $arrayRivit;
$stringLength = strlen($string);

vaan:

$i = 1;
$string = $arrayRivit[$i]; // (0 = ensimmäinen, 1 = toinen,...)
$stringLength = strlen($string);

dartvaneri [23.08.2012 10:28:07]

#

Nyt sulla $arrayRivit on taulukko , ja kun sijoitat sen muuttujan string ,niin stringistä ei suinkaan tule merkkikojonoa, vaan se on edelleen taulukko.

latenleffahylly [23.08.2012 10:49:26]

#

Ajattelin että järkevin tapa saada ne rivit, jotka haluan - on ottaa talteen rivit jotka sisältävät lainausmerkit.

CSV:

---tyhjä rivi---
Title,CURRENCY_CodelistValue,txtb_day,txtb_value
Australian dollari,AUD,10.08.2012,"1,1661"
Brasilian real,BRL,10.08.2012,"2,4772"

<?php
$CSVtiedosto = "valuuttakurssit.csv";

$arrayRivit = file($CSVtiedosto);

  foreach ($arrayRivit as $rivit) {

  $rivit2 = explode('\n',$rivit);

  $rivit36 = $rivit2[0];

  $stringLength = strlen($rivit36);

    if($stringLength > 10){
      echo "merkkijono<br>";
    }
    else{
      echo "tyhja<br>";
    }
}
?>

Lebe80 [23.08.2012 13:30:05]

#

Tiedätkö sä ees mitä sä oot tekemässä?

Eli teetkö jonkun ihmeen takia nyt asiat jotenkin älyttömän vaikeesti, varsinkin kun ne vois tehdä helpostikin?

Php:ssa kuitenkin on olemassa valmiit funktiot csv-tiedostoille, ja tätäkin on tarjottu sinulle tuolla aikaisemmissa viesteissä...

edit:
Tuntuuko susta jotenkin, että taulukot sekoittaa sun pääsi? Eli onko nuo taulukkomuuttujat jotenkin uusi asia sinulle?

latenleffahylly [23.08.2012 13:49:36]

#

Kaikki on uutta. Juu palaan alkuun, eli miten puretaan CSV-tiedosto, kiitän.

Lebe80 [23.08.2012 14:41:14]

#

latenleffahylly kirjoitti:

Kaikki on uutta. Juu palaan alkuun, eli miten puretaan CSV-tiedosto, kiitän.

RTFM?


Eli oletko kokeillut esim. Googlata taikasanoilla:
http://lmgtfy.com/?q=php csv

Ohjelmointi ei ole sitä, että muistat ihan kaiken ulkoa, vaan enemmänkin sitä, että osaat etsiä tietoa itse omatoimisesti ja tiedät mitä sinun pitää tehdä.

latenleffahylly [23.08.2012 14:53:42]

#

Saan usein error raportin jossa kerrotaan että kyse string ja kone luulee että array.

dartvaneri [23.08.2012 20:12:43]

#

Tai sitten se vaan yksin kertaisesti on array, eikä merkkijono. Sun kannataanee putkan php oppaasta nyt opiskella taulukot, merkkijonot, muuttujat, yms.

latenleffahylly [23.08.2012 20:36:25]

#

fgetcsv — Gets line from file pointer and parse for CSV fields

Dv, tai joku, voitteko ystävällisesti suomentaa tuon. Mielestäni tulos on array eli taulukko, mutta luultavasti sitten käsittelen sitä string <- tarkoitetuilla funktioilla.

Teuro [23.08.2012 20:42:33]

#

Katso fgetcsv() funktion ensimmäinen esimerkki. Funktio siis palauttaa taulukon, johon kentät on valmiiksi ositeltu, joten niitä ei tarvitse käsin parsia.

latenleffahylly [23.08.2012 21:00:12]

#

Okei, okei.. vaikka olen tehnyt tuonkin mallin useasti - nyt tajusin, kiitos Teuro. Minulla on äärimmäisen haitallinen tapa tehdä yksinkertaisesta asiasta vaikea, suuri sotku.

Tuota, tuota.. alla olevalla koodilla laitan CSV-tiedoston rivit allekkain ja aloitan jatkossa merkkijonojen manipuloinnin.

<?php
$row = 1;
if (($handle = fopen("valuuttakurssit.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, "\n")) !== FALSE) {
        $num = count($data);
        $row++;
        for ($c=0; $c < $num; $c++) {
            echo $data[$c] . "<br>\n";
        }
    }
    fclose($handle);
}
?>

TULOSTUS:

---TÄSSÄ LIENEE TYHJÄ RIVI---
Title,CURRENCY_CodelistValue,txtb_day,txtb_value
Australian dollari,AUD,10.08.2012,"1,1661"
Brasilian real,BRL,10.08.2012,"2,4772"

Lisäys:

Laitan tämän nyt vielä:

ERROR: "strlen() expects parameter 1 to be string, array given..."

$attributes = array($csvRivit);

        if (strlen($attributes) < 3) {
            echo "1";
        } else {
            echo "2";
        }

Lisäys:

Kokeilin PHP.net mallia ja sama tulos??

<?php

$attributes = array('one', 'two', 'three');

if (strlen($attributes) == 0 && !is_bool($attributes)) {
    echo "We are in the 'if'\n";  //  PHP 5.3
} else {
    echo "We are in the 'else'\n";  //  PHP 5.2
}

?>

Warning: strlen() expects parameter 1 to be string, array given in... on line 16
We are in the 'if'

Lisäys:

-------------------------------------------

Tällanenkin löytyi:

strlen() returns NULL when executed on arrays, and an E_WARNING level error is emitted.

jlaire [24.08.2012 06:22:53]

#

latenleffahylly kirjoitti:

ERROR: "strlen() expects parameter 1 to be string, array given..."

$attributes = array($csvRivit);

        if (strlen($attributes) < 3) {

Niin? strlen() haluaa stringin mutta annat sille arrayn. Mikä tässä on epäselvää?

Taulukon koon saa funktiolla count() https://www.php.net/manual/en/function.count.php

latenleffahylly [24.08.2012 06:56:56]

#

Strlen laskee merkkien määrän. Count sanojen/objektien.

Hello World

Strlen: 11
Count: 2

Yritän löytää Array funktioista tapaa, jolla laskea merkkien määrä. Mielestäni strlen pystyy tähän myös kunhan koodi on oikein muotoiltu.

Macro [24.08.2012 07:44:06]

#

$pituus = 0;
for($i = 0; $i < count($array); $i++) {
  $pituus += strlen($array[$i]);
}

latenleffahylly [24.08.2012 09:00:51]

#

Tänks Macro, nyt sitten onnistuin saamaan kaikkien rivien merkkien määrän ja tajusin että tarvitsen myös rivien sisällön, huoh.. täytyy alkaa tutkimaan kunnolla noita Array Functioita.

<?php
  $csvTiedosto = "valuuttakurssit.csv";
  $rivi = 1;
    if (($csvArray = fopen($csvTiedosto, "r")) !== FALSE) {
      while (($csvRivi = fgetcsv($csvArray, 1000, "\n")) !== FALSE) {

        $pituus = 0;
        for($x = 0; $x < count($csvRivi); $x++) {
        $pituus += strlen($csvRivi[$x]);
        }

        if($pituus === 0 || $pituus === 48 ){
        // echo "<p>poistetaan tyhjat rivit ja otsikko rivi</p>";
        }
        else{
        $halututRivit = $pituus;
        // echo $halututRivit . "<br>";
        }
      }
      fclose($csvArray);
    }
  ?>

TULOSTUS:

poistetaan tyhjat rivit ja otsikko rivi
poistetaan tyhjat rivit ja otsikko rivi
42
38
42
40
44
44
41
42
44
37
44
35
39
44
37
36
37
40
38
37
36
41
38
42
39
38
37
38
36
40
47
40
44
poistetaan tyhjat rivit ja otsikko rivi

Lebe80 [24.08.2012 09:41:30]

#

Älä nyt turhaan ajattele niitä taulukoita mörköinä.

Sä voit aina ottaa arrayn solun sisään ihan tavalliseen apumuuttujaan:

$tavallinenMuuttuja = $munTaulukkomuuttujanSolunArvo[23];

Esim. jos sulla on taulukossa ihmisten nimiä:

$nimetArray = array("Mikko","Late","Samppa","Jorma","Pirjo");

$nimi = $nimetArrat[1];
echo $nimi; // Late
echo strlen($nimi); // 4
$nimetArray[1] = "Simo"; // Korvataan taulukosta nimi Late Simolla

Tietenkin taulukosta voi tehdä moniulotteisen, ja usein se on selvyyden vuoksi järkevääkin.

latenleffahylly [24.08.2012 10:06:10]

#

aa.. tuon mahdollisuuden olen unohtanut täysin, vaikka jo perusteissa. Eli rivien muuttamisen. Jokatapauksessa olen tajunnut vasta nyt erään merkittävän asian eli mitä FOREACH tekee ARRAY:lle.

1.) fgetcsv -> tuo CSV-tiedoston sisällön taulukkomuodossa (array)

2.) foreach -> muuttaa arrayn sisällön riveiksi eli merkkijonoiksi (string)

3.) etsi funktio, jolla voi käsitellä merkkijonoa (string)

4.) if-rakenne -> palauttaa (boolean) totuusarvon (true, false)

...

katsotaan sitten myöhemmin mitä tämän jälkeen tapahtuu.

Teuro [24.08.2012 16:44:00]

#

latenleffahylly kirjoitti:

2.) foreach -> muuttaa arrayn sisällön riveiksi eli merkkijonoiksi (string)

Väärin foreach rakenne vain kahlaa taulukon läpi. Samalla rakenne mahdollistaa eri nimisten taulukon indeksien käsittelyn yhdellä muuttujalla.

The Alchemist [25.08.2012 07:02:51]

#

If-rakenne ei myöskään palauta yhtään mitään. If-ehdon sisällä oleva lauseke evaluoituu totuusarvoksi, jonka mukaan valitaan oikea haara if-else-ketjussa.

latenleffahylly [25.08.2012 13:36:53]

#

Erittäin mystinen ongelma? Tulostus näyttää oikein, mutta tietokanta ammottaa tyhjyyttä?


TULOSTUS:
Australian dollari AUD 10.8.2012 1.1661
Brasilian real BRL 10.8.2012 2.4772
jne.

TIETOKANTA:
id valuutanNimi lyhenne pvm valuutta1 valuutta2
1 0000-00-00 0 0
2 0000-00-00 0 0
jne.

<!DOCTYPE html>
<html>
  <head>
    <title>Valuuttakurssit</title>
  </head>
  <body>

  <?php
  $csvTiedosto = "valuuttakurssit.csv";

  $servername = 'localhost';            // palvelimen nimi
  $dbusername = 'xxx';                  // käyttäjän nimi
  $dbpassword = 'xxx';                  // käyttäjän salasana
  $dbname = 'xxx';                      // tietokannan nimi


  // funktio 1: tietokantayhteys()
  tietokantayhteys($servername,$dbname,$dbusername,$dbpassword);
  function tietokantayhteys($servername,$dbname,$dbuser,$dbpassword){

    global $con;
    $con = mysql_connect("$servername","$dbuser","$dbpassword");
      if (!$con) {
        die('Could not connect: ' . mysql_error());

      }
     mysql_select_db("$dbname", $con);

      $sql="INSERT INTO valuuttakurssi (valuutanNimi, lyhenne, pvm, valuutta1, valuutta2)
      VALUES
      ('$valuutanNimi','$lyhenne','$pvm','$valuutta1','$valuutta2')";

      if (!mysql_query($sql,$con)) {
        die('Error: ' . mysql_error());

      }
    mysql_close($con);

  } // funktio loppuu

    if (($csvArray = fopen($csvTiedosto, "r")) !== FALSE) {
      while (($csvRivit = fgetcsv($csvArray, 1000, "\n")) !== FALSE) {
        foreach($csvRivit as $rivi){

          if (strstr($rivi, '"') !== false) {

            $halututRivit = $rivi;

            $rivit2osaan = explode('"', $halututRivit);

            $osat = $rivit2osaan;

            $merkit = $osat[0];
            $luvut = $osat[1];

            $merkit3osaan = explode(',',$merkit);

            $valuutanNimi = $merkit3osaan[0];
            $lyhenne = $merkit3osaan[1];
            $pvm1 = $merkit3osaan[2];

            $pvm2 = str_replace(".", "-", $pvm1);
            $pvm3 = explode('-',$pvm2);

            $pp = $pvm3[0];
            $kk = $pvm3[1];
            $vv = $pvm3[2];

            $pvm = $vv . "-" . $kk . "-" . $pp;

            $luvut2 = str_replace(array(",", "\xC2\xA0"), array(".", ""), $luvut);

            $luvut3 = explode('.',$luvut2);

            $valuutta1 = $luvut3[0];
            $valuutta2 = $luvut3[1];

            // tietokantaan tallentaminen ja sieltä tulostaminen ja lopuksi tietokantayhteyden sulkeminen

            // valuuttakurssi                       - taulun nimi
            // id             - 1,2,3 jne.          - AUTO_INCREMENT, Primary Key
            // valuutanNimi   - Australian Dollari  - VARCHAR(55)
            // lyhenne        - AUD                 - CHAR(3)
            // pvm            - 2012-08-10          - DATE
            // valuutta1      - 1                   - INT
            // valuutta2      - 1661                - INT

            tietokantayhteys($servername,$dbname,$dbusername,$dbpassword);

              echo "<table>
                      <tr>
                        <td width='250px'>" . $valuutanNimi . "</td>
                        <td width='100px'>" . $lyhenne . "</td>
                        <td width='100px' class='pvm'>" . date("j.n.Y", strtotime($pvm)) . "</td>
                        <td width='100px'>" . $valuutta1 . "." . $valuutta2 . "</td>
                      </tr>
                    </table>";

              }
            }
          }
        fclose($csvArray); // suljetaan csv-tiedosto
      }
    ?>

  </body>
</html>

Macro [25.08.2012 13:40:30]

#

Eihän tossa koodissa haeta tietokannasta mitään, vaan ne tulevat tosta csv-tiedostosta.

Eikä tuolla rivillä 29 alkavassa kyselyssä edes syötetä mitään tietokantaan. Alustamattomia muuttujia koitat tunkea tiekantaan, eihän silloin tule mitään tavaraa.

Ps. Avaat tietokantayhteyden foreach-silmukassa?

latenleffahylly [25.08.2012 16:33:55]

#

Macro ja muut, tein tällaisen funktion ja käytän sitä foreach silmukan sisällä, heti silmukan alussa.

foreach($csvRivit as $rivi){
  connectDB();

Tässä funktio, jolla avataan tietokantayhteys ja valitaan tietokanta, jota käytetään.

function connectDB() {
    $username = "xxx";
    $pwd      = "xxx";
    $host     = "localhost";
    $dbname   = "xxx";

    $con = mysql_connect("$host", "$username", "$pwd");
    if (!$con) {
      die('Could not connect: ' . mysql_error());
    }

    mysql_select_db("$dbname", $con);
  }

Nyt sitten minulla on ongelmia tehdä toinen funktio joka hoitaisi oikeaoppisesti alla olevan koodin. Mikä avuksi, kuinka monta funktiota olisi järkevä? Pahoittelut että en täysin ymmärrä miten funktioita kannattaisi käyttää.

Eli alla olevasta koodista pitäisi tehdä funktio ja kutsua sitä foreach silmukan loppu puolella.

// alustetaan muuttujat
$valuutanNimi = mysqli_real_escape_string($merkit3osaan[0]);
$lyhenne =      mysqli_real_escape_string($merkit3osaan[1]);
$pvm =          mysqli_real_escape_string($pvm3[2] . "-" . $pvm3[1] . "-" . $pvm3[0]);
$valuutta1 =    mysqli_real_escape_string($luvut3[0]);
$valuutta2 =    mysqli_real_escape_string($luvut3[1]);

$sql = "INSERT INTO valuuttakurssi (valuutanNimi, lyhenne, pvm, valuutta1, valuutta2)
VALUES
('$valuutanNimi','$lyhenne','$pvm','$valuutta1','$valuutta2')";

if (!mysql_query($sql)) {
  die('Error: ' . mysql_error());

}

Macro [25.08.2012 16:47:06]

#

<?php
connectDB();
$tiedosto = file("tiedosto");

foreach($tiedosto as $rivi) {
	mysql_query(...); // lisää rivi tietokantaan
	echo $rivi;
}

latenleffahylly [25.08.2012 16:49:57]

#

Okei, eli järkevää on avata tietokantayhteys heti koodin alussa ja tuo SQL juttu, ei edes tehdä erillistä funktiota. Kiitän!

The Alchemist [25.08.2012 19:32:30]

#

Ei, ei, ei. Noita vanhoja mysql-alkuisia php:n funktioita ei saa enää käyttää. Sanotaanhan niin jo niiden kaikkien ohjeissakin php.netissä.

https://www.php.net/manual/en/function.mysql-query.php

Lue Ohjelmointiputkan php-oppaasta, miten pdo:ta käytetään.

latenleffahylly [25.08.2012 20:00:38]

#

Juu.. tein tuon tulostamisen käyttäen PDO:ta. Sen laittaminen funktion sisään sen sijaan on täyttä tuskaa.

<!DOCTYPE html>
<html>
  <head>
    <title>Tehtava 1 - tulostus</title>
    <link rel="stylesheet" type="text/css" href="tyylit.css" />
  </head>
  <body>

  <?php
  // funktio
  function infoDB() {
    $username = "***";
    $pwd      = "***";
    $host     = "localhost";
    $dbname   = "***";

    // muodostetaan yhteys tietokantaan
    try {
        $yhteys = new PDO("mysql:host=$host;dbname=$dbname", "$username", "$pwd");
    } catch (PDOException $e) {
        die("VIRHE: " . $e->getMessage());
    }
    // virheenkäsittely: virheet aiheuttavat poikkeuksen
    $yhteys->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    // merkistö: käytetään latin1-merkistöä; toinen yleinen vaihtoehto on utf8.
    $yhteys->exec("SET NAMES latin1");

    // valmistetaan kysely
    $kysely = $yhteys->prepare("SELECT * FROM valuuttakurssi");
    // suoritetaan kysely
    $kysely->execute();

  // näytetään kyselyn tulokset taulukossa
  echo "<table id='valuutta'>";
  echo "<tr><th>valuutan nimi</th><th>lyhenne</th><th>pvm</th><th>kurssi</th></tr>";
  // käsitellään tulostaulun rivit yksi kerrallaan
  while ($rivi = $kysely->fetch()) {
    // $rivi["id"]
    // $rivi["valuutanNimi"]
    // $rivi["lyhenne"]
    // $rivi["pvm"]
    // $rivi["valuutta1"]
    // $rivi["valuutta2"]
    echo "<tr>";
    echo "<td>" . htmlspecialchars($rivi["valuutanNimi"]) . "</td>";
    echo "<td width='100px'>" . htmlspecialchars($rivi["lyhenne"]) . "</td>";
    echo "<td width='100px'>" . date("j.n.Y", strtotime($rivi["pvm"])) . "</td>";
    echo "<td width='100px'>" . htmlspecialchars($rivi["valuutta1"]) . "." . htmlspecialchars($rivi["valuutta2"]) . "</td>";
    echo "</tr>";
  }
  echo "</table>";

  }

  // kutsutaan funktiota
  infoDB();
  ?>

  </body>
</html>

The Alchemist [25.08.2012 20:30:23]

#

Tuossa funktiossa ei ole mitään järkeä. Et voi availla tietokantayhteyksiä noin holtittomasti. Saat luoda täsmälleen yhden yhteyden per skriptin suorituskerta, et jokaisessa funktiossa omaansa. (Varsinkin kun jokainen kutsu aukaisee uuden yhteyden.)

Samassa funktiossa ei pitäisi muutenkaan suorittaa tietokantakyselyitä ja tulostaa näytölle dataa. Ne ovat kaksi eri asiaa ja ne täytyy pitää erillään.

<?php

class DataModel {
    private $database;

    public function __construct($database) {
        $this->database = $database;
    }

    public function getData() {
        $query = 'SELECT ...';
        $smt = $this->database->query($query);

        return $smt->fetchAll();
    }
}

class DataView {
    private $data;

    public function setData($data) {
        $this->data = $data;
    }

    public function show() {
        if (!$this->data) {
            $this->error();
            return;
        }

        foreach ($this->data as $i => $row) {
            $x = $row['x'];
            $y = $row['y'];

            print "{$i}: {$x} ja {$y}\n";
        }
    }

    private function error() {
        print "Tietoa ei löytynyt!\n";
    }
}

$database = new PDO(...);
$model = new DataModel($database);

$view = new DataView();
$view->setData($model->getData());
$view->show();

Tuossa on ajatustasolla esitelty yksi tapa hoitaa homma. Toki luokkien käyttäminen ei ole pakollista, vaikkakin se tekee kaikesta paljon yksinkertaisempaa kuin olla ilman. Asian voi silti hoitaa ihan proseduraalisesti pelkillä funktioillakin.

function get_config($category) {
    static $config;

    if (!$config) {
        // array( 'database' => array(), 'joku_muu' => array() )
        $config = file_get_contents('config.php');
    }

    return $config[$category];
}

function get_database() {
    static $db;

    if (!$db) {
        try {
            $conf = get_config('database');
            $db = new PDO(...);
        } catch (PDOException $e) {
            throw new Exception("Tietokanta ei toimi!");
        }
    }

    return $db
}

function get_data() {
    $db = get_databsae();
    $db->query('SELECT ...');
    return $db->fetchAll();
}

function show_data($data) {
    foreach ($data as $i => $row) {
        $x = $row['x'];
        $y = $row['y'];

        print "{$i}: {$x} ja {$y}\n";
    }
}

function show_error($message) {
    print "Virhe: {$message}\n";
}

// Sovellus
$data = get_data();

if (!$data) {
    show_error('Tietoa ei löytynyt!');
} else {
    show_data($data);
}

latenleffahylly [26.08.2012 15:40:20]

#

Just joo.. kivan näköistä koodia - vielä kun ymmärtäisi jotain. Juu.. harjoittelen tällä hetkellä funktioita. Sitten siirryn luokkiin.

Nuo alkemistin koodit laitan säilöön ja vielä jonain päivänä ymmärrän ne kohta kohdalta. Perusidea olisi tehdä 2 funktiota:

Funktio1: Avaa tietokantayhteys (pdo)
Funktio2: Sulje tietokantayhteys (pdo)

ja oikeaoppinen tapa kutsua funktioita muualla koodissa. Palaan taas hieman taaksepäin ja alan rakentelemaan pieniä yksinkertaisia funktioita. Tällä hetkellä liittyen Tehtävään 1, viimeinen ongelmani on erikoismerkkien tallentaminen tietokantaan. Ne tallentuvat aivan oudun näköisinä. Mielestäni tämä ei ole hyvä koska jälkeenpäin en osaa niitä muuntaa järkevän näköiseksi.

Esimerkkinä: TÅ¡ekin koruna CZK 10.8.2012 25.205

Kyseessä Tšekin koruna

dartvaneri [26.08.2012 22:23:06]

#

latenleffahylly kirjoitti:

harjoittelen tällä hetkellä funktioita. Sitten siirryn luokkiin.

Suosittelen opettelemaan kunnolla kaikki perusasiat(mukaanlukien funktiot), ennen kuin siirryt luokkiin. Turha vaivata päätä luokkien takia, kun on niin paljon muuta vaikeaa ja mietimistä ihan perusasioissa.

latenleffahylly kirjoitti:

Funktio2: Sulje tietokantayhteys (pdo)

Ei ole tarvetta PDO:ssa.

reca [29.08.2012 10:57:04]

#

Enpä ole pitkään aikaan tänne kirjoitellut, mutta nyt on pakko.

Järkyttävää. Hyvin järkyttävää. Luin äsken koko keskustelun.. Onko tässä koko jutussa mitään järkeä?

Nyt täytyis pistää peli poikki. Tässä on ilmeisesti otettu vähän liian isoa alkuharppausta. Taitaa olla kyseessä ensimmäinen PHP (tai yleensäkään mikään) -koodaus?

Mielestäni pitäisi lähteä ihan alusta. Kuten tässäkin ketjussa on jo useammin ehdotettu, lue alkuun noi perus PHP-oppaat putkasta. Tarkoitan nimenomaan PHP-oppaita, enkä niitä PHP & MySQL-oppaita.

Alat ensin tehdä ihan perusharjoituksia. Tulostusta, muuttujien käsittelyä ja vertailua, silmukkarakenteita ja syntaksia.. jne.. Aloitat siis perusjutuista, eikä niin, että "hei haluan tehdä tollasen systeemin" ja sitte lähtee mopo käsistä.

Perusasiat on nyt niin hukassa, että on ihan turhaa miettiä miten joku asia toteutetaan, kun henkilö ei edes osaa käyttää koko kieltä. Sama kuin opettelisit jotakin uutta kieltä ja mietit millä sanoilla sanoisit jonkun lauseen, mutta et edes tiedä sanajärjestystä.

En halua loukata, vaan saada ymmärtämään, että on aika aloittaa ihan alusta. Ihan alusta.

EDIT:
Menin erheessä vielä lukemaan muita lastenleffahyllyn keskusteluja. En jaksa käyttää suoria lainauksia (joten uskokaa, mikäli haluatte), mutta asenteessa voisi olla myös hieman korjaamista. Toisessa viestiketjussa kävi ilmi, että ajattelet koodauksen vain copy-pasteksi ja hieman virittelyä päälle.

Ei toimi homma niin. Jos et osaa koodata, niin et myöskään osaa muuttaa koodia. Sitten kun osaat kirjoittaa koodia "tyhjästä", niin voit alkaa muokkailemaan ja tekemään suurempia asioita.

Eli aloitat vaan kirjoittamaan "tyhjästä". Ei, et osaa mitään kovin vaikeaa, mutta toivottavasti osaat vaikka tulostaa tekstiä ruudulle? Siitä voit sitten lähteä perusoppailla eteenpäin.

dartvaneri [29.08.2012 11:54:32]

#

reca kirjoitti:

Aloitat siis perusjutuista, eikä niin, että "hei haluan tehdä tollasen systeemin" ja sitte lähtee mopo käsistä.

Mielestäni on paljon tehokaampaa opetella kieli jonkun projektin kautta, kuin vain oppaita lukemalla. Itsekkin alkuvaiheissa aloitin lukemalla useasti putkan oppaan läpi. Eipä siitä paljoa ymmärtänyt. Mutta kun lähtee valmiista koodista muokkailemaan ja rakentelemaan omia juttuja päälle, oppii ehkä tehokkaammin.
Itsekkin tuossa php & mysql oppaassa olevasta esimerkki koodista(muistaakseni verkkokauppa koodi) Lähin sitten rakentelemaan. Yhtään php koodia en ollut aikasemmin saanut yrityksistä huolimatta rakennettua. Mutta kun siihen rupesi sitten muokkailemaan, niin johan alko asiat valkenemaan.

Mutta toki oppaatkin on hyvin tärkeä lukea läpi vaikka useaan kertaan.

Tämä siis minun mielipiteeni asiasta, ja eihän se jokaisen kohdalla näin mene.

Lebe80 [29.08.2012 12:05:06]

#

dartvaneri kirjoitti:

reca kirjoitti:

Aloitat siis perusjutuista, eikä niin, että "hei haluan tehdä tollasen systeemin" ja sitte lähtee mopo käsistä.

Mielestäni on paljon tehokaampaa opetella kieli jonkun projektin kautta, kuin vain oppaita lukemalla.

Aivan, mutta nyt ei vertaillakaan lukemista ja koodailua, vaan sitä, että lähdetään ekana ohjelmointiprojektina tekemään jotain omille taidoille täysin ylimitoitettua projektia.

Eli ohjelmointi pitäisi aloittaa "Hello worldeistä" ja sitä kautta "Arvaa numero"-tyylisiin yksinkertaisiin projekteihin ja kasvattaa sitä omaa tietämystään.

latenleffahylly [29.08.2012 15:58:48]

#

No niin..

Olette kaikki 3 täysin oikeassa. Mielestäni koodamista voi oppia tekemällä projektin, jossa on useita ongelmakohtia joita sitten ratkotaan. Ongelmanratkontaa ja loogista päättelykykyä.

Toki recan pointti on ihan oikea. Rakenne ja tyhjältä pöydältä koodaamaan lähteminen, mutta ihan vain pelkkiä alku oppaita lukemalla ei pääse eteenpäin. Olen oppaita käynyt läpi ja läpi ja läpi...

1.) Teen projektia
2.) Kohtaan ongelman
3.) Palaan oppaaseen ja yritän soveltaa esimerkkiä omaan ongelmaani
4.) Ratkaisu, joka TALLENNETAAN muistiin, jotta voin ottaa sen myöhemmin käyttöön tarvittaessa

hmm..

No tavallaan omalla kohdallani käyn koko ajan perusteita läpi, mutta yritän myös rakentaa turhan vaativaa projektia eteenpäin. Tapahtumapalvelu versio 2.

Kiitos dartvanerin kommentista eli olen täysin samaa mieltä: "Mielestäni on paljon tehokaampaa opetella kieli jonkun projektin kautta, kuin vain oppaita lukemalla." Itse koen todella vaikeaksi nuo oppaat. Tuntuu että tekemällä ja toistamalla jotain jää päähän.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta