Mam tabele z userami (MySQL):
CREATE TABLE `users` ( `u_id` bigint(20) NOT NULL AUTO_INCREMENT, `u_login` varchar(100) NOT NULL DEFAULT '', `u_haslo` varchar(34) NOT NULL DEFAULT '', `u_nick` varchar(40) DEFAULT NULL, `u_znajomi` longtext DEFAULT NULL, `u_aktywny` int(1) NOT NULL DEFAULT '1', PRIMARY KEY (`u_id`), UNIQUE KEY `u_login` (`u_login`), ) TYPE=InnoDB AUTO_INCREMENT=4 ; INSERT INTO `users` VALUES (1, 'login1', 'd4b21940e8f49a14903e6310e8cd14f4', 'nick1', 'a:1:{i:0;i:3;}',1); INSERT INTO `users` VALUES (2, 'login2', 'd4b21940e8f49a14903e6310e8cd14f4', 'nick2', 'a:1:{i:0;i:3;}',1); INSERT INTO `users` VALUES (3, 'login3', 'd4b21940e8f49a14903e6310e8cd14f4', 'nick3', 'a:2:{i:0;i:1;i:1;i:2;}',1);
Pole u_znajomi zawiera informacje o tym, kto jest znajomym danego usera (w postaci tablicy, zapisywanej w formie
zserializowanej). User login3 ma zatem znajomych: login1 i login2, a userzy login1 i login2 maja zapisanego: login3.
Najwazniejsza rzecz jest tutaj taka, ze jesli jeden user ma zapisanego znajomego, to ten znajomy musi miec w znajomych
tez tego usera - nie moze byc tak, ze jeden ma zapisanego jakiegos, a ten drugi nie ma o tym userze informacji.
Pole u_aktywny - jesli ma wartosc 1 - user jest aktywny w serwisie
Jezeli jakis user chce byc czyims znajomym, zaprasza go (po akceptacji zostaje znajomym). Informacja o zaproszeniach
zapisana jest w tabeli:
CREATE TABLE `zaproszenia` ( `z_id` bigint(20) NOT NULL AUTO_INCREMENT, `u1_id` bigint(20) NOT NULL DEFAULT '0', `u2_id` bigint(20) NOT NULL DEFAULT '0', `z_data` int(10) NOT NULL DEFAULT '0', PRIMARY KEY (`z_id`), KEY `u1_id` (`u1_id`), KEY `u2_id` (`u2_id`), KEY `z_data` (`z_data`) ) TYPE=InnoDB AUTO_INCREMENT=2 ;
gdzie: u1_id - id usera wysylajacego zaproszenie (w kodzie php - $id1)
u2_id - id usera zapraszanego ($id2)
Zalozmy ze user login1 wyslal zaproszenie do login2 (jesli sa juz znajomymi, to nie mozna wyslac zaproszenia, wyswietlam
info, ze sa juz znajomymi). Zatem w tabeli zaproszenia mamy rekord:
INSERT INTO `zaproszenia` VALUES (1, 1, 2, 1149851150);
I teraz user login2 chce zaakceptowac zaproszenie, zatem $id1=1; $id2=2;
Kod w php realizujacy akceptacje zaproszenia jest nastepujacy:
<?php $core->query ("SET AUTOCOMMIT=0"); // $core->query - moja funkcja wykonujaca zapytania MySQL'a $core->query ("BEGIN"); // poczatek transakcji - dzialamy na dwoch tabelach $core->query ("LOCK TABLES users WRITE, zaproszenia WRITE"); // blokuje tabele, by miec pewnosc, ze w miedzy // czasie nie akceptuje zaproszenia, lub go nie usuwa - w koncu moze otworzyc strone w wielu przegladarkach $blad=0; $core->query ("DELETE FROM zaproszenia WHERE u1_id=".$id1." AND u2_id=".$id2); // usuwam zaproszenie if ($blad==0) { $core->query ("SELECT u_znajomi FROM users WHERE u_id=".$id2." LIMIT 1"); $znajomi1=$core->query_result[0]['u_znajomi']; // znajomi usera, ktory akceptuje zaproszenie if ($znajomi1!=NULL) { if (!in_array ($id1,$znajomi1)) $znajomi1[]=$id1; // zapisuje, jesli user nie byl znajomym, jesli byl, to w ogole nie mozna wyslac z
aproszenia } else $znajomi1[]=$id1; $core->query ("SELECT u_aktywny, u_znajomi FROM users WHERE u_id=".$id1." LIMIT 1"); if ($core->query_result[0]['u_aktywny']!=1) // nie ma juz usera, ktory zapraszal => mozna usunac zaproszenie // kod ponizej: odblokowujemy tabele, i wyswietlamy strone informacyjna $znajomi2=$core->query_result[0]['u_znajomi']; // znajomi usera, ktory zapraszal => istnieje dalej w serwisie if ($znajomi2!=NULL) { } else $znajomi2[]=$id2; $core->query ("UPDATE users SET u_znajomi='".$znajomi1."' WHERE u_id=".$id2); // update znajomych usera, ktory akceptuje zaproszenie if (mysql_affected_rows()!=1) $blad++; // musi byc przetworzony jeden wiersz, bo wiemy, ze nie byli znajomymi } if ($blad==0) { $core->query ("UPDATE ".$core->prefix."_users SET u_znajomi='".$znajomi2."' WHERE u_id=".$id1); } if ($blad>0) { $core->query ("ROLLBACK"); // odrzucenie $core->query ("UNLOCK TABLES"); } else { $core->query ("COMMIT"); // akceptacja $core->query ("UNLOCK TABLES"); } exit; } ?>
I teraz pytanie: czy powyzsze rozwiazanie problemu znajomosci userow jest dobre? Tzn. czy zapewnione sa warunki:
- w czasie dzialania skryptu userzy nie usuna zaproszenia (bo moga w osobnym miejscu)
- na pewno u obydwoch userow zostanie zapisana informacja o znajomych - czyli u zapraszanego id usera, ktory go zapraszal, a u tego co zapraszal id usera zapraszanego
Pytania sa trywialne i raczej nie powinienem ich zadawac, lecz zdarzylo mi sie raz tak, ze jeden user (powiedzmy o id 5) ma zapisana informacje o znajomosci z userem (np. 6), lecz user 6 nie ma infa o nr 5...
Moze nie powinienem uzywac blokad tabel skoro mam transakcje? Prosze o pomoc
