Как сделать редактирование профиля на php
Эта статья является переводом шестой части нового издания учебника Мигеля Гринберга, выпуск которого автор планирует завершить в мае 2018.Прежний перевод давно утратил свою актуальность.
Я, со своей стороны, постараюсь не отставать с переводом.
Это шестой выпуск серии Flask Mega-Tutorial, в котором я расскажу вам, как создать страницу профиля пользователя.
Для справки ниже приведен список статей этой серии.
Примечание 1: Если вы ищете старые версии данного курса, это здесь.
Чтобы создать страницу профиля пользователя, давайте сначала напишем новую функцию просмотра, которая будет отображаться в /user/ URL.
Реализация этой функции просмотра довольно проста. Сначала я пытаюсь загрузить пользователя из базы данных, используя запрос по имени пользователя. Вы уже видели, что запрос базы данных может быть выполнен путем вызова all() , если вы хотите получить все результаты, или first() , если вы хотите получить только первый результат или, если же ничего, соответствующего критериям поиска, не найдется, то эти методы вернут None. В этой функции представления я использую вариант first() , называемый first_or_404(), который работает точно так же, как first() , когда есть результаты, но в случае отсутствия результатов автоматически обратно клиенту отправляется ошибка 404. Выполняя запрос таким образом, я не могу проверить, возвратился ли запрос пользователя, потому что, когда имя пользователя не существует в базе данных, функция не вернется, и вместо этого будет вызвано исключение 404.
Шаблон user.html показан ниже:
Единственное интересное изменение здесь — вызов url_for() , который используется для создания ссылки на страницу профиля. Поскольку функция просмотра профиля пользователя принимает динамический аргумент, функция url_for() получает значение для него как аргумент ключевого слова. Поскольку это ссылка, которая указывает на профиль пользователя в журнале, я могу использовать current_user Flask-Login для генерации правильного URL-адреса.
Аватары
Я уверен, вы согласитесь с тем, что страницы профиля, которые я только что построил, довольно скучны. Чтобы сделать их более интересными, я собираюсь добавить пользовательские аватары, но вместо того, чтобы иметь дело с возможно большой коллекцией загруженных изображений на сервере, я собираюсь использовать сервис Gravatar для предоставления изображений для всех пользователей.
Обратите внимание, что некоторые расширения веб-браузера, такие как Ghostery, блокируют изображения Gravatar, поскольку они считают, что Automattic (владельцы Gravatar) могут определять, какие сайты вы посещаете, на основе запросов, которые они получают для вашего аватара. Если вы не видите аватары в своем браузере, скорее всего проблема в расширениях браузера.
Поскольку аватары связаны с пользователями, имеет смысл добавить логику, которая генерирует URL-адреса аватара для пользовательской модели.
Если вы заинтересованы в ознакомлении с другими вариантами, предлагаемыми службой Gravatar, посетите их сайт документации.
Следующий шаг — вставить изображения аватара в шаблон профиля пользователя:
Большой плюс заключается в том, что пользовательский класс отвечает за возвращение URL-адресов аватаров.И если в какой-то день я решу, что аватары Gravatar не то, что я хочу, я могу просто переписать метод avatar() , чтобы возвращать разные URL-адреса, и все шаблоны начнут показывать новые аватары автоматически.
Вот так у Сьюзен, которой нет
(Прим. переводчика) А вот так с реальным аккаунтом Gravatar.
Использование sub-templates Jinja2
Чтобы вызвать этот подшаблон из шаблона user.html, я использую оператор include Jinja2:
Более интересные профили
Одна из проблем, с которой сталкиваются новые страницы профиля пользователя, заключается в том, что они на самом деле многого не показывают. Пользователи любят рассказывать о чем то на этих страницах, поэтому я позволю им написать что-то о себе, чтобы показать здесь.
Я также буду следить за тем, когда последний раз каждый пользователь обращался к сайту, а также показывать его на странице своего профиля.
Первое, что мне нужно сделать для поддержки всей этой дополнительной информации, — это расширить таблицу пользователей в базе данных двумя новыми полями:
Каждый раз, когда база данных изменяется, необходимо создать миграцию базы данных. В главе 4 я показал вам, как настроить приложение для отслеживания изменений базы данных с помощью сценариев миграции. Теперь у меня есть два новых поля, которые я хочу добавить в базу данных, поэтому первым шагом будет создание сценария миграции:
Прим. переводчика: советую команды, да и тексты набирать самому. Получать ошибки/опечатки. Исправлять их. Все это процесс обучения, который сильно поможет в будущем.
Вот пример ошибки:
Результат команды migrate выглядит хорошо, поскольку он показывает, что были обнаружены два новых поля в классе User. Теперь я могу применить это изменение к базе данных:
Надеюсь, вы понимаете, насколько полезно работать с инфраструктурой миграции. Любые пользователи, которые находились в базе данных, все еще существуют, структура миграции оперативно применяет изменения в сценарии миграции, не разрушая никаких данных.
На следующем шаге я собираюсь добавить эти два новых поля в шаблон профиля пользователя:
Обратите внимание, что я обертываю эти два поля в условных выражениях Jinja2, потому что хочу, чтобы они были видимыми, если они заполнены. На этом этапе эти два новых поля пусты для всех пользователей, поэтому вы не увидите эти поля, если запустите приложение прямо сейчас.
Запись последнего времени посещения для пользователя
Начнем с поля last_seen , более простого из двух. То, что я хочу сделать, это записать текущее время в этом поле для конкретного пользователя всякий раз, когда пользователь отправляет запрос на сервер.
Добавление логина для установки этого поля во всевозможные функции просмотра, которые могут быть запрошены у браузера, очевидно, нецелесообразно, но выполнение немного общей логики перед запросом, отправляемым в функцию просмотра, является общей задачей в веб-приложениях, которые Flask предлагает его как родную функцию. Взгляните на решение:
Если вы просмотрите страницу своего профиля после внесения этого изменения, вы увидите строку "Last seen on" (Последнее посещение) с временем, близким к текущему.
И если вы перейдете от страницы профиля и затем вернетесь, вы увидите, что время постоянно обновляется.
Тот факт, что я храню эти временные метки в часовом поясе UTC, делает время, отображаемое на странице профиля, также в формате UTC. До кучи ко всему этому, формат времени — это не то, что вы ожидаете, поскольку видим отображение внутреннего представление объекта datetime Python. На данный момент я не буду беспокоиться об этих двух проблемах, так как я расскажу о теме обработки дат и времени в веб-приложении в следующей главе.
Редактор профиля
По хорошему пользователям нужно предоставить форму, в которой они могут ввести некоторую информацию о себе. Форма позволит пользователям изменить свой логин и другие данные, а также написать что-то о себе, чтобы быть сохраненным в новом поле about_me. Давайте напишем класс для такой формы:
Шаблон, который отображает эту форму, показан ниже:
И, наконец, вот функция, которая связывает все вместе:
Эта функция просмотра несколько отличается от другой, обрабатывающей форму. Если validate_on_submit() возвращает True , я копирую данные из формы в объект пользователя, а затем записываю объект в базу данных. Но когда validate_on_submit() возвращает False , это может быть вызвано двумя разными причинами. Во-первых, это может быть связано с тем, что браузер просто отправил запрос GET , на который мне нужно ответить, предоставив исходную версию шаблона формы. Во-вторых, это также возможно в случае, когда браузер отправляет запрос POST с данными формы, но что-то в этих данных является недопустимым. Для этой формы мне нужно рассматривать эти два случая отдельно. Когда форма запрашивается в первый раз с запросом GET , я хочу предварительно заполнить поля данными, которые хранятся в базе данных, поэтому мне нужно сделать обратное тому, что я сделал в случае отправки, и переместить данные, хранящиеся в полях пользователя, в форму, поскольку это гарантирует, что эти поля формы имеют текущие данные, хранящиеся для пользователя. Но в случае ошибки проверки я не хочу ничего писать в поля формы, потому что они уже были заполнены WTForms. Чтобы различать эти два случая, я проверяю request.method , который будет GET для первоначального запроса, и POST для отправки, которая не прошла проверку.
Чтобы пользователи могли получить доступ к странице редактора профилей, следует добавить ссылку на страницу профиля:
5. Задача
Переделайте вашу авторизацию и регистрацию на новые изученные функции.
файл register.php (часть кода)
";
>
>
else <
$emailText color:red\"> enter the correct email
";
>
>
else <
$passwordText color:red\"> Your password must contain from 6 to 12 characters
";
>
>
else <
$loginText color:red\"> Your login must contain from 4 to 10 characters
";
>
>
else <
$loginText color:red\"> Login can contain only Latin letters or numbers
";
>
>
else <
$loginText color:red\"> Enter a valid username or password or email. Must not contain an empty string
";
>
>
else <
$passwordText color:red\"> enter the correct password
В прошлой части мы исправляли и переводили интерфейс нашего приложения. Сегодня мы, как анонсировалось ранее, добавим страницу просмотра профиля пользователя и выведем формы для редактирования информации о пользователе и для смены пароля.
Для удобства изучения сходники проекта теперь доступны на GitHub.
По просьбам читателей в комментариях и в обратной связи немного исправил предыдущую часть, добавив использование компонента интернационализации для перевода интерфейса.
Итак, приступим. В модуле user на данный момент имеется только контроллер DefaultController .
Дадим пользователю возможность просматривать и редактировать свой профиль. Для этого добавим новый контроллер ProfileController , доступный только для авторизованных пользователей. Сделаем его пока с единственным действием index . В этом действии мы получаем модель текущего пользователя и передаём в представление:
Вспомним, что наша модель User реализовывает интерфейс IdentityInterface и её класс указан в качестве identityClass для компонента Yii::$app->user :
и при авторизации в качестве Yii::$app->user->identity используется именно экземпляр модели User текущего пользователя. Это значит, что в качестве $model мы могли бы использовать прямо этот экземпляр Yii::$app->user->identity . Но безопаснее в ходе выполнения действия контроллера не давать доступа к самому экземпляру Yii::$app->user->identity . Поэтому мы ещё раз загрузили экземпляр пользователя из базы данных:
При этом не возникнет проблем с пустым identity , так как с помощью поведения AccessControl мы разрешаем доступ ко всем действиям этого контроллера только авторизованным пользователям.
В представлении modules/user/views/profile/index.php будем просто выводить информацию о пользователе с помощью виджета DetailView :
Теперь мы можем попробовать отобразить профиль. Для удобства добавим в меню пункт Профиль :
и не забудем добавлять переводы по мере необходимости в файлы в созданных на прошлом уроке папках messages/en и messages/ru .
С нашими правилами маршрутизации эта страница будет доступна по адресу /user/profile . Мы могли бы не создавать отдельный контроллер ProfileController и поместить этот функционал прямо в DefaultController::actionIndex , чтобы профиль отображался по адресу /user . Но для нашего удобства всё-таки вынесли. Иначе DefaultController окажется слишком большим.
Давайте ещё сделаем так, чтобы с пока нерабочего (так как действия actionIndex в DefaultController пока нет) адреса /user нас автоматически перекидывало на /user/profile . Просто добавим действие и поместим в него перенаправление на соседний контроллер:
Теперь при ручном переходе по адресу /user не вывалится ошибка, а сработает редирект на профиль:
Редактирование: сценарии и формы
Итак, наша текущая модель пользователя хранит правила валидации для имени пользователя, адреса электронной почты и статуса:
Нашу модель можно выводить в форму редактирования с любыми полями из этих. Например, мы могли бы вывести форму с полем для адреса электронной почты, создав действие редактирования в контроллере ProfileController :
и сделав для него представление с формой:
Из формы будут приниматься все перечисленные в rules() поля. И если пользователь с помощью инструментов разработчика в браузере добавит в форму поле User[status] или User[username] , то может изменить недоступные ему поля. Но нам нужно сохранить эти поля для редактирования в панели администратора.
Для решения этой проблемы можно пойти двумя путями. Их мы и рассмотрим.
Сценарии модели
Любая модель в Yii2 позволяет задавать ей несколько сценариев использования, для которых можно задавать разные правила валидации и для смены поведения.
Нам нужно ввести два сценария: один для администратора (со всеми правилами) и второй для пользователя в его профиле. По умолчанию в модели все правила рассматриваются для сценария default , хранящегося в константе Model::SCENARIO_DEFAULT . Так что нам остаётся добавить один сценарий profile . Обозначим его также константой User::SCENARIO_PROFILE :
Теперь нам нужно определить, какие правила будут работать у администратора, а какие на странице профиля пользователя. Можно пойти путём Yii1 , введя в специфические правила указания применимости on к сценарию либо исключения except :
И фреймворк для сканирования атрибутов запустит метод scenarios() модели, который обойдёт все правила и построит список сценариев и полей для них.
Но это не очень удобно с большим количеством правил. Намного удобнее оставить правила как есть и самому переопределить метод scenarios() , где вручную перечислить нужные для каждого сценария поля:
Этими строками мы разрешим пользователю редактировать только адрес электронной почты. А все остальные поля разрешим менять в будущем только администратору.
Теперь в действии редактирования профиля не забудем указать модели нужный нам сценарий:
И добавим само представление modules/user/views/profile/update.php с формой:
Пока у нас здесь всего одно поле:
Но в будущем можем реализовать и другие настройки профиля.
Теперь рассмотрим другой подход.
Модели форм
Использовать сценарии удобно, но это немного захламляет модель. Если мы вспомним наши страницы логина, регистрации, восстановления пароля, то для них почему-то добавлены отдельные модели LoginForm, SignupForm и PasswordResetForm.
Но ведь, по сути, это относится к модели пользователя. Их бы можно было реализовать с помощью единственной модели User со сценариями SCENARIO_LOGIN , SCENARIO_SIGNUP и подобными. Но кроме различия правил валидации в этих моделях есть свои специфические методы login() , signup() и прочие, которые нужны только для одного действия.
Если бы мы собрали все эти сценарии использования в одной модели User , то там оказалось бы слишком много вспомогательного кода для реализации всех случаев жизни. И, в итоге, наша модель из простой записи ActiveRecord превратилась бы в большой комбайн с десятками и сотнями методов и вспомогательных полей.
Именно поэтому ради упрощения кода для реализации специфичных форм желательно создавать отдельные модели.
Во-вторых, повышает безопасность, так как при описании сценариев можно нечаянно ошибиться и открыть какое-нибудь служебное поле, а при использовании отдельного класса пользователь не имеет прямого доступа к редактированию исходной модели User .
И, в третьих, внутри такой отдельной модели удобно добавлять любой код, любые public поля, оперировать любыми другими сущностями. Например, подписать пользователя на рассылку, если он поставил галочку в поле subscribe . Помещать это всё в одну модель User было бы слишком громоздко.
Так что добавим новую форму для редактирования данных пользователя с полем $email :
У нас нет в базе отдельной таблицы profile , так что мы будем использовать только модель User . Мы переопределили конструктор так, чтобы получать эту модель. Поменяем теперь контроллер:
Всё. Сценарий SCENARIO_PROFILE нам здесь больше не нужен.
Чтобы не загромождать модель User , сделаем смену пароля отдельной от редактирования профиля формой.
Для формы ввода создадим модель PasswordChangeForm и добавим три поля для нового и текущего паролей и правила валидации для них. В эту модель через конструктор мы будем передавать модель пользователя, чей пароль нужно будет изменить. Для валидации текущего пароля создадим отдельный метод-валидатор currentPassword , который будет проверять правильность пароля, вызывая метод validatePassword переданной ему модели пользователя:
Добавим действие смены пароля в наш контроллер:
и добавим представление modules/user/views/profile/passwordChange.php :
Теперь в соседнее представление просмотра профиля index.php добавим ссылки на эти действия:
В приложении теперь появилась страница просмотра профиля:
страница редактирования данных (пока у нас всего одно поле):
и страница смены пароля:
Вот и всё. А дальше:
Подписывайтесь на рассылку (форма в сайдбаре), чтобы не пропустить продолжение и получать полезные фишки, и оставляйте свои предложения или замечания в комментариях. И оставляйте предложения по темам будущих вебинаров здесь. Спасибо!
Безопасная система авторизации и регистрации является одним из важнейших элементов при создании проекта с нуля. Один из возможных способов — это создание системы регистрации с помощью PHP и MySQL .
Хотя в Интернете есть много пособий на эту тему, большинство из них предназначено для продвинутых пользователей.
Эта статья расскажет о том, как создать простую версию системы авторизации и регистрации пользователей с использованием PHP и MySQL для начинающих. Давайте начнем!
Ресурсы, необходимые для работы с этим руководством:
- Xampp ( PHP версии 5.3 или более поздней и MySQL версии 4.1.3 или более поздней );
- Базовые знания по PHP , HTML и CSS ;
- Время и терпение.
Что мы создаем
Настройка сервера
Вы можете использовать любой хостинг с поддержкой PHP и MySQL ( только убедитесь, что он поддерживает PHP версии 5.3 или более поздней и MySQL версии 4.1.3 или более поздней ).
Но в этой статье в качестве сервера будет использоваться Xampp . Если до этого не работали с Xampp , эта статья может помочь вам разобраться, как его должным образом установить на вашем компьютере.
Шаг 1 – MySQL
Во-первых, создайте базу данных и таблицу, которая будет содержать все регистрационные данные. Вы можете сделать это вручную с помощью графического интерфейса пользователя PhpMyAdmin или использовать для вставки этой информации SQL .
Взгляните на приведенный ниже код SQL :
Обратите внимание, что все данные представляют собой varchar , и даже пароль позже будет преобразован в символ md5 , чтобы обеспечить его безопасность.
Кроме того, используйте auto_increment для автоматического назначения идентификаторов или номеров пользователям, которые будут регистрироваться в системе.
Теперь, когда таблица создана, нужно задать разметку и стили CSS , а затем PHP -код.
Шаг 2 — Разметка
Для разметки, нам нужно включить три файла, и все они должны быть сохранены в формате « .php «, так как мы создаем программу сценариев на стороне сервера.
Сначала создайте файл login.php . Скопируйте в него приведенный ниже код:
С помощью этого кода вы получите результат, который показан на рисунке ниже:
Далее, создаем файл register.php . Скопируйте и вставьте в него приведенный ниже код:
С помощью этого кода вы получите следующий результат:
Далее, создаем файл intropage.php . Он будет служить в качестве страницы приветствия после того, как пользователь успешно авторизовался в системе:
Этот код даст нам следующий результат:
Шаг 3 — CSS
Теперь, когда разметка готова, нужно добавить CSS -код. В основном, он будет содержать стили для класса страниц container, а также для кнопок и некоторых других элементов, таких как текстовые поля и лайки:
К этому времени, вы уже должны получить тот же результат, что и на изображении, приведенном в начале статьи.
Шаг 4 — Многоразово используемые элементы
Теперь, когда у вас готовы разметка и стили CSS , попробуйте задействовать такие многоразово используемые элементы, как раздел заголовка и раздел подвала. В корневой папке создайте новую папку и назовите ее “ includes “.
В ней будут содержаться все включаемые файлы. Затем в папке includes создайте новый файл и назовите его header.php . Скопируйте часть раздела заголовка в каждый из трех PHP -файлов, созданных нами ранее. Таким образом, у вас получится:
Следующее, что вам нужно сделать, это удалить разметку, скопированную из файла header.php во всех трех PHP -файлах и заменить ее следующим PHP -кодом:
Теперь, сделайте то же самое с подвалом. Скопируйте приведенный ниже код и вставьте его в новый файл footer.php . Он будет включать в себя раздел подвала:
Затем снова удалите эту часть во всех трех файлах PHP и замените ее следующим кодом:
Шаг — 5 Подключение к базе данных
Теперь, когда вы включили файлы разделов заголовка и подвала, пора создать новый включаемый файл. Назовите его constants.php и скопируйте в него следующий код:
В приведенном выше коде, мы создали константы информации базы данных. Теперь мы можем легко изменять информацию всякий раз, когда это необходимо.
Далее, в папке includes создайте новый файл и назовите ее connection.php . В нем будут храниться коды подключения к базе данных. Скопируйте и вставьте в него код, приведенный ниже:
Включите файл connection.php в файлах login.php и register.php , так как эти два файла необходимы для кода управления подключением. Скопируйте приведенный ниже код и вставьте его перед включением файла header.php :
Шаг — 6 Конфигурация файла register.php
Теперь необходимо преобразовать форму регистрации в полноценную систему регистрации. Чтобы сделать это, нужно добавить включение еще нескольких файлов PHP после включения header.php . Скопируйте и вставьте приведенный ниже код в файл register.php :
Шаг — 7 Конфигурация файла login.php
Теперь, когда пользователи могут регистрироваться на сайте, необходимо создать систему авторизации. С помощью этого очень простого PHP -кода, вы можете включить систему авторизации. Скопируйте код и вставьте его перед разметкой в файл login.php :
В приведенном выше коде, перед перенаправлением пользователя на страницу intropage.php , которую мы добавим чуть позже, вы в первую очередь должны проверить, была ли установлена сессия .
Шаг — 8 Конфигурация файла intropage.php
Мы установили все, что нужно для файлов register.php и login.php . Теперь вы просто должны обеспечить, чтобы пользователь оставался в системе при перенаправлении на страницу intropage.php . Скопируйте и вставьте приведенный ниже код в файл intropage.php :
Обратите внимание, что оператор if был создан для проверки, установлена ли сессия, и в зависимости от этого должен ли пользователь перенаправляться на страницу login.php или остаться на странице intropage.php .
Шаг — 9 Конфигурация файла logout.php
Наконец, чтобы пользователь мог выйти из системы, нужно удалить сессию с помощью session_destroy .
Скопируйте данный код в файл logout.php :
Заключение
Сегодня мы узнали, как создать простую систему авторизации, используя PHP и MySQL . Конечно, существует много аспектов, которые нужно учитывать, когда речь идет о безопасности, но это уже неплохое начало.
Вы можете изменять приведенные в этой статье коды по своему усмотрению. Если у вас есть идеи по их улучшению, буду рад услышать об этом в комментариях.
Надеюсь, вам понравилась эта статья. Увидимся в следующий раз!
пришлось покапать чтобы заработало, вот моя редакция кода:
обработчик register.php
if(isset($_POST["register"])) if(!empty($_POST['full_name']) && !empty($_POST['email']) && !empty($_POST['username']) && !empty($_POST['password'])) $full_name= htmlspecialchars($_POST['full_name']);
$email=htmlspecialchars($_POST['email']);
$username=htmlspecialchars($_POST['username']);
$password=htmlspecialchars($_POST['password']);
$query=mysql_query("SELECT * FROM user WHEREusername='".$username."'");
$numrows=mysql_num_rows($query);
if($numrows==0)
$sql .$full_name."','".$email."', '".$username."', '".$password."')";
$result=mysql_query($sql);
if($result) $message = "Account Successfully Created";
>
else $message = "Failed to insert data information! SQL query:".$sql;
>
>
else $message = "That username already exists! Please try another one!";
>
>
else $message = "All fields are required!";
>
>
?>
md5 шифрование так и не нашел в коде ?
Как добавить $hashed_password
Объясните новичку, как работает система донатов на сайте, как её создать и подключить к базе данных, и как менять цену на игровую валюту, буду очень благодарен!
скрипты полностью рабочие до версии php 5.5
а улучшить напиши функцию для удаление нежелательных тегов типа и и экранирование если проскочили для начала
для поля user_login
и пару проверок смысл пихать полностью голый код народ приходит правит в итоге проЁ пароли от мыл и на главной странице (_!_) если комедию русскою смотрел по хоттабыча то в курсе и писать надо что какая функция делает а не пихать от болды if($numrows==0) //проверяем равна она нулю или нет если не равна идем дальше если равна значит пустая выводим ошибку
Каждый раз когда я хочу написать какой-либо интересный мне пост, я всегда смотрю в гугле, что уже имеется по этой теме. Если интернет уже переполнен ею, то я стараюсь выбрать что-либо другое.
И мне показалось очень странным, что тема создания кастомной страницы профиля пользователей особо и не поднималась, если бегло пробежаться по результатам поиска, то можно увидеть уйму статей, которые должны помочь с произвольной формой регистрации или добавлением полей в профиль пользователя в админке, я об этом писал много лет назад здесь и здесь соответственно.
Даже на англоязычных сайтах я ничего не нашел (не знаю, может искал плохо), конечно некоторые решения имелись, но все они были плагинами.
Пример произвольной страницы профиля пользователя на одном из созданных мной сайтов.
Шаг 1. Шаблон страницы
Кое-что про шаблоны страниц я тоже уже писал, поэтому сейчас сразу перехожу к коду.
Шаг 2. PHP-файл для обработки сохраняемых данных
Это и есть содержимое файла profile-update.php , который в прошлом шаге мы решили разместить прямо в папке с темой.
Если у вас есть вопросы по работе кода или предложения по его доработке, прошу вас проследовать в комментарии :)
Почти все функции, использованные в коде статьи
Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.
Пишите, если нужна помощь с сайтом или разработка с нуля.
Комментарии — 14
Вау как вовремя! :) Спасибо.
Миша, а может у тебя есть идеи как вывести создание постов? или уже есть готовая статья?
Например опубликовал запись + также есть возможность отредактировать или удалить его.
Такой ответ я думаю лучше оформить все в отдельный пост (вот тебе как идея для нового поста). Так как в инете ничего годного нет. А у тебя мануалы самые понятные :)
Читайте также: