Скрипт конструктора сайтов php
Как я создавал очередной конструктор сайтов
Всем привет, меня зовут Саша. Я создаю свой конструктор сайтов. Я получил первых платящих пользователей. Все они преимущественно из США и Европы.
Я хочу поделиться историей своего пути, который включает кодинг, краудфандинг и продвижение.
Disclaimer: я регулярно читаю Хабр уже больше 10 лет. Я помню много знаменательных событий этого сообщества. Навскидку: переход ко флэту, разделение, воссоединение, эпичные посты Мосигры и Madrobots, поражающие глубиной мысли комментарии господина Meklon’a.
К сожалению, все это время я боялся написать сюда, потому что всегда думал, что в сообществе Хабра сидят только топовые специалисты и меня с моими ничтожными знаниями тут засмеют.
За последние несколько лет я получил уникальный опыт не только в программировании, но и в продвижении своих проектов. А именно нужда в продвижении останавливает многие начинания талантливых программистов. Поэтому, возможно, мой опыт будет полезен той части аудитории, которая хочет уметь не только программировать пет-проекты, но и делать так, чтобы мир их использовал.
Мой бэкграунд
Но почему именно эта заезженная до дыр, дико конкурентная ниша? Давайте обо всём по порядку.
Я начинал предпринимательскую деятельность в третьем классе. Я покупал в канцтоварах лак с блёстками и продавал девочкам. Это произошло само собой. Вывел гипотезу → влил денежку (со сборов бутылок) → проверил спрос → влил больше денежек.
Потом был вуз, мне нужны были деньги. Поработав продавцом интернета, я быстро устал от бесконечного дерьма и открыл свой интернет-магазин. Удачно выбрав нишу, я смог мгновенно выйти на прибыль около 7000 рублей в месяц, что позволило мне кормиться в студенческие годы.
Интернет-магазин требовал доработок. Пришлось учиться кодить. В 2014 году я написал первую строчку кода. Меня быстро утащило в волшебный мир программирования. Кроличья нора оказалась удивительно глубока и забориста. Я закрыл магазин и устроился верстальщиком в студию. Через год уволился и пошёл работать фрилансером на Upwork.
Я понимал, что должен пилить свой проект.
Но как, чёрт возьми, это сделать?!
Первые проекты
Я работал как фрилансер на Диму. Этот парень — один из лучших дизайнеров в Петербурге. Он также обладает очень редким талантом — тонко чувствовать тренды и предугадывать их.
Мы быстро сработались и начали много общаться на внерабочие темы.
Выяснилось, что нас объединяла страсть к вебу и всепоглощающее желание делать свои проекты.
Дима предложил идею — создать крутой HTML-шаблон и продавать его. У него был чёткий маркетинговый план, и это меня подкупило. Мы взялись за дело.
В течение двух лет мы вместе создали несколько успешных коммерческих проектов. И благодаря уникальному таланту Димы и моему редкому навыку создания веб-анимаций мы скоро (не без страданий) вышли на стабильную прибыль и стали жить только на свои проекты. Как же это было круто!
Криптовалюты
Наши проекты приносили стабильную прибыль, но роста не было. HTML-шаблоны и WordPress-темы оказалось очень сложно масштабировать. Нам едва хватало на скромную жизнь, на найм новых людей денег не было.
Мы грезили созданием своего SaaS. Пытались даже начинать пилить его. Но страх и пустеющий кошелёк заставлял возвращаться к старым проектам. Мы уже долго стагнировали и депрессовали. На новый рывок, откровенно говоря, не хватало яиц.
Летом 2017 года мы познакомились с криптовалютой. Вновь мной овладела идея быстрого обогащения. Вновь я уверовал, что все мои беды и несчастья решаться шестизначной цифрой на счёте. Как же я ошибался!
Некто Юра предложил нам стать сооснователями в одном перспективном криптовалютном проекте. Вместе втроём мы решили делать агрегатор криптовалютных бирж. Мы полностью заморозили наши веб-проекты и занялись этим агрегатором.
Всё начиналось восхитительно. Наш третий партнёр благодаря своей харизме и таланту оратора привлёк ангельские инвестиции.
Но из-за отсутствия опыта мы утонули в нахлынувших деньгах. Тратили их совсем не на тех людей и не на те цели. Нет, кокаином мы не обмазывались и на Lamborghini не гоняли, но покупки вроде билетов на псевдоэлитные конференции потихоньку точили наш бюджет. И вскоре мы обанкротились и закрылись.
К проектам Димы я решил не возвращаться и начать свою тему.
Восстаю из пепла
У меня кончались деньги. Раньше меня это вгоняло в панику, но в этот раз я решил мыслить иначе и действовать с учётом ошибок прошлого. Сперва я сел и решил, чем буду заниматься. Здесь без сомнения победила ниша веб-дизайна и разработки.
Но что конкретно делать? Я повидал множество конструкторов сайтов. И у меня сложился свой vision.
Я уверовал, что конструктор сайтов должен быть жёстко ориентирован на определённую ЦА. Ни в коем случае не быть универсальным инструментом, подходящим и для салона ноготочков, и для мобильного приложения, и для стоматологии.
Сайту с мобильным приложением нужны свои фишки: кнопки «Скачать в AppStore», мокапы телефонов, генератор страниц terms of service и другие мелкие специфичные приблуды. А сайту ноготочков же нужны другие фишки (я без понятия какие).
Если делать универсал, то ты, во-первых, перегрузишь UI, во-вторых, сделаешь хорошо 1000 людям, вместо того чтобы сделать офигенно 10 людям. А если ты маленький человечишка без денег и связей (как я), выбирай второй путь.
Я очень люблю стартапы, поэтому я решил делать конструктор сайтов для стартапов. Так как я многому научился в предыдущих проектах, о продвижении я не беспокоился (ирония в том, что я не задействовал и 1% своего опыта в продвижении, так как в фултайме занимался продуктом. Клиенты появляются только за счёт сарафанки и SEO).
Уверен в продукте, уверен в продвижении, уверен в рынке.
А вот за деньги не уверен. Ведь они кончаются, а прибыль будет неизвестно когда. Но как я сказал, я решил учесть предыдущий опыт и забить* на деньги.
Моя позиция такова: если ты делаешь востребованную годноту, то деньги появятся сами. Так и вышло.
* Может не сработать, если у вас есть дети или другие финансовые обязательства. Не является рекомендацией.
Как я привлёк 500 тысяч рублей за 0% доли
Крайне недооценённый способ. И речь сейчас не о Kickstarter и даже не об AppSumo. Так как же поднять бабла? Куда нажать?
Давайте сначала молнией пробежимся по Kickstarter и AppSumo.
Kickstarter даёт вам возможность создать свою страничку и собрать денежку. Сложности: для вывода денег нужно юридическое лицо в США, нужно усердно продвигать страницу, очень много работы по оформлению страницы, нужно придумать разнообразные награды, SaaS — непопулярная тема на Kickstarter. Нужно влить на страничку посевные деньги — вроде уже собрали 20% (уверен, так все делают).
AppSumo сжирает 50–70% профита своей комиссией. Да. Я тоже офигел. К тому же аудитория AppSumo огромна, поэтому кампания принесёт слишком много денег. Из предыдущего опыта я выяснил, что слишком много денег — так же плохо, как и слишком мало. Я один в команде, много мне не надо. Мне только дайте скромные десять зарплат на покушать, и я все сделаю.
Но люди оценили эту скромность.
Приватный раунд
Мне посоветовали провести приватный краудфандинг-раунд. Как это делается?
1. Создаёшь страницу, где описываешь продукт, и добавляешь ссылку на roadmap в Trello. Roadmap нужен, чтобы показать, куда движется проект, как он будет развиваться. Обозначьте план ваших работ на следующие 6–12 месяцев.
2. Презентуешь публике готовый MVP своего сервиса. MVP — это первая версия продукта, работающий прототип. Мой MVP уже был достаточно хорош и даже неплохо продавался, но в нём нельзя было править контент в онлайне — только экспортировать HTML и править всё локально. Я просто пообещал сделать полноценный онлайн-редактор контента с хостингом. Нужно отметить, что скорее всего, качественный MVP и стал главной причиной моего успеха.
Сейчас кто-то из читателей грустно всхлипнет, ведь у них нет денег даже на MVP. Друзья, вытрите же слёзы! Создание большинства MVP стоит от 5000 до 200 тысяч рублей. Либо можно найти человека, который сделает всё бесплатно на энтузиазме — история знает много таких кейсов. Самое сложное тут — понять, что же такое MVP для вашего проекта.
4. Просто продвигаешь свою страницу с оффером 🙂 Да, это самое сложное и неочевидное. Давайте-ка поподробнее.
Для начала я представил оффер публике на Product Hunt. Так как мой MVP был успешен на PH (Product of a Day, 1500 upvotes), оффер увидело много человек. Я сходу продал 20 подписок. Но этого было мало, я не знал, что делать дальше.
Однако помощь пришла сама.
На меня вышел некто Nitesh Manav с предложением запустить мой оффер в своей маленькой LTD-ориентированной Facebook-группке. Оказывается, в Facebook есть множество таких вот групп. Это огромная масса людей, которые только и ждут, чтобы влить куда-нибудь денег.
Nitesh взял небольшой процент (и кстати, сам купил одну копию). Этот позитивный мужик помог мне грамотно составить оффер и отвечал на вопросы людей о моём продукте в группе на протяжении шести месяцев! У меня остались крайне позитивные впечатления от работы с ним. Пишите ему, если хотите так же.
На успех запуска оффера в группе повлияло четыре фактора:
Один год одиночества
Ой, я же не умею программировать! Я всю жизнь только верстал и лапшекодил на jQuery + PHP. Как быть?
Вариант 1: нанять программистов.
Но я не учёл много важных дополнительных факторов: я профан в найме людей. Сколько месяцев уйдёт на подбор нормальной команды? Также я профан в менеджменте. Сколько денег я сожгу, прежде чем научусь ставить таски?
Самое важное (и отдельно спасибо Косте за то, что вправил мозги) — если сторонний человек сделает проект и уволится, то я не смогу поддерживать кодовую базу или экстренно восстановить работоспособность. А ведь я отвечаю за uptime сайтов своих клиентов. Я должен быть уверен в каждом аспекте продукта.
Вариант 2: научиться программировать и сделать всё самому.
Плюсы очевидны: я буду уверен в проекте, смогу его поддерживать. Смогу лучше ставить таски команде разработчиков в будущем, смогу увереннее нанимать кодеров. И главное — вероятность смерти проекта стремится к нулю. Он умрёт, только если я умру. Минусы: дохренища работы, вероятность сделать хлипкую неподдерживаемую архитектуру.
И я обложился учебниками, заручился поддержкой верных друзей (Костя, Артур, Слава — вы герои проекта!) и неспеша, с толком сделал проект за год. Архитектура благодаря моим опытным советникам получилась более-менее сносная. Всё работает как часы, можно создавать сайты, редактировать их.
Главное — теперь я плаваю в коде своего проекта как рыба в воде. Также бонусом я стал сносным фулстек-разработчиком, что позволит мне эффективно вести команду.
Постепенно, пока я пилил продукт, мой сайт продвинулся на первую страницу по запросу «landing page builder for startup». Пошли органические продажи. Также хорошо работает сарафанка.
Признаюсь, кодить один проект в одиночку целый год было очень тяжело. Единственный мой друг — это IDE. Общение только с кодом часами напролёт, каждый день.
Я дважды ездил в отпуск, но всё равно выгорел. Я стал забывать, как общаться с людьми (одна из причин, почему я организовал IndieHackers-SPb-митапы). Свою лепту внесла и Випассана. После неё у меня уже шестой месяц подряд растёт уровень дереализации.
В общем, я сильно изменился. Надеюсь, найм классных ребят и постоянное общение с ними поможет мне вернуть себя тогдашнего.
Отзывы пользователей
Будущее
Я не умею и не люблю планировать. Мои планы рушатся в девяти из десяти случаев. К чёрту их!
Не люблю я также гонки и KPI.
Я просто спокойно и уверенно делаю своё дело, и всё. Это мой стиль. Вырасту в этом году не на 200%, а на 50% — ну и ладно. Тоже норм.
Мне один MBA на серьёзных щах затирал, что если нет графика роста в форме хоккейной клюшки, то можно закрывать проект (okay.jpg).
Индустрия стартапов всё ещё молода. И со временем будут появляться всё новые и новые стили создания и ведения проектов. Не исключено, что и мой спокойный стиль станет обыденностью.
Сейчас я хочу нарастить оборот, достаточный для найма сотрудников. Надеюсь, запуск на Product Hunt мне в этом поможет. Если нет, смещу фокус с продукта на продвижение.
Дальше я подамся в Y Combinator и поеду в Сан-Франциско смотреть на бомжей и учиться ремеслу стартапера. Это будет весело и полезно.
Появляется много конкурентов, старые обрастают фичами и скупают весь траффик. Но я уверен в будущем Unicorn Platform, потому что точно знаю, что моя страсть к стартапам и вебу не умрёт. А значит, пока я жив, стартапы будут получать лучшие лендосы, а я — постоянных клиентов.
Скрипт «Конструктор сайтов». Одностраничник за пару минут
Скрипт «Конструктор сайтов»
Это не просто движок для сборки сайта — это многопользовательский скрипт, где каждый посетитель может собрать себе сайт и прямо с конструктора опубликовать в интернет одним щелчком мышки.
Возможности
Регистрация.
Шаблоны распределены по блокам, т.е, не целиком сайт, а блоки: шапки (header), подвал (footer), контент и т.д. Вы или клиент собираете сайт по своему вкусу.
Готовые шаблоны по темам.
Редактирование: можно редактировать как сам блок целиком, так и его отдельные детали (меню, текст, картинки, видео и т.д.), изменять стили, цвета, размеры…
Неограниченное создание и добавление страниц.
Публикация. Опубликовать сайт очень легко. Достаточно нажать на кнопку публикация, система по FTP связывается с сервером и копирует файлы на хостинг. Всё делается автоматически.
Экспорт сайта.
Сайт также можно после сборки сохранить на компьютере. и многое многое другое…
Система настолько проста и удобна в обращении, что с ней справится даже домохозяйка
МАТЕРИАЛ, ПОКА НЕ ДОСТУПЕН!
Конструктор PHP
Конструктор класса PHP может содержать столько аргументов или параметров, сколько необходимо. Также можно определить конструктор вообще без параметров.
Важно отметить, что PHP-конструктор вызывается только один раз. И мы не можем вызвать конструктор явно, он вызывается автоматически при создании объекта.
Так как конструктор является магическим методом, он будет иметь отличительную метку магических методов — два подчеркивания в начале. Для определения конструктора мы используем ключевое слово construct :
Пример PHP-конструктора
Теперь мы добавим конструктор в этот класс. Помните, что в ООП PHP конструкторы — это магические методы, следовательно, они начинаются с двух символов подчеркивания и ключевого слова construct :
Создаем объекты этого класса с помощью ключевого слова new :
PHP-конструктор с несколькими аргументами
Мы добавим новую переменную age в класс Human :
Мы создали два объекта, и они содержат начальные значения двух переменных-членов. Следует отметить, что согласно основам PHP ООП конструктор нельзя вызвать более одного раза, но мы можем изменять значения переменных-членов.
Поэтому в классе Human мы создадим два метода, один устанавливает возраст, а второй — имя. Конструктор используется, только чтобы задать начальные значения любой переменной. В дальнейшем, если нужно изменить это значение, мы будем использовать эти функции.
Тот же класс с двумя дополнительными методами:
Мы можем вызывать два новых метода, чтобы изменить имя или возраст. Добавим в пример еще два метода, чтобы вывести имя и возраст:
Полный пример использования конструктора класса PHP ООП с четырьмя функциями:
Еще один пример PHP-конструктора
Давайте посмотрим, как используется конструктор. Сначала создаем простой класс с одним свойством и одной функцией:
Это простой класс, который содержит одну переменную данных, название машины, и метод вывода этого названия.
Теперь добавим конструктор, который будет задавать значение name в момент создания объекта. В ООП PHP код конструктора будет выглядеть следующим образом:
Теперь создаем из класса объект:
Выводим значение данных переменной через вызов метода get_carname() :
Результат будет следующим:
Это простой пример создания конструктора с инициализацией значения членов объекта. Это значение не фиксированное. Мы можем изменить его при необходимости. Тем не менее, это отличный способ инициализации объектов.
В примере после добавления этого кода инициализируются экземпляры класса, чтобы создать объекты. Тот же функционал достигается с помощью конструктора:
Теперь объекты созданы и инициализированы с названиями и ценами на момент создания объекта, это достигается с помощью конструктора.
Этот PHP-код дает следующий результат:
Up to date astrology
Up to date PHP
Up to date DB
25
36
17
Мы видим, что полученный результат тот же самый, но он достигнут с помощью конструктора.
ООП PHP пример базы данных, в котором используется конструктор класса PHP :
Как самостоятельно сделать сайт на PHP?
PHP и HTML
Как видно на скриншоте, строка не отображается в html коде страницы. И в браузере, и в коде видны лишь возвращенные дата и время. А это значит, что скрипт был обработан на серверной стороне. Поэтому создание сайта на php кардинально отличается от написания простых html страниц.
Динамический сайт
Современные сайты бывают двух основных типов:
Динамический сайт на php состоит из следующих файлов:
Как пишется сайт на PHP
Имеется html сайт со следующей структурой и дизайном:
Код файла style.css :
Перед тем, как написать сайт на php до конца, весь html код нужно раскинуть по нескольким файлам:
А если просмотреть в браузере html код страницы, то вы увидите код первоначального исходника:
Конечно, этот вариант подходит лишь для генерации основной страницы сайта. Но если код боковушки убрать в отдельный файл, тогда шаблон можно использовать и для генерации внутренних страниц сайта.
Путь в обход
Но такая разработка сайта требует затраты сил, наличия специализированного программного обеспечения и знаний. Поэтому хотелось бы найти более легкий вариант. Тогда следует воспользоваться конструктором php сайтов.
С более подробным обзором популярных онлайн-конструкторов сайтов можно ознакомиться здесь. В интернете встречаются и десктопные версии конструкторов сайтов, но большая их часть платная.
Но генерация страниц ресурса происходит в них динамически. Наиболее популярные CMS :
Создание web приложения на PHP с иcпользованием Firebird и Laravel
Привет Хабр!
В прошлой статье я рассказывал о пакете для поддержки СУБД Firebird в фреймворке Laravel. На этот раз мы рассмотрим процесс создания web приложения с использованием СУБД Firebird на языке PHP с использованием Laravel.
Обзор драйверов для работы с Firebird
Обзор расширения Firebird/Interbase
Расширение Firebird/Interbase появилось раньше и является наиболее проверенным. Для установки расширения Firebird/Interbase в конфигурационном файле php.ini необходимо раскомментировать строку
или для UNIX подобных систем строку
Это расширение требует, чтобы у вас была установлена клиентская библиотека fbclient.dll/gds32.dll (для UNIX подобных систем fbclient.so) соответствующей разрядности.
Замечание для пользователей Win32/Win64 Для работы этого расширения системной переменной Windows PATH должны быть доступны DLL-файлы fbclient.dll или gds32.dll. Хотя копирование DLL-файлов из директории PHP в системную папку Windows также решает проблему (потому что системная директория по умолчанию находится в переменной PATH), это не рекомендуется. Этому расширению требуются следующие файлы в переменной PATH: fbclient.dll или gds32.dll. |
В Linux это расширение в зависимости от дистрибутива можно установить одной из следующих команд (необходимо уточнить поддерживаемые версии, возможно, необходимо подключить сторонний репозиторий):
Это расширение использует процедурный подход к написанию программ. Функции с префиксом ibase_ могут возвращать или принимать в качестве одного из параметров идентификатор соединения, транзакции, подготовленного запроса или курсора (результат SELECT запроса). Этот идентификатор имеет тип resource. Все выделенные ресурсы необходимо освобождать, как только они больше не требуются. Я не буду описывать каждую из функций подробно, вы можете посмотреть их описание по ссылке, вместо этого приведу несколько небольших примеров с комментариями.
Вместо функции ibase_connect вы можете применять функцию ibase_pconnect, которая создаёт так называемые постоянные соединения. В этом случае при вызове ibase_close соединение не закрывается, все связанные с ней ресурсы освобождаются, транзакция по умолчанию подтверждается, другие виды транзакций откатываются. Такое соединение может быть использовано повторно в другой сессии, если параметры подключения совпадают. В некоторых случаях постоянные соединения могут значительно повысить эффективность вашего веб приложения. Это особенно заметно, если затраты на установку соединения велики. Они позволяют дочернему процессу на протяжении всего жизненного цикла использовать одно и то же соединение вместо того, чтобы создавать его при обработке каждой страницы, которая взаимодействует с SQL-сервером. Этим постоянные соединения напоминают работу с пулом соединений. Подробнее о постоянных соединениях вы может прочитать по ссылке.
Многие ibase функции позволяют не передавать в них идентификатор соединения (транзакции, подготовленного запроса). В этом случае эти функции используют идентификатор последнего установленного соединения (начатой транзакции). Я не рекомендую так делать, в особенности, если ваше веб приложение может использовать более одного подключения.
Функция ibase_query выполняет SQL запрос и возвращает идентификатор результата или true, если запрос не возвращает набор данных. Эта функция помимо идентификатора подключения (транзакции) и текста SQL запроса может принимать переменное число аргументов в качестве значений параметров SQL запроса. В этом случае наш пример выглядит следующим образом:
Очень часто параметризованные запросы используются многократно с различным набором значений параметров, в этом случае для повышения производительности рекомендуется использовать подготовленные запросы. В этом случае сначала необходимо сначала получить идентификатор подготовленного запроса с помощью функции ibase_prepare, а затем выполнять подготовленный запрос с помощью функции ibase_execute.
Подготовленные запросы гораздо чаще используются, когда необходима массовая заливка данных.
По последнему примеру можно увидеть один из недостатков этого расширения, а именно, функции с переменным числом аргументов не очень удобны для параметризованных запросов. Этот недостаток проявляется особенно ярко, если вы пытаетесь написать универсальный класс для исполнения любых запросов. Гораздо удобнее было бы, если параметры можно было передавать одним массивом. Конечно, существуют обходные пути вроде вот такого:
Расширение Firebird/Interbase не работает с именованными параметрами запроса.
По умолчанию расширение Firebird/Interbase автоматически стартует транзакцию по умолчанию после подключения. Транзакцию по умолчанию подтверждается при закрытии соединения функцией ibase_close. Её можно подтвердить или откатить раньше, если вызвать методы ibase_commit или ibase_rollback передав в них идентификатор соединения, или не передавая ни чего (если вы используете единственное соединение.)
Если вам необходимо явное управление транзакциями, то необходимо стартовать транзакцию с помощью функции ibase_trans. Если параметры транзакции не указаны, то транзакция будет начата с параметрами IBASE_WRITE | IBASE_CONCURRENCY | IBASE_WAIT. Описание констант для задания параметров транзакции можно найти по ссылке php.net/manual/ru/ibase.constants.php. Транзакцию необходимо завершать с помощью метода ibase_commit или ibase_rollback передавая в эти функции идентификатор транзакции. Если вместо этих функций использовать функции ibase_commit_ret или ibase_rollback_ret, то транзакция будет завершаться как COMMIT RETAIN или ROLLBACK RETAIN.
Умолчательные параметры транзакции подходят для большинства случаев. Дело в том что соединение с базой данных, как и все связанные с ним ресурсы существуют максимум до конца работы PHP скрипта. Даже если вы используете постоянные соединения, то все связанные ресурсы будут освобождены после вызова функции ibase_close. Несмотря на сказанное, настоятельно рекомендую завершать все выделенные ресурсы явно, вызывая соответствующие ibase_ функции.
Пользоваться функциями ibase_commit_ret и ibase_rollback_ret настоятельно не рекомендую, так как это не имеет смысла. COMMIT RETAIN и ROLLBACK RETAIN были введены для того, чтобы в настольных приложениях сохранять открытыми курсоры при завершении транзакции.
ibase функции не бросают исключение в случае возникновения ошибки. Часть функций возвращают false, если произошла ошибка. Обращаю ваше внимание, что результат сравнивать с false необходимо строгим оператором сравнения ===. Потенциально ошибка может возникнуть поле вызова любой ibase функции. Текст ошибки можно узнать с помощью функции ibase_errmsg. Код ошибки можно получить с помощью функции ibase_errcode.
Расширение Firebird/Interbase позволяет взаимодействовать с сервером Firebird не только посредством SQL запросов, но и используя Service API (см. функции ibase_service_attach, ibase_service_detach, ibase_server_info, ibase_maintain_db, ibase_db_info, ibase_backup, ibase_restore). Эти функции позволяют получить информацию о сервере Firebird, сделать резервное копирование, восстановление или получить статистику. Эта функциональность требуется в основном для администрирования БД, поэтому мы не будем рассматривать её подробно.
Расширение Firebird/Interbase так же поддерживает работу с событиями Firebird (см. функции ibase_set_event_handler, ibase_free_event_handler, ibase_wait_event).
Обзор расширения PDO (драйвер Firebird)
Расширение PDO предоставляет обобщённый интерфейс для доступа к различным типам БД. Каждый драйвер базы данных, в котором реализован этот интерфейс, может представить специфичный для базы данных функционал в виде стандартных функций расширения.
PDO и все основные драйверы внедрены в PHP как загружаемые модули. Чтобы их использовать, требуется их просто включить, отредактировав файл php.ini следующим образом:
Этот шаг необязателен для версий PHP 5.3 и выше, так как для работы PDO больше не требуются DLL.
Далее нужно выбрать DLL конкретных баз данных и либо загружать их во время выполнения функцией dl(), либо включить их в php.ini после php_pdo.dll. Например:
Эти DLL должны лежать в директории extension_dir. Драйвер pdo_firebird требует, чтобы у вас была установлена клиентская библиотека fbclient.dll/gds32.dll (для UNIX подобных систем fbclient.so) соответствующей разрядности.
В Linux это расширение в зависимости от дистрибутива можно установить одной из следующих команд (необходимо уточнить поддерживаемые версии, возможно, необходимо подключить сторонний репозиторий):
Соединения устанавливаются автоматически при создании объекта PDO от его базового класса. Конструктор класса принимает аргументы для задания источника данных (DSN), а также необязательные имя пользователя и пароль (если есть). Четвёртым аргументом можно передать массив специфичных для драйвера настроек подключения в формате ключ=>значение.
Установив свойство \PDO::ATTR_ERRMODE в значение \PDO::ERRMODE_EXCEPTION, мы установили режим, при котором любая ошибка, в том числе и ошибка при подключении к БД, будет возбуждать исключение \PDOException. Работать в таком режиме гораздо удобнее, чем проверять наличие ошибки после каждого вызова ibase_ функций.
Для того чтобы PDO использовал постоянные соединения необходимо в конструктор PDO в массиве свойств передать PDO::ATTR_PERSISTENT => true. |
Метод query выполняет SQL запрос и возвращает результирующий набор в виде объекта \PDOStatement. В этот метод помимо SQL запросы вы можете передать способ возвращения значений при фетче. Это может быть столбец, экземпляр заданного класса, объект. Различные способы вызова вы можете посмотреть по ссылке http://php.net/manual/ru/pdo.query.php.
Если необходимо выполнить SQL запрос, не возвращающий набор данных, то вы можете воспользоваться методом exec, который возвращает количество задействованных строк. Этот метод не обеспечивает выполнение подготовленных запросов.
Если в запросе используются параметры, то необходимо пользоваться подготовленными запросами. В этом случае вместо метода query необходимо вызвать метод prepare. Этот метод возвращает объект класса \PDOStatement, который инкапсулирует в себе методы для работы с подготовленными запросами и их результатами. Для выполнения запроса необходимо вызвать метод execute, который может принимать в качестве аргумента массив с именованными или неименованными параметрами. Результат выполнения селективного запроса можно получить с помощью методов fetch, fetchAll, fetchColumn, fetchObject. Методы fetch и fetchAll могут возвращать результаты в различном виде: ассоциативный массив, объект или экземпляр определённого класса. Последнее довольно часто используется в MVC паттерне при работе с моделями.
Пример использования именованных параметров.
Для поддержки именованных параметров PDO производит предобработку запроса и заменяет параметры вида :paramname на «?», сохраняя при этом массив соответствия между именем параметра и номерами его позиций в запросе. По этой причине оператор EXECUTE BLOCK не будет работать, если внутри него используются переменные маркированные двоеточием. На данный момент нет никакой возможности заставить работать PDO с оператором EXECUTE BLOCK иначе, например, задать альтернативный префикс параметров, как это сделано в некоторых компонентах доступа.
Передать параметры в запрос можно и другим способом, используя так называемое связывание. Метод bindValue привязывает значение к именованному или неименованному параметру. Метод bindParam привязывает переменную к именованному или неименованному параметру. Последний метод особенно полезен для хранимых процедур, которые возвращают значение через OUT или IN OUT параметр (в Firebird механизм возврата значений из хранимых процедур другой).
Нумерация неименованных параметров в методах bindParam и bindValue начинается с 1.
По умолчанию PDO автоматически подтверждает транзакцию после выполнения каждого SQL запроса, если вам необходимо явное управление транзакциями, то необходимо стартовать транзакцию с помощью метода \PDO::beginTransaction. По умолчанию транзакция стартует с параметрами CONCURRENCY | WAIT | READ_WRITE. Завершить транзакцию можно методом \PDO::commit или \PDO::rollback.
К сожалению метод beginTransaction не предоставляет возможности изменить параметры транзакции, однако вы можете сделать хитрый трюк, задав параметры транзакции оператором SET TRANSACTION.
Ниже представлена сводная таблица возможностей различных драйверов для работы с Firebird.
Возможность | Расширение Firebird/Interbase | PDO |
---|---|---|
Парадигма программирования | Функциональная | Объектно-ориентированная |
Поддерживаемые БД | Firebird, Interbase, Yaffil и другие клоны Interbase. | Любая БД, для которой существует PDO драйвер, в том числе Firebird. |
Работа с параметрами запросов | Только неименованные параметры, работать не очень удобно, поскольку используется функция с переменным числом аргументов. | Есть возможность работать как с именованными, так и неименованными параметрами. Работать очень удобно, однако некоторые возможности Firebird (оператор EXECUTE BLOCK) не работают. |
Обработка ошибок | Проверка результата функций ibase_errmsg, ibase_errcode. Ошибка может произойти после вызова любой ibase функции при этом исключение не будет возбуждено. | Есть возможность установить режим, при котором любая ошибка приведёт к возбуждению исключения. |
Управление транзакциями | Даёт возможность задать параметры транзакции. | Не даёт возможность задать параметры транзакции. Есть обходной путь через выполнение оператора SET TRANSACTION. |
Специфичные возможности Interbase/Firebird | Есть возможность работать с расширениями Service API (backup, restore, получение статистики и т.д.), а также с событиями базы данных. | Не позволяет использовать специфичные возможности, с которыми невозможно работать, используя SQL. |
Из приведённой таблицы видно, что большинству фреймворков гораздо удобнее пользоваться PDO.
Выбор фреймворка для построения WEB приложения
Небольшие web сайты можно писать, не используя паттерн MVC. Однако чем больше становится ваш сайт, тем сложнее его поддерживать, особенно если над ним работает не один человек. Поэтому при разработке нашего web приложения сразу договоримся об использовании этого паттерна.
Установка Laravel и создание проекта
Прежде чем устанавливать Laravel вам необходимо убедится, что ваше системное окружение соответствует требованиям.
Самый простой способ установить composer под windows – это скачать и запустить инсталлятор Composer-Setup.exe. Инсталлятор установит Composer и настроит PATH, так что вы можете вызвать Composer из любой директории в командной строке.
Если необходимо установить Composer вручную, то необходимо запустить
Этот скрипт осуществляет следующие действия:
Подробнее об установке composer смотри здесь.
Теперь устанавливаем сам Laravel:
Если установка прошла успешно, то приступаем к созданию каркаса проекта.
Ждём завершения, после чего у нас будет создан каркас проекта. Описание структуры каталогов можно найти в документации по Laravel. Нас будут интересовать следующие каталоги:
В секции require добавьте требуемые пакеты следующим образом:
Теперь можно запустить обновление пакетов командой (запускать надо в корне веб приложения)
После выполнения этой команды новые пакеты будут установлены в ваше приложение. Теперь можно приступить к настройке. Для начала выполним команду
которая создаст дополнительные файлы конфигурации для пакета zofe/rapyd.
В файле config/app.php добавим два новых провайдера. Для этого добавим две новых записи в ключ providers
Теперь перейдём к файлу config/databases.conf, который содержит настройки подключения к базе данных. Добавим в ключ connections следующие строки
Поскольку мы будем использовать наше подключение в качестве подключения по умолчанию, установим следующее
В файле конфигурации config/rapid.php изменим отображение дат так, чтобы они были в формате принятом в России:
Первоначальная настройка закончена, теперь мы можем приступить непосредственно к написанию логики web приложения.
Создание моделей
Фреймворк Laravel поддерживает ORM Eloquent. ORM Eloquent — красивая и простая реализация паттерна ActiveRecord для работы с базой данных. Каждая таблица имеет соответствующий класс-модель, который используется для работы с этой таблицей. Модели позволяют читать данные из таблиц и записывать данные в таблицу.
Создадим модель заказчиков, для упрощения этого процесса в Laravel есть artisan команда.
Этой командой мы создаём шаблон модели. Теперь изменим нашу модель так, чтобы она выглядела следующим образом:
По аналогии создадим модель товаров – Product.
Теперь создадим модель для шапки счёт-фактуры.
В этой модели можно заметить несколько дополнительных функций. Функция customer возвращает заказчика связанного со счёт фактурой через поле CUSTOMER_ID. Для осуществления такой связи используется метод belongsTo, в который передаются имя класса модели и имя поле связи. Функция lines возвращают позиции счёт-фактуры, которые представлены коллекцией моделей InvoiceLine (будет описана далее). Для осуществления связи один ко многим в функции lines используется метод hasMany, в который передаётся имя класса модели и поле связи. Подробнее о задании отношений между сущностями вы можете почитать в разделе Отношения документации Laravel.
Функция pay осуществляет оплату счёт фактуры. Для этого вызывается хранимая процедура SP_PAY_FOR_INVOICE. В неё передаётся идентификатор счёт фактуры. Значение любого поля (атрибута модели) можно получить из свойства attributes. Вызов хранимой процедуры осуществляется с помощью метода executeProcedure. Этот метод доступен только при использовании расширения sim1984/laravel-firebird.
Теперь создадим модель для позиций счёт фактуры.
В этой модели есть функция product, которая возвращает продукт (модель App/Product), указанный в позиции счёт фактуры. Связь осуществляется по полю PRODUCT_ID с помощью метода belongsTo.
В этой модели мы переопределили операции insert, update и delete так, чтобы они выполнялись, используя хранимые процедуры. Эти хранимые процедуры помимо собственно операций вставки, редактирования и удаления пересчитывают сумму в шапке накладной. Этого можно было бы и не делать, но тогда пришлось бы выполнять в одной транзакции модификацию нескольких моделей. Как это сделать будет показано далее.
Теперь немного поговорим о том, как работать с моделями в Laravel для выборки, вставки, редактирования и удаления данных. Laravel оперирует данными с помощью конструктора запросов. Полное описание синтаксиса и возможностей этого конструктора вы можете найти по ссылке. Например, для получения всех строк поставщиков вы можете выполнить следующий запрос
Этот конструктор запросов является довольно мощным средством для построения и выполнения SQL запросов. Вы можете выполнять также фильтрация, сортировку и соединения таблиц, например
Однако гораздо удобнее работать с использованием моделей. Описание моделей Eloquent ORM и синтаксиса запроса к ним можно найти по ссылке laravel.ru/docs/v5/eloquent. Так для получения всех элементов коллекции поставщиков необходимо выполнить следующий запрос
Следующий запрос вернёт первые 20 поставщиков отсортированных по алфавиту.
Для сложных моделей связанные отношения или коллекции отношений могут быть получены через динамические атрибуты. Например, следующий запрос вернёт позиции счёт-фактуры с идентификатором 1.
Добавление записей осуществляется через создание экземпляра модели, инициализации его свойств и сохранение модели с помощью метода save.
Для изменения запись её необходимо найти, изменить необходимые атрибуты и сохранить методом save.
Для удаления записи её необходимо найти и вызвать метод delete.
Удалить запись по ключу можно и гораздо быстрее с помощью метода destroy. В этом случае можно удалить модель не получая её экземпляр.
Существуют и другие способы удаления записей, например «мягкое» удаление. Подробно о способах удаления вы можете прочитать по ссылке.
Теперь поговорим немного о транзакциях. Что это такое я рассказывать не буду, а лишь покажу, как их можно использовать совместно с Eloquent ORM.
Всё что находится в функции обратного вызова, которая является аргументом метода transaction, выполняется в рамках одной транзакции.
Создание контроллеров и настройка маршрутизации
Фреймворк Laravel имеет мощную подсистему маршрутизации. Вы можете отображать ваши маршруты, как на простые функции обратного вызова, так и на методы контроллеров. Простейшие примеры маршрутов выглядят вот так
В первом случае мы регистрируем обработчик GET запроса для корня сайта, во втором – для POST запроса с маршрутом /foo/bar.
Вы можете зарегистрировать маршрут сразу на несколько типов HTTP запросов, например
Из маршрута можно извлекать часть адреса и использовать его в качестве параметров функции-обработчика
Параметры маршрута всегда заключаются в фигурные скобки. Подробнее о возможности настройки маршрутизации вы можете посмотреть в документации глава «Маршрутизация». Маршруты настраиваются в файле app/Http/routes.php в Laravel 5.2 и routes/wep.php в Laravel 5.3.
Вместо того чтобы описывать обработку всех запросов в едином файле маршрутизации, мы можем организовать её использую классы Controller, которые позволяют группировать связанные обработчики запросов в отдельные классы. Контроллеры хранятся в папке app/Http/Controllers.
Все Laravel контроллеры должны расширять базовый класс контроллера App\Http\Controllers\Controller, присутствующий в Laravel по умолчанию. Подробнее о написании контроллеров вы можете почитать в документации в главе HTTP-Контроллеры.
Напишем наш первый контроллер.
Теперь необходимо связать методы контроллера с маршрутом. Для этого в routes.php (web.php) необходимо внести строку
Здесь имя контроллера отделено от имени метода символом @.
Для быстрого построения интерфейса с сетками и диалогами редактирования будем использовать пакет «zofe/rapyd». Мы его уже подключили ранее. Классы пакета zofe/rapyd берут на себя построение типичных запросов к моделям Eloquent ORM. Изменим контроллер заказчиков так, чтобы он выводил данные в сетку (grid), позволял производить их фильтрацию, а также добавлять, редактировать и удалять записи через диалоги редактирования.
Laravel по умолчанию использует шаблонизатор blade. Функция view находит необходимый шаблон в директории resources/views, делает необходимые замены в нём и возвращает текст HTML страницы. Кроме того, она передаёт в него переменные, которые становятся доступными в шаблоне. Описание синтаксиса шаблонов blade вы можете найти в документации в разделе Шаблонизатор Blade.
Шаблон для отображения заказчиков выглядит следующим образом:
Этот шаблон сам унаследован от шаблона master, кроме того он подключает шаблон menu. Меню довольно простое, состоит из трёх пунктов Заказчики, Продукты и Счёт фактуры.
В шаблоне master подключаются css стили и JavaScript файлы с библиотеками.
Шаблон редактора заказчика customer_edit выглядит следующим образом
Контроллер товаров сделан аналогично контроллеру поставщиков.
Контроллер счёт фактур является более сложным. В него добавлена дополнительная функция оплаты счёта. Оплаченные счёт фактуры подсвечиваются другим цветом. При просмотре счёт фактуры отображаются так же её позиции. Во время редактирования счёт фактуры есть возможность редактировать и её позиции. Далее я приведу текст контроллера с подробными комментариями.
Редактор счёт фактур имеет не стандартный для zofe/rapyd вид, поскольку нам необходимо выводить сетку с позициями счёт фактур. Для этого мы изменили шаблон invoice_edit следующим образом.
Теперь, когда все контроллеры написаны, изменим маршруты так, чтобы наш сайт на стартовой странице открывал список счёт фактур. Напоминаю, что маршруты настраиваются в файле app/Http/routes.php в Laravel 5.2 и routes/wep.php в Laravel 5.3.
Здесь маршрут /invoice/pay/
Напоследок приведу несколько скриншотов получившегося веб приложения.