Автор Тема: Singleton и registry шаблони  (Прочетена 2967 пъти)

0 Потребители и 1 Гост преглежда(т) тази тема.

gatakka

  • Hero Member
  • *****
  • Благодарности
  • -Казани: 0
  • -Получени: 19
  • Публикации: 681
Singleton и registry шаблони
« -: 31 Януари 2010, 21:26:46 »
** Тази тема дискутира:: Singleton и registry шаблони **
Автор: Гатака
« Последна редакция: 15 Април 2015, 22:51:04 от Avalanche »
За да знаеш трябва да питаш,
но за да знаеш някой трябва да ти отговори на питанията.
Добре дошли в Научи Ме!

yani21

  • Full Member
  • ***
  • Благодарности
  • -Казани: 1
  • -Получени: 4
  • Публикации: 201
Отг:Singleton и registry шаблони
« Отговор #1 -: 23 Февруари 2010, 17:51:04 »
Много добър урок, както и останалите от поредицата за ООП. Надявам се, че ще има още.  :)

ma3x_ip

  • Newbie
  • *
  • Благодарности
  • -Казани: 0
  • -Получени: 0
  • Публикации: 1
Отг:Singleton и registry шаблони
« Отговор #2 -: 14 Март 2010, 18:20:33 »
Най-добрите видео уроци на бг :)

mgrozdanov

  • Full Member
  • ***
  • Благодарности
  • -Казани: 1
  • -Получени: 0
  • Публикации: 136
Re:Singleton и registry шаблони
« Отговор #3 -: 24 Февруари 2011, 00:21:58 »
Имам клас, в който имам инстанция $db = db::getInstance(); Този клас го инклудвам в страница, която ми визуализира HTML,  и ако в тази страница опитам да създам друга инстанция $db1 = db::getInstance(); ми дава Cannot redeclare class. Как мога да избегна тази грешка, защото явно ще ми трябват инстанции и в класовете и в с траниците, които генерират html.

HD

  • Administrator
  • Hero Member
  • *****
  • Благодарности
  • -Казани: 208
  • -Получени: 165
  • Публикации: 3077
Re:Singleton и registry шаблони
« Отговор #4 -: 24 Февруари 2011, 08:12:39 »
Дай кода да видим, защото така ни караш да гадаем какво точно искаш да направиш :)

mgrozdanov

  • Full Member
  • ***
  • Благодарности
  • -Казани: 1
  • -Получени: 0
  • Публикации: 136
Re:Singleton и registry шаблони
« Отговор #5 -: 24 Февруари 2011, 09:46:11 »
Файла, който ми генерира html с инстанция $db1 = db::getInstance();


Код: PHP
  1. <?php
  2. include 'class/class.db.php';
  3. $db = db::getInstance();
  4. if($_POST['reg'] == 1){
  5.         include 'class/class.regUser.php';
  6.         $reg = new regUser($_POST['name'], $_POST['family'], $_POST['email'], $_POST['pass'], $_POST['pass2']);
  7. }
  8.  
  9. include 'class/class.template.php';
  10. $template = new template('ян бибиян', 'destska kushnia', 'keys');
  11.  
  12.  
  13. ?>
  14.  
  15. <a name="reg" id="reg"></a>
  16. <?php echo $_SESSION['msg'] ?>
  17. <?php unset($_SESSION['msg']) ?>
  18. <form action="registration.php" method="post" id="regForm">
  19. <h2>Регистрационна форма</h2>
  20. <fieldset>
  21. <legend>Персонална информация</legend>
  22. <dl>
  23.   <dt>Име:</dt>
  24.     <dd><input name="name" id="name" type="text" size="50" value="<?php echo $reg->val['name']?>" /><?php echo $reg->err['name']?></dd>
  25.   <dt>Фамилия:</dt>
  26.     <dd><input name="family" id="family" type="text" size="50" value="<?php echo $reg->val['family']?>" /><?php echo $reg->err['family']?></dd>
  27.   <dt>email адрес</dt>
  28.     <dd><input name="email" id="email" type="text" size="50" value="<?php echo $reg->val['email']?>"/><?php echo $reg->err['email']?></dd>
  29. </dl>
  30. </fieldset>
  31.  
  32. <fieldset>
  33. <legend>Информация за регистрация</legend>
  34. <dl>
  35.   <dt>Парола</dt>
  36.     <dd><input name="pass" id="pass" type="password" size="50" /><?php echo $reg->err['pass']?></dd>
  37.   <dt>Потвърдете паролата</dt>
  38.     <dd><input name="pass2" id="pass2" type="password" size="50" /> минимум 5 символа</dd>
  39.  
  40. </dl>
  41. </fieldset>
  42. <input name="reg" type="hidden" value="1" />
  43. <input name="" type="submit" value="регистрация" class="button" id="button1"/>
  44. </form>
  45. <?php
  46. $template->siteFooter();
  47.  

При събмит на форма за регистрация имам проверката:

if($_POST['reg'] == 1){
   include 'class/class.regUser.php';
   $reg = new regUser($_POST['name'], $_POST['family'], $_POST['email'], $_POST['pass'], $_POST['pass2']);
}

и се инклудва class.regUser.php, вкойто имам:

Код: PHP
  1. <?php
  2. include 'class.users.php';
  3.  
  4. class regUser extends users{
  5.                 public $name;
  6.                 public $family;
  7.                 public $email;
  8.                 public $password;
  9.                 public $password2;
  10.                 public $val=array();
  11.                 public $message;
  12.                 public $err=array();
  13.                
  14.     function __construct($name, $family, $email, $password, $password2) {
  15.         $this->name = $this->input($name);
  16.                 if(strlen($this->name)<3){
  17.                         $this->err['name'] = 'Името трябва да бъде най-малко 3 символа';
  18.                         $this->val['name'] = $this->name;      
  19.                 }
  20.                
  21.         $this->family = $this->input($family);
  22.                 if(strlen($this->family)<3){
  23.                         $this->err['family'] = 'Фамилията трябва да бъде най-малко 3 символа';
  24.                         $this->val['family'] = $this->name;    
  25.                 }
  26.                
  27.         $this->email = $email;
  28.                 if($this->checkEmail($this->email) == false){
  29.                         $this->err['email'] = 'Въведете валиден емайл адрес';
  30.                         $this->val['email'] = $this->email;
  31.                 }
  32.                
  33.         $this->password = md5($password);
  34.         $this->password2 = md5($password2);
  35.                
  36.                 if($this->password != $this->password2){
  37.                         $this->err['pass'] = 'Паролите не съвпадат!';
  38.                 }
  39.                
  40.                 if(empty($err)){
  41.                         include 'class/class.db.php';
  42.                         $db1 = db::getInstance();
  43.                         $db1->dbQuery('INSERT INTO users (user, family, pass, email, ip)
  44.                                                         VALUES ("'.$this->name.'", "'.$this->family.'", "'.$this->password.'", "'.$this->email.'", "'.$_SERVER['REMOTE_ADDR'].'")');
  45.                         $_SESSION['msg'] = 'Успешна регистрация';                    
  46.                         header('location:registration.php');
  47.                         exit;
  48.                 }
  49.                 else{
  50.                         return $arr;
  51.                 }
  52.     }
  53.  
  54.        
  55. ///////////////
  56.         private function checkEmail($str){
  57.                 if(!preg_match("/^[_\.0-9a-zA-Z-]+@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,6}$/i", $str)) {
  58.                         return false;
  59.                 }
  60.                 else {
  61.                         return true;
  62.                 }      
  63.         }              
  64. //////////////
  65.        
  66. }
  67.  
  68.  

В конструктора след като са минали всичките проверки правя инстанция $db1 = db::getInstance(); и вкарвам юзера в базата данни. Само където не вкарвам нищо, получавам Cannot redeclare class db.

Може би не е добре да инклудвам класа в същия файл където ми е хтмл то , а да си направия някакъв отделен файл за обработка?
« Последна редакция: 24 Февруари 2011, 17:23:34 от echeveria »

edembg

  • Newbie
  • *
  • Благодарности
  • -Казани: 0
  • -Получени: 2
  • Публикации: 47
Re:Singleton и registry шаблони
« Отговор #6 -: 28 Юли 2011, 20:44:40 »
Здравейте всички.

Трябва да призная, че макар че имам доста стаж с PHP в момента ми се налага да ползвам наистина обектно ориентирано програмиране за пръв път. По тази причина посещавам този сайт и сверявамк знаията си. Може да звучи смешно, но singleton клас ползвах за пръв път в actionscript. И ми направи впечатление, че в урока примера не би работил правилно, поне според мойто мнение. Ако ползваме хипотетичната ситуация от примера и съм си направил singleton клас за връзка с базата данни. Моят клас не прави връзка с базата в конструктора, а при първа заявка. Ако предположим, че имам три обекта, които ползват база данни и всеки от тях в конструктора си присвоява резултата от DB::getInstanse(), на практика всеки клас има копие от инстанцията на класа за връзка с базата. В този случай при заявка към базата и от трите ми лкаса бих получип по една връзка с базата за всеки един от тях. Поне моят опит показва такова поведение на скрипта.

Дали това е така? И дали възможно решение на проблема е метода getInstance да не връща самия обект, а адрес към него?
Ще бъда благодарен за всеки отговор.
И най-ярките личности си плащат тока

FireSword

  • Newbie
  • *
  • Благодарности
  • -Казани: 0
  • -Получени: 0
  • Публикации: 3
Re:Singleton и registry шаблони
« Отговор #7 -: 14 Август 2011, 17:21:16 »
Здравейте всички.

Трябва да призная, че макар че имам доста стаж с PHP в момента ми се налага да ползвам наистина обектно ориентирано програмиране за пръв път. По тази причина посещавам този сайт и сверявамк знаията си. Може да звучи смешно, но singleton клас ползвах за пръв път в actionscript. И ми направи впечатление, че в урока примера не би работил правилно, поне според мойто мнение. Ако ползваме хипотетичната ситуация от примера и съм си направил singleton клас за връзка с базата данни. Моят клас не прави връзка с базата в конструктора, а при първа заявка. Ако предположим, че имам три обекта, които ползват база данни и всеки от тях в конструктора си присвоява резултата от DB::getInstanse(), на практика всеки клас има копие от инстанцията на класа за връзка с базата. В този случай при заявка към базата и от трите ми лкаса бих получип по една връзка с базата за всеки един от тях. Поне моят опит показва такова поведение на скрипта.

Дали това е така? И дали възможно решение на проблема е метода getInstance да не връща самия обект, а адрес към него?
Ще бъда благодарен за всеки отговор.

Здравей.
Примерът работи правилно във всички случай, защото свойството на което се присвоява инстанцията и методът за взимане на инстанция са статични и това означава, че те не зависят от инстанцията на класа, т.е. ако извикаш втори път статичния метод getInstance() и го присвоиш на втора променлива в самия метод проверката
Код: PHP
  1.     public static function getInstance(){
  2.         if(!isset (self::$instance)){
  3.             //Присвояваме името на класа посредством магическата константа __CLASS__
  4.             $class_name = __CLASS__;
  5.             //Създаваме инстанция на класа и я присвояваме на статичното свойство
  6.             self::$instance = new $class_name;
  7.         }
  8.        
  9.         return self::$instance;
  10.     }
  11.  
ще установи, че вече съществува инстанция на класа и следователно на новата променлива ще бъде присвоена същата инстанция, т.е ти можеш метода getInstance() да го извикваш колкото пъти искаш, но той ще връща само една инстанция.

Виж този пример:
Код: PHP
  1. class Singleton{
  2.    
  3.     /**
  4.      * Статично свойство в което ще се съхранява единствената инстанция
  5.      * @access private
  6.      */
  7.     private static $instance = null;
  8.    
  9.     public $text;
  10.  
  11.  
  12.     /*
  13.      * Правейки конструктора private предотвратяваме директното създаването
  14.      * на инстанция на класа
  15.      * @access private
  16.      */
  17.     private function __construct(){
  18.        echo 'Класът е успешно инстанциран <br/>';
  19.     }
  20.    
  21.     /**
  22.      * Статичен метод който, ще бъде достъпен извън класа и чрез който ше се
  23.      * създаден неговата инстанция
  24.      * @access public
  25.      */
  26.     public static function getInstance(){
  27.         if(!isset (self::$instance)){
  28.             //Присвояваме името на класа посредством магическата константа __CLASS__
  29.             $class_name = __CLASS__;
  30.             //Създаваме инстанция на класа и я присвояваме на статичното свойство
  31.             self::$instance = new $class_name;
  32.         }
  33.        
  34.         return self::$instance;
  35.     }
  36.    
  37.     /**
  38.      *  Не позволява на потребителя да клонира инстанцията
  39.      *  @access public
  40.      */
  41.    
  42.     public function __clone()
  43.     {
  44.         trigger_error('Клонирането е забранено', E_USER_ERROR);
  45.     }
  46.    
  47.     public function display_message(){
  48.         echo 'Съдържание: <br/>' . $this->text . '<hr/>';
  49.     }
  50. }
  51.  
  52. $c_name = 'Singleton';
  53.  
  54. //Присвояваме инстанция на класа
  55. $obj = $c_name::getInstance();
  56. $obj1 = $c_name::getInstance();
  57. //Задаваме стойност на свойството
  58. $obj->text = 'Примерно Съдържание 1';
  59. $obj1->text = 'Променено съдържание';
  60. $obj->display_message();
  61. $obj1->display_message();
  62. /**
  63.  * Примерът показва че метода getInstance връща САМО 1 инстанция на класа!!!
  64.  */

Ако инстанцията не беше 1 би следвало извикването на метода display_message() от два различни обекта след промяната да върне различен резултат, а както виждаш резултата е един и същ:

Класът е успешно инстанциран
Съдържание:
Променено съдържание
Съдържание:
Променено съдържание



« Последна редакция: 14 Август 2011, 18:06:55 от FireSword »

FireSword

  • Newbie
  • *
  • Благодарности
  • -Казани: 0
  • -Получени: 0
  • Публикации: 3
Re:Singleton и registry шаблони
« Отговор #8 -: 14 Август 2011, 17:34:55 »
Файла, който ми генерира html с инстанция $db1 = db::getInstance();


Код: PHP
  1. <?php
  2. include 'class/class.db.php';
  3. $db = db::getInstance();
  4. if($_POST['reg'] == 1){
  5.         include 'class/class.regUser.php';
  6.         $reg = new regUser($_POST['name'], $_POST['family'], $_POST['email'], $_POST['pass'], $_POST['pass2']);
  7. }
  8.  
  9. include 'class/class.template.php';
  10. $template = new template('ян бибиян', 'destska kushnia', 'keys');
  11.  
  12.  
  13. ?>
  14.  
  15. <a name="reg" id="reg"></a>
  16. <?php echo $_SESSION['msg'] ?>
  17. <?php unset($_SESSION['msg']) ?>
  18. <form action="registration.php" method="post" id="regForm">
  19. <h2>Регистрационна форма</h2>
  20. <fieldset>
  21. <legend>Персонална информация</legend>
  22. <dl>
  23.   <dt>Име:</dt>
  24.     <dd><input name="name" id="name" type="text" size="50" value="<?php echo $reg->val['name']?>" /><?php echo $reg->err['name']?></dd>
  25.   <dt>Фамилия:</dt>
  26.     <dd><input name="family" id="family" type="text" size="50" value="<?php echo $reg->val['family']?>" /><?php echo $reg->err['family']?></dd>
  27.   <dt>email адрес</dt>
  28.     <dd><input name="email" id="email" type="text" size="50" value="<?php echo $reg->val['email']?>"/><?php echo $reg->err['email']?></dd>
  29. </dl>
  30. </fieldset>
  31.  
  32. <fieldset>
  33. <legend>Информация за регистрация</legend>
  34. <dl>
  35.   <dt>Парола</dt>
  36.     <dd><input name="pass" id="pass" type="password" size="50" /><?php echo $reg->err['pass']?></dd>
  37.   <dt>Потвърдете паролата</dt>
  38.     <dd><input name="pass2" id="pass2" type="password" size="50" /> минимум 5 символа</dd>
  39.  
  40. </dl>
  41. </fieldset>
  42. <input name="reg" type="hidden" value="1" />
  43. <input name="" type="submit" value="регистрация" class="button" id="button1"/>
  44. </form>
  45. <?php
  46. $template->siteFooter();
  47.  

При събмит на форма за регистрация имам проверката:

if($_POST['reg'] == 1){
   include 'class/class.regUser.php';
   $reg = new regUser($_POST['name'], $_POST['family'], $_POST['email'], $_POST['pass'], $_POST['pass2']);
}

и се инклудва class.regUser.php, вкойто имам:

Код: PHP
  1. <?php
  2. include 'class.users.php';
  3.  
  4. class regUser extends users{
  5.                 public $name;
  6.                 public $family;
  7.                 public $email;
  8.                 public $password;
  9.                 public $password2;
  10.                 public $val=array();
  11.                 public $message;
  12.                 public $err=array();
  13.                
  14.     function __construct($name, $family, $email, $password, $password2) {
  15.         $this->name = $this->input($name);
  16.                 if(strlen($this->name)<3){
  17.                         $this->err['name'] = 'Името трябва да бъде най-малко 3 символа';
  18.                         $this->val['name'] = $this->name;      
  19.                 }
  20.                
  21.         $this->family = $this->input($family);
  22.                 if(strlen($this->family)<3){
  23.                         $this->err['family'] = 'Фамилията трябва да бъде най-малко 3 символа';
  24.                         $this->val['family'] = $this->name;    
  25.                 }
  26.                
  27.         $this->email = $email;
  28.                 if($this->checkEmail($this->email) == false){
  29.                         $this->err['email'] = 'Въведете валиден емайл адрес';
  30.                         $this->val['email'] = $this->email;
  31.                 }
  32.                
  33.         $this->password = md5($password);
  34.         $this->password2 = md5($password2);
  35.                
  36.                 if($this->password != $this->password2){
  37.                         $this->err['pass'] = 'Паролите не съвпадат!';
  38.                 }
  39.                
  40.                 if(empty($err)){
  41.                         include 'class/class.db.php';
  42.                         $db1 = db::getInstance();
  43.                         $db1->dbQuery('INSERT INTO users (user, family, pass, email, ip)
  44.                                                         VALUES ("'.$this->name.'", "'.$this->family.'", "'.$this->password.'", "'.$this->email.'", "'.$_SERVER['REMOTE_ADDR'].'")');
  45.                         $_SESSION['msg'] = 'Успешна регистрация';                    
  46.                         header('location:registration.php');
  47.                         exit;
  48.                 }
  49.                 else{
  50.                         return $arr;
  51.                 }
  52.     }
  53.  
  54.        
  55. ///////////////
  56.         private function checkEmail($str){
  57.                 if(!preg_match("/^[_\.0-9a-zA-Z-]+@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,6}$/i", $str)) {
  58.                         return false;
  59.                 }
  60.                 else {
  61.                         return true;
  62.                 }      
  63.         }              
  64. //////////////
  65.        
  66. }
  67.  
  68.  

В конструктора след като са минали всичките проверки правя инстанция $db1 = db::getInstance(); и вкарвам юзера в базата данни. Само където не вкарвам нищо, получавам Cannot redeclare class db.

Може би не е добре да инклудвам класа в същия файл където ми е хтмл то , а да си направия някакъв отделен файл за обработка?

Singleton шаблонът позволява САМО ЕДНА ИНСТАНЦИЯ на класа. Причината да използваш този шаблон е точно тази - да не се разрешава съдаването на повече от една инстанция, защо ти е втора инстанция след като вече имаш една $db.
Използвай нея.
« Последна редакция: 14 Август 2011, 17:37:58 от FireSword »

edembg

  • Newbie
  • *
  • Благодарности
  • -Казани: 0
  • -Получени: 2
  • Публикации: 47
Re: Singleton и registry шаблони
« Отговор #9 -: 29 Август 2011, 12:53:03 »
Благодаря FireSword.

Имах предвид малко по-различен начин на ползване на singleton класове. Намерих време и направих този пример:

<?php
class S {
   private static $instance;
   private $vars = array();
   
   private function __construct() {

   }
   
   public static function get_instance() {
      if (self::$instance == null) self::$instance = new S();
      return self::$instance;
   }
   
   public function set_value($name, $value) {
      $this->vars[$name] = $value;
   }
   
   public function get_value($name) {
      if (isset($this->vars[$name])) return $this->vars[$name];
      else return null;
   }
   
   public function get_vars() {
      return $this->vars;
   }
}

class A {
   private $reg;
   
   public function __construct() {
      $this->reg = S::get_instance();
      $this->reg->set_value('A', 'Class A');
   }
   
   public function get_vars() {
      return $this->reg->get_vars();
   }
}

class B {
   private $reg;
   
   public function __construct() {
      $this->reg = S::get_instance();
      $this->reg->set_value('B', 'Class B');
   }
   
   public function get_vars() {
      return $this->reg->get_vars();
   }
}

$a = new A();
$b = new B();

print "Values from A<br />\n<pre>";
print_r($a->get_vars());
print "</pre>\n<br /><br />\n";

print "Values from B<br />\n<pre>";
print_r($b->get_vars());
print "</pre>\n";
?>

Резултата от изпълнението е:

Values from A

Array
(
    [A] => Class A
    => Class B
)



Values from B

Array
(
    [A] => Class A
    => Class B
)

Това показва, че наистина както и да се ползва singleton клас винаги се работи е една единствена инстанция.

Благодаря отново.
И най-ярките личности си плащат тока

borovaka

  • Hero Member
  • *****
  • Благодарности
  • -Казани: 1
  • -Получени: 48
  • Публикации: 906
Re: Singleton и registry шаблони
« Отговор #10 -: 29 Август 2011, 18:57:37 »
//offtopic
Дето викаха в top gear " доказахме, че най-бързата кола наистина е най-бърза " :)
Та извода е прост: "Колкото по-големи ла*ната - толкова по-малка щетата! ... моралната де, не материалната"