За последние 24 часа нас посетил 16191 программист и 1313 роботов. Сейчас ищет 731 программист ...

настройка родителя из ребенка

Тема в разделе "Прочие вопросы по PHP", создана пользователем Koc, 28 сен 2009.

  1. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Есть класс-родитель. Creators. В нем реализация синглтона и синглтона с поддержкой нескольких инстанций. Из класса-потомка нужно задавать настройку: у нас может быть одна инстанция класса или множество. Как это лучше сделать?
     
  2. sorteros

    sorteros Активный пользователь

    С нами с:
    28 авг 2009
    Сообщения:
    54
    Симпатии:
    0
    Множественный singleton - это пять баллов!
     
  3. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Лучше не использовать синглтон таким способом.

    Создай Builder или Factory и получай синглтон от них.
    Но с наследованием это никак не связано.
     
  4. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    просто в фабрику нужно передавать имя класса и она его создает.. А я думаю это сделать через наследование а конструктор создаваемого класса - протектед.
     
  5. kostyl

    kostyl Guest

    Koc
    Ниче не понял. Это когда создаешь объект надо вернуть признак можно ли создавать еще такие?
     
  6. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Используй кодогенерацию внутри фабрики.
    Никто тебя не обязывал иметь уже готовый класс, ты можешь его генерировать по определенным правилам из определенного шаблона.

    Наследование от Синглтона - суть ошибка архитектуры.

    P.S. А что собственно надо? может тебя устроит, к примеру, Registry?
     
  7. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Мда, это я загнул насчет фабрики (пожалуй не стоит в ней использовать кодогенерацию). Но в Builder ты точно можешь использовать кодогенерацию.
     
  8. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Koc
    А для чего такое вообще потребовалось?)))
     
  9. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    ACL!
    PHP:
    1.  
    2. <?php
    3. class PermissionsManager extends UsersCommon
    4. {
    5.     private static $instance = NULL;
    6.    
    7.     private $users = array();
    8.    
    9.     private $data = array(
    10.         'rules'  => array(),
    11.         'groups' => array(),
    12.         'users'  => array()
    13.     );
    14.    
    15.     private function __construct()
    16.     {
    17.         $this->db = Database::getInstance();
    18.     }
    19.    
    20.     public static function instance()
    21.     {
    22.         return (self::$instance) ? self::$instance : self::$instance = new self;
    23.     }
    24.    
    25.     public function addRule($title)
    26.     {
    27. // ...
    28. class UsersManager extends UsersCommon
    29. {
    30.     private static $instance = NULL;
    31.    
    32.     private $fields = array();
    33.    
    34.     private function __construct()
    35.     {
    36.         $this->db = Database::getInstance();
    37.     }
    38.    
    39.     public static function instance()
    40.     {
    41.         return (self::$instance) ? self::$instance : self::$instance = new self;
    42.     }
    43.    
    44.     public static function generateSalt($length = 3)
    45.     {
    46. // ...
    47. class UsersFields extends UsersCommon
    48. {
    49.     private static $instance = NULL;
    50.    
    51.     private $fields = array();
    52.    
    53.     private function __construct()
    54.     {
    55.         $this->db = Database::getInstance();
    56.     }
    57.    
    58.     public static function instance()
    59.     {
    60.         return (self::$instance) ? self::$instance : self::$instance = new self;
    61.     }
    62.    
    63.     /**
    64.      * UsersFields::add()
    65.      *
    66.      * @param string $title
    67.      * @param int $type
    68.      * @return int fieldId
    69.      */
    70.     public function add($title, $type)
    71.     {
    72. // ...
    73. class Users extends UsersCommon
    74. {
    75.     private static $instance = NULL;
    76.    
    77.     private $permissions = array();
    78.     private $groups      = array();
    79.     private $users       = array();
    80. //# private $resources   = array();
    81.     private $userData    = array(
    82.         'id'   => array(),
    83.         'name' => array(),
    84.         'mail' => array()
    85.     );
    86.    
    87.     private function __construct()
    88.     {
    89.         $this->db = Database::getInstance();
    90.     }
    91.    
    92.     public static function instance()
    93.     {
    94.         return (self::$instance) ? self::$instance : self::$instance = new self;
    95.     }
    96. // ...
    97. class User extends UsersCommon
    98. {
    99.     private static $instance = NULL;
    100.    
    101.     private $users;
    102.    
    103.     private $userId   = NULL;
    104.     private $passHash = NULL;
    105.    
    106.     private $needReCheckAuth = true;
    107.     private $isAuthenticated = false;
    108.    
    109.     private function __construct()
    110.     {
    111.         $this->db = Database::getInstance();
    112.         $this->users = Users::instance();
    113.        
    114.         $this->userId = isset($_COOKIE[self::COOKIE_NAME_ID]) ?
    115.             $_COOKIE[self::COOKIE_NAME_ID] : NULL;
    116.        
    117.         $this->passHash = isset($_COOKIE[self::COOKIE_NAME_HASH]) ?
    118.             $_COOKIE[self::COOKIE_NAME_HASH] : NULL;
    119.     }
    120.    
    121.     public static function instance()
    122.     {
    123.         return (self::$instance) ? self::$instance : self::$instance = new self;
    124.     }
    125.  
    + есть Rewrite - синглтон
    + Database - множество инстанций
    + FormValidator - множество инстанций
    + NewsCollection
    + ContentCollection
    + ...

    знаю, что наследовать от синглтона глупо, но тут выделение класса так и просится
     
  10. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Наследовать не только глупо, оно еще и работать без костылей не будет.

    Какие методы ты хочешь унаследовать от Синглтона?
    Только контроль количества инстансов?
     
  11. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    создание экземпляров и контроль их количества
     
  12. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Смысла нет.

    Весь Синглтон это 2 свойства и 1 метод из 3 строк.

    В общем, не ленись, а просто пропиши. Поверь опыту - это целесообразнее и проблем меньше :)
    В крайнем случае создай template в IDE для Синглтонов :)

    Максимум что можешь сделать это передавать иницализацию БД :)

    PHP:
    1. $user = User::getInstance(DB::getInstance());
    Это позволит убрать статическую зависимость от прослойки БД.

    Если так уж хочется облегчить работу, то подумай над кодогенерацией. Хотя при тех объемах кода, что ты привел...
    Смысла тоже мало, но даст опыт :)
     
  13. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Синглтон - это в первую очередь идея, а не паттерн, инстанция должна быть одна.
    Что есть Creators? Parent?
     
  14. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Инстанций у Синглтона может и больше быть :)

    Фокус именно в контроле их числа.

    И, да, не стоит путать паттерн программирования и паттерн(шаблон) кода.

    Паттерн программирования - это методика решения задачи, а не конкретная ее реализация.
    Паттерн(шаблон) кода - это заготовка.
     
  15. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Creators - реализация создания нескольких экземпляров классов и получения их через метки. Его используют FormValidator, FV_Advanced, NewsCollection.
    PHP:
    1. <?
    2. NewsCollection::create('someNews')
    3. ->orderBy('date', 'ASK');
    4. // ...
    5. if (isset($_GET['cid'])
    6. NewsCollection::getInstance('someNews')
    7. ->filterBy('category', $_GET['cid'])
    8. // ...
    9. NewsCollection::getInstance('someNews')
    10. ->get('links', 'title', 'short_text');
    11.  
     
  16. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    а чем не Ъ Регистри, я не понял?
     
  17. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    например я не знаю: создан ли уже экземпляр Rewrites. Я-то обращусь в регистр за ним, а если его там нет? Можно создавать и помещать его туда, но тогда уж проще оставить все как есть: + один метод и одно свойство
     
  18. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Кажется, понял проблему. Не вижу разницы принципиальной разницы, между одной или несколькими инстанциями - методу getInstance сделать параметр необязательным. Если он не передан, то считается, что одна (первая).
     
  19. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    [vs]
    даа! Это оно. Именно по такому принципу и сделан класс Creators. Но получается что мы извне контролируем кол-во создаваемых экземпляров, что не есть гуд. Поэтому мне нужно в потомке, будь то *Collection или Rewrites задать настройку: синглтон это или можно много экземпляров создавать. И в этой теме я спрашиваю народ: как же лучше эту настройку сделать?

    Пока идея это сделать в виде статической переменной, которой нет в родителе. Если она !isset или false - одноинстанционный, в противном случае - мульти.
     
  20. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Лучше не делать настройку.

    Не наследуй Синглтон... вообще.

    Сделай шаблон класса Синглтон, и создавай на его базе сколько угодно путем правки кода! но не наследования!
     
  21. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Simpliest
    идею понял. Но что тут плохого? я же по сути предлагаю отказ от избыточности, повторяющегося куска кода.
     
  22. kostyl

    kostyl Guest

    блин сперва вроде понял про синглтон, но потом опять запутался....
    Поэтому оффтопом спрошу:
    Кос, чесно говоря класс Юзер просто жесть. Если не секрет зачем там юзерсы?
    И еще вопрос ко всем:
    че за прикол писать $this->db = Database::getInstance(); Это чтобы потом короче было $this->db->query? Че ссылки то плодить?
     
  23. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Users - для всех пользователей.

    User - для текущего пользователя, который этот скрипт запускает. Его паблик методы:
    статические, но могут быть запущены и через полученную инстанцию
    isAuthenticated
    isAdmin (включает проверку на аутентификацию)
    isRoot

    logIn($name, $pass, $asAdmin = false) (пытается залогиниться под посланными параметрами. Если че не так - бросает искл.)
    logOut
    getBaseInfo($field = NULL) (возвращает всякие параметры типа логина, мыла и тд)

    опять статические
    getPermissions
    getGroups
    checkPermission($permission)
    checkResource($resource, $resourceId)
    value($field) (похоже на getBaseInfo, но это не базовые параметры а опциональные, которые через UsersFields создаются)

    User работает через Users, просто нам не нужно знать или указывать ID текущего юзера.
    PHP:
    1. <?
    2. // ...
    3.     public static function getPermissions()
    4.     {
    5.         return self::instance()->users->getPermissions(self::instance()->userId);
    6.     }
    7.    
    8.     public static function getGroups()
    9.     {
    10.         return self::instance()->users->getGroups(self::instance()->userId);
    11.     }
    12.    
    13.     public static function checkPermission($permission)
    14.     {
    15.         return self::instance()->users->checkPermission($permission, self::instance()->userId);
    16.     }
    17.    
    18.     public static function checkResource($resource, $resourceId)
    19.     {
    20.         return self::instance()->users->checkResource($resource, $resourceId, self::instance()->userId);
    21.     }
    22.    
    23.     public static function value($field)
    24.     {
    25.         return UsersManager::instance()->value(self::instance()->userId, $field);
    26.     }
    27. // ...
    28.  
    Переменные в методах меняются местами и скачут как потерпевшие. Я в курсе.

    ну типа того. А это плохо?
     
  24. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    пока суть да дело, у нас появилась такая вот какашенция:
    PHP:
    1. <?php
    2.  
    3. abstract class Creators
    4. {
    5.     /**
    6.      * @var array array of class instances
    7.      **/
    8.     protected static $instances = array();
    9.    
    10.     final private function __clone() {}
    11.    
    12.     final private function createClass($class, $params)
    13.     {
    14.         if ($params) {
    15.             $reflection = new ReflectionClass($class);
    16.             return $reflection->newInstanceArgs($params);
    17.         } else {
    18.             return new $class();
    19.         }
    20.     }
    21.    
    22.     final public static function instance($id = 'default', $params = NULL)
    23.     {
    24.         $class = get_called_class();
    25.        
    26.         if (isset(self::$multi)) {
    27.             if (self::$multi) {
    28.                 return (isset(self::$instances[$class][$id])) ?
    29.                     self::$instances[$class][$id] :
    30.                     self::$instances[$class][$id] = self::createClass($class, $params);
    31.             }
    32.         } else {
    33.             return (isset(self::$instances[$class])) ?
    34.                 self::$instances[$class] :
    35.                 self::$instances[$class] = self::createClass($class, $params);
    36.         }
    37.     }
    38. }
    39.  
    40. if (!function_exists('get_called_class')):
    41. //TODO:find another analog
    42.     function get_called_class()
    43.     {
    44.         $bt = debug_backtrace();
    45.         $lines = file($bt[1]['file']);
    46.         preg_match(
    47.             '/([a-zA-Z0-9\_]+)::' . $bt[1]['function'] . '/',
    48.             $lines[$bt[1]['line']-1],
    49.             $matches);
    50.         return $matches[1];
    51.     }
    52. endif;
    53.  
    54. @@ -1,6 +1,6 @@
    55. -abstract class UsersCommon
    56. +abstract class UsersCommon extends Creators
    57. @@ -42,5 +42,5 @@
    58.    
    59. -   final private function __clone() {}
    60. +   protected static $multi = false;
    61.  
    несмотря на отговоры товарища из Донецка, в тестовом режиме сделал. Посмотрю: будет ли какое-то удобство от этой какашки или нет. Один черт это идет коммитом и я смогу откатиться если что-то пойдет не так.
     
  25. kostyl

    kostyl Guest

    ну не знаю.
    Вообще привожу свои примеры:
    PHP:
    1.    
    2. <?php
    3. class User extends KTF_Object {
    4.     /**
    5.      * @var array
    6.      */
    7.     private static $_UserObjectsPool = array();
    8.  
    9.     public function  __construct($UserId = NULL) {
    10.         parent::_SetKeyField('id', KTF_Db::KTF_Db_Format_Int, $UserId);
    11.         parent::_SetTableName(USER_MAIN_TABLE);
    12.         parent::_AddMainProperty('Id', 'id', KTF_Db::KTF_Db_Format_Int);
    13.         parent::_AddMainProperty('Login', 'login', KTF_Db::KTF_Db_Format_Str);
    14.         parent::_AddLazyProperty('Password', USER_MAIN_TABLE, 'pswd');
    15.         parent::_AddLazyProperty('Email', USER_MAIN_TABLE, 'email');
    16.     }
    17. //......
    18.     /**
    19.      * @static
    20.      * @param in $UserId
    21.      * @return User
    22.      */
    23.     public static function GetInstance($UserId = NULL)
    24.     {
    25.         if(!$UserId) {
    26.             return new User(NULL);
    27.         }
    28.         $UserUdentifiers = self::GetIdentifiers();
    29.         if(isset($UserUdentifiers[$UserId])) {
    30.             if(isset(self::$_UserObjectsPool[$UserId])) {
    31.                 return self::$_UserObjectsPool[$UserId];
    32.             }
    33.             else {
    34.                 self::$_UserObjectsPool[$UserId] = new User($UserId);
    35.                 return self::$_UserObjectsPool[$UserId];
    36.             }
    37.         }
    38.         else {
    39.             return new User(NULL);
    40.         }
    41.     }
    42.