Тому в даному випадку бачу таке правильне рішення:- створити клас ПараметриДоступу і при необхідності звертатись до методів об'єкта створеного на його основі.Як у мене зараз? (коли я почав переписування, потім зупинився): Є клас Checker і в ньому багато всяких перевірок; і параметри доступу,і довжина текстового рядка, і багато іншого.Чи правильно буде те рішення, що я виділив жирним?
struct iChecker;struct iCheckerProvider { virtual ~iCheckerProvider() {} virtual iChecker &getChecker() = 0;};struct iChecker { virtual ~iChecker() {} virtual bool canRead() = 0; virtual bool canWrite() = 0; virtual bool canWhatever() = 0;};struct iData; // data to store or modifystruct iElement : iCheckerProvider { virtual ~iElement() {} virtual iData &getData() = 0;}struct Post : iElement { .. impl};struct Gallery : iElement {.. impl};struct Music : iElement {..impl};void writeToBD(iElement &e) { if (e.getChecker().canWrite()) { iData &d = e.getData(); database->write(e); } else { throw PermissionError(); }}
Піймав я колись "глюк" пов'язаний з динамічною типизацією: в case були числа і текстові рядки . Не відразу зрозумів що і до чого.
Описую "проблему":- користувач може створювати Пост (текстове повідомлення), може його редагувати, і тд., але тут розглядаємо тільки створення і редагування Поста.- Пост має два параметри доступу. 1 - доступ до перегляду, 2 доступ до коментування.- при відправці Поста на сервер в бд, перевіряються параметри доступу (допустимі значення 1, 2, 3)Якби в проекті був тільки Пост, можна було б написати приватний метод і все, але в проекті іще є фотоальбоми користувача.Якби були тільки Фотоальбом і Пост можна було б створити клас в якому написати загальні методи для Фотоальбому та Поста і зробити наслідування від/з цього класу. Тобто загальні методи (в даному прикладі ПеревіркаПараметрівДоступу) "приклеїлись" б до класу Пост та класу Фотоальбом.- коли з'являться нові приблуди (голосування, музика, відео та інш) на сайті, то можна буде за допомогою наслідування вирішити проблему перевірки параметрів доступу, але я вважаю що таке наслідування це вже ускладнення.
Хоча я і не зрозумів, чи питання в контексті с++ чи якогось динамічного (js наприклад).
наслідування від вже існуючих класів вважається bad practice. краще написати купу інтерфейсів і наслідуватися від них од
Що робити? Одне з можливих рішень - додати ще одну абстракцію, єдиною метою якої буде авторизація дії користувача. Тобто вона має дати однозначну відповідь на запитання - чи може конкретний користувач виконати певну дію (наприклад побачити, створити, змінити, видалити) над певним об'єктом системи (наприклад пост, відео, фото і т.д.).
Тому в даному випадку бачу таке правильне рішення:- створити клас ПараметриДоступу і при необхідності звертатись до методів об'єкта створеного на його основі.
interface I_Post{ public function get_view_acc(); public function get_comm_acc(); public function is_avtor();// ...// ...}interface I_Foto{ public function get_view_acc(); public function get_comm_acc(); public function is_avtor();// ...// ...}
class Post implements I_Post { public function __construct($ddb, $pid) { //Запит до бд і заповнення класу даними $q = 'select uid_posts,postacc,postcomacc from posts where pid=?'; $rawdata = $ddb->prepare($q); $qr = new qresult($ddb);...... $x = $qr->numrow($rawdata); if ($x != 1) { //нема поста $rawdata->close();// er(51); $e = new err(); $e->er(51); //НЕМА ПОСТА і exit } $res = $rawdata->bind_result($this->uid_posts, $this->view_acc, $this->comm_acc); $qr->bindres($res); $res = $rawdata->fetch(); $qr->fetch($res); $rawdata->close(); } public function get_view_acc() { return($this->view_acc); } public function get_comm_acc() { return($this->comm_acc); } public function is_avtor() { //без перевірки залогыненості if ($_SESSION['uid'] == $this->uid_posts) { //uid_posts - автор поста return(true); } return(FALSE); }}
interface I_UserAvtorize{ public function get_view_acc($obj); public function get_comm_acc($obj); public function is_avtor($obj);}
class UserAvtorize implements I_UserAvtorize { public function get_view_acc($obj) { return($obj->view_acc); } public function get_comm_acc($obj) { return($obj->comm_acc); } public function is_avtor($obj) { //поки що без перевірки залогыненості if ($_SESSION['uid'] == $obj->obj_avtor) { return(true); } return(FALSE); }}
class Post { public function __construct($ddb, $pid) { //Запит до бд і заповнення класу даними $q = 'select uid_posts,postacc,postcomacc from posts where pid=?'; $rawdata = $ddb->prepare($q); $qr = new qresult($ddb); $qr->prep($rawdata); $res = $rawdata->bind_param('i', $pid); $qr->bindpar($res); $res = $rawdata->execute(); $qr->exec($res); $x = $qr->numrow($rawdata); if ($x != 1) { //нема поста $rawdata->close();// er(51); $e = new err(); $e->er(51); } $res = $rawdata->bind_result($this->obj_avtor, $this->view_acc, $this->comm_acc); $qr->bindres($res); $res = $rawdata->fetch(); $qr->fetch($res); $rawdata->close(); }
class Foto { public function __construct($ddb, $fotoid) { //Запит до бд і заповнення класу даними $q = 'select uid_foto,albacc,albcomacc from alb join foto on albid=albid_foto where fotoid=?'; $rawdata = $ddb->prepare($q); $qr = new qresult($ddb); $qr->prep($rawdata); $res = $rawdata->bind_param('i', $fotoid); $qr->bindpar($res); $res = $rawdata->execute(); $qr->exec($res); $x = $qr->numrow($rawdata); if ($x != 1) { //фото нема $rawdata->close();// er(62); $e = new err(); $e->er(62); } $res = $rawdata->bind_result($this->obj_avtor, $this->view_acc, $this->comm_acc); $qr->bindres($res); $res = $rawdata->fetch(); $qr->fetch($res); $rawdata->close(); } }
@$pid = $_GET['id']; //Я знаю що напряму так не можна звертатись до $_GET, та іще й із @ попереду echo $pid; $post = new Post($ddb, $pid); $user_avtorize = new UserAvtorize($post); echo '<br><br>'; echo ($user_avtorize->get_view_acc($post)); echo '<br><br>'; echo ($user_avtorize->get_comm_acc($post)); echo '<br><br>'; var_dump($user_avtorize->is_avtor($post)); exit;
$fotoid = $_GET['id']; echo $fotoid; $foto = new Foto($ddb, $fotoid); $user_avtorize = new UserAvtorize($foto); echo '<br><br>'; echo ($user_avtorize->get_view_acc($foto)); echo '<br><br>'; echo ($user_avtorize->get_comm_acc($foto)); echo '<br><br>'; var_dump($user_avtorize->is_avtor($foto)); exit;
...
ну шо там? як там твої поліморфізми? розібрався?
$u = new CreateUser(); $User = $u->newUser($ddb); //Користувач створюється на початку скрипта десь далеко зверху// ...// ...// ...// ... $Post = new Post($ddb, $pid); //тут може створюватись пост,фото, фотоальб або щось інше //обов'зково з методом show() $User->view($Post); //а тут метод view() містить рядок $obj->show(); //Для чого так? Користувач може передивлятись потс, фото, фотоальбом. //а Пост, Фото, Фотоальбом можуть показувати себе