Ищу курс по PHP
Посоветуйте курс по PHP с выполнением итогового проекта. Желательно, который прошли сами (не для рекламы).
Посоветуйте курс по PHP с выполнением итогового проекта. Желательно, который прошли сами (не для рекламы).
Здравствуйте . Столкнулся с проблемкой, не могу найти какую-нибудь вакансию после долгого перерыва.
Работал в web с 2014 по 2018 годы. Занимался версткой, установкой верстки на cms, попутно правил какой-то php код внутри этих cms. Большинство сайтов тогда использовали jQuery, поэтому лепил с помощью него слайдеры и datepicker'ы.
Вполне себе работал и на сыр с маслом хватало, но после одного проекта - выгорел и ушёл. Сейчас вот появилось желание вернуться, прошерстил бегло то, что стало минимумом, вроде docker, vue.js, laravel. Составил резюме и...нафиг бы никому не сдался. Даже до собеседования не пройти, одни отказы везде. Везде требуется коммерческий опыт от года, а кое-где от 3 лет, даже на позицию джуна. А еще гит-репозитории со своими пет-проектами просят. Странно это как по мне. Все равно, что с начинающего строителя требовать фото дачного домика, который он для себя строит.
Может кто подскажет как вообще действовать и можно ли сейчас пробить эту стену?
Сложность: средняя.
Необходимое время: 30 мин.
В статье представлена инструкция по созданию своего компонента для движка InstantCMS2. В конце статьи приведена ссылка на архив с исходным кодом и содержимым всех файлов из этой инструкции. Пример внешнего вида компонента, который можно создать, используя данный туториал, представлен на иллюстрации.
@akiritch в моем предыдущем посте Продолжение поста «Зарплаты ректората МГТУ им. Н.Э. Баумана» усомнился #comment_325445602 в наличии функции отображения зарплат ка карте по регионам. Поэтому публикую здесь на Пикабу исходный код модуля для движка InstantCMS 2, который мы используем на сайте сообщества Зарплата бюджетников - этот исходный код в свое время был опубликован на Хабре (там фрагменты с кодом более читыемые, потому что сохраняются отступы в начале строк и присутствует подсветка синтаксиса PHP).
Для начала несколько слов про движок соц.сети / сообщества / блогосоциальной сети InstantCMS2. Эта бесплатная CMS может являться отличным компромиссом, возможно, лучшим из существующих.
В базовой версии уже заложен более богатый функционал по сравнению с LiveStreet CMS.
Скриншот сравнения функционала не привожу, потому что по ссылке дана информация не по самой последней версии движка InstantCMS.
Из минусов — количество модулей, дополнений, тем для данного движка достаточно ограничено. Качество технической поддержки немного хромает. Живого активного сообщества вокруг данного движка нет, а регистрация на форуме вообще только по приглашению. Но все эти минусы с лихвой перекрывает факт бесплатности движка InstantCMS 2.
Из плюсов — из коробки предоставляется сразу: форум, профили пользователей с возможность добавления в друзья, статьи, блоги, новости, группы, фотоальбомы, статичные страницы сайта. А также комментарии, ленты RSS, поля RSS, возможность настраивать главное меню, нормальная модерация и вполне удобная админка.
Скачать движок InstantCMS 2 с функцией авто-установки можно с официального сайта проекта.
Процесс установки хорошо документирован и интуитивно понятен.
Перейдем непосредственно к вопросу написания отдельного компонента.
Для создания нового компонента создайте папку, в которой будет ваш компонент (назовем его newcomponent), в директории \SiteDirectory\system\controllers\, т.е полный адрес к созданной директории будет \SiteDirectory\system\controllers\newcomponent\ — все буквы в названии компонента должны быть строчными, это важно!
Далее в этой папке создаем файл frontend.php — это главный файл, без которого компонент не будет работать.
В этом файле создаем класс с таким же названием. Название класса совпадает с названием папки. И этот класс наследуется от системного класса cmsFrontend.
В этом классе мы имеем возможность добавлять методы, описывающие действия компонента.
Что такое действия компонента? Давайте взглянем на следующее изображение:
Каждый адрес страницы состоит из нескольких сегментов:
/controller — Название компонента.
/action — Название действия. Каждый компонент может иметь несколько действий внутри себя.
/p1/p2/p3/… — Любое количество параметров, необходимых для этого действия.
Как определяется действие компонента? Определяется публичный метод в классе компонента, который называется actionНазваниеДействияСБольшойБуквы. Для главной страницы компонента siteaddress.ru/newcomponent/ необходимо определить метод actionIndex(). Для внутренней страницы компонента siteaddress.ru/newcomponent/act/ необходимо определить метод actionAct().
Файл frontend.php
<?php
class newcomponent extends cmsFrontend {
public function actionIndex() {
$template = cmsTemplate::getInstance();
$template->render('index');
}
public function actionAct() {
$errors = false;
$form = $this->getForm('newForm');
$is_submitted = $this->request->has('submit');
$newForm = $form->parse($this->request, $is_submitted);
if ($is_submitted){
$errors = $form->validate($this, $newForm);
if (!errors) {
$choropleth = $this->model->getChoropleth($newForm);
}
if (!errors) {
cmsUser::addSessionMessage(LANG_FORM_ERRORS, 'error');
}
}
$template = cmsTemplate::getInstance();
$template->render('act', array(
'form' => $form,
'errors' => $errors,
'newForm' => $newForm
));
}
}
?>
Внимательный читатель заметил использование метода $this->model->getChoropleth().
Для использования методов модели в директории \SiteDirectory\system\controllers\newcomponent\ создаем файл model.php
Однако читать данные мы будем из файлов, поэтому поставим здесь заглушку. Описание файла модели приведено с целью обучения.
Файл model.php
<?php
class modelNewComponent extends cmsModel {
public function getChoropleth($average_zarplata) {
$choropleth = array();
return $choropleth;
}
}
?>
Строка $template->render('index'); определяет вывод настоящего шаблона, который должен быть создан в директории \SiteDirectory\templates\default\controllers\newcomponent\. Где \default — название используемой темы на сайте (можно найти и скачать новую тему с сайта сообщества instantcms и изменить используемую тему через админку), папку \newcomponent необходимо будет создать самостоятельно, это папка для шаблонов нового компонента.
В этой папке должен быть создан файл index.tpl.php для главной страницы компонента, и act.tpl.php — для внутренней.
Файл index.tpl.php
<?php
$this->setPageTitle('Заголовок страницы в названии окна браузера');
$this->addBreadcrumb('Название страницы в цепи хлебных крошек');
$this->addToolButton(array(
'class' => 'item',
'title' => 'Название кнопки в меню действий для перехода на внутреннюю страницу компонента',
'href' => $this->href_to('act')
));
?>
<h1>Главный заголовок страницы</h1>
<p>Содержание страницы</p>
Внутренняя страница компонента будет содержать форму выбора параметров.
Для начала создадим папку \forms\ в папке нашего компонента \SiteDirectory\system\controllers\newcomponent\.
В директории \SiteDirectory\system\controllers\newcomponent\forms\ создаем файл form_newForm.php
Форма будет очень простой, она предлагает пользователю выбрать два параметра из выпадающих списков.
Файл form_newForm.php
<?php
class formNewcomponentnewform extends cmsForm {
public function init() {
return array(
array(
'type' => 'fieldset',
'childs' => array (
new fieldList('par1', array(
'title' => 'Параметр1',
'items' => array (
"ТекстовыйИдентификатор1" => "ТекстовыйПараметр1",
"ТекстовыйИдентификатор2" => "ТекстовыйПараметр2"
)
)),
new fieldList('par2', array(
'title' => 'Параметр2',
'items' => array (
1 => "1",
2 => "2"
)
))
)
)
);
}
}
?>
После этого перейдем к созданию шаблона для внутренней страницы компонента /act — создаем файл act.tpl.php и размещаем его в директории \SiteDirectory\templates\default\controllers\newcomponent\.
Для создания уникального сервиса воспользуемся разработкой пользователя KoGor (пользуясь случаем, хочу передать огромную благодарность за проведенный KoGor 'ом труд и хорошо оформленную и интуитивно понятную статью) — инфограммой карты Российской Федерации с распределением по регионам.
В результате, у нас должна получится примерно такая приятная карта России:
Файл act.tpl.php
<?php
$this->setPageTitle('Заголовок страницы в названии окна браузера');
$this->addBreadcrumb('Название главной страницы компонента в цепи хлебных крошек', $this->href_to(''));
$this->addBreadcrumb('Название страницы в цепи хлебных крошек');
$arr_par1_id = array('ТекстовыйИдентификатор1' => 1 ,
'ТекстовыйИдентификатор2' => 2
);
$filename='/upload/zarplata-'.$arr_par1_id[$_GET['par1']].'-'.$_GET['par2'].'.csv';
if (!isset ($_GET['par1']) || !isset ($_GET['par2'])) $filename='/upload/zarplata-1-1.csv';
$this->renderForm($form, $newForm, array(
'action' => '',
'method' => 'get',
'toolbar' => false
), $errors);
?>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="http://d3js.org/queue.v1.min.js"></script>
<script type="text/javascript" src="http://d3js.org/topojson.v0.min.js"></script>
<!-- <script type="text/javascript" src="http://d3js.org/topojson.v1.min.js"></script> -->
<style>
path {
stroke:white;
stroke-width: 1px;
}
body {
font-family: Arial, sans-serif;
}
.city {
font: 10px sans-serif;
font-weight: bold;
}
.legend {
font-size: 12px;
}
div.tooltip {
position: absolute;
text-align: center;
width: 150px;
height: 25px;
padding: 2px;
font-size: 10px;
background: #FFFFE0;
border: 1px;
border-radius: 8px;
pointer-events: none;
}
</style>
<script type="text/javascript">
var width = 720,
height = 375;
// Setting color domains(intervals of values) for our map
var color_domain = [10000, 15000, 20000, 30000, 50000]
var ext_color_domain = [0, 10000, 15000, 20000, 30000, 50000]
var legend_labels = ["до 10000 руб.", "10000-15000 руб.", "15000-20000 руб.", "20000-30000 руб.", "30000-50000 руб.", "от 50000 руб."]
var color = d3.scale.threshold()
.domain(color_domain)
.range(["#ff1300", "#ff4e40", "#ff7d73", "#ffba00", "#ffcb40", "#adfcad"]);
var div = d3.select("form").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("form").append("svg")
.attr("width", width)
.attr("height", height)
.style("margin", "10px auto");
var projection = d3.geo.albers()
.rotate([-105, 0])
.center([-10, 65])
.parallels([52, 64])
.scale(500)
.translate([width / 2, height / 2]);
var path = d3.geo.path().projection(projection);
//Reading map file and data
queue()
.defer(d3.json, "/upload/russia.json")
.defer(d3.csv, "<?php echo $filename; ?>")
.await(ready);
//Start of Choropleth drawing
function ready(error, map, data) {
var rateById = {};
var nameById = {};
data.forEach(function(d) {
rateById[d.RegionCode] = +d.AverageZarplata;
nameById[d.RegionCode] = d.RegionName;
});
//Drawing Choropleth
svg.append("g")
.attr("class", "region")
.selectAll("path")
.data(topojson.object(map, map.objects.russia).geometries)
//.data(topojson.feature(map, map.objects.russia).features) <-- in case topojson.v1.js
.enter().append("path")
.attr("d", path)
.style("fill", function(d) {
return color(rateById[d.properties.region]);
})
.style("opacity", 0.8)
//Adding mouseevents
.on("mouseover", function(d) {
d3.select(this).transition().duration(300).style("opacity", 1);
div.transition().duration(300)
.style("opacity", 1)
div.text(nameById[d.properties.region] + " : " + rateById[d.properties.region])
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY -30) + "px");
})
.on("mouseout", function() {
d3.select(this)
.transition().duration(300)
.style("opacity", 0.8);
div.transition().duration(300)
.style("opacity", 0);
})
// Adding cities on the map
d3.tsv("/upload/cities.tsv", function(error, data) {
var city = svg.selectAll("g.city")
.data(data)
.enter()
.append("g")
.attr("class", "city")
.attr("transform", function(d) { return "translate(" + projection([d.lon, d.lat]) + ")"; });
city.append("circle")
.attr("r", 3)
.style("fill", "lime")
.style("opacity", 0.75);
city.append("text")
.attr("x", 5)
.text(function(d) { return d.City; });
});
}; // <-- End of Choropleth drawing
//Adding legend for our Choropleth
var legend = svg.selectAll("g.legend")
.data(ext_color_domain)
.enter().append("g")
.attr("class", "legend");
var ls_w = 20, ls_h = 20;
legend.append("rect")
.attr("x", 20)
.attr("y", function(d, i){ return height - (i*ls_h) - 2*ls_h;})
.attr("width", ls_w)
.attr("height", ls_h)
.style("fill", function(d, i) { return color(d); })
.style("opacity", 0.8);
legend.append("text")
.attr("x", 50)
.attr("y", function(d, i){ return height - (i*ls_h) - ls_h - 4;})
.text(function(d, i){ return legend_labels[i]; });
</script>
Для того, чтобы карта заработала, остался последний шаг. Размещаем файлы cities.tsv, russia.json, zarplata-1-1.csv, zarplata-1-2.csv, zarplata-2-1.csv, zarplata-2-2.csv (приведены в архиве, ссылка на который есть в конце статьи) в директории \SiteDirectory\upload\.
Заходим по адресу siteaddress.ru/newcomponent/act/ — здесь все регионы на карте России подкрашены темно-серым цветом и при наведении появляется название региона — NaN. Для отображения каких-нибудь реальных данных замените значения в последнем столбце .csv файлов на численные данные.
Подобный модуль разработан мною для сайта ЗарплатаБюджетников.РФ в разделе Карта зарплат. Демо модуля можно посмотреть по ссылке. (сейчас данных нет, модуль отключен, а чтобы собрать карту, нужны регистрации с указанием зарплат и регионов от пользователей)
Напоследок, небольшой хинт. В дефолтном шаблоне по умолчанию в InstantCMS 2 боковая колонка вместе с меню действий пропадает при уменьшении ширины окна браузера. Но на мобильных девайсах исчезновение боковой колонки и меню действий очень не удобно, т.к. у пользователей пропадает довольно таки много возможных действий. Для изменения этой ситуации можно проделать следующее. Найдите в директории \templates\default\css\ файл theme-layout.css, и замените в нем кусочек кода
/* Media Queries ============================================================ */
@Media screen and (max-width: 980px) {
#body section { width:100% !important; }
#body aside { display:none; }
}
@Media screen and (max-width: 800px) {
#body section { width:100% !important; }
#body aside { display:none; }
на
/* Media Queries ============================================================ */
@media screen and (max-width: 980px) {
#body section { width:100% !important; }
#body aside { width:100% !important; }
}
@media screen and (max-width: 800px) {
#body section { width:100% !important; }
#body aside { width:100% !important; }
Т.е. по факту необходимо исправить всего 2 строчки #body aside { display:none; } на #body aside { width:100% !important; } — после этого боковая колонка при уменьшении ширины браузера будет съезжать в основную колонку после находящегося в нем контента (перед футером).
Все описанные скрипты и файлы можно скачать в архиве, который нужно будет просто загрузить и распаковать в корневую директорию вашего сайта, работающего на InstantCMS2.
Здравствуйте Уважаемые Пикабушники! Прошу помочь. Есть простенький сайт на php (для универа). на локалке все работало. но по требованиям надо разместить на каком-нибудь хостинге и показать на защите. Хостинг зарегистрировал sprinthost.ru, сайт залил туда, базу создал пустую. при попытке подключения:
SQLSTATE[HY000] [1045] Access denied for user 'f1037213_main'@'vilir.from.sh' (using password: YES)
Помогите пожалуйста
в файле functions.php прописано:
function get_db()
{
try {
$host = 'mysql:host=' . DB_HOST . '; dbname=' . DB_NAME . '; charset=utf8';
$settings = [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
];
return new PDO($host, DB_LOGIN, DB_PASSWORD, $settings);
} catch (PDOException $ex) {
die($ex->getMessage());
}
}
он ссылается на config.php
<?php
const DB_HOST = 'заполнено';
const DB_NAME = 'f1037213_main';
const DB_LOGIN = 'f1037213_main';
const DB_PASSWORD = 'заполнено';
session_start();
Здравствуйте, пикабушники! Если среди Вас есть программисты, то хотел бы попросить совета. Хочу создать сайт для своей работы, где будут таблицы с данными, куда зарегистрированные аккаунты смогут вносить изменения. И такой, что я сам смогу вносить изменения, но у меня будет больше прав и возможностей. На каком языке лучше написать? Я посмотрел, что именно для работы с базой данных подходит phpmyadmin. Пробовал немного написать на html, css, js, но судя по постам в интернете и по личному опыту эта группа не сильно подойдет для базы данных, так сказать вызовет больше трудностей кажется.
Какими будут Ваши советы?
Привет коллеги, хочу вынести на ваш суд свой проект PHPize.online
Онлайн песочница для всех актуальных версий PHP и баз данных на одном экране.
Также есть возможность исправления ошибок при помощи ChatGPT бесплатно и без регистрации
Свое мнение пишите в комментариях
Смотрю тут не очень оживленная группа, тем не менее опубликую здесь свой проект.
https://PHPize.online песочница с последними версиями PHP и поддержкой PDO и MYSQLi для работы с SQL
В ClickHouse есть встроенная веб-консоль для работы с базой данных, позволяет лишь выполнять SQL-запросы, штука быстрая, удобная, просто открываешь в браузере сайт по адресу http://localhost:8123/ и можешь работать с базой данных.
Решил сделать аналогичную, для работы с другими базами данных, для реализации выбрал язык PHP, можно запустить где угодно, хоть на калькуляторе, даже если нет веб-сервера (php -S localhost:8089 pdoconsole.php). Можно закинуть скрипт на любой хостинг, где есть поддержка PHP, и работать на удалённом сервере. Получилась эдакий простой phpmyadmin, или pgadmin, для тех, кто предпочитает работать с базами данных через SQL. Поддерживаются все базы данных, что работают через библиотеку PDO.
Всё находится в одном файле pdoconsole.php, браузер загружает страницу одним HTTP-запросом, в дальнейшем SQL-запросы отправляются через AJAX (библиотека htmx.js), результат выводится в таблицу, в которой можно разворачивать столбцы одной строки, и смотреть их в виде строк. Оформление сделано на bootstrap5, поддерживается тёмная тема, можно работать даже со смартфона, вёрстка адаптивная.
В начале файла pdoconsole.php можно заменить ключ шифрования на случайную длинную фразу, ей шифруются данные подключения к базе данных, которые хранятся в cookie долгое время. История запросов хранится в sessionStorage браузера, стирается после закрытия вкладки. Можно работать одновременно с разными базами данных через параметр ?prefix=dbname
Исходный код и полное описание: https://github.com/ibnteo/pdoconsole