Ne povećava se brojač u globalnoj varijabli

Treba mi najprostiji brojač stavki u narudžbi. Nemam nekog iskustva s PHP-om, ali me baš frustrira što na ovako jednostavnim problemima ne dolazim do rješenja, pa moram da pitam druge.

Pokušavam preko ključne riječi GLOBAL. U order_number.php postavljam inicijalnu vrijednost varijable: $item = 0;. Koristim je u save_item_order.php, prvo tako što je povećavam:

GLOBAL $item;
$item++;

a kasnije pišem u bazu. Vrijednost $item je 1. I to prođe bez problema.
Prelazim u index.php i preko forme se vraćam u order_number.php sve dok ima stavki narudžbe za unositi. Međutim, $item uvijek ima vrijednost 1. Ne povećava se.

$item = 1;
$item++;

To je osnova.

Mislim da se ne razumijemo.
U jednoj skripti postavljam $item = 0 (može i 1, nebitno) i onda tu varijablu želim koristiti u drugoj.

Pa zadnju vrijednost moras pokupiti iz baze i tek prije slanja iduce narudzbe moras povecati za +1.

btw. zadatak je malo nejasan, pogotovo bez ikakvog koda.
Idealno bi bilo da stavis na github ili sl.

Htio bih izbjeći korištenje baze za ovo.
Suština je da mi treba neki brojač koji bi se uvećavao, ali pošto se prelazi iz skripte u skriptu treba biti globalan, da bi zadržao vrijednost. I to je sve.

Izgleda da sam pogrešno shvatio ovo “globalno”. :blush:

Meni treba da iniciram varijablu u order_number.php:

$item = 0;

A onda da je povećavam/koristim u save_item_order.php:

GLOBAL $item;
$item++;

Ovako kako sam pokušavao radilo bi da je save_item_order.php funkcija unutar order_number.php.
A meni treba da su zasebni fajlovi. Ima li nekog jednostavnoog rješenja bez korištenja baze?

Ček jel to misliš kada više ljudi naručuje? Recimo prvi kupac ima 1 a drugi 2 treći 3 itd?

Onda bi morao iz baze ili snimanje u txt pa čitanje iz nje…

Ili ako misliš jednom kupcu da ima redni broj ako su 2 ili više artikala? Tada koristi if then else da ispita prenešenu varijablu…

Prvo iz baze uzmem podatke o kupcima.
Nakon toga korisnik unosi broj narudžbe.
E onda, dok unosi stavke narudžbe (ne znam koliko će ih biti), trebaju mi njihovi redni brojevi.
Kad završi, sve planiram gurnuti u bazu.

Pa stavi hidden input type i tu gurni broj i preuzmi te povećaj i opet spremi…

1 Like

Life cycle ili ti životni vijek varijabli u php-u traje od reguesta do requsta na server. Znači svaki puta skoro sve kreće iz nule. Permanentni su samo zapisi u fileovima i u bazi.
Osim toga postoje session varijable i cookie. Session varijable žive onoliko koliko traje session korisnika, a cookie dok ne isteknu ili se ne obrišu od strane korisnika.

Tebi treba permanent varijabla. Što mozes riješiti na više načina.
Ja osobno u svakom programskom jeziku u kojem radim imam metode za get i set permanent varijabli. Koje mogu ovisno o zadanom tipu permanent varijable preživjet i bildanje programa. (Za jezike koji se bildaju, poput C#)

Po meni bi svaki jezik to trebao imat…vrlo korisna stvarčica.

A logika za složit nešto tako nije mudrolija.
Set metoda unutar sebe odlučije hoće li zapis gurnut u bazu (ako ima pristup bazi i inicijalizirana je potrebna tablica) …a ako nema, onda se koristi txt file-ovima za zapis stanja varijabli. Sama varijabla da bi zadržala svoj type prilikom spremanja kasnije za dohvat… se konvertira i sprema u JSON formatu. To ujedno omogućuje da se pohrani bilo kakav multidimensionalni objekt. A kod dohvata varijable se naravno iz JSONa natrag rekovera u izvorni oblik.

Također je praktično kod spremanja dodati parametar “duration” koji govori koliko dugo ta varijabla smije živjet. Pa kod dohvata se provjeri duration i vraća null za slučaj da je istekao. Tu se da igrati i sa vrstama permanent varijabli, gdje valja primjetiti da je nativna session varijabla zapravo samo jedna podvrsta od svih mogućih/primjenjivih permanent varijabli.

Ovo je inače vrlo korisno složiti i iz razloga što te ovakve sitnice tjeraju da smišljaš i dodaješ polja u bazu koja se koriste samo “jednom”. Nagrđuje bazu.
Dok set i get metoda se vežu uz samo jednu tablicu koja ima polja npr: varname, value, liveTill
…i u tu jednu tablicu stanu sve takve đinđe koje će ti zatrebat…ne samo u ovom programu, nego si rješio taj problem i za sve ostale programe koje ćeš pravit.

1 Like

@Tarak Ako unaprijed znaš da ćeš item inicijalizirat na 0 ili na 1, zašto to mora bit u odvojenom fajlu i zašto globalna? Sve to možeš uraditi u save_item_order.php

Mislim da je prijedlog od @spiderman jako dobar, da staviš hidden polje.

I ovo što je @bozoou napisao je jako korisno. Globalna varijabla ti neće preživjet novi request tako da, ako moraš sačuvat vrijednost između 2 requesta, spremi je u session.

Možeš li staviti kod od forme ovdje da vidimo koje podatke šalješ? Meni djeluje da s jedne stranice šalješ niz stavki na drugu, i želiš uz to dodati i redni broj stavke? Ako je tako, onda jednostavno tamo gdje čitaš stavke možeš proć for petljom kroz sve, inicijalizirat brojač i uvećavat ga za 1 da dodaš redni broj svakoj stavki.

1 Like

Djeluje k’o da struktura baze nije najbolje složena.
Loša praksa u PHP-u je korištenje global varijabli. To se ne koristi više u strukturi modernog PHP-a.
Tako da rješavati nešto što je u startu loše je loše samo po sebi.
Šta je problem u upisivanju u bazu svaki submit forme?
Ako sam dobro shvatio, tebi treba ovakva struktura:

orders
id, some_other_attr

items
id, item_data_param

item_order
id, item_id, order_id

U sve tri tabele se postavi da je id BIGINT NOT NULL AUTO_INCREMENT.
Uopšte ne treba razmišljati o ID-ju pri upisu u bazu jer će se sam uvećavati svaki upis.
Ako treba pobrojati stavke neke narudžbine, to ide sa:

// example; 
// @todo credentials should be in .env file 
// @todo DB class instantiation should be separeted
$stmt = (new PDO($dsn, "username", "password", $options))->prepare("SELECT COUNT(id) FROM item_order WHERE order_id = ?");
$stmt->execute([$some_order_id]);
$arr = $stmt->fetchAll(PDO::FETCH_ASSOC);
if(!$arr) {
    exit('No rows');
}
var_export($arr);
$stmt = null;

Programiranje nije “samo uzmi veći čekić” metodologija.
Mislim može al’ ne funkcioniše na obimnijim zahtjevima tako da otpočetka treba isplanirati a ovo ovde u temi je baš bazična stvar.

2 Likeova

Ne samo u PHP-u, nego u bilo cemu :slight_smile:

1 Like

$GLOBALS[] je još dobro, u PHP-u postoji eval(string $code): mixed funkcija za koju vrijedi: ako treba da koristiš eval, definitivno nešto ne radiš dobro.

Ispravak: “najvjerovatnije nešto ne radiš dobro.”
Postoje situacije koje su rješive jedino sa evalom. Doduše rijetke su, ali ipak postoje. Nebi eval postojao da nema svoj use-case. :slight_smile:

Ne.

U svakom slučaju za početnu ideju sa globals-ima tj. umjesto istih, treba koristiti Memcached il’ Redis.

Iskombinovao sam po savjetima iz topica pa je nekako proradilo. Sad su mi jasnije i nove mogućnosti koje se mogu koristiti za ovaj problem. Zato,

@spiderman, hvala, nisam o tom ni razmišljao
@bozoou posebna zahvala za detaljno objašnjenje i vrlo korisne savjete
@igor hvala, veoma mi je korisno tvoje mišljenje
@tpojka što se čekića tiče, trenutno koristim macolu. :blush: znam, svjestan sam svojih mana i krhkog znanja, ali to je valjda prvi korak da se ide dalje. drugog izbora i nemam. hvala za pomoć.
@belmin primio k znanju. :wink:

2 Likeova

:+1:

Sa perspektive korištenja, ako je u pitanju neki dashboard za magacin gdje 2-3 ljudi ima pristup nemoj uopšte da se zamaraš i gledaš da nešto ne koristiš. Na ovo mislim:

Baza upravo za to i postoji.
A ostavio sam ti kako to automatski radi. Tj. kako treba raditi.
MySQL treba sam da uredi autoincrement id da bi se bilo maksimalno sigurno da u tom dijelu neće doći do problema.

S tim da čitam temu još dvaput i mogu priznati da mi nije jasno šta pokušavaš.
Šta je tačno brojač stavki u narudžbi?
Ako imaš stranicu i na njoj kliknem
kupi točak, volan, vrata jesu li to 3 stvake u narudžbi
ili ako kliknem
kupi 4 točka, dvoja vrata i 1 volan jesu li to 7 stavki u narudžbi?

Nažalost teško je šta dalje reći bez poznavanja strukture tabela i poznavanja tačnog business request-a - koji je input a koji željeni output.

Ako imaš još informacija i možeš ih podijeliti, postavi na temu. Što više detalja, prije će se naći odgovor.

2 Likeova

Ovo sa korištenjem baze je (jednostavan ali meni) odličan savjet, jer sad vidim da generalno nije trebalo bježati od takvog rješenja. Mada autoincrement za ovaj moj kontekst nije odgovarajuće rješenje iz više razloga. Sigurno se struktura može prilagoditi i tome, ali izabrao sam ovaj put, sada taj dio radi i vozim dalje. Ovdje napominjem da sam još “na vi” sa OOP, pa koristim proceduralno.

Vidio sam i ja kasnije da sam krenuo sa konfuznim objašnjavanjem pa da sad probam popraviti. Dobro si pretpostavio da se radi o dashboardu koji bi koristio manji broj ljudi. Glavni sadržaj su narudžbe. One imaju neodređeni broj stavki (zato mi je trebao brojač). Stavka je ustvari svaki proizvod/artikl zasebno. Jedina karakteristika stavke (proizvoda/artikla) je dimenzija. Predviđeno je i polje ako treba dodati neki opis/napomenu, ali to je manje bitno.

Svaka stavka narudžbe ima jedan od mogućih statusa - primljeno/obrada/završeno/transport/isporučeno (u meniju). Recimo da je ovo primjer kad se klikne na OBRADA:

PRIMLJENO | OBRADA | ZAVRŠENO | TRANSPORT | ISPORUČENO

narudžba 123
:arrow_left: (1) 540x110 :arrow_right:
:arrow_left: (2) 185x520 :arrow_right:
:arrow_left: (3) 225x195 :arrow_right:
:arrow_left: (4) 465x230 :arrow_right:

narudžba 141
:arrow_left: (1) 345x280 :arrow_right:
:arrow_left: (2) 170x130 :arrow_right:
:arrow_left: (3) 240x205 :arrow_right:

Broj stavke je u zagradi, a njena vrijednost je preuzeta iz baze i smještena u $row['stavkaNarudzba'].

Strelice (a href) s lijeve i desne strane svake stavke služe da se status te stavke promijeni u prvi niži ili prvi viši. Ustvari, lijeva strelica ima funkciju da status stavke vrati korak nazad ako je greškom dospio na tekuće mjesto (npr. ako je u ZAVRŠENO da ga vrati u OBRADA, pa bi kad se klikne na OBRADA bio prikazan tamo, a u ZAVRŠENO ga više ne prikazuje).

Aktuelni problem mi je kako da nakon klika na jednu od strelica izbrišem stavku sa ekrana. Promijeniti status u bazi ne bi trebao biti problem (preko href-a), ali kako bi trebao izgledati onclick za a element ili ima neki drugi način?

Vidio sam post dok sam ček’o mašinu sa servisa pa mi se nije odgovaralo s telefona.
Mislim da sada s novim detaljima znam (tj. mogu [tačno] pretpostaviti) šta ti je
problem.

Nemoj prebrzo pretpostavljati:

Kako i dalje mislim da je upravo suprotno u pitanju tj. sad sam skoro siguran da autoincrement field rješava problem, možeš li navesti koji su to razlozi prije nego ponudim rješenje (a da bi’ i definitivno bio siguran u validnost rješenja)?