Это для меня не очень делает смысл Класс не может быть статик или не статик, статическими могут быть свойства и методы класса. Инстанс это экземпляр класса, инстанцирование это создание экземпляра класса. Статические свойства и методы позволяют обращаться к ним без создания экземпляра класса.
Собственно, в статье приводится пример синглтона, в котором возвращается копия(не копия) статического свойства PHP: public static function get_instance() { if ( ! isset( self::$instance ) ) { self::$instance = new self(); } return self::$instance; } Я склоняюсь к такому подходу с синглтоном: PHP: class DB { private static $connection; private function connect() { if(!(self::$connection instanceof ...)) { self::$connection = ...; // подключение к БД } } final protected function query($query,...) { $this->connect(); //выполнение запроса и все такое } } class myDB extends DB { public function my_function() { ... $this->query('...'); ... } } $abc = new myDB(); $abc->my_function(); Это тоже говнофича?
@keren, здесь говорится о том (и @Fell-x27 достаточно хорошо аргументировал свою позицию), что, хотя php позволяет смешивать в одном классе статику и не-статику, это не является хорошей практикой программирования. Т.е. либо у тебя класс, предназначенный для того, чтоб создавались его экземпляры (объекты), и тогда в нём нет статики, либо у тебя утилитный класс, в котором всё статика, и тогда ты не создаёшь его объекты. @Maputo, насколько я понял нескольких лекторов, синглтоны нужно создавать через DI-контейнеры и Service Locator. Хотя сам я делаю обычные синглтоны, если проект не слишком сложный.
@mkramer, впринципе в статье рассмотрены хорошие альтернативы. Но сам "плохой" синглтон рассматривается в довольно частном случае.
Нехорошая практика это не смешивание статики и нестатики в классе, а статическое обращение к не статическим свойствам и методам класса. Те прежде чем обратится к чему либо статически нужно сделать статическим то к чему обращаешься, но от куда обращаешься не обязательно должно быть статическим.
Не, это не нехорошая практика, это баг php, который устранили. А вот смешивание статики и не статики имеет действительно описанные @Fell-x27 недостатки, а именно
Задача, создать input с помощью ООП: PHP: echo $form->input(['type'=>'text', 'value'=>'!!!']); //Код выше выведет <input type="text" value="!!!"> Правильно ли сделал, есть ли по лучше решение? PHP: <?php error_reporting(E_ALL); class Form { private $type ; private $value; public function input($arr) { $this->type = $arr['type']; $this->value = $arr['value']; return '<input type="' .$this->type . '" value="' .$this->value . '">'; } } $form = new Form; echo $form->input(['type'=>'text', 'value'=>'!!!']); ?>
Это уже не ООП это просто ты используешь объекты)). Верстку лучше оставить на своем месте, а объекту формы отдавать данные которые пришли на обработку)
@Dimon2x input без name бесполезен, а вот под каждый type можно и отдельный класс PHP: use Zend\Form\Element; use Zend\Form\Form; $text = new Element\Text('firstName'); $text->setLabel('Enter your name'); $form = new Form('my-form'); $form->add($text);
PHP: <?php error_reporting(E_ALL); class Form { private $type ; private $value = ''; private $placeholder; private $action = ''; private $method; private $name; private $className; public function checkValue($arr) { if (array_key_exists('value', $arr)) { $this->value = $arr['value']; } } public function checkName($arr) { if (array_key_exists('name', $arr)) { $this->name = 'name="'.$arr['name'].'"'; } } public function checkClass($arr) { if (array_key_exists('class', $arr)) { $this->className = 'class="' . $arr['class'] . "\" "; } } public function input($arr) { $this->type = $arr['type']; $this->checkName($arr); $this->checkValue($arr); $this->checkClass($arr); return '<input ' . $this->className . $this->name . ' type="' .$this->type . '" value="' .$this->value . '">'; } public function password($arr) { $this->type = 'password'; $this->checkName($arr); $this->checkValue($arr); $this->checkClass($arr); return '<input '. $this->className . $this->name .' type="' .$this->type . '" value="' .$this->value . '">'; } public function submit($arr) { $this->type = 'submit'; $this->checkName($arr); $this->checkValue($arr); $this->checkClass($arr); return '<input ' . $this->className . $this->name .' type="' .$this->type . '" value="' .$this->value . '">'; } public function textarea($arr) { $this->placeholder = $arr['placeholder']; $this->name = $arr['name']; $this->checkValue($arr); $this->checkClass($arr); return '<textarea ' . $this->className . $this->name . ' placeholder="' . $this->placeholder. '">' . $this->value . '</textarea>'; } public function open($arr) { $this->action = $arr['action']; $this->method = $arr['method']; $this->checkClass($arr); return '<form '.$this->className.' action="'.$this->action.'" method="'.$this->method.'">'; } public function close() { return '</form>'; } } $form = new Form; echo $form->open(['action'=>'index.php', 'method'=>'POST']) . "\n"; echo "\t ". $form->input(['type'=>'text', 'placeholder'=>'Ваше имя', 'name'=>'name', 'class'=>'name']) . "\n"; echo "\t ". $form->password(['placeholder'=>'Ваш пароль', 'name'=>'pass', 'class'=>'user-password']) . "\n"; echo "\t ". $form->submit(['value'=>'Отправить']) . "\n"; echo $form->close(); ?>
Не понимаю, я создал класс, который всё наследует от класса Form и почему, если после отправки, не сохраняется значение в input name? PHP: class SmartForm extends Form { public function checkValue($arr) { if(!empty($_POST['name'])) { $this->value = $_POST['name']; } parent::checkValue($arr); } } $form2 = new SmartForm; echo $form2->open(['action'=>'./2.php', 'method'=>'POST']) . "\n"; echo "\t ". $form2->input(['type'=>'text', 'placeholder'=>'Ваше имя', 'name'=>'name', 'class'=>'name']) . "\n"; echo "\t ". $form2->password(['placeholder'=>'Ваш пароль', 'name'=>'pass', 'class'=>'user-password']) . "\n"; echo "\t ". $form2->submit(['value'=>'Отправить']) . "\n"; echo $form2->close();
Если Вы хотите в дочернем классе использовать какие-либо скрытые свойства - им надо ставить область видимости protected, а не private. Еще есть DOM-элементы в php для создания таких вещей.
Я изменил на protected. Теперь другая проблема, в value почему-то сохраняется значение, почему, если я его удаляю? В поле name и password будут одинаковые значения PHP: class SmartForm extends Form { public function delValue() { $this->value = null; } public function checkValue($arr) { echo '<pre>'; print_r($_POST); echo '</pre>'; if(!empty($_POST['name'])) { $this->value = $_POST['name']; } if(!empty($_POST['pass'])) { $this->value = $_POST['pass']; } parent::checkValue($arr); } } $form2 = new SmartForm; echo $form2->open(['action'=>'./2.php', 'method'=>'POST']) . "\n"; echo "\t ". $form2->input(['type'=>'text', 'placeholder'=>'Ваше имя', 'name'=>'name', 'class'=>'name']) . "\n"; echo "\t ". $form2->password(['placeholder'=>'Ваш пароль', 'name'=>'pass', 'class'=>'user-password']) . "\n"; echo "\t ". $form2->submit(['value'=>'Отправить']) . "\n"; echo $form2->close();
Вы пытаетесь переопределить родительский метод, но при этом его явно не вызываете в коде. А вызываете родительские методы, которые вызывают свои непереопределенные методы. И я так и не нашел где используется delValue()?
@Maputo PHP: public function password($arr) { $this->type = 'text'; $this->checkName($arr); $this->delValue(); $this->checkValue($arr); $this->checkClass($arr); return '<input '. $this->className . $this->name .' type="' .$this->type . '" value="' .$this->value . '">'; } --- Добавлено --- Вообще не понимаю, почему после отправки, в значения подставляется Отправить? PHP: class SmartForm extends Form { public function checkValue($arr) { if(!empty($_POST['pass'])) { $this->value = $_POST['pass']; } parent::checkValue($arr); } } $form2 = new SmartForm; echo $form2->open(['action'=>'./2.php', 'method'=>'POST']) . "\n"; echo "\t ". $form2->input(['type'=>'text', 'placeholder'=>'Ваше имя', 'name'=>'name', 'class'=>'name']) . "\n"; echo "\t ". $form2->password(['placeholder'=>'Ваш пароль', 'name'=>'pass', 'class'=>'user-password']) . "\n"; echo "\t ". $form2->submit(['value'=>'Отправить']) . "\n"; echo $form2->close(); --- Добавлено --- Почему я его не использую, я же его переопределил? --- Добавлено --- ВооНе понимаю, почему после отправки, в значения подставляется Отправить? А как его вызвать в коде?
@Dimon2x, когда Вы вызываете родительский метод, внутри которого есть checkValue - этот самый checkValue берется из родительского класса, а не из дочернего. То что Вы пытаетесь реализовать - решается с помощью "контекста" или еще чего. В крайнем случае нужно определить поточнее какие методы должны быть определены в родительском классе, а какие в дочернем. Ну и посмотрите сами - насколько выгодно использовать такие классы? Не проще ли организовать это с помощью старого доброго html? Хотите потренироваться с классами и генерацией html - попробуйте сделать класс для создания таблиц из двумерных массивов, чтобы код с использованием класса выглядел так: PHP: $table = new Table($two_dimensional_array); echo $table;
@Maputo Мне же надо, как-то учить ООП. --- Добавлено --- Почему берется из родительского класса, а не из дочернего? Я же переопределил.
@Dimon2x, ООП нужно учить так как его будете в дальнейшем применять. ООП - для удобства придумали, а не для того, чтобы отделить "хороших" программистов от "плохих". Потому что Вы вызываете в коде родительские методы. Если бы Вы еще переопределили и методы input(), password() и submit() - вызывался бы дочерний метод. Rem.: одного переопределения мало - нужно использовать вызов дочернего метода внутри переопределенных методов.
Навели тень на плетень... @Dimon2x Если создается объект наследника (smartForm) - то из методов базового (Form) класса (input и прочие в этом примере) посредством $this->checkValue() вызывается именно метод класса smartForm, раз уж checkValue переопределен, а не базового (Form). Для этого не надо переопределять в наследнике методы input и другие. В данном случае метод checkValue был не столько переопределен, сколько дополнен... и в нем присутствует явный вызов метода из класса-родителя (parent::checkValue). Надо определиться - нужен этот вызов вообще, и если нужен - то до кода из класса smartForm, или после.
@Sail он нужен после условия, потому что в условии задаётся значение для value и потом уже идёт проверка в checkValue, что value не пуста и надо подставить в значение PHP: class Form { protected $value; public function checkValue($arr) { if (array_key_exists('value', $arr)) { $this->value = $arr['value']; } } PHP: public function input($arr) { $this->type = $arr['type']; $this->checkName($arr); $this->checkValue($arr); $this->checkClass($arr); return '<input ' . $this->className . $this->name . ' type="' .$this->type . '" value="' .$this->value . '">'; } PHP: class SmartForm extends Form { public function checkValue($arr) { if(!empty($_POST['name'])) { $this->value = $_POST['name']; } return parent::checkValue($arr); } } Только почему то не работает
@Sail, да. Вы правы. То что я описал не относится к этой ситуации. Это происходит только при попытке переопределить приватные родительские методы.
На самом деле, генерация форм - это полезный инструмент, и он включен во многие фреймворки. И как правило, там же валилация, токены против csrf и тд
Почему после отправки, в ключ [password] попадает значение отправить, как такое возможно? PHP: <?php error_reporting(E_ALL); class Form { protected $type ; protected $value; protected $placeholder; protected $action = ''; protected $method; protected $name; public function checkValue($arr) { if (array_key_exists('value', $arr)) { $this->value = $arr['value']; } } public function checkName($arr) { if (array_key_exists('name', $arr)) { $this->name = 'name="'.$arr['name'].'"'; } } public function input($arr) { $this->type = $arr['type']; $this->checkName($arr); $this->checkValue($arr); return '<input ' . $this->name . ' type="' .$this->type . '" value="' .$this->value . '">'; } public function password($arr) { $this->type = 'text'; $this->checkName($arr); $this->checkValue($arr); return '<input '. $this->name .' type="' .$this->type . '" value="' .$this->value . '">'; } public function submit($arr) { $this->type = 'submit'; $this->checkName($arr); $this->checkValue($arr); return '<input ' . $this->name .' type="' .$this->type . '" value="' .$this->value . '">'; } public function open($arr) { $this->action = $arr['action']; $this->method = $arr['method']; return '<form action="'.$this->action.'" method="'.$this->method.'">'; } public function close() { return '</form>'; } } class SmartForm extends Form { public function checkValue($arr) { if(!empty($_POST['password'])) { echo '<pre>'; print_r($_POST); echo '</pre>'; $this->value = $_POST['password']; } return parent::checkValue($arr); } } $form2 = new SmartForm; echo $form2->open(['action'=>'./2.php', 'method'=>'POST']) . "\n"; echo "\t ". $form2->input(['type'=>'text', 'placeholder'=>'Ваше имя', 'name'=>'name', 'class'=>'name']) . "\n"; echo "\t ". $form2->password(['placeholder'=>'Ваш пароль', 'name'=>'password', 'class'=>'user-password']) . "\n"; echo "\t ". $form2->submit(['value'=>'Отправить']) . "\n"; echo $form2->close(); ?>