Предлагаю вашему вниманию свое решение по генерации html на PHP. Задача вроде бы тривиальная, но хотелось бы, чтобы это было расширяемо, кратко, но в тоже время с хорошим функционалом. Получилось вроде не плохо.

Сразу скажу( как многие считают в комментариях), что задача ставилось не написать шаблонизатор (которых и так много) и не заменить шаблонизатор JavaScript. Я прекрасно знаю, что true way это разделять html и данные. Но мне понадобилось писать html в классах, для создания компонентов фреймворка, на подобие CGridView в yii, стоит ли в таких местах выносить html в отдельные файлы решать вам.

Основная цель, избавится от html в классах и функциях.

Простой пример, обычная кнопка:

CHtml::create()
    ->p()
        ->a(array('href' => 'http://habrahabr.ru', 'class' => 'btn'))
            ->text('Перейти')
    ->render();

Результат:

<p><a href="http://habrahabr.ru" class="btn">Перейти</a></p>



Ничего хитрого, можно было бы этим и ограничется, но захотелось циклы:

$arr = array('1' => 'Первый', '2' => 'Второй');

CHtml::create()
	 ->select($options)
		->each(CHtml::plainArray($arr, 'value', 'text'))
			->option('array("value" => $data->value)')
				 ->text('$data->text')
		->end()
	->endEach()


Тут понадобилось вызвать функцию plainArray() которая превращает массив в виде:
$arr = array(
    array('value' => '1', 'text' =>'Первый'), 
    array('value' => '2', 'text' => 'Второй')
);

Теги внутри цикла могут содержать функции или строки с eval выражениями, вложенность любая, пример с таблицей:

$columns = array(
    array('id' => 'NAME', 'label' => 'Имя'),
    array('id' => 'AGE', 'label' => 'Возраст')
);

$data = array(
    array('NAME' => 'Петр', 'AGE' => 29),
    array('NAME' => 'Василий', 'AGE' => 32)
);

CHtml::create()
	->table()
		->thead()
			 ->tr()
			->each($columns)
				 ->th()
					->text(function($column){
						 return $column['label'];
					})
                                 ->end()
			->endEach()
 			->end()
		->end()
			->tbody()
			->each($data)
				->tr()
				->each($columns)
					->td()
						->text(function($row, $column) {
	                                              return $row[$column['id']];
						})
					->end()
				->endEach()
				->end()
			->endEach()
->render();


Незакрытые теги закрываются автоматически.

Класс можно расширить, вплоть до использования в формах. Расширить можно за счет наследования или внедрения зависимости, за то, как будет выводится каждый тег и его атрибуты используется одна функция, поэтому можно легко переопределить это поведение.


class CMyHtml extends CHtml {

	public function a($options = array()) {
		$default = array(
			'href' => 'javascript:void(0)'
		);
		return parent::a(array_replace($default, $options));
	}
}



class CForm {
        
        private $_lastLabel = '';
	public function __construct(CModel $model, CHtml $html = null) {
		$this->_model = $model;
		$this->_html = $html ?: CHtml::create();
	}

	public function __call($method, $ps) {
		$options = $ps ? $ps[0]: array();

		if ($method === 'label') {
			$this->_lastLabel = isset($options['for']) ? $this->_model->getLabel($options['for']) : '';
		}

		if ($method === 'text' && $this->_lastLabel) {
			$options = $options ?: $this->_lastLabel;
			$this->_lastLabel = '';
		}
               $this->_html->$method($options);
	       return $this;
       }
}


Само решение можно посмотреть и попробовать на github.

Спасибо за внимание.

Комментарии (87)


  1. enleur
    04.11.2015 15:18
    +16

    Один вопрос — зачем?


    1. stagnantice
      04.11.2015 15:23
      -2

      Ну во-первых код выглядит чище без <?, ?>, во вторых для генерации более сложных компонентов системы на php, без использования html.


      1. Delphinum
        04.11.2015 17:33
        +3

        HTML код на чистом PHP, выглядит чище, чем HTML код с примесью PHP? )


        1. stagnantice
          04.11.2015 18:52

          если им нужно манипулировать, то так и так будет через php.


  1. fleaump
    04.11.2015 15:20
    +11

    Есть же шаблонизаторы, чтобы не мешать код и верстку. А тут верстка остается все равно в коде.


    1. stagnantice
      04.11.2015 15:23
      -4

      Задача не ставилась облегчить работу верстальщику, а только облегчить жизнь тому, кто вынужден в php вставлять html.


      1. fleaump
        04.11.2015 15:30
        +1

        так шаблонизаторы и убирают этот «костыль», когда впаивают в код верстку, чтобы так не делали.


        1. stagnantice
          04.11.2015 17:18
          -1

          а причем тут они? я его не писал


      1. fleaump
        04.11.2015 15:51
        +23

        Это походу просто этап такой.

        1) начал кодить — код+ html в одном файле
        2) уже делишь код на несколько php файлов, освоил include, но верстка все равно вперемешку
        3) начал понимать что что то как то не очень — решил «генерировать» html в ходе кода
        4) гордишься своей гениальностью и хочешь со всеми поделиться
        5) понимаешь, что все равно херь какаято
        6) начинаешь понимать, что надо разделять не просто по php файлам, а еще по сильнее — отделять верстку
        7) недолго гугля находишь — шаблонизаторы
        8) пытаешься освоить какойнибудь легковестный шаблонизатор
        9) освоил — понял, что много кода тянет лишнего — в просто шаблонизаторе овер кода, чем ты написал на проект
        10) написал свой шаблонизатор в 100 строк!
        11) гордишься своей гениальностью и хочешь со всеми поделиться
        12)начинает не хватать функциональности и гибкости — городишь костыли в коде и расширяешь функционал своего шаблонизатора, чтобы всё же используя возможность своего шаблонизатора все же не сорваться и не воткнуть кусок верстки
        13)Шаблонизатор уже подошел к 1к строк кода, и все равно всплывает, что не хватает возможностей.
        14)Успокоился пришел в %ПОПУЛЯРНЫЙ_ШАБЛОНИЗАТОР%


        1. Akdmeh
          04.11.2015 16:51
          +7

          15) Написал об этом коментарий на хабрахабре


          1. mapron
            04.11.2015 16:54
            +1

            конечно, ведь

            хочешь со всеми поделиться


            продолжу:
            16) возвращаешься к идее использования php как шаблонизатора, просто вынося шаблоны в отдельный файл.


            1. stagnantice
              04.11.2015 17:23

              			if($element instanceof CFormInputElement)
              			{
              				if($element->type==='hidden')
              					return "<div style=\"visibility:hidden\">\n".$element->render()."</div>\n";
              				else
              					return "<div class=\"row field_{$element->name}\">\n".$element->render()."</div>\n";
              			}
              


              Код из Yii, скажите, а они на каком сейчас этапе?


              1. fleaump
                04.11.2015 17:37

                на этапе
                ? надо переписать

                подход собрать гору данных и скормить их шаблонизатору для отрисовки в разы проще — не надо в ходе кода городить и подстраиваться под отрисовку.


                1. stagnantice
                  04.11.2015 17:44
                  -1

                  То есть вы против html кода в php в любом случае? Ну это ваша позиция, я считаю что он допустим для отрисовки стандартных интерфейсов, например того же bootstrap. И есть куча решений, где html код вшит в php.


                  1. fleaump
                    04.11.2015 18:34
                    +1

                    php и создан чтобы отдавать html. Но логику от отрисовки лучше отделять, чтобы в будущем не мучиться если надо перенести кудато код.


                    1. stagnantice
                      04.11.2015 18:54
                      -1

                      я согласен, но у меня отрисовку можно будет менять только через расширение классов, так изначально задумывалось. Я пишу компоненты, через которые будут использоваться при написании сайта, а не сам сайт и его вьюшки с дизайном.


                      1. fleaump
                        04.11.2015 19:43

                        Но вот это

                        CHtml::create()
                        ->table()
                        ->thead()
                        ->tr()
                        ->each($columns)
                        ->th()
                        ->text(function($column){
                        return $column['label'];
                        })
                        ->end()
                        ->endEach()
                        ->end()
                        ->end()

                        всёж верстка, если кому-то понадобиться после допилить сайт и где то что то передвинуть или дорисовать атрибут, он полезет в ядро, менять там. В будущем, когда надо будет обновить движок, то апдейт сломает, то что поправили. Поэтому и рисуют элементы и мелкие части используя шаблоны — просто отправил туда массив переменных, и оно само наложило это всё и отрисовало. И это никак не влияет на обновления + скины.


                        1. stagnantice
                          04.11.2015 20:13
                          -1

                          Я не для сайта это делаю, а для фреймворка, это компонент выводит таблицу. Но можно пользоваться им, можно от него от наследоваться, а можно и вовсе написать свое, никто не запрещает. Но будет сделано так, чтобы в 90% случаев хватило использование стандартного, чтобы облегчить всем жизнь.


              1. michael_vostrikov
                04.11.2015 17:58

                На этапе «уже давно вышла вторая версия», которая использует класс Html.
                Класс для генерации html подходит для внутреннего использования (например, в другом классе для работы с формами), но для верстки страниц лучше использовать обычные теги с кодом на php или шаблонизатором.


                1. stagnantice
                  04.11.2015 18:03
                  -2

                  Ну я пытался сделать нечто похожее.


                  1. andrewnester
                    04.11.2015 22:10
                    +1

                    но не вышло :(


        1. Delphinum
          04.11.2015 17:34
          +2

          8) пытаешься освоить какойнибудь легковестный шаблонизатор

          PHP достаточно легковесный шаблонизатор? )


        1. kovalevsky
          04.11.2015 17:36

          4й шаг уже давно пройден, автор даёт ссылку на гитхаб, где у него уже целый фреймворк собственный


  1. andrew_tch
    04.11.2015 15:32
    -7

    Оггосподи.

    С ужасом понимаю что PHP постам только минусы ставить, увы.


    1. mapron
      04.11.2015 16:55
      -5

      И не говорите… (сам писал 5 лет на PHP, но то что в посте — лучше даже не распространять).


  1. hellman
    04.11.2015 16:28

    А где защита от XSS?


  1. michael_vostrikov
    04.11.2015 17:11
    +4

    Сделаю картинкой, чтобы было видно все сразу:

    Скрытый текст
    image


    1. stagnantice
      04.11.2015 17:24
      -4

      Скажите, что я тут должен увидеть?


      1. michael_vostrikov
        04.11.2015 17:30
        +4

        — меньше строк
        — разная подсветка для html и php кода
        — подсветка открывающего и закрывающего тега
        — возможность свернуть содержимое тега


        1. stagnantice
          04.11.2015 17:40
          -3

          а теперь представьте что этот код у вас где-то в классе, и этот html надо возвращать чтобы отправить письмо.


          1. Delphinum
            04.11.2015 17:44
            +2

            $template = new Template('mail.tpl');
            
            $mail = new Mail;
            $mail->setBody($template->render($data));
            $mail->send();
            


            1. stagnantice
              04.11.2015 18:04
              -5

              а файл у вас прям рядом лежит? и так с каждым классом надо будет думать куда файл положить да?


              1. Delphinum
                04.11.2015 18:06
                +1

                Лично у меня шаблоны писем складируются в каталог mails.

                и так с каждым классом надо будет думать куда файл положить да?

                Это не столь сложная задача чтоб о ней думать )


                1. stagnantice
                  04.11.2015 19:30
                  -3

                  Ну, мне это не подходит. Мне нужно писать компоненты, в которых html внутри не изменится. Может если бы у меня была просто отправка писем, я бы не стал заморачиваться и сделал как вы.


                  1. Delphinum
                    04.11.2015 19:40
                    +1

                    Ну шаблонизатор можно использовать без шаблонизации:

                    $template = new Template('mail.tpl');
                    
                    $mail = new Mail;
                    $mail->setBody($template->render([]));
                    $mail->send();
                    

                    или вы о чем?

                    Народ возмущается тому, что вы предлагаете писать:
                    $html->head()->title('Hello');
                    

                    Вместо:
                    <html>
                      <head>
                        <title>Hello</title>
                    

                    Второй вариант может и длинее, но привычнее.


                    1. stagnantice
                      04.11.2015 20:02

                      Я так не предлагаю писать, боже упаси!
                      Этот класс я буду использовать только внутри других классов — компонентов, где заранее известно какие теги и классы будут.

                      Главная цель — избавить классы от html. Другие цели не ставились. Да, можно выносить html в файлы, но у меня html практически статичный, мне легче создать его каким-то объектом.


                      1. Delphinum
                        04.11.2015 20:13

                        Я и говорю, что легче писать HTML, а не писать PHP который генерит HTML )


    1. kovalevsky
      04.11.2015 17:35

      Намного приятнее смотрится, если использовать if/endif, foreach/endforeach и и прочее вместо фигурных скобок в HTML.


  1. kovalevsky
    04.11.2015 17:24

    Для Вас расширяемость ограничивается extend'ом?

    и…

    			->option('array("value" => $data->value)')
    				 ->text('$data->text')
    

    шта?


    1. stagnantice
      04.11.2015 17:26

      Там должна быть функция, которая вернет массив атрибутов, либо такой вариант. Переопределить можно любой тег, добавив классы. Первое расширение которое я пишу для bootstrap.


      1. kovalevsky
        04.11.2015 17:32

        Да я с вашего гитхаба Вам приколов ещё накидать могу. Там по логике в коде видно, что оно писалось из головы и придумывалось на ходу



  1. vosi
    04.11.2015 18:27
    +2

    картинка_про_тролейбус_из_хлеба.bmp


    1. Delphinum
      04.11.2015 18:31
      +3

      Похоже баг хабра. Не беспокойтесь, я поправлю!

      картинка_про_тролейбус_из_хлеба.bmp
      image


      1. vosi
        04.11.2015 18:42
        +2

        это не бмп, это жпег!!!
        еще один баг!111


      1. vshemarov
        05.11.2015 01:29
        +1

        Реальность всегда превзойдет фантазию — никогда не думал, что известная картинка будет реализована в жизни. Зачот!


  1. m1el
    04.11.2015 18:31
    +3

    Я считаю, что генерация HTML при помощи DOM-подобных приемов это очень правильный подход, и автор пытается это сделать.

    Но получается криво.


    1. Delphinum
      04.11.2015 18:32

      Вы про DOMDocument?


      1. m1el
        04.11.2015 18:35
        +1

        Можно использовать и DOMDocument для генерации HTML, и это подходит под мой критерий. Но апи у него очень громоздкое.
        В качестве примера того что я имею в виду я выберу React.js.


  1. andrew_tch
    04.11.2015 19:06
    +1

    А вообще это haml. Или jade.

    Чем это пилить — пофиксите пару багов в парсере того или другого для php.


    1. stagnantice
      04.11.2015 19:16
      -1

      Да я в курсе про haml, писал на нем в Ruby on Rails. Но хотелось написать свое, и написал.


      1. andrew_tch
        04.11.2015 19:21
        +1

        ну так раз: packagist.org/search/?q=haml

        и два — там надо было писать хамл, а не чудо спагететвое и называть его революционным способом регенации html из php )


        1. stagnantice
          04.11.2015 19:27
          -1

          где я его так назвал?) Спасибо за ссылку на композер) я знаю где он лежит.


  1. x88
    04.11.2015 19:49
    +1

    Практически полностью отказались от компонентов CHtml. Один кастомный CGridView сжирает на 7мб памяти больше, чем нативные foreach. Сейчас php дорос до удобной шаблонизации без дополнительных надстроек, и не стоит бояться шорт-тэгов:
    <?php foreach($myArr as $id =>$obj): ?>
    <?php if ($obj->isShow): ?>
    <?=$var; ?>
    <?php endif; ?>
    <?php endforeach; ?>


    1. stagnantice
      04.11.2015 19:50

      Спасибо, буду иметь ввиду


    1. Delphinum
      04.11.2015 19:52
      -2

      Можно легко заменить <?php на <? с помощью директивы short_open_tag, если вы не планируете пользовать PHP шаблонизацией в XML.


      1. x88
        04.11.2015 20:02
        -1

        В некоторых проектах использование такой формы еще является стандартом. О шорт тэгах я кстати и написал.


      1. zelenin
        04.11.2015 21:10

        что не соответствует psr-1 и добавляет проблем сторонним пользователям.


        1. Delphinum
          04.11.2015 21:14

          Когда вы пишете готовый сервис, у вас в компании могут быть свои стандарты, которые (возможно) отличаются от psr-1, и это вполне нормально.


          1. zelenin
            04.11.2015 21:16

            конечно же, но это не повод советовать их использовать на хабре.


            1. Delphinum
              04.11.2015 21:18
              -2

              Почему же не повод? Psr-1 это не обязательство, а всего лишь стандарт. Я его не соблюдаю и имею право советовать это другим программистам.


              1. zelenin
                04.11.2015 21:30

                а советовать надо best practices. а это следование рекомендованным стандартам. рекомендуя свои внутренние корпоративные стандарты без аргументации, вы плодите зло на Земле в виде например фреймворка автора.
                Все современные популярные библиотеки следуют psr-1,2,4. Это удобно, единообразно, и не заставляет разработчика привыкать к новому для себя кодстайлу.
                Стандарт в области кодстайла удобен не тем, что он лучше (многие моменты могут породить холивар вкусовщины), а тем, что он стандарт.


                1. Delphinum
                  04.11.2015 21:58
                  +2

                  а советовать надо best practices. а это следование рекомендованным стандартам.

                  А если я не согласен со стандартом, то мне надо вздохнуть и все равно рекомендовать стандарт?


                  1. zelenin
                    04.11.2015 22:08

                    Тут в комментах много советов автору. Комментирующие видимо хотят подтолкнуть его на путь истинный. Что хотите вы, я не в курсе.
                    Мое мнение таково: есть два варианта — либо вы советуете стандарт ибо он де-факто выигрышен тем, что стандарт, либо в случае несогласия со стандартом, предлагаете свой вариант, обосновывая почему ваш вариант лучше, ведь возможно вы и правы. Если вы считаете, что ваш, третий вариант — рекомендовать без аргументации — правилен, то обсуждение можно закрыть — я неавторитетен вас учить поведению на отраслевых ресурсах.


                    1. Delphinum
                      04.11.2015 22:19

                      Тут в комментах много советов автору. Комментирующие видимо хотят подтолкнуть его на путь истинный. Что хотите вы, я не в курсе

                      Я автору не советов не следовать psr-1. Вы что то путаете.
                      Мое мнение таково

                      Вы хотите чтоб я продемонстрировал используемый мной стандарт да еще и сравнил его с psr в комментариях? )


                      1. zelenin
                        04.11.2015 22:29

                        неиспользование шорт-тегов — один из пунктов psr-1.
                        Прочтите нашу ветку еще раз — не надо еще одной итерации с начала.


                        1. Delphinum
                          04.11.2015 22:33

                          неиспользование шорт-тегов — один из пунктов psr-1

                          Я разве спорю?
                          Прочтите нашу ветку еще раз — не надо еще одной итерации с начала

                          Не наблюдаю моего отступления от моего мнения, как и ваших аргументов.


                          1. zelenin
                            04.11.2015 22:40

                            вы не спорите, что это стандарт, но упоминаете, что можно юзать их, отключив директиву в php.ini. Это вредный совет, поскольку это пассивная рекомендация писать нестандартизированный код. Тот же автор увидит ваш комментарий и подумает: а действительно, зачем не везде <?php, ведь <? короче и компактнее. Не всем очевидно, что это вредно.


                            1. Delphinum
                              04.11.2015 22:48

                              Это вредный совет, поскольку это пассивная рекомендация писать нестандартизированный код

                              Видимо кроме PSR вы другие стандарты не воспринимаете )
                              Тот же автор увидит ваш комментарий и подумает: а действительно, зачем не везде <?php, ведь <? короче и компактнее

                              И верно подумает.
                              Не всем очевидно, что это вредно

                              Даже мне не очевиден вред использования тегов.


                              1. zelenin
                                04.11.2015 22:58

                                есть принятый сообществом единый стандарт. Ключевое словосочетание «принятый сообществом». Это был прорыв, т.к. объединил все разрозненные кодстайлы, существовавшие до этого. Это значит, что все ведущие, все современные библиотеки используют один кодстайл. Вам очевидна выгода использование единого кодстайла? Очевидна выгода единого стандарта?
                                Подумает верно, ведь действительно шорт-теги короче и компактнее (хотя не дает никакого профита при разработке), но не полезнее.
                                Вред простой: а) для использования шорт-тегов нужно включать дополнительную директиву — не всегда возможно, б) библиотека с шорт-тегами не будет работать при настройках по умолчанию (а шорт-теги это все-таки не функциональная фича), в) тег <? неоднозначен (как вы упомянули выше)
                                С <?php проблем никаких нет, поэтому это стандартизированный тег.


                                1. Delphinum
                                  04.11.2015 23:02
                                  -1

                                  есть принятый сообществом единый стандарт

                                  Да что вы привязались то ко всему стандарту в целом, я о частностях его говорю )
                                  Вред простой: а) для использования шорт-тегов нужно включать дополнительную директиву — не всегда возможно, б) библиотека с шорт-тегами не будет работать при настройках по умолчанию (а шорт-теги это все-таки не функциональная фича), в) тег <? неоднозначен (как вы упомянули выше)
                                  С <?php проблем никаких нет, поэтому это стандартизированный тег.

                                  Меня всегда улыбало использование стандарта во вред разработки )


                                  1. zelenin
                                    04.11.2015 23:06

                                    Я аргументировал все что можно — вы продолжаете оперировать абстракциями.
                                    Я указал, что использование шорт-тега идет во вред разработке. Неиспользование во вред не идет.


                                    1. Delphinum
                                      04.11.2015 23:08

                                      Ок, приведу пример. У меня компания, в ней работает десяток программистов. Код закрытый и распространять его мы не планируем. Все программисты сходятся во мнении, что писать <? ?> им проще чем <?php ?>. Хостится система на наших серверах и включить дериктиву мы можем. Мы пользуем PSR, но не пользуем некоторыми его частностями. Как думаете, мы все попадем в ад?


                                      1. zelenin
                                        04.11.2015 23:14

                                        так с этого и началось: внутри своей компании используйте что хотите.
                                        Аналогично: у нас продукт 4-летней давности, в легаси-коде используются шорт-теги, но все разработчики понимают ценность следованию стандартам и весь новый код пишут в psr-1,2,4.

                                        Вы продолжаете юлить. Есть понимание, что следование стандартам важно?


                                        1. Delphinum
                                          04.11.2015 23:16

                                          А где в этой ветке вы нашли мои слова относительно использования <? в библиотеках?

                                          Вы продолжаете юлить. Есть понимание, что следование стандартам важно?

                                          Я лишь изучаю ваш догматизм, не более того )


                                          1. zelenin
                                            04.11.2015 23:19

                                            квалифицирую вас как тролля.


                                            1. Delphinum
                                              04.11.2015 23:24

                                              Ну дело ваше.


    1. Finesse
      05.11.2015 12:49
      +1

      Предлагаю такой вариант шорт-тэгов:
      <?php foreach($myArr as $id =>$obj) { ?>
        <?php if ($obj->isShow) { ?>
          <?=$var; ?>
        <?php } ?>
      <?php } ?>


      1. Delphinum
        05.11.2015 12:56

        Говорят что использование { } в HTML делает код менее читабельным, ибо не понятно что именно закрывается очередной скобкой }, а закрываться это может далеко внизу.


        1. Finesse
          05.11.2015 13:21

          Название закрывающего тега тоже не всегда говорит, какой именно тег открывался (если много одинаковых тегов). Нужно применять отступы, в этом случае будет понятно и с }, и с endif. HTML, в котором не используются отступы, плохо читаем.


      1. x88
        05.11.2015 15:30
        -1

        Такое надо брить codeSniffer'ом


  1. zelenin
    04.11.2015 21:22
    +2

    на всякий случай напишу: у автора там на гитхабе целый фреймворк, который явно вдохновлен yii1 (год создания — 2008) и его стандартами тех лет. Поэтому автор не отделяет добро от зла и вряд ли внимает доводам из комментов.


  1. batmandarkside
    04.11.2015 22:38
    +1

    Что за жесть :-(


  1. MTonly
    04.11.2015 22:55
    +1

    Смешивать на одном логическом уровне разные сущности (в данном случае — имена элементов типа tbody и действия типа each или render) — путь в никуда. Вот добавят в стандарт HTML элементы each или render, и приехали. ;-)


  1. Zhandos
    04.11.2015 23:28

    Мои глаза…


  1. Finesse
    05.11.2015 12:44

    Обычный HTML вместо такого кода компактнее, проще и понятнее. Конструкции с тег()->end() выглядят отталкивающе. Было бы более элегантно, если бы оно было сделано как в jQuery.


  1. duke_nu
    05.11.2015 13:25
    +1

    верстальщик вернул хтмл, потом его полностью надо переписать на шаблонизаторе. затратно по времени, могут возникнуть проблемы с внесением изменений.