Это копия, сохраненная 4 марта 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (необязательно).
Предыдущий тред был тут: >>425537
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП отвечает даже на самые нубские вопросы. ОП заходит где-то раз в день, не жди его, решай задачки дальше.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Учебник дает основы языка PHP, но чтобы делать сайты, этого недостаточно. Если ты его прошел, то надо переходить в более серьезным задачкам, которые научат тебя как выдавать страницы в браузер, работе с таблицами в БД, работе с формами, MVC.
- Простая, но полезная задача сделать список студентов: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Yii2: https://gist.github.com/codedokode/8733007
- Если ты все их решил, переходи к Symfony 2/Doctrine 2
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP на сервере для отдачи странички в браузер: https://php.net/manual/ru/tutorial.php Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что, задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://gist.github.com/codedokode/10539213
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.github.io/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git:
Нужен ли ООП, фреймворки, MVC? — Да, однозначно. Посмотри любую вакансию.
Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.net/45000175
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
Где искать работу и заказы — hh.ru, geekjob.ru, brainstorage.me, fl.ru, odesk.com. Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода.
Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492
Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- Название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек
- мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
PSR-1: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-2-coding-style-guide.md
> https://github.com/MindiMakridi/Students Исправил вроде, кроме переменных.
https://github.com/tokotun/matriculant
Немного переделал. В общих чертах протестировал, хотя с моей-то внимательностью могу много чего упустить из виду. С автоматическими тестами, что ли начать разбираться
Завтра буду делать доступ к полям класса private/protected. И прописывать к ним методы.
Наполнить надо фронтенд, но все данные приходили через ajax. В пхп у меня собственно и были все обращения к базе и получение всей нужной информации, после чего передавал json на фронт.
Ну и почему бы не захардкодить? Сделай скрипт заглушку один раз для таких случаев. Ну или посмотри в сторону firebase
Зачем смотреть в строну firebase если можно использовать ту же БД что использовалась ранее и залить в нее небольшой тестовый дамп.
>5 значений ширины у одной картинки? и все публичные? Я не понимаю, что это вообще значит.
$width - исходная ширина
$maxWidth - максимальная ширина, заданная пользователем
$newWidth - Новая ширина, вычисляемая для "вырезания" изображения из оригинала и вставки его в новое изображение
$cropX - Количество пикселей которые надо обрезать
$newWidth_p - Новая ширина, для нового изображения, в которое будет вставлен обрезанный оригинал.
>Метод createThumbnailеще хуже. Чтобы он работал корректно, надо сначала задать значения полей $this->newWidth_p, $this->newHeight_p, $this->x, $this->y, $this->cropX, $this->cropY, $this->newWidth, $this->newHeight но как программист об этом догадается? Это не метод, а мина замедленного действия которая рано или поздно сломает код.
>Надо сначала задать значения полей
Они задаются сначала, функцией calculateImage.
>но как программист об этом догадается?
А как я догадаюсь, о чем догадается программист?
>Чтобы гарантировать что эти свойства будут заданы, ты должен выставлять их в конструкторе (так как он гарантированно вызывается при создани и объекта), и может быть сделать все их непубличными, чтобы их нельзя было стереть снаружи. Тогда код будет надежным.
Я сейчас еще больше запутался... Эти свойства вычисляются методом, зачем кому-то принудительно вызывать метод создания превью без метода вычисления его свойств? Хорошо, допустим кому-то взбредет это в голову. Тогда мне нужно будет в этом методе сделать проверку на эти свойства или же в конструкторе вызвать метод вычисления свойств превью, а уже в нем делать проверку на свойства.
=========================================
В целом, я, кажется, начинаю понимать, что код должен быть понятным для другого программиста. Т.е. задавать названия переменных и функций чтобы из названия было понятно зачем они нужны. Но непонятно такой момент:
>Это не метод, а мина замедленного действия которая рано или поздно сломает код.
Как она сломает код рано или поздно? Что от количества генераций превью будет метятся код?
Код сломать может только программист, и вот собственно вопрос - Как я узнаю каким образом он будет ломать код?
Может есть какие-то стандарты в написании кода? От чего можно оттолкнутся.
Мне всегда казалось что код должен быть максимально простым, т.е. решение должно быть очевидным и максимально коротким, а так же, безопасным (чтобы пользователь не смог сломать все или воспользоваться как-нибудь багами системы).
Я признаю что мой код никуда не годиться, но я писал его с кашей в голове, и даже не знаю как эту кашу переворить. Даже не знаю от чего отталкиваться теперь и к чем придти.
Как в общем узнать к чему стремиться?
>5 значений ширины у одной картинки? и все публичные? Я не понимаю, что это вообще значит.
$width - исходная ширина
$maxWidth - максимальная ширина, заданная пользователем
$newWidth - Новая ширина, вычисляемая для "вырезания" изображения из оригинала и вставки его в новое изображение
$cropX - Количество пикселей которые надо обрезать
$newWidth_p - Новая ширина, для нового изображения, в которое будет вставлен обрезанный оригинал.
>Метод createThumbnailеще хуже. Чтобы он работал корректно, надо сначала задать значения полей $this->newWidth_p, $this->newHeight_p, $this->x, $this->y, $this->cropX, $this->cropY, $this->newWidth, $this->newHeight но как программист об этом догадается? Это не метод, а мина замедленного действия которая рано или поздно сломает код.
>Надо сначала задать значения полей
Они задаются сначала, функцией calculateImage.
>но как программист об этом догадается?
А как я догадаюсь, о чем догадается программист?
>Чтобы гарантировать что эти свойства будут заданы, ты должен выставлять их в конструкторе (так как он гарантированно вызывается при создани и объекта), и может быть сделать все их непубличными, чтобы их нельзя было стереть снаружи. Тогда код будет надежным.
Я сейчас еще больше запутался... Эти свойства вычисляются методом, зачем кому-то принудительно вызывать метод создания превью без метода вычисления его свойств? Хорошо, допустим кому-то взбредет это в голову. Тогда мне нужно будет в этом методе сделать проверку на эти свойства или же в конструкторе вызвать метод вычисления свойств превью, а уже в нем делать проверку на свойства.
=========================================
В целом, я, кажется, начинаю понимать, что код должен быть понятным для другого программиста. Т.е. задавать названия переменных и функций чтобы из названия было понятно зачем они нужны. Но непонятно такой момент:
>Это не метод, а мина замедленного действия которая рано или поздно сломает код.
Как она сломает код рано или поздно? Что от количества генераций превью будет метятся код?
Код сломать может только программист, и вот собственно вопрос - Как я узнаю каким образом он будет ломать код?
Может есть какие-то стандарты в написании кода? От чего можно оттолкнутся.
Мне всегда казалось что код должен быть максимально простым, т.е. решение должно быть очевидным и максимально коротким, а так же, безопасным (чтобы пользователь не смог сломать все или воспользоваться как-нибудь багами системы).
Я признаю что мой код никуда не годиться, но я писал его с кашей в голове, и даже не знаю как эту кашу переворить. Даже не знаю от чего отталкиваться теперь и к чем придти.
Как в общем узнать к чему стремиться?
Оп подскажет как лучше подключать скрипты?
как быстрее?
так: <script src="http://code.jquery.com/jquery-1.9.0.js"></script>
или так: <script type="text/javascript" src="js/jquery.simplemodal.js"></script>
Я не оп, конечно, но первый вариант может подвести тебя. Был недавно случай, я на хабре видел, как кто-то хакнул этот самый jquery cdn и что-то подсовывал вместо кошерного jquery (или просто что-то дописал в код библиотеки, типа тут был васян). Иногда эти сервера просто недоступны (хотя может это просто слухи). Один фиг, я считаю лучше сжать, прогнать через минифаер и сервить самому. Инетерсно послушать другие мнения.
Ну тестовый дамп наверно не подойдет, т.к название полей, таблиц и т.д нельзя показывать. Нужно что-нибудь типа локальных файлов с данными.
Лучше это относительное понятие. Если ты делаешь коммерческий продукт и твой хостинг-провайдер может обеспечить аптайм больше/выше чем CDN, грузи к нему. Если нет, используй CDN. Что касается скорости, могу предположить что это вопрос географического расположения серверов и настроек сети. Но с трудом могу представить при каких нагрузках это может оказать заметное влияние. В целом я бы рекомендовал грузить все себе, просто потому что например можно по ходу дела ознакомится с бовером ну и даже поглядеть исходники тех бибилиотек что используешь, это всегда полезно.
Забыл подписаться, не ОП
Стремись к этому. http://learn.javascript.ru/write-unmain-code
Неплохая статья даёт общее понимание о том как писать код.
Со своего сервера. Удаленный сервер может:
- быть на техобслуживании
- лечь из-за нагрузки
- лечь из-за ошибок
- быть заблокирован государством
То есть при использовании чужого сервера ты повышаешь шансы что скрипт будет не доступен. Более того, так как это JS и он блокирует загузку страницы то пользователи будут видеть белвый экран и крутящийся круг и только через пару минут (если пользователь не закроет окно) браузер перестанет ждать и продолжит загрузку.
Много лет назад я тоже подключал скрипты , по моему jQuery, с западных CDN. CDN умудрился лечь ровно в тот момент, когда директор компании-заказчика решил посмотреть сайт.
Если кратко: подключать скрипты с чужих CDN профита нет, риски даунтайма есть.
Более того, обычно современный сайт весит полмегабайта-мегабайт и я не вижу вообще выгоды от переноса одного 30-килобайтового скрипта на CDN. А зачем тогда в твиттере и западных блогах и учебниках пиарят такой способ? Не знаю, может компании-владельцы CDN хотят собирать статистику кто на какие сайты заходит?
> Если ты делаешь коммерческий продукт и твой хостинг-провайдер может обеспечить аптайм больше/выше чем CDN, грузи к нему. Если нет, используй CDN.
Ты не прав. Добавление второй точки отказа (сторонний сервер) только понижает надежность. Насчет того что аптайм у CDN выше — если твой сервер лег, пользователь все равно ничего не увидит и работает в этот момент CDN или нет, не важно.
Считается что главная выгода использвоания CDN в том, что у них есть быстрые сервера во многих точках мира, которые будут ближе к пользователю, и более дешевый трафик (собственно цена трафика как раз и является важным поводом заморачиваться с CDN). Но во-первых, у CDN может не быть точки присутствия в России, во-вторых, западные сервера могут опасть под блокировки, в-третьих, если это бесплатный CDN, то там нет никаких гарантий и компенсаций за даунтайм.
CDN имеет смысл исплоьзовать например если ты выносишь всю статику (скрипты/стили/картинки) на CDN и у тебя пользователи из разных стран мира, и трафик в CDN стоит дешевле чем на хостинге. То есть это актуально для крупных сайтов, использующих свой или платный CDN.
А выносить один-единственный скрипт вообще смысла никакого нет.
Сделай JSON файлы и отдавай их. Алсо, если есть описание АПИ и возвращаемых результатов в машинночитаемом виде, данные можно генерировать программно.
Но вообще задача надуманная. быстрее и проще дать тестовый дамп, а все что ты написал только замедляет разработку. Я надеюсь, всю эту возню хотя бы оплачивают.
Сделай задачу про регистрацию абитуриентов тогда на Юи. Без генераторов, пиши руками. Также, по максимуму используй стандартные компоненты Юи и по минимумму пиши свой код.
Например, для отображения таблиц с сортировкой в Юи есть готовый компонент — грид. Надо использовать именно его, а не писать свой велосипед. Аналогично, там есть средства для вывода и обработки форм.
>> но как программист об этом догадается?
> А как я догадаюсь, о чем догадается программист?
Надо писать как можно более очевидный код. В идеале так, что неправильно вызвать его вообще невозможно. Давай я попробую дать несколько примеров:
Хорошая функция получает аргументы, что-то с ними делает и возвращает результат. Ее название понятно и объясняет что она делает:
$result = goodFunction($a, $b, $c);
$rubles = convertDollarsToRoubles($dollars, $rate);
За счет использования тайп-хинтов и проверки аргументов хорошую функцию нельзя вызвать с неправильными аргументами, например передать в нее число если требуется массив.
Чтобы пользовать хорошей функцией, нет необходимости смотреть ее код - все и так очевидно. Потому писать и поддерживать код с использованием таких функций легко и быстро.
Плохая функция ведет себя по-разному в зависимости от того, была вызвана ли до нее другая функция, от глобальных переменных, и без полного разбора исходного кода не догадаешься как ее вызвать, чтобы получить нужный результат. Тип ее аргументов не определен, в нее можно передавать и массивы, и строки, и числа, но сработает ли она в этом случае правильно, понять трудно. Даже если ты передаешь неправильные аругменты, никаких сообщений об ошибке не выведется (ха-ха-ха, попробуй догадайся почему результат неправильный).
// сначала мы должны вызвать prepare и установить курс иначе функция ниже не заработает:
prepareConverting($rate);
// Также мы должны выставить глобальные переменные, которые задают валюту перевода
$convertFrom = 'USD';
$convertTo = 'RUR';
// Сумма в долларах должна быть помещена в POST:
$_POST['sum']['dollars'] = 100500;
// Функция выведет результат на экран, а не вернет в переменную потому сделать мы с ним ничего не можем
convertToRubles( );
Теперь перейдем к объектам. Хороший объект получает все нужные ему зависимости через конструктор. В нем мало публичных методов, а публичных полей обычно нет вообще. Все методы в нем являются «хорошими функциями» из примера выше.
Один хороший класс занимается только одной задачей, другие задачи он поручает другим классам. В полях он хранит только свои свойства, которые требуют постоянного хранения. Обычно объект представляет собой модель какой-то вещи из реального мира, а поля хранят свойства этой вещи. Ну например, у объекта «Автомобиль» в гоночной игре могут быть свойства «текущая скорость», «координаты».
Хороший ООП код предпочитает ислоьзовать объекты вместо сложных массивов.
Вот пример хорошего объекта, который позволяет сохранять посты в блоге в базе данных:
class PostMapper {
public function __construct(PDO $pdo) { ... }
public function save(Post $post) { .... }
public function validate(Post $post) { ... }
.... непубличные методы не показаны ...
}
// Так как для работы объекта нужен PDO, то мы передаем его при создании
$postMapper= new PostMapper($pdo);
// Создаем объект-пост
$post = new Post( );
$post->setTitle('Один день Ивана Ивановича');
$post->setText(...);
// сохраняем в базу
$postMapper->save($post);
Класс написан так, что неправильно использовать его не получится.
Плохой класс — это класс, который написан по противоположному подходу. Он может использовать исключительно статические методы, все методы и поля публичны, чтобы какая-то функция сработала, надо заранее вывать несколько других функций и проставить значения полей. Плохой класс содержит одновременно и код работы с базой данных, и код вставки смайликов в текст, и код вывода списка пользователей в формате HTML.
Вот пример плохого класса:
// Сначала надо вызвать Connect иначе он не сможет соединиться с БД
PostMapper::$pdo = $pdo;
PostMapper::connect( );
// Затем надо создать массив с информацией о посте
$postArray = array(
'title' => 'Один день Ивана Ивановича',
'text' => '....',
'author' => 'Anonymous'
);
// Массив надо обработать иначе пост вставится, но без текста
DataProcessor::processDataArray($postArray);
// Дата добавления передается в MySQL-формате
$_POST['added'] = '2015-01-01 12:00:00';
// Не забыть выставить имя таблицы, а то вставится комментарий вместо поста!
PostMapper::$tableName = 'posts_table';
// Подготавливаем SQL-запрос - не забыть что тут нестатический метод
$postMapper= new PostMapper( );
$postMapper->prepareQuery( );
// делаем вставку в базу данных c помощью отдельного класса (каждый должен заниматься своим делом!)
SomeOtherClass::insertIntoDatabase( );
Вот как-то так. Надеюсь, что примеры дадут хотя бы немного понимания, как надо и как не надо писать. Если что-то тут непонятно или кажется неправильным, так и пиши.
>> но как программист об этом догадается?
> А как я догадаюсь, о чем догадается программист?
Надо писать как можно более очевидный код. В идеале так, что неправильно вызвать его вообще невозможно. Давай я попробую дать несколько примеров:
Хорошая функция получает аргументы, что-то с ними делает и возвращает результат. Ее название понятно и объясняет что она делает:
$result = goodFunction($a, $b, $c);
$rubles = convertDollarsToRoubles($dollars, $rate);
За счет использования тайп-хинтов и проверки аргументов хорошую функцию нельзя вызвать с неправильными аргументами, например передать в нее число если требуется массив.
Чтобы пользовать хорошей функцией, нет необходимости смотреть ее код - все и так очевидно. Потому писать и поддерживать код с использованием таких функций легко и быстро.
Плохая функция ведет себя по-разному в зависимости от того, была вызвана ли до нее другая функция, от глобальных переменных, и без полного разбора исходного кода не догадаешься как ее вызвать, чтобы получить нужный результат. Тип ее аргументов не определен, в нее можно передавать и массивы, и строки, и числа, но сработает ли она в этом случае правильно, понять трудно. Даже если ты передаешь неправильные аругменты, никаких сообщений об ошибке не выведется (ха-ха-ха, попробуй догадайся почему результат неправильный).
// сначала мы должны вызвать prepare и установить курс иначе функция ниже не заработает:
prepareConverting($rate);
// Также мы должны выставить глобальные переменные, которые задают валюту перевода
$convertFrom = 'USD';
$convertTo = 'RUR';
// Сумма в долларах должна быть помещена в POST:
$_POST['sum']['dollars'] = 100500;
// Функция выведет результат на экран, а не вернет в переменную потому сделать мы с ним ничего не можем
convertToRubles( );
Теперь перейдем к объектам. Хороший объект получает все нужные ему зависимости через конструктор. В нем мало публичных методов, а публичных полей обычно нет вообще. Все методы в нем являются «хорошими функциями» из примера выше.
Один хороший класс занимается только одной задачей, другие задачи он поручает другим классам. В полях он хранит только свои свойства, которые требуют постоянного хранения. Обычно объект представляет собой модель какой-то вещи из реального мира, а поля хранят свойства этой вещи. Ну например, у объекта «Автомобиль» в гоночной игре могут быть свойства «текущая скорость», «координаты».
Хороший ООП код предпочитает ислоьзовать объекты вместо сложных массивов.
Вот пример хорошего объекта, который позволяет сохранять посты в блоге в базе данных:
class PostMapper {
public function __construct(PDO $pdo) { ... }
public function save(Post $post) { .... }
public function validate(Post $post) { ... }
.... непубличные методы не показаны ...
}
// Так как для работы объекта нужен PDO, то мы передаем его при создании
$postMapper= new PostMapper($pdo);
// Создаем объект-пост
$post = new Post( );
$post->setTitle('Один день Ивана Ивановича');
$post->setText(...);
// сохраняем в базу
$postMapper->save($post);
Класс написан так, что неправильно использовать его не получится.
Плохой класс — это класс, который написан по противоположному подходу. Он может использовать исключительно статические методы, все методы и поля публичны, чтобы какая-то функция сработала, надо заранее вывать несколько других функций и проставить значения полей. Плохой класс содержит одновременно и код работы с базой данных, и код вставки смайликов в текст, и код вывода списка пользователей в формате HTML.
Вот пример плохого класса:
// Сначала надо вызвать Connect иначе он не сможет соединиться с БД
PostMapper::$pdo = $pdo;
PostMapper::connect( );
// Затем надо создать массив с информацией о посте
$postArray = array(
'title' => 'Один день Ивана Ивановича',
'text' => '....',
'author' => 'Anonymous'
);
// Массив надо обработать иначе пост вставится, но без текста
DataProcessor::processDataArray($postArray);
// Дата добавления передается в MySQL-формате
$_POST['added'] = '2015-01-01 12:00:00';
// Не забыть выставить имя таблицы, а то вставится комментарий вместо поста!
PostMapper::$tableName = 'posts_table';
// Подготавливаем SQL-запрос - не забыть что тут нестатический метод
$postMapper= new PostMapper( );
$postMapper->prepareQuery( );
// делаем вставку в базу данных c помощью отдельного класса (каждый должен заниматься своим делом!)
SomeOtherClass::insertIntoDatabase( );
Вот как-то так. Надеюсь, что примеры дадут хотя бы немного понимания, как надо и как не надо писать. Если что-то тут непонятно или кажется неправильным, так и пиши.
В твоем случае надо:
- закрыть все публичные свойства в классе Thumbnail и удалить лишние
- закрыть все методы которые не требуется вызывать снаружи
- сделать так, чтобы любой публичный метод можно было вызвать в любой момент. То есть мы можем сразу вызывать createThumbnail не вызывая перед этим никаких calculateImage, и все будет работать.
- перенести аргументы из конструктора в createThumbnail
Вот такого: «ты должен сначала вызвать метод A перед тем как вызывать метод B» — быть не должно в принципе. Ибо когда у тебя в программе 1000 классов и 10 000 методов, как ты будешь запоминать что надо перед чем вызывать?
Но можно сделать по-другому: методу B нужен объект который возвращает только метод A. Тогда ты будешь вынужден сначала вызвать A чтобы получить этот объект (либо создать объект вручную). Так делать можно, так как это очевидно.
Также, класс надо переименовать. Твой класс — это не Thumbnail (класс хранящий информацию об одной превьюшке), а ThumbnailCreator (класс создающий превьюшки в любых количествах). Неправильное название тоже затрудняет понимание кода.
> зачем кому-то принудительно вызывать метод создания превью без метода вычисления его свойств? Хорошо, допустим кому-то взбредет это в голову.
Я хочу создать превьюшку. Я вижу метод createThumbnail который это делает (это понятно из его названия). Ага, он-то мне и нужен! Чтобы его вызвать, мне достаточно создать объект и вызвать метод:
$t = new Thumbnail(...);
$t->createThumbnail(...);
Зачем мне вызвать другие методы (писать лишний код) если можно написать в 2 строчки?
Зачем мне вызывать calculateImae если я не хочу ничего рассчитывать, а хочу просто создать превьюшку?
Если вызов calculateImage необходим для createThumbnail, пусть они сами друг друга там вызывают. Зачем эту работу перекладывать на меня? Я хочу просто написать 2 строчки и чтобы все работало само.
> Тогда мне нужно будет в этом методе сделать проверку на эти свойства или же в конструкторе вызвать метод вычисления свойств превью, а уже в нем делать проверку на свойства.
Если без этого никак то да, придется сделать так. зато я смогу создавать превьюшки твоим классом написав всего 2 строчки.
> код должен быть понятным
В идеале он должен быть написан так, что неправильно использовать его не получится. Пример из жизни: разъемы. Ты не можешь воткнуть вилку зарядного устройства в гнездо от наушников потому что они разной формы и размера. Твой код должен быть таким же.
А твой код как раз неочевиден: догадаться что надо сначала вызвать calculateIamge без полного разбора кода невозможно.
> Как она сломает код рано или поздно? Что от количества генераций превью будет метятся код?
Другой программист или ты сам позже в другом месте захочет использовать класс Thumbnail и потратит кучу времени на выяснение почему он не работает. Кучу времени так как код неочевиден и надо его разбирать и смотреть как он работает вместо того чтобы просто прочесть название функции и все понять сразу.
> Мне всегда казалось что код должен быть максимально простым, т.е. решение должно быть очевидным и максимально коротким, а так же, безопасным (чтобы пользователь не смог сломать все или воспользоваться как-нибудь багами системы).
Правильно.
> Я признаю что мой код никуда не годиться, но я писал его с кашей в голове, и даже не знаю как эту кашу переворить. Даже не знаю от чего отталкиваться теперь и к чем придти.
Пробуй писать дальше, показывай код, задавай вопросы. Это тред для начинающих, цель которого как раз научить делать правильно.
Давай для начала попробуем хотя бы правильно написать класс генерации превьюшки или какой-то другой класс.
Там все либо на фреймворках, либо вообще на кмс (за каким хером вы ищите програмиста и юзаете кмс?). А мелкие задания если и попадаются, их выставляют только для бизнес аккаунтов (нахуя?)
Вам тут оп распинается про DI и классы-заглушки, а вы не читаете что ли?
Потому что сайты пишут на фреймворках и CMS. B соответственно без их знания или желания разобраться 95% заказов тебе недоступны. На «чистом» PHP решают только разве что задачки про считалку из моего учебника, а сайты делают на HTML/CSS/JS и готовых библиотеках.
Но все равно, найти можно. По моему ты просто ленишься. Вот что я нашел без CMS и фреймворков.
> Написать простой скрипт , записи значения в базу и отправки на емейл. PHP + MYSQL
> Необходимо написать 100 текстов объявлений о продаже элитных квартир, каждое длиной в 500-600 знаков (с пробелами).
> Требуется удаленный контент-менеджер для занесения товаров на сайт интернет-магазина.
> Нужен Java (ох лол)-программист, несложный скрипт или jQuery. Должны поочередно подсвечиваться иконки,....
> Итак, есть одностраничный сайт – нужно сделать копию его функционала 1:1. Дизайн можно взять с сайта донора. Уверен что спецу работа на 1 день (ох лол)
> прикрутить плагин загрузки файлов jQuery File Upload на сайт
> Нужно доделать анкету на сайте new.fastmoney.ru new.fastmoney.ru/anketa/s... – при выборе "Адрес проживания совпадает с адресом регистрации?...
> Провести адаптивную модернизацию сайта rybhoz-civilsk.ru/
> Написать на php простой (ох лол) биллинг. Необходимо регистрация, регистрация через соцсети, прием оплат через робокассу и история оплат.
> Вывод папок и файлов на странице с помощью PHP
> подредактировать php скрипт – задача на 5-10 минут.
> Нужно создать или реализовать на готовом скрипте сервис сокращения ссылок
> Создать шапку для сайта
> Необходимо написать скрипт на PHP для работы с изображениями (картинками
Это то что я на первых 3 страницах нашел. Если ты это сам не смог найти то сначала тебе надо изучить работу функции поиска на фриланс-сайтах. Потмоу что с таким подходом ты далеко не уйдешь.
Хотя если кто-то из анонов хочет, пусть скидывает примеры заданий. Почему бы и нет. Но они вряд ли будут отличаться от того что написано выше.
Не знаю. А что это меняет? Тебе сложно найти подходящие задачи из-за низкого уровня знаний в первую очередь, так как таких, как ты, там сто тысяч человек, и все они конкурируют за эти несколько заданий.
Понял все лолы кроме биллинга. Это типа не такая уж простая задач, требующая в том числе согласования с конторой, предоставляющей такие услуги?
Переводить текст ошибки не пробовал?
https://github.com/someApprentice/ThumbnailService
Решил перенести некоторые методы из Upload в новый класс Functions (не знаю как правильно назвать чтобы понятно было, но там будут писаться полезные функции такие как например, генерация хэша изображения или создание директории). Все методы вызываются статически т.к, мне показалось что $functions = new Functions; как-то не совсем понятно. В общем хотелось бы услышать твои замечания по этому поводу.
Про остальные замечания, которые ты писал выше, я не забыл, и сделаю их, как разберусь с архитектурой, и вообще с моим пониманием ООП надо что-то делать.
> новый класс Functions (не знаю как правильно назвать чтобы понятно было, но там будут писаться полезные функции такие как например, генерация хэша изображения или создание директории)
Мелкие, не относящиеся к чему-то конкетному методы обычно собирают в класс Util или Utility со всеми статическими методами.
http://en.wikipedia.org/wiki/Utility_pattern
Но я конечно еще посмотрю, может ты там половину кода в util засунул.
> моим пониманием ООП надо что-то делать.
задачки решать наверно?
ImageManager лучше сделать на нестатических методах. static методы используют только в редких случаях вроде паттерна Utility или методов которым не нужен экземляр объекта.
Непонятно зачем нужен вообще класс Upload? Что он делает? Не проще ли метод uploadFile тогда перенести в ImaeManager? Или наоборот, всю работу с файлами и папками перенести в Upload?
Сейчас у тебя работа с файлами и папками для загуженных файлов (создание папок, определение пути к файлу, проверка типа файла, сохранение файла) фактически размазана по 3 классам: Upload, Functions, ImageManager. Надо собрать все в одном месте.
> $connect = Connect::getPdo( );
Это надо убрать и передавать PDO через конструктор.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L88
> return $insert;
зачем возвращать объект PDO Statement? Что с ним можно потом сделать?
> public static function uploadFile($name, $temp, $extension) {
Непонятно зачем передавать отдельным параметром extension. Мы же всегда его можем получить из name?
> "uploads/" . $directory . '/' . $name
Этот кусок скопипащен раз 5. Сделай лучше метод типа getImagePath() который возвращает полный путь к файлу.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Functions.php#L28
> public static function getExtension($name) {
Из названия следует что метод определяет расширение файла а на самом деле он его еще и проверяет по списку. Я думаю, проверку надо оттуда убрать так как в названии про нее ничего не сказано.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/ImageManager.php#L30
> unlink("uploads/" . $name);
ты сохраняешь файл в "uploads/" . $directory . '/' . $name а удаляешь из другого места. Не надо копиастить код, надо хранить путь в переменной.
ImageManager лучше сделать на нестатических методах. static методы используют только в редких случаях вроде паттерна Utility или методов которым не нужен экземляр объекта.
Непонятно зачем нужен вообще класс Upload? Что он делает? Не проще ли метод uploadFile тогда перенести в ImaeManager? Или наоборот, всю работу с файлами и папками перенести в Upload?
Сейчас у тебя работа с файлами и папками для загуженных файлов (создание папок, определение пути к файлу, проверка типа файла, сохранение файла) фактически размазана по 3 классам: Upload, Functions, ImageManager. Надо собрать все в одном месте.
> $connect = Connect::getPdo( );
Это надо убрать и передавать PDO через конструктор.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L88
> return $insert;
зачем возвращать объект PDO Statement? Что с ним можно потом сделать?
> public static function uploadFile($name, $temp, $extension) {
Непонятно зачем передавать отдельным параметром extension. Мы же всегда его можем получить из name?
> "uploads/" . $directory . '/' . $name
Этот кусок скопипащен раз 5. Сделай лучше метод типа getImagePath() который возвращает полный путь к файлу.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Functions.php#L28
> public static function getExtension($name) {
Из названия следует что метод определяет расширение файла а на самом деле он его еще и проверяет по списку. Я думаю, проверку надо оттуда убрать так как в названии про нее ничего не сказано.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/ImageManager.php#L30
> unlink("uploads/" . $name);
ты сохраняешь файл в "uploads/" . $directory . '/' . $name а удаляешь из другого места. Не надо копиастить код, надо хранить путь в переменной.
>
> <?php
> require_once 'autoload.php'
> ?>
Это должно быть только в файлах типа index.php а не скопипащено в каждыйы файл с классом.
> https://github.com/someApprentice/ThumbnailService/blob/master/upload.php#L38
> if (($thumbnailWidth != '' xor $thumbnailHeight != '') or ($thumbnailWidth != '' and $thumbnailHeight != '')) {
Не используй xor в лонгических условиях (слишком сложно) и упрости этот код. Что ты хотел сказать? Если хотя бы один параметр указан? Тогда тебе хватит OR.
Покажи код. Для начала можешь сделать упрощенную версию: номер телефона всегда начинается только с цифры 8 после которой идет 9 любых цифр без минусов, скобок , и т.д.
position: absolute;
left: 17px;
width: 32.5%;
При изменении ширины окна изменяется высота этих слайдшоу(так они помещаются на странице в любом случае). Как в условии плавающей высоты отцентрировать их по вертикали?
Нет, не оплачивают. Просто на предыдущей работе я занимался проектом, и хотел в портфолио его выложить как следует, с полным кодом фронтенда. Кода там довольно много, как раз хороший пример, что работал над не совсем маленьким проектом. Ну и без данных там весь функционал пропадает, довольно плохо получится.
Да сделать просто json файлы кажется адекватной идеей, скорее всего так и поступлю.
Тогда сделай чуть сложнее: между цифрами может быть любое число скобок, дефисов, пробелов. Это подойдет для задачи.
По моему я переборщил, да?
'/^8([(- ][0-9]{3}[(- ][0-9]{3}[(- ][0-9]{2}[(- ][0-9]{2}[(- ]*)$/'
У тебя же ошибка: PHP Warning: preg_match(): Compilation failed: range out of order in character class at offset 6 in /home/kpQzwB/prog.php on line 8
Минус это спецсимвол внутри квадратных скобок и надо его экранировать.
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный.
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 2 списка номеров (правильные и нет), добавь их в программу и напиши цикл, который их по очереди прогоняет через регулярку и проверяет что они определяются как надо (если нет — надо вывести какой именно номер не распознается правильно).
Вот список номеров:
Правильные: array('84951234567', '+74951234567', '8-495-1-234-567', ' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67', '8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567', '8 ( 999 ) 1234567', '8 999 123 4567');
Неправильные: array('02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', // неверный код страны
'+8 234 5678901', // либо 8 либо +7
'7 234 5678901' // нет +
);
Скачай себе какой-нибудь микрофреймворк. Slim, для примера. И разбирайся уже на нем.
Лепил дерьмо на пхп с 14 лет, в общем нужно восстановить свои навыки. Синтаксис и прочее я знаю, имею ввиду наработать практические навыки.
В оп-пост гляди. Открываешь учебник ОПа и смотришь какие задачи можешь выполнить, а в каких не уверен.
Не глянешь вот это?:
https://github.com/d-beekeeper/ratchat
Если не лень, просмотри пожалуйста. Сделай, так сказать, ревизию кода.
Там в Readme описание, что это такое и как работает.
Единственное, где я сознательно вставил свой костыль - это авторизация через API вконтакта. Просто чтобы самому получше разобраться с oAuth
Кстати если подскажешь какую нибудь готовую oAuth библиотеку для Silex-Symphony (или вообще универсальную) для однообразной авторизации юзера через кучу разных соцсетей - буду очень благодарен.
Заранее спасибо.
http://ideone.com/mWiW77
Выдает кучу ошибок которые тем не менее не мешают отобразить в конце верный результат. Ошибки на сколько я понял связаны с тем что не во всех циклах $newPath['time'] существует, но как пофиксить не понял.
в гугле советуют делать так
<a href="file:///C:/Windows">Открыть диск C:/Windows</a>
а у меня такое не работает.
input type="text". грубо говоря можно в форме отправляя запрос на скрипт. но тебе врядли. тебе лучше по аяксу на событие какое-то, типа изменения, сам решишь, точно так же будет ебать скриптик и сохранять. ну и еще вариант на каком-нибудь ангуларе, все свое на фронтенде сразу, если не ошибаюсь.
Я тупой. Как в регулярное выражение, скажем, '/^\\+?8?7?[0-9]{10}$/' добавить проверку знаков в это [0-9]?
Регулярки такого не поддерживают, тебе нужно вызывать хаскель, и уже там функцию определять.
Прочитай пикрелейтед. Тебе нужны фундаментальные знания, а не жалкие всхлипы анонов про регекспы. И вообще каких знаков проверка-то? Есть дорожные знаки, а есть унарные отображения из множества R в R, типа + и -.
Помогает, было доказано учёными из Кэмбриджа. Только без фанатизма - самую писечку записывай, а потом повторяй время от времени. Сам факт записывания даёт больше всего профита. Ещё помогают mind maps, их лучше от руки рисовать, а потом можно в программу типа freemind перенести. Можешь личную вики запилить (я gollum использую, мне норм), тоже полезно пополнять. Лично я уже привык всё это использовать - без этого как-то не идёт обучение. Я ещё исходный код и API распечатываю на принтере и обклеиваю всю квартиру. Потом когда иду делать кофе, могу прочитать про какую-нибудь стандартную либу на стене, или паттерны там. Даже на потолок клею, лол. Ещё использую Anki для переодической ревизии своих знаний и сам с собой на английском говорю. Иногда по скайпу общаюсь ну ты понел. Про жизнь вообще забудь.
с одной версией один работает, второй нет. с другой работает второй, а первый нет. Подключал jquery-migrate
и работают оба скрипта, но криво, короче не так как следует.
> Про жизнь вообще забудь.
Да у меня ее и нет.
>я gollum использую, мне норм
Gollum? Что это такое? Гугл ничего не дал.
Благодарю за помощь, анонче.
Допустим, я выписал функцию error_reporting (что делает, как работает). Мне нписанное тупо зубрить/представлять/с чем-то ассоциировать? Как у тебя это усваивается в голове?
Вопрос, конечно, тупой, но я никогда особо не обучал себя сам, потому спрашиваю.
А я пробовал и так и сяк. И вики пилить ,и просто записывать. Рукой в тетради лучший вариант. Пока записываешь запомнишь и поймешь больше, чем пока читал. Тру стори.
упс, сохранить не могу.
Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'sdfsdf@dfss.dgh' for key 'email'' in C:\localhost\www\matriculant\app\MatriculantMapper.php
<?php
error_reporting(-1);
$str[] = "";
for ($i = 0; $i < 5; $i++)
{
$numb = mt_rand(0, 9);
$str += $numb;
}
echo $str;
?>
Блядь, $str[переменная i] += $numb;
Спасибо, попробую.
...
private $variables = array("title"=>"DEFAULT_TITLE");
...
public function set_var($name, $value){
$this->variables[$name] = $value;
}
...
}
...
$templater->set_var('url_path','http://'.$_SERVER['HTTP_HOST']);
$templater->set_var('rel',$templater->variables['url_path'].substr($templater->variables['path'],strlen(ROOT_DIR)));
...
echo $this->variables['url_path'] Выводит значение нормально
echo $this->variables['rel']; Не выводит вообще ничего!
Видимо вот здесь:
$templater->variables['url_path'].substr($templater->variables['path'],strlen(ROOT_DIR))
Кроется ошибка.
Какая?
Алсо, каким тегом в макабе оформлять код?
Просто там много кода, раскиданного по разным *.php файлам, которые друг друга вызывают через require_once, поэтому будет нечитаемо, если в ideone выкладывать.
Вот и какого черта он мне на 7-ом и 2-ом ошибку выдаёт? Причем выдаёт постоянно, что бы я туда не подставил.
странно у меня не постоянно.
Возможно ты путаешь индексы в массиве. Массив начинается с 0 а не с 1.
Или возможно, когда ты подставляешь другое значение, у тебя остаётся лишний пробел в ячейке массива.
Я другой анон, но как раз хочу выучить и кмс и фреймворки, обычное пхп, вроде бы не определённом уровне знаю. На уровне написания небольшого интернет-магазина с типичным функционалом. Я вот только никак не могу понять как вообще учить фреймворки и КМС, если по фреймворкам я ещё находил кое-какие руководства, то по КМС вообще непонятно.
Я всегда нахожу руководства как для контент-манаджера, не могу ничего найти с точки зрения ПХП. Кто как учил КМС и Фреймворки, может поделиться опытом?
Доки же. Для cms тоже должны быть. В крайнем случае ищи видеогайды по своей cms, статьи на хабре или еще где, вот это все. Всегда можно найти как залезть поглубже в это говно. Хуево ищешь короче.
http://ideone.com/5oyfFZ
Дело забыл.
Выдает ошибку
> preg_split(): Compilation failed: missing ) at offset 234 in /home/kkWr5I/prog.php on line 8
google: %cms_name% development guide
Томущо ты не читаешь текст ошибки
Все бы хорошо, но у тебя там XSRF неисправленная. Разумеется оставлять код с уязвимостями никак нельзя.
У тебя по-прежнему есть XSRF. Ты наверно не понимаешь, как она работает (или забыл ее исправить). Давай я покажу, как ее использовать.
Зайди на свой сайт, зарегистрируйся (чтобы создались куки и ты был авторизован). Затем создай и помести на любой сайт (можно на тот же самый) файл xsrf.html с таким содержимым (проверь что в action стоит правильный адрес): http://ideone.com/qJy0dX
После этого положи файл в любую папку на сервере и открой в браузере. Это будет работать даже если файл поместить на другой вирутальный хост или открыть из папки на диске. Если все верно, то при заходе на страницу профиль пользователя поменяется. То есть злоумышленнику достаточно любым спосоюом заманить пользователя на свой сайт, чтобы отправить форму от его имени.
Эта уязвимость работает потому, что можно автоматически отправить форму скриптом и в качестве action можно указать любой адрес, в том числе на другом домене.
Надо это исправить, добавив в форму код и проверяя его на совпадение с кодом из кук.
Кстати, аналогично можно разлогинить любого пользователя, заманив его на специально подготовленную страницу. По этой причине в ссылку/форму для разлогинивания тоже принято добавлять код. Этим конечно никому особо не навредишь, но ведь это учебное задание и ты должен уметь защищаться от таких уязвимостей.
В будущем бороться с XSRF станет легко так как новые браузеры уже посылают при любом запросе заголовок Origin: http://example.com/ который указывает с какого домена отправлена форма, и можно будет автоматически на уровне сервера отвергать любые POST запросы с чужих доменов. Но пока надо использовать токены.
> $report = "Изменения сохранены";
> header("Location: http://students.ru/profile.php?msg=$report");
Вообще, лучше использовать условные коды-обозначения например registered, или числа (для них в коде разумеется надо сделать константы), а не сам текст. А то появляется простор для мошенничества, например злоумышленник может подставить какой-нибудь свой текст на страницу («Внесите X руб. на мой счет для продолжения регистрации»).
Может тут конечно этим и не воспользуешься, но в общем так делать не стоит. Список сообщений должен быть жестко задан в коде.
> https://github.com/MindiMakridi/Students/blob/master/index.php#L103
> $link = htmlspecialchars($currentPage) . "?order=" .
htmlspecialchars надо использовать там где текст выводится, то есть в шаблоне. А когда экранирование делается в одном месте, а вывод совсем в другом, глядя на шаблон, трудно понять все ли правильно заэкранировано. Ну и htmlspecialchars достаточно написать 1 раз:
htmlspecialchars($currentPage . "?order=" . $sort. "&direction=" .... )
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L29
> <a href=<?= $link ?>&num=<?= $i * $recordsPerPage ?>><?= $i + 1 ?>
Атрибут надо брать в кавычки. Иначе браузер может решить что какой-нибудь спецсимвол его завершает и обрезать его. Чтобы не заучивать правила какие символы надо писать в кавычках, а какие можно не писать, лучше всегда ставить кавычки в аттрибутах. Пройдись по коду и заключи все атрибуты тегов в кавычки.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L34
> else {
Почему перед else несколько пустых строк? Создается ощущение что он тут вообще идет как отедльная команда и сам по себе. if/else пишется так:
if () {
...
} else {
...
}
> https://github.com/MindiMakridi/Students/blob/master/lib/functions.php#L20
> return $code = $_COOKIE['studentscookie']['code'];
зачем в одной строке совмещать создание переменной и return? Это 2 отдельных команды и лучше писать так:
$code = $_COOKIE['studentscookie']['code'];
return $code;
А еще лучше вообще не создавать тут переменную:
return $_COOKIE['studentscookie']['code'];
Ну и вообще, если у тебя есть где-то присваивание вида $x = ... то оно должно идти отдельной строкой, а не быть внутри другой команды (исключение — for, там можно так делать). Если прятать присваивание внутри других команд, его становится труднее заметить. А в данной ситуации переменная вообще не нужна так как никогда не используется.
В общем, из ошибок только XSRF, и несколько мелких замечаний к коду.
Все бы хорошо, но у тебя там XSRF неисправленная. Разумеется оставлять код с уязвимостями никак нельзя.
У тебя по-прежнему есть XSRF. Ты наверно не понимаешь, как она работает (или забыл ее исправить). Давай я покажу, как ее использовать.
Зайди на свой сайт, зарегистрируйся (чтобы создались куки и ты был авторизован). Затем создай и помести на любой сайт (можно на тот же самый) файл xsrf.html с таким содержимым (проверь что в action стоит правильный адрес): http://ideone.com/qJy0dX
После этого положи файл в любую папку на сервере и открой в браузере. Это будет работать даже если файл поместить на другой вирутальный хост или открыть из папки на диске. Если все верно, то при заходе на страницу профиль пользователя поменяется. То есть злоумышленнику достаточно любым спосоюом заманить пользователя на свой сайт, чтобы отправить форму от его имени.
Эта уязвимость работает потому, что можно автоматически отправить форму скриптом и в качестве action можно указать любой адрес, в том числе на другом домене.
Надо это исправить, добавив в форму код и проверяя его на совпадение с кодом из кук.
Кстати, аналогично можно разлогинить любого пользователя, заманив его на специально подготовленную страницу. По этой причине в ссылку/форму для разлогинивания тоже принято добавлять код. Этим конечно никому особо не навредишь, но ведь это учебное задание и ты должен уметь защищаться от таких уязвимостей.
В будущем бороться с XSRF станет легко так как новые браузеры уже посылают при любом запросе заголовок Origin: http://example.com/ который указывает с какого домена отправлена форма, и можно будет автоматически на уровне сервера отвергать любые POST запросы с чужих доменов. Но пока надо использовать токены.
> $report = "Изменения сохранены";
> header("Location: http://students.ru/profile.php?msg=$report");
Вообще, лучше использовать условные коды-обозначения например registered, или числа (для них в коде разумеется надо сделать константы), а не сам текст. А то появляется простор для мошенничества, например злоумышленник может подставить какой-нибудь свой текст на страницу («Внесите X руб. на мой счет для продолжения регистрации»).
Может тут конечно этим и не воспользуешься, но в общем так делать не стоит. Список сообщений должен быть жестко задан в коде.
> https://github.com/MindiMakridi/Students/blob/master/index.php#L103
> $link = htmlspecialchars($currentPage) . "?order=" .
htmlspecialchars надо использовать там где текст выводится, то есть в шаблоне. А когда экранирование делается в одном месте, а вывод совсем в другом, глядя на шаблон, трудно понять все ли правильно заэкранировано. Ну и htmlspecialchars достаточно написать 1 раз:
htmlspecialchars($currentPage . "?order=" . $sort. "&direction=" .... )
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L29
> <a href=<?= $link ?>&num=<?= $i * $recordsPerPage ?>><?= $i + 1 ?>
Атрибут надо брать в кавычки. Иначе браузер может решить что какой-нибудь спецсимвол его завершает и обрезать его. Чтобы не заучивать правила какие символы надо писать в кавычках, а какие можно не писать, лучше всегда ставить кавычки в аттрибутах. Пройдись по коду и заключи все атрибуты тегов в кавычки.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L34
> else {
Почему перед else несколько пустых строк? Создается ощущение что он тут вообще идет как отедльная команда и сам по себе. if/else пишется так:
if () {
...
} else {
...
}
> https://github.com/MindiMakridi/Students/blob/master/lib/functions.php#L20
> return $code = $_COOKIE['studentscookie']['code'];
зачем в одной строке совмещать создание переменной и return? Это 2 отдельных команды и лучше писать так:
$code = $_COOKIE['studentscookie']['code'];
return $code;
А еще лучше вообще не создавать тут переменную:
return $_COOKIE['studentscookie']['code'];
Ну и вообще, если у тебя есть где-то присваивание вида $x = ... то оно должно идти отдельной строкой, а не быть внутри другой команды (исключение — for, там можно так делать). Если прятать присваивание внутри других команд, его становится труднее заметить. А в данной ситуации переменная вообще не нужна так как никогда не используется.
В общем, из ошибок только XSRF, и несколько мелких замечаний к коду.
http://ideone.com/VMAre5
Я вижу, ты код красивее оформил? Это хорошо, читать стало чуть удобнее. И публичные свойства убрал. Совсем хорошо. Если что, для геттеров/сеттеров во многих редакторах есть сниппеты (либо их можно нагуглить), которые позволяют их быстро создавать. Вот например мой сниппет для Sublime 3: https://gist.github.com/codedokode/cd2f41c8dcf1237fde4b
Еще геттеры/сеттеры можно не создавать, а использовать магические методы get/set ( http://php.net/manual/ru/language.oop5.overloading.php#object.get ), но они сильно усложняют понимание кода, и в учебной задаче наверно не стоит их использовать.
Для начала, по архитектуре замечание. Паттерн «data mapper» подразумевает, что для работы с базой данных мы создаем классы, по одному на каждую таблицу, и только эти классы могут напрямую работать с базой, причем каждый в первую очередь со своей таблицей (но может использовать другие таблицы в запросах, для джойнов например). SQL кода в других класах быть не должно. А что у тебя?
> https://github.com/tokotun/matriculant/blob/master/app/Template.php#L14
Твой класс template не должен лезть в базу. Он должен вызывать для этого методы MatriculantMapper (ну и на всякий случай напомню что в свою очередь класс Data Mapper не должен лезть в POST, COOKIE, что либо выводить на экран).
В твоем случае лучше всего сделать функцию isLoggedIn (если хочется проще) или объект вроде Auth (если посложнее) который отвечает за залогинивание, разлогинивание и проверку заглогиненности.
Вообще, если очень хочется, можно сделать класс который в полях хранит переменные для шаблона. Такой класс принято называть ViewModel или PageModel. Но тогда ты должен передавать все переменные только через него (а не половину напрямую, а половину через класс) и для каждого шаблона нужен свой класс ViewModel так как они используют разный набор переменных. По моему, в этой простой задаче проще передавать переменые напрямую, но если тебе хочется заморочиться, можешь сделать классы. Классы типа ViewModel обычно делают для использования в яваскрипте вместе с data binding (если будешь изучать Knockout или Angular, узнаешь что это за байндинг), а на стороне PHP не используются.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L37
> print_r($matriculant);
Отладочный код не удалил. Полезно перед коммитом делать git diff (или, что удобнее, аналогичную команду в GUI утилите для работы с git) и кратко просматривать что коммитишь.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L13
> protected function bindField($statment,
Тут для statement стоит указать класс PDOSTatement.
> https://github.com/tokotun/matriculant/commit/06d18822dd9afc3fa6519c0e0a2636559bb6fc70#diff-0
> ингорировать файлы в папке boostrap
Это зачем? Чтобы тайком от меня править код бутстрапа?
> https://github.com/tokotun/matriculant/blob/master/templates/header.php#L13
> <?php if ($_SERVER['PHP_SELF'] == '/matriculant/index.php'):
Тут конечно было бы лучше сделать переменную, которая задает название подсвеченного раздела. Ну не знаю, тут сайт из 2 страниц, можно и так оставить, но вообще правильнее через переменную.
Аналогично тут
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L10
> if ($_GET['action'] == 'update'):?>
Лучше бы не лезть в GET а использовать переменную, а в GET лезть в login.php
> setcookie('id', $matriculant->getId(), strtotime('+10 year'), null, null, false, true);
У кук есть интересный параметр path. Он определяет, на каких страницах должна быть доступна кука и по умолчанию он равен адресу той страницы где она выставляется. Если его явно не выставлять в '/' то возможны интересные труднообнаружимые баги: например, кука выставляемая страницей /user/login.php не будет передаваться на страницу /index.php. Почитай про куки:
http://citforum.ru/internet/html/cookie.shtml (очень древняя статья, зато на русском)
http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path (англ)
Домен выставлять явно не надо, так как по умолчанию берется домен сайта.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L77
Комментарий пишется либо над строчкой, либо справа, но не снизу. Также, для функций есть специальный формат комментария, который некоторые IDE даже распознают и выводят в качестве подсказки при наведении на имя функции:
https://ru.wikipedia.org/wiki/PHPDoc
http://habrahabr.ru/post/162535/
(Я не говорю что надо везде ставить комментарии. Но раз уж ты ставишь, то используй общепринятые способы, а не придумывай свои).
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L83
> foreach ($columns as $keyColumn => $valueColumn)
Используй array_keys (заодно почитай какие вообще есть функции работы с массивами: http://php.net/manual/ru/ref.array.php ). Алсо, не пиши foreach в одну строку, после скобки { надо делать перенос строки.
Также, в данном случае надо переделать функцию чтобы в columns сразу передавался нужный массив. Иначе это сильно усложняет функцию — как не читая код, догадаться что имена колонок передаются как ключи массива? Не делай так, используй более очевидный способ когда в функцию просто передается массив имен колонок.
Более того, передавать список извне еще и менее безопасно, так как непонятно, глядя на код функции, откуда приходит этот список и можно ли ему доверять. Лучше все же вписать список прямо в функцию или сделать метод у MMapper вроде getAllowedSortColumns.
Насчет функций getErrorName(), getErrorSurname() можно оставить как у тебя, хотя я бы наверно сделал одну функцию, в которую передается имя поля, а при передаче несуществующего имени выкидывал бы исключение. Но можно и как у тебя оставить, никакой ошибки тут нету.
XSS в поиске вроде нет — я проверил вводом волшебной комбинации <b>>"'© (при наличии XSS часть символов не отобразится либо вставится в виде HTML кода). Только наверно стоит при поиске в поле поиска тоже подставлять введенный текст.
В общем, я думаю, все уже практически сделано, остается только исправить мелкие замечания. Будешь дальше файлообменник делать? С использованием Slim, Twig (кстати с ним тебе не придется писать htmlspecialchars так как там есть автоескейпинг).
Я вижу, ты код красивее оформил? Это хорошо, читать стало чуть удобнее. И публичные свойства убрал. Совсем хорошо. Если что, для геттеров/сеттеров во многих редакторах есть сниппеты (либо их можно нагуглить), которые позволяют их быстро создавать. Вот например мой сниппет для Sublime 3: https://gist.github.com/codedokode/cd2f41c8dcf1237fde4b
Еще геттеры/сеттеры можно не создавать, а использовать магические методы get/set ( http://php.net/manual/ru/language.oop5.overloading.php#object.get ), но они сильно усложняют понимание кода, и в учебной задаче наверно не стоит их использовать.
Для начала, по архитектуре замечание. Паттерн «data mapper» подразумевает, что для работы с базой данных мы создаем классы, по одному на каждую таблицу, и только эти классы могут напрямую работать с базой, причем каждый в первую очередь со своей таблицей (но может использовать другие таблицы в запросах, для джойнов например). SQL кода в других класах быть не должно. А что у тебя?
> https://github.com/tokotun/matriculant/blob/master/app/Template.php#L14
Твой класс template не должен лезть в базу. Он должен вызывать для этого методы MatriculantMapper (ну и на всякий случай напомню что в свою очередь класс Data Mapper не должен лезть в POST, COOKIE, что либо выводить на экран).
В твоем случае лучше всего сделать функцию isLoggedIn (если хочется проще) или объект вроде Auth (если посложнее) который отвечает за залогинивание, разлогинивание и проверку заглогиненности.
Вообще, если очень хочется, можно сделать класс который в полях хранит переменные для шаблона. Такой класс принято называть ViewModel или PageModel. Но тогда ты должен передавать все переменные только через него (а не половину напрямую, а половину через класс) и для каждого шаблона нужен свой класс ViewModel так как они используют разный набор переменных. По моему, в этой простой задаче проще передавать переменые напрямую, но если тебе хочется заморочиться, можешь сделать классы. Классы типа ViewModel обычно делают для использования в яваскрипте вместе с data binding (если будешь изучать Knockout или Angular, узнаешь что это за байндинг), а на стороне PHP не используются.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L37
> print_r($matriculant);
Отладочный код не удалил. Полезно перед коммитом делать git diff (или, что удобнее, аналогичную команду в GUI утилите для работы с git) и кратко просматривать что коммитишь.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L13
> protected function bindField($statment,
Тут для statement стоит указать класс PDOSTatement.
> https://github.com/tokotun/matriculant/commit/06d18822dd9afc3fa6519c0e0a2636559bb6fc70#diff-0
> ингорировать файлы в папке boostrap
Это зачем? Чтобы тайком от меня править код бутстрапа?
> https://github.com/tokotun/matriculant/blob/master/templates/header.php#L13
> <?php if ($_SERVER['PHP_SELF'] == '/matriculant/index.php'):
Тут конечно было бы лучше сделать переменную, которая задает название подсвеченного раздела. Ну не знаю, тут сайт из 2 страниц, можно и так оставить, но вообще правильнее через переменную.
Аналогично тут
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L10
> if ($_GET['action'] == 'update'):?>
Лучше бы не лезть в GET а использовать переменную, а в GET лезть в login.php
> setcookie('id', $matriculant->getId(), strtotime('+10 year'), null, null, false, true);
У кук есть интересный параметр path. Он определяет, на каких страницах должна быть доступна кука и по умолчанию он равен адресу той страницы где она выставляется. Если его явно не выставлять в '/' то возможны интересные труднообнаружимые баги: например, кука выставляемая страницей /user/login.php не будет передаваться на страницу /index.php. Почитай про куки:
http://citforum.ru/internet/html/cookie.shtml (очень древняя статья, зато на русском)
http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path (англ)
Домен выставлять явно не надо, так как по умолчанию берется домен сайта.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L77
Комментарий пишется либо над строчкой, либо справа, но не снизу. Также, для функций есть специальный формат комментария, который некоторые IDE даже распознают и выводят в качестве подсказки при наведении на имя функции:
https://ru.wikipedia.org/wiki/PHPDoc
http://habrahabr.ru/post/162535/
(Я не говорю что надо везде ставить комментарии. Но раз уж ты ставишь, то используй общепринятые способы, а не придумывай свои).
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L83
> foreach ($columns as $keyColumn => $valueColumn)
Используй array_keys (заодно почитай какие вообще есть функции работы с массивами: http://php.net/manual/ru/ref.array.php ). Алсо, не пиши foreach в одну строку, после скобки { надо делать перенос строки.
Также, в данном случае надо переделать функцию чтобы в columns сразу передавался нужный массив. Иначе это сильно усложняет функцию — как не читая код, догадаться что имена колонок передаются как ключи массива? Не делай так, используй более очевидный способ когда в функцию просто передается массив имен колонок.
Более того, передавать список извне еще и менее безопасно, так как непонятно, глядя на код функции, откуда приходит этот список и можно ли ему доверять. Лучше все же вписать список прямо в функцию или сделать метод у MMapper вроде getAllowedSortColumns.
Насчет функций getErrorName(), getErrorSurname() можно оставить как у тебя, хотя я бы наверно сделал одну функцию, в которую передается имя поля, а при передаче несуществующего имени выкидывал бы исключение. Но можно и как у тебя оставить, никакой ошибки тут нету.
XSS в поиске вроде нет — я проверил вводом волшебной комбинации <b>>"'© (при наличии XSS часть символов не отобразится либо вставится в виде HTML кода). Только наверно стоит при поиске в поле поиска тоже подставлять введенный текст.
В общем, я думаю, все уже практически сделано, остается только исправить мелкие замечания. Будешь дальше файлообменник делать? С использованием Slim, Twig (кстати с ним тебе не придется писать htmlspecialchars так как там есть автоескейпинг).
https://tech.yandex.ru/pdd/doc/reference/email-ml-add-docpage/
C меня лучи добра!
POST запросы из скрипта делаются с помошью CURL. Ему просто массив параметров передаешь, он сам тело запроса формирует
http://ideone.com/WepQw3
И сколько обычно стажировка идёт?
Алсо там что-то вроде "базовых знаний" по php и mysql.
Базовые, это какие?
PHP вот курсик ОПа допрохожу, сегодня начал читать пикрелейтед, вроде неплохо подано, но, если я не ебусь в глаза, практических заданий там нет особо.
По MySQL у меня знания нулевые, на данный момент.
Ньюфаг, не гоните плз.
Спасибо!
Там приведен текст HTTP запроса. Но как туманно намекнул анон выше, в PHP есть расширения и библиотеки для работы с протоколом HTTP и отправлять запрос с их помощью гораздо удобнее так как не надо руками устанавливать соединение, правильно формировать и отправлять данные, правильно разбирать пришедший ответ.
В PHP встроено расширение curl, но оно довольно низкоуровневоее и неудобное. Удоюнее пользоваться сторонней библиотекой, например Guzzle. Почитай ее мануал или погугли «как отправить POST запрос с помощью Guzzle»
Если ты не знаешь что такое и как работает HTTP, тебе будет трудно понять как решить заадчу. HTTP — это протокол (протокол это стандарт для обмена данными, что-то вроде языка на котором общаются компьютеры друг с другом) для передачи данных и файлов, именно с его помощью твой браузер общается с сервером и запрашивает и отправляет данные когда ты открываешь какой-то сайт. Почитай статьи по ссылкам или нагугли их сам:
https://ru.wikipedia.org/wiki/HTTP
http://habrahabr.ru/post/215117/
HTTP относительно простой протокол. Ты можешь сам увидеть какие запросы шлет твой браузер, открыв инспектор на любом сайте (Ctrl + Shift + I) на вкладке Network, и покликать по ссылкам.
Никсон может и годится для ознакомления, но книга очень старая, а примеры кода там напоминают так называемый «быдлокод», то есть содержат уязвимости, ошибки.
Лучше если есть время, решить хотя бы 2 или 3 задания из тех что даются после учебника ОПа. Ссылки на них стоят в ОП-посте этого треда, задача про студентов и файлообменник.
> Базовые, это какие?
Язык PHP: циклы, ифы, регулярки, работа с массивами и строками, ООП, стандартные функции PHP. Может быть требуется еще умение сделать простую страничку, на котрой можно ввести сумму в долларах и получить сколько это рублей.
По MySQL, не базовый, а полный список того что хорошо бы знать, перечислем тут: https://gist.github.com/codedokode/10539213#%D0%9D%D0%B0-%D1%87%D1%82%D0%BE-%D1%81%D1%82%D0%BE%D0%B8%D1%82-%D0%BE%D0%B1%D1%80%D0%B0%D1%82%D0%B8%D1%82%D1%8C-%D0%B2%D0%BD%D0%B8%D0%BC%D0%B0%D0%BD%D0%B8%D0%B5
Это может напугать начинающего, но реально там неделя-две максимум изучать, а знания будут хорошие. В реальности часто требуется меньше знаний, но лучше переучить чем недоучить, верно?
> И сколько обычно стажировка идёт?
2-3 месяца, но в сытые годы высокой цены на нефть в Москве брали всех подряд и стажировали по полгода.
Вышел новый никсон, в интернетах есть или нет не знаю, но на русский точно переведен. Впрочем, там также рассказывается например про mysqli а не про PDO, так что непонятно.
А если ты пока не осилил гит и гитхаб (хотя в ОП посте есть ссылка на git book на русском языке), то можешь открыть gist.github.com и постить туда. Он поддерживает добавление файлов перетаскиванием на страницу.
Спасибо огромное, дальше, я думаю, сам справлюсь. Очень хорошо все расписал. Добра тебе!
Анон, прежде чем продолжать делать без сомнения интересный и инновационный проект Templater, прочти пункт 6 из этой статьи (остальные тоже не помешает прочесть): http://habrahabr.ru/post/230737/
Повторю еще раз про mysqli. Действительно, в PHP сейчас есть 2 актуальных библиотеки для работы с БД: PDO и mysqli. PDO более известная и раскрученная, хотя если срого сравнивать, фич в mysqli больше (но с другой стороны там нет исключений при ошибках).
Но многие сайты, учебники выбирают mysqli не из-за фич. Они выбирают ее потому что она поддерживает функции, аналогичные устаревшей mysql, которые достаточно чуть переименовать: mysql_query -> mysqli_query
Это значит что если ты видишь использование mysqli на функциях вроде mysql_query, 99% что перед тобой устаревший материал 10-летней давности в котором просто приписали буковку i (и может быть до сих пор вставляют переменные в текст запроса). Подумай, стоит ли читать про допотопный подход без использования ООП?
Или лучше прочесть более современную статью про вроде этих:
- про PDO: http://habrahabr.ru/post/137664/
- про MySQLi c ООП-подходом: http://habrahabr.ru/post/141127/
> Вот я закидываю их в директорию которую у меня слушает апач, создаю там папки models , views и controllers , в каждом index.php
Ты что-то перепутал. Напрямую ты обращаешься либо к скрипту-контроллеру (например /index.php, /register.php) либо вообще у тебя все обращения идут на один скрипт index.php а он уже определяет какой контроллер вызвать. А к моделям и шаблонам ты из браузера не обращаешься напрямую. Их подключает контроллер.
Почитай например эту статью:
- http://habrahabr.ru/post/150267/ (тут дана не совсем правильная картинка MVC, там приведена картинка MVC для десктопных GUI приложений, а не для сайтов, также используются статические методы)
Заметь что в статье используется ООП. Конечно, сам по себе принцип MVC не требует исплоьзования ООП, но на практиве все MVC фреймворки обычно его (ООП) используют.
После статьи советую изучить фреймворк Yii 2 — он тоже исплоьзует ООП.
>>432545
У меня есть такие вещи:
- учебник для изучения основ PHP (циклы, ифы, массивы, строки, ООП). Если ты что-то из этого плохо помнишь, советую почитать и порешать задачи, решения постить в тред ссылкой на ideone. Ссылка в ОП-посте.
- задачи для тех кто уже хорошо знает основы PHP. Как раз на практические навыки. Для начала можем решить задачу про регистрацию студентов и файлообменник, ссылки есть в ОП-посте. задачи очень полезные. Для их решения знание ООП обязательно, ООП объясняется простым понятным языком в последней главе учебника.
- дополнительные неплохие задачи на изучение HTML/CSS/JS/MySQL. они позволят увидеть какие места ты плохо знаешь и дать тебе ссылки и советы по изучению. В идеале хорошо бы их прорешать.
В общем, открой ОП-пост, посмотри что там есть и выбери что ты хочешь решать. Если у тебя есть какие-то вопросы, что-то непонятно, хочется проверить решение, нужна подсказка, пиши в тред, я отвечу.
Анон, я с удовольствием посмотрю, но уже не сегодня. Сегодня я успел только полистать документацию по reactphp, ratchet и еще чему-то, а код посмотреть лшь мельком. Но я проверю позже, штука интересная.
Ты не делал никаких нагрузочных тестов? Вроде мерять задержку в зависимости от числа клиентов, тестировать время подключения в зависимости от числа, потребление памяти сервером, потребление CPU/памяти браузером? Раз уж ты делаешь многопользовательский чат, думаю, были бы полезно научиться мерять производительность и искать узкие места. Я могу позже придумать метрики, которые надо измерять, и может посоветовать какой-то инструмент для этого.
Сразу скажу, у меня есть ощущение что при залогинивании из нескольких браузеров/устройств одним пользователем там могут быть какие-то баги. Ты проверял это?
Я сужу вот по этому коду:
> https://github.com/d-beekeeper/ratchat/blob/master/app/Server/RatchetServer.php#L112
закрытие соединения != выход юзера из комнаты
Также, здесь название функции неудачное:
https://github.com/d-beekeeper/ratchat/blob/master/app/Chat.php#L122
> public function leftUserFromRoom(User $user, $roomName)
> if ($this->roomHandler->removeUserFromRoom($user,$roomName)) {
Не очень понятно в чем разница между 2 функциями (а она должна быть, ведь они названы по-разному).
Позже я посмотрю код внимательнее.
А, еще, если будешь тестировать производительность то стоит поставить более хорошую библиотеку для ReactPHP. Скорее всего по умолчанию он использует StreamSelectLoop который не требует расширений. Но он основан на системном вызове ядра Select (получить список сокетов на которых доступны данные), производительность которого с ростом числа соединений стремится к нулю. Подробнее про проблему большого числа соединений:
http://www.kegel.com/c10k.html#top (англ, может быть сложно понять начинающему)
Так как select не может обеспечить нужной произвдительности, в ядро linux добавили оптимизированные методы (epoll по моему), и написали библиотеки libevent, libev, libuv, которые используют более быстрый метод и позволяют организовать event loop для обработки сокетов. Соответственно, установив расширение для PHP, ты сможешь использовать более производительсный способ работы с скоетами. Подключение, как я понимаю, не требует менять сам код, так как разница асбтрагируется внутри reactphp.
Потому для повышения производительности стоит поставить расширение вроде libev/libuv к PHP и использовать более быстрые сокеты. Список поддерживаемых драйверов тут: https://github.com/reactphp/react/wiki/Event-Loop-Implementations
libevent самая старая библиотека. libev более новая и тут http://libev.schmorp.de/bench.html пишут что она быстрее. Про libuv я ничего не знаю, кроме того что она используется как основа event loop в Node.JS.
Ну и еще, если делать тесты, было бы интересно попробовать запустить приложение под hiphop (JIT компилятор от фейсбука который может выполнять код быстрее — на долгоживущих процессах выгода должна быть).
> Кстати если подскажешь какую нибудь готовую oAuth библиотеку для Silex-Symphony (или вообще универсальную) для однообразной авторизации юзера через кучу разных соцсетей - буду очень благодарен.
Я ищу обычно библиотеки на phptrends. Вводи туда разные ключевые слова (oauth, symfony oauth, silex oauth) и посомтри что найдется. Я вижу например вот эта популярна:
https://github.com/thephpleague/oauth2-client
Если искать по symfony oauth то на первом месте вот это, но она по моему только под Symfony, то есть она хорошо интегрируется именно в большие проекты, а вот насчет Silex это вряд ли:
https://github.com/hwi/HWIOAuthBundle
Если в них нет поддержки нужного тебе сервиса, можешь дописать плагин и выложить в опенсорс. Это наверно лучше чем свою систему лепить.
По словам silex oauth там тоже что-то выпадает: https://github.com/gigablah/silex-oauth
Я кстати тут решил глянуть в твоем гитхабе (любопытно же), не делал ли ты что-то раньше из наших заданий и увидел там файлообменник. Интересно :3 Хотя не помню, видел ли я его раньше? Наверно, нет. Но если ты с файлообменника перешел на Symfony (ну или хотя бы Silex) и асинхронные сокеты, это прогресс.
Кстати, ты тестами позаниматься не хочешь? Тесты — вещь интересная, но их мало где пишут и не везде пишут правильно. А ведь они очень полезны и дают ощущение надежности кода, да и возможность в любой момент проверить все ли верно работе, тоже очень помогает. Ну и плюс это ступенька в твоем уровне знаний. Тесты для кода, тесты для веб-приложений. У меня есть урок-обзор (да, он пока плохонький, и примеров надо бы больше сделать, и может что-то объяснить, и задача там в конце неправильно придумана, надо ее переделать): https://gist.github.com/codedokode/a455bde7d0748c0a351a Но вот что-то пока никто до этого урока не дошел.
Не хочешь как-нибудь тестирование поизучать?
А, еще, если будешь тестировать производительность то стоит поставить более хорошую библиотеку для ReactPHP. Скорее всего по умолчанию он использует StreamSelectLoop который не требует расширений. Но он основан на системном вызове ядра Select (получить список сокетов на которых доступны данные), производительность которого с ростом числа соединений стремится к нулю. Подробнее про проблему большого числа соединений:
http://www.kegel.com/c10k.html#top (англ, может быть сложно понять начинающему)
Так как select не может обеспечить нужной произвдительности, в ядро linux добавили оптимизированные методы (epoll по моему), и написали библиотеки libevent, libev, libuv, которые используют более быстрый метод и позволяют организовать event loop для обработки сокетов. Соответственно, установив расширение для PHP, ты сможешь использовать более производительсный способ работы с скоетами. Подключение, как я понимаю, не требует менять сам код, так как разница асбтрагируется внутри reactphp.
Потому для повышения производительности стоит поставить расширение вроде libev/libuv к PHP и использовать более быстрые сокеты. Список поддерживаемых драйверов тут: https://github.com/reactphp/react/wiki/Event-Loop-Implementations
libevent самая старая библиотека. libev более новая и тут http://libev.schmorp.de/bench.html пишут что она быстрее. Про libuv я ничего не знаю, кроме того что она используется как основа event loop в Node.JS.
Ну и еще, если делать тесты, было бы интересно попробовать запустить приложение под hiphop (JIT компилятор от фейсбука который может выполнять код быстрее — на долгоживущих процессах выгода должна быть).
> Кстати если подскажешь какую нибудь готовую oAuth библиотеку для Silex-Symphony (или вообще универсальную) для однообразной авторизации юзера через кучу разных соцсетей - буду очень благодарен.
Я ищу обычно библиотеки на phptrends. Вводи туда разные ключевые слова (oauth, symfony oauth, silex oauth) и посомтри что найдется. Я вижу например вот эта популярна:
https://github.com/thephpleague/oauth2-client
Если искать по symfony oauth то на первом месте вот это, но она по моему только под Symfony, то есть она хорошо интегрируется именно в большие проекты, а вот насчет Silex это вряд ли:
https://github.com/hwi/HWIOAuthBundle
Если в них нет поддержки нужного тебе сервиса, можешь дописать плагин и выложить в опенсорс. Это наверно лучше чем свою систему лепить.
По словам silex oauth там тоже что-то выпадает: https://github.com/gigablah/silex-oauth
Я кстати тут решил глянуть в твоем гитхабе (любопытно же), не делал ли ты что-то раньше из наших заданий и увидел там файлообменник. Интересно :3 Хотя не помню, видел ли я его раньше? Наверно, нет. Но если ты с файлообменника перешел на Symfony (ну или хотя бы Silex) и асинхронные сокеты, это прогресс.
Кстати, ты тестами позаниматься не хочешь? Тесты — вещь интересная, но их мало где пишут и не везде пишут правильно. А ведь они очень полезны и дают ощущение надежности кода, да и возможность в любой момент проверить все ли верно работе, тоже очень помогает. Ну и плюс это ступенька в твоем уровне знаний. Тесты для кода, тесты для веб-приложений. У меня есть урок-обзор (да, он пока плохонький, и примеров надо бы больше сделать, и может что-то объяснить, и задача там в конце неправильно придумана, надо ее переделать): https://gist.github.com/codedokode/a455bde7d0748c0a351a Но вот что-то пока никто до этого урока не дошел.
Не хочешь как-нибудь тестирование поизучать?
> Выдает кучу ошибок
Ошибки надо исправить. У тебя ошибки из-за того что тут:
> $newPath = makeOneStep($paths, $stationName, $endPoint, $time, $lowerTime, $pathDone);
> if (!$lowerTime || ($newPath['time'] < $lowerTime)) {
Нет проверки на то, что makeOneStep нашла путь. Она ведь могла не найти путь и в этом случае возвращает пустой массив (кстати почему? нет логики. Лучше возвращать null).
То есть прежде чем обращаться к newPath['time'] надо проверить что в нем вообще что-то есть.
тут по-прежнему ошибка:
> $time += $paths[$startPoint][$stationName]['time'];
Допустим мы сейчас в A, и из нее можно проехать в B, C, D, E, F, ... Z. Цикл foreach начинает перебирать вершины B, C ... Z и на каждом шаге мы в time прибавляем время проезда от A до текущей вершины, то есть время пути AB, AC ...
В итоге в time к концу цикла будет старое значение time + AB + AC + AD + AE + AF ... + AZ. Что оно значит?
То есть в этой переменной хранится бессмысленное число которое непонятно что значит. И это число в итоге идет в параметр time пути. Это может привести к тому что будет взят не самый оптимальный путь.
В общем, избавься от ненужной переменной, сделай чтобы при отсутствии пути функция возвращала null, а не пустой массив, исправь ситуацию с вычислением времени пути.
В строке 161-162 ради понятности напиши return array( ...);
Время (33) по моему у тебя выводится неправильное. Посчитай по карте сам.
То есть ты близок к решению, но надо исправить ошибки.
> Выдает кучу ошибок
Ошибки надо исправить. У тебя ошибки из-за того что тут:
> $newPath = makeOneStep($paths, $stationName, $endPoint, $time, $lowerTime, $pathDone);
> if (!$lowerTime || ($newPath['time'] < $lowerTime)) {
Нет проверки на то, что makeOneStep нашла путь. Она ведь могла не найти путь и в этом случае возвращает пустой массив (кстати почему? нет логики. Лучше возвращать null).
То есть прежде чем обращаться к newPath['time'] надо проверить что в нем вообще что-то есть.
тут по-прежнему ошибка:
> $time += $paths[$startPoint][$stationName]['time'];
Допустим мы сейчас в A, и из нее можно проехать в B, C, D, E, F, ... Z. Цикл foreach начинает перебирать вершины B, C ... Z и на каждом шаге мы в time прибавляем время проезда от A до текущей вершины, то есть время пути AB, AC ...
В итоге в time к концу цикла будет старое значение time + AB + AC + AD + AE + AF ... + AZ. Что оно значит?
То есть в этой переменной хранится бессмысленное число которое непонятно что значит. И это число в итоге идет в параметр time пути. Это может привести к тому что будет взят не самый оптимальный путь.
В общем, избавься от ненужной переменной, сделай чтобы при отсутствии пути функция возвращала null, а не пустой массив, исправь ситуацию с вычислением времени пути.
В строке 161-162 ради понятности напиши return array( ...);
Время (33) по моему у тебя выводится неправильное. Посчитай по карте сам.
То есть ты близок к решению, но надо исправить ошибки.
>>433197
Ответил выше.
>>432604
Что значит на локальную? На твоем компьютере? В этом нет смысла, так как твоя папка не будет доступна с другог окомпьютера, а сайт должен быть доступен везде.
А так, file:/// должно работать. В Хроме и FF работает.
Что значит у тебя не работает? Какая у тебя ОС? Что выводитяс при клике на ссылку?
>>432618
сделать форму и сохранять данные в базу.
>>432620
Тут нет выгоды от ангулара так как с ним гораздо сложнее чем по быстрому на обычной форме сделать наверно.
>>432623
Ты или кто-то другой ниже уже написал:
(что угодно){10} — регулярка в скобках должна совпасть с текстом 10 раз подряд
>>433197
Ответил выше.
>>432604
Что значит на локальную? На твоем компьютере? В этом нет смысла, так как твоя папка не будет доступна с другог окомпьютера, а сайт должен быть доступен везде.
А так, file:/// должно работать. В Хроме и FF работает.
Что значит у тебя не работает? Какая у тебя ОС? Что выводитяс при клике на ссылку?
>>432618
сделать форму и сохранять данные в базу.
>>432620
Тут нет выгоды от ангулара так как с ним гораздо сложнее чем по быстрому на обычной форме сделать наверно.
>>432623
Ты или кто-то другой ниже уже написал:
(что угодно){10} — регулярка в скобках должна совпасть с текстом 10 раз подряд
Может и поможет, не знаю. Но не выписывай все подряд, а только ключевые слова (названия функций или терминов) без пояснений. Тогда на следующий день ты можешь взглянуть на листок и попробовать вспомнить. а если забыл то погуглить. А объяснения наверно писать излишне, если ты понял идею, то тебе хватит одного слова чтобы вспомнить.
Ну и пиши код каждый день. Это самая важная часть обучения, практическая. И решения пости в тред для проверки.
>>432658
У jQUery есть метод noConflict для такого подключения, но это будет очень геморройно. может проще поменять библиотеку или исправить код?
> сам с собой на английском говорю.
> Иногда по скайпу общаюсь
Но хотя бы по скайпу не сам с собой?
Я кстати тоже бумагу использую, я на нее кандзи выписываю (которые позже все равно успешно забываю).
>>432665
попробуй выписывать только название либо название + 2-3 слова поясняющую зачем она. А позже пересматривать листок и вспоминать. Но вообще, учить функции не требуется. Если ты постоянно пишешь код (в идеале часов по 8-10 в день) то ты все нужные функции запомнишь. А те, что не запомнишь, всегда можно посмотреть в мануале. Я не первый год на PHP пишу, но все равно периодиечски в мануал лезу. Главное знать, что для этого или того в php есть функция.
Также, IDE при вводе имени функции выдают подсказки по ней.
То есть что я хочу сказать: главное запоминать идеи и концепции, (например что элементы массива перебираются через цикл foreach или что в PHP есть функция, допустим для получения ключей массива или поиска символа в строке, или то что для поиска текста по шаблону есть регулярные выражения или то что классы можно наследовать), а наизусть ее навзание или тем более аргументы учить не надо. Это всегда можно нагуглить. Главное, пиши код как можно больше. Теория не запоминается если нет практики.
Ну и запоминать идеи и концепции проще, так как их меньше чем функций в PHP.
По идее если ты используешь функции в коде, то со временем запоминаешь (вплоть до того что руки запомниают какие клавиши жать), а если не используешь и забыл, то всегда можно нагуглить. Не надо заниматься зубрежкой, выгоднее изучить общие идеи и концепции, а как функция пишется или используется искать через гугл.
>>432708
Базу почисти и перезалей дамп. У меня та же ошибка была.
>>432728
Плюс складывает только числа по математическим правилам. Для склеивания (конкатенации не по-русски) строк используй точку: http://php.net/manual/ru/language.operators.string.php
>>432738
> каким тегом в макабе оформлять код?
Никаким. Сломали эту фичу.
>>432747
Ты используешь несуществующую переменную regxp (наверно имелось в виду check)
>>432771
То же самое.
>>432780
А как ты рельсы с метеором собрался объединять? метеор же JS использует на сервере.
Можно вкатиться, но я рельсы знаю очень плохо, так что больше буду HTML/JS проверять тогда. Ну и раз ты используешь такую сложную вещь как meteor.js, ты хорошо изучил его документацию? Знаешь, как он устроен и как работает?
Мне не нравится meteor, я тут полистал документацию (она плохая и невнятная, так как нормально не описывает ни концепции ни архитектуру), узнал что эти велосипедисты зачем-то сделали свой менеджер пакетов вместо npm, мне не нравится handlebars (у него ужасный и неудачный синтаксис), идея выполнять один код и там и там (во-первых, в этом не смысла, во-вторых, интуиция говорит что скоро код превратится в лапшу из Meteor.isServer/isClient со всеми вытекающими багами). Не нравится заточенность на MongoDB (у нее сових недостатков хватает).
Мне кажется он подходит для какой-то ниши (там где надо обновлять данные на большом числе клиентов), но делать на нем все подряд как минимум глупо. Ну и неизвестно. как он будет себя вести например на сложной верстке с большим числом данных.
Ну это так, мое мнение. Разобраться в нем в любом случае полезно.
По идее если ты используешь функции в коде, то со временем запоминаешь (вплоть до того что руки запомниают какие клавиши жать), а если не используешь и забыл, то всегда можно нагуглить. Не надо заниматься зубрежкой, выгоднее изучить общие идеи и концепции, а как функция пишется или используется искать через гугл.
>>432708
Базу почисти и перезалей дамп. У меня та же ошибка была.
>>432728
Плюс складывает только числа по математическим правилам. Для склеивания (конкатенации не по-русски) строк используй точку: http://php.net/manual/ru/language.operators.string.php
>>432738
> каким тегом в макабе оформлять код?
Никаким. Сломали эту фичу.
>>432747
Ты используешь несуществующую переменную regxp (наверно имелось в виду check)
>>432771
То же самое.
>>432780
А как ты рельсы с метеором собрался объединять? метеор же JS использует на сервере.
Можно вкатиться, но я рельсы знаю очень плохо, так что больше буду HTML/JS проверять тогда. Ну и раз ты используешь такую сложную вещь как meteor.js, ты хорошо изучил его документацию? Знаешь, как он устроен и как работает?
Мне не нравится meteor, я тут полистал документацию (она плохая и невнятная, так как нормально не описывает ни концепции ни архитектуру), узнал что эти велосипедисты зачем-то сделали свой менеджер пакетов вместо npm, мне не нравится handlebars (у него ужасный и неудачный синтаксис), идея выполнять один код и там и там (во-первых, в этом не смысла, во-вторых, интуиция говорит что скоро код превратится в лапшу из Meteor.isServer/isClient со всеми вытекающими багами). Не нравится заточенность на MongoDB (у нее сових недостатков хватает).
Мне кажется он подходит для какой-то ниши (там где надо обновлять данные на большом числе клиентов), но делать на нем все подряд как минимум глупо. Ну и неизвестно. как он будет себя вести например на сложной верстке с большим числом данных.
Ну это так, мое мнение. Разобраться в нем в любом случае полезно.
Ищи developer docs.
Wordpress: http://codex.wordpress.org/%D0%94%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D0%B8%D1%8F_%D0%B4%D0%BB%D1%8F_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%B0
Wordpress, англ: http://codex.wordpress.org/Developer_Documentation
Также, там есть «designer docs» то есть документация по созданию тем и натягиванию верстки (так как верстальщиков на западе почему-то назвают designer): http://codex.wordpress.org/Blog_Design_and_Layout
Drupal: https://www.drupal.org/documentation/develop
Drupal, создание тем: https://www.drupal.org/documentation/theme
Ну и так далее.
Если ты незнаком с конкретной CMS, стоит начать с установки и чтения руководства пользователя, а не разработчика, чтобы ты сначала научился админкой пользоваться.
Скобки не хватает открытой
>>433140
Вместо (\\-|\\(|\\)| ) гораздо удобнее и короче использовать [()\\-\\s]
Не называй переменные по-русски. Не знаешь английский, используй гугл транслейт или словари.яндекс.
> $chistka = '#((\\-|\\(|\\)| )*){10}#';
Тут непонятно зачем {10} приписана. Это выражение явно непраивльное, упрости его чтобы там было не больше 4-5 символов.
В общем да, работает, но надо доработать. ну и проверить что номера из неправильного списка все отсеиваются.
>>433189
Норм. Но имей в виду, что для поиска пути есть готовые алгоритмы (котооые лучше предоженного в задаче), например Дейкстра неплохой: https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D1%83%D1%82%D0%B8
1) Почему все не рекомендуют ставить апач как службу под виндой и, упаси боже, делать его доступным из сети? Это правда так небезопасно? Как обезопаситься тогда?
2) зачем постоянно прописывать хосты в hosts, как прописывать их, если хочешь расшарить виртуальные хосты в сеть и как прописывать их на vps под никсами?
3) Решил заранее посмотреть вакансии и обалдел - джуниор, php, HTML/CSS, js(jquery), mvc, 2-4 фреймворка, опыт администрирования, еще что-нибудь, зарплата 40к. Это нормально, что даже сишнику с зарплатой вдвое выше надо знать вдвое меньше, чем джуниору php? Или достаточно поверхностных знаний уровня helloworld по тому же js?
>Почему все не рекомендуют ставить апач как службу под виндой
Я ставлю так как в этом случае он запускается при старте компьютера. Плохого ничего нет.
> и, упаси боже, делать его доступным из сети?
Если ты делаешь его доступным снаружи, и ты не NAT (например не за роутером), по может быть соседи по локалке смогут зайти на твои локальные сайты, и например оставить там какие-нибудь нехорошие комментарии (если в примеру ты делаешь блог). Ну и если у тебя там какой-нибудь phpmyadmin и база без пароля, то они смогут залезть в нее.
> зачем постоянно прописывать хосты в hosts
Чтобы обращаться к локальному сайту по имени. Запись в hosts говорит ОС на твоем компьютере что имени X соотвутетвует Ip адрес Y.
> как прописывать их, если хочешь расшарить виртуальные хосты в сеть
Надо понимать что такое DNS и как она работает. DNS это система которая преобразует имя хоста вроде example.com в IP-адрес. Подробнее в вики: https://ru.wikipedia.org/wiki/DNS
Как видишь, DNS состоит из частей, которые под нашим контролем (файл hosts или свой DNS сервер) и которые не под нашим (чужой DNS сервер).
Потому тут все зависит от того, какая сеть. если это твоя локальная сеть, то проще всего поднять свой DNS сервер (такая функция может быть даже в некоторых роутерах, хотя я не уверен) и поменять настройки подсоединенных к сети устройств чтобы они использовали его.
Если ты хочешь поделиться своим сайтом со всем интернетом, тут все сложнее. Тебе надо:
- купить домен
- настроить для своего компьютера «белый», то есть доступный снаружи, Ip адрес (эта услуга есть не у всех провайдеров и обычно она платная).
- настроить домен чтобы он указывал на твой внешний IP адрес
> как прописывать их на vps под никсами?
Ты прописываешь хосты не на сервере а на компьютере с которого смотришь сайт, чтобы он мог понять какому IP соответствует имя хоста. Если ты арендуешь VPS то скорее всего к нему бесплатно дают технический домен вроде server1234.example.com и ты можешь пользоваться им без настройки.
>Почему все не рекомендуют ставить апач как службу под виндой
Я ставлю так как в этом случае он запускается при старте компьютера. Плохого ничего нет.
> и, упаси боже, делать его доступным из сети?
Если ты делаешь его доступным снаружи, и ты не NAT (например не за роутером), по может быть соседи по локалке смогут зайти на твои локальные сайты, и например оставить там какие-нибудь нехорошие комментарии (если в примеру ты делаешь блог). Ну и если у тебя там какой-нибудь phpmyadmin и база без пароля, то они смогут залезть в нее.
> зачем постоянно прописывать хосты в hosts
Чтобы обращаться к локальному сайту по имени. Запись в hosts говорит ОС на твоем компьютере что имени X соотвутетвует Ip адрес Y.
> как прописывать их, если хочешь расшарить виртуальные хосты в сеть
Надо понимать что такое DNS и как она работает. DNS это система которая преобразует имя хоста вроде example.com в IP-адрес. Подробнее в вики: https://ru.wikipedia.org/wiki/DNS
Как видишь, DNS состоит из частей, которые под нашим контролем (файл hosts или свой DNS сервер) и которые не под нашим (чужой DNS сервер).
Потому тут все зависит от того, какая сеть. если это твоя локальная сеть, то проще всего поднять свой DNS сервер (такая функция может быть даже в некоторых роутерах, хотя я не уверен) и поменять настройки подсоединенных к сети устройств чтобы они использовали его.
Если ты хочешь поделиться своим сайтом со всем интернетом, тут все сложнее. Тебе надо:
- купить домен
- настроить для своего компьютера «белый», то есть доступный снаружи, Ip адрес (эта услуга есть не у всех провайдеров и обычно она платная).
- настроить домен чтобы он указывал на твой внешний IP адрес
> как прописывать их на vps под никсами?
Ты прописываешь хосты не на сервере а на компьютере с которого смотришь сайт, чтобы он мог понять какому IP соответствует имя хоста. Если ты арендуешь VPS то скорее всего к нему бесплатно дают технический домен вроде server1234.example.com и ты можешь пользоваться им без настройки.
> Это нормально, что даже сишнику с зарплатой вдвое выше надо знать вдвое меньше, чем джуниору php?
Это тебе кажется, что меньше. Я сомневаюсь, что со знаниями типичного PHP джуниора можно вообще что-то написать на Си. Ты же в одних указателях запутаешься. Да и на вакнсии «сишника» обычно требуется не только умение написать функцию сортировки массива, а Си++, шаблоны, std::, Boost, какую-нибудь GUI библиотеку и знание особенностей разных API.
> Или достаточно поверхностных знаний уровня helloworld по тому же js?
Зачастую да.
Хорошо. Тогда еще маленькое улучшение сделай. Подумай, как упростить выражение в $replace. Ну например, если сначала очистить номер, то replace можно будет записать значительно в более простой форме.
А у меня белый ип, в итоге поднятые у меня сайты доступны не только по локалке. Я не против тащемта.
Ну это твое дело, ок. Но вообще, сайты удобнее хостить на хостинге хотя бы потому что при перезагрузке/зависании/проблемах с электричеством/забыл за инет заплатить/взял ноут с собой они не отключатся.
Ага, мне просто не жалко, если какая-то хрень забредет.
Спасибо.
>Лучше если есть время, решить хотя бы 2 или 3 задания из тех что даются после учебника ОПа. Ссылки на них стоят в ОП-посте этого треда, задача про студентов и файлообменник.
Ну я сейчас заканчиваю учебник ОПа, да. Вроде неплохо справляюсь, пока что.
Калькулятор делал, Денвер поставил себе.
>но лучше переучить чем недоучить
Согласен, да и хочется впечатление получше о себе произвести. :з
Просто и поскорее устроиться на работу хочется тоже.
>>433199
Ну я не в ДСах, но околомиллионник.
А что могут спрашивать на собеседовании?
Что в резюме писать?
> Сразу скажу, у меня есть ощущение что при залогинивании из нескольких браузеров/устройств одним пользователем там могут быть какие-то баги. Ты проверял это? закрытие соединения != выход юзера из комнаты
Интуиция тебя не обманула :) Да, если из нескольких браузеров один и тот же юзер зайдет в комнату, а потом в одном из браузеров выйдет из комнаты - то он пропадет из списка юзеров этой комнаты. Хотя из других браузеров он всё ещё сможет посылать в них сообщения.
Очевидно надо как то запоминать соответствие "отдельный юзер -> массив его подключений -> массив комнат каждого подключения". И рассылать извещение о выходе из комнаты только тогда, когда нет больше ни одного подключения с этой комнатой.
>Не очень понятно в чем разница между 2 функциями
В том что removeUserFromRoom только удаляет юзера из комнаты в БД, а leftUserFromRoom ещё и генерирует эвент чата, типа "выход юзера из комнаты".
>>433292
>А, еще, если будешь тестировать производительность то стоит поставить более хорошую библиотеку для ReactPHP. Скорее всего по умолчанию он использует StreamSelectLoop... libevent самая старая библиотека....
Да, все это есть в доках к Ratchet. Я на свой тестовый сервер libevent не ставил, но, судя по докам Ratchet, достаточно просто её поставить, и она начнет автоматически использоваться. Ничего в коде менять не надо.
>Я ищу обычно библиотеки на phptrends
Супер, то что надо, спасибо. Буду тоже пользоваться. Пороюсь там. HWIOAuthBundle выглядит многообещающе.
>Я кстати тут решил глянуть в твоем гитхабе (любопытно же), не делал ли ты что-то раньше из наших заданий и увидел там файлообменник.
Ты его проверял, это было почти год назад, не трать время.
>Кстати, ты тестами позаниматься не хочешь? Тесты — вещь интересная
Да, обязательно, только чуть позже. Щас я осиливаю
http://symfony.in.ua/creating-blog-symfony2-symblog-tutorial.html
Как закончу - потом в планах книжка
Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
А потом тестами займусь
> Ты не делал никаких нагрузочных тестов?
Нет, не делал. Но очевидно, что будет проблема, если к чату будет подключено много AJAX клиентов. Ибо каждый такой клиент - это 1 запрос в секунду. 50 клиентов - 50 запросов\сек.
Там надо серьёзно поработать над кешированием, чтоб БД не сдохла под навалом запросов.
Кто внятно и структурировано может объяснить, что должен знать и уметь php-программист на позициях:
-junior
-middle
-senior
Проблема в том, что скоро планирую устраиваться куда-нибудь в офис. До этого фрилансил. Соответственно объективно себя оценить не могу. И не знаю на какую позицию отправлять резюме.
если ты только начинаешь, ещи senior позиции
junior это роли для матёрых девелоперов
middle - менеджеры/hr
И стоило тратить время чтобы такую хуйню сказать? Юмор уровня /b.
strtr очень умная функция, ищет сначала длинные кусочки как я понял, а потом уже короткие
могла бы мой "тест" побуквенно заменить, но нет, заменила целиком.
http://ideone.com/rljkHI
Видел я эту книгу давно. Там простые вопросы очень. Это какой уровень? Junior?
Сап, программач.
Есть один проект, который мне поручили разработать, суть такова:
клиент-серверное веб приложение по типу дневника. Требуется, чтобы все изменения происходили без перезагрузки странички, ну, и быстро/безопасно, очевидно.
Т.к. никогда ранее подобное не писал, решил спросить здесь, насчёт адекватности архитектуры, элементы которой таковы:
- тонкий сервер (php) и толстый клиент (js);
- не использовать сессии, ограничившись куками (через js), в которых хранить имя юзера и хэш пароля;
- при каждом действии юзера, подразумевающем обращение к серверу, генерировать ajax запрос, куда включать и данные юзера из кук для проверки прав доступа;
- все действия на сервере делать, используя PDО, чтобы исключить риск SQL-инъекций;
Наверняка здесь подход дико кривой и местные гуру не одобрят, но я очень буду рад любому совету/ссылке/примеру по аналогичным реализациям.
Спасибо.
Там же написано
Толстый клиент - это скорей десктоп приложение, а в твоем случае необходимо реализовать одностраничное приложение (SPA, или как его называли раньше Rich Internet Application). Хранить ассоциированную с пользователем информацию лучше на стороне сервера, а пользователю отдавать идентификатор сессии в виде куки. Этот паттерн описан у Фаулера под названием "хранение информации на стороне сервера и на стороне клиента". Далее тебе необходим слой персистирования данных - лучше всего заюзать какую нибудь легковесную ORM. Соответственно, тебе потребуется составить модель данных предметной области - выделить основные сущности, взаимосвязи между ними, их атрибуты. Эту работу лучше всего произвести в первую очередь. Не забудь о нормализации этой модели в случае использования реляционного источника данных. Затем тебе необходимо спроектировать структуру объектов, которые будут передаваться от сервера к клиенту и обратно. Такие объекты принято называть DTO, очень рекомендую прочитать описание этого паттерна все у того же Фаулера. Серверный код может формировать json с этими объектами по запросу пользователя.
Если каждый объект предсетной области досткпен по уникальному адресу, а действия над объектом выполняются при помощи GET/POST/PUT/DELETE методов - речь идет о RESTFul API. Существует масса решений для организации такого подхода, рекомендую взять готовый код и связать его с твоей ORM.
1) Т.е. при корректном логине, присваивать новый сгенерированный идентификатор, записывать его в БД и проверять уже соответствие ему при каждом действии до тех пор, пока юзер не сделал логаут?
2) ORM простенькую планировал сам накидать, но если таки использовать, какую посоветуешь?
3) Тоже планировал использовать JSON для получения данных, но не будет ли проблем при больших массивах данных?
Фаулера почитаю, спасибо за ответ.
Потому что вы байтоёбы, вот и беситесь.
Не знаю, может быть потому что там чсвшные личности сидят по большей части? Ну а мы тут копошимся в своем мирке не претендуя ни на что.
Наоборот же крестопетух ни на что не претендует, кроме чсв в своем же манямирке. Местные - вечные студентики с лаба1.срр. О том, что там в реальной жизни крутого делается на любимых крестах они только рассуждать могут, сами не принимая в этом участия, вот и бесятся.
>Местные - вечные студентики с лаба1.срр.
И как можно "любить" язык, когда у тебя лаба1.cpp? Ты же ничего о нем не знаешь.
мимо-лаба8.cpp
Утята, вот и любят.
Да, сначала длинные, а потом короткие, это специально (иначе длинные не заменятся).
>>433641
> толстый клиент (js);
Толстый клиент — это полноценное JS приложение с моделями на клиенте.Если ты шлешь аякс и получаешь куски с сервера то это не толстый клиент, а просто создание видимости тостого клиента и практиечской пользы от этого никакой нет (но работать будет без перезагрузки, да).
JS приложение сделать намного сложнее, его преимущества в том, что оно может например работать в офлайне (теоретически может, большинство ангулар- и метеор- детей сделать так все равно не умеют, так как это не описано в мануале). Недростатки в неиндексируемости гуглом, надо больше труда, скорее всего нужна нода на сервере чтобы не дублировать код, сложности при большиъ объемах данных. В общем, выбирать надо тщательно проанализировав задачу.
В твоем случае думаю нужен простой вариант с аяксом (еще раз повторю что смыла использовать тут аякс особо нет, кроме как проверит твои знания).
> генерировать ajax запрос, куда включать и данные юзера из кук для проверки прав доступа;
Они и так по умолчанию передаются вместе аякс запросом.
> Наверняка здесь подход дико кривой и местные гуру не одобрят
Не обобряют бессмысленное прикручивание аякса но раз так требует задание...
> Хранить ассоциированную с пользователем информацию лучше на стороне сервера, а пользователю отдавать идентификатор сессии в виде куки.
Ты предлагаешь добавить лишнюю сущность - сессию без пояснения зачем. Информация о пользователе и так наверно хранится в БД.
Не говоря о том что сессии и REST вообще плохо стыкуются (потмоу что stateless transfer).
> Далее тебе необходим слой персистирования данных - лучше всего заюзать какую нибудь легковесную ORM
Да, это хорошая идея, но приложение простое, таблиц и связей мало, может быстрее на SQL запросах сделать чем разбираться с ORM. ORM становится необходим когда таблиц/связей много, а когда их мало и на запросах несложно написать.
> Такие объекты принято называть DTO
По моему DTO это другое. Тем более что JSON (который обычно используется) не передает объекты. Соответственно и DTO тут нет и не нужно.
В общем, ты написал какую-то ерунду. Лучше бы написал как сдеать чтобы модели и там и там не дублировать (мое решение — не испольщовать модели на клиенте а использовать аякс).
REST API хорощо подходит для написания АПИ, но плохо подходит для приложений. Почему — предлагаю экспертам по новомодным хипстатехнллогиям догадаться самостоятельно.
>>433661
> Т.е. при корректном логине, присваивать новый сгенерированный идентификатор, записывать его в БД и проверять уже соответствие ему при каждом действии до тех пор, пока юзер не сделал логаут?
Это лишнее усложнение которое ничего не дает
> ORM простенькую планировал сам накидать, но если таки использовать, какую посоветуешь?
Либо готовую либо на SQL запросах делать, как быстрее выйдет
> Тоже планировал использовать JSON для получения данных, но не будет ли проблем при больших массивах данных?
Твое дело, но по моему проще передавать с сервера готовый HTML. Формально требования задачи соблюдены. У тебя задача сделать проще и быстрее или усложнить себе жизнь?
Ошибки убрал, но вот с time не придумал ещё как пофиксить
>В итоге в time к концу цикла будет старое значение time + AB + AC + AD + AE + AF ... + AZ.
Не знаю куда впихнуть тогда счетчик чтобы не плюсовал всё подряд, есть подсказки?
Я уже попробовал переделать функцию чтобы она все результаты вывела в массив и уже результаты отсеять по времени, но массив семимерный выходит и с ним потом сложно будет работать.
> Не знаю куда впихнуть тогда счетчик чтобы не плюсовал всё подряд, есть подсказки?
Сделать копию переменной
Прибавлять время к этой копии, не трогая саму исходную переменную.
>>433747
1) В ТЗ явно не фигурирует JSON и AJAX, это моя идея, т.к. я раньше с ними работал, под них есть готовые наброски кода.
2) Первое время у проекта не будет мощного сервера, поэтому я и стараюсь максимально разгрузить серверный код, ограничившись работой с БД, и, чтобы минимизировать как нагрузку, так и объём данных, переводить их в JSON и отправлять клиенту.
3) >Это лишнее усложнение которое ничего не дает
Но это же лучше, чем хранить хэш пароля в куках?
Сап пхпач.
Я начал проходить ваш первый учебник и столкнулся с первой своей проблемой.
http://ideone.com/dycYT5
Расскажите как записать дешифровку шифровки чегото я сам не догоняю.
> Первое время у проекта не будет мощного сервера, поэтому я и стараюсь максимально разгрузить серверный код, ограничившись работой с БД
На сколько ты разгрузишь серверный код? С чего ты взял что рендеринг на клиенте ускорит работу сервера? Ты хотя бы оценку (не говоря про тесты) делал? Ты ради воображаемой оптимизации меняешь архитектуру. Так ты далеко не уйдешь.
Ну и архитектуру надо планировать исходя из того как будет использоваться приложение. Я не очень понял о каком дневнике идет речь, о школьном? В этом случае надо учитывать что скорее всего родители будут октрывать этот дневник раз в день в лучшем случае, и им без разницы с перезагрузкой он работает или нет (и простой HTML в таком случае будет открываться быстрее). А вот интерфейс преподавателя, с которым он будет работать, скорее всего будет постоянно открыт и там при грмаотном подходе можно повысить удобство работы за счет аякса или создания клиентского приложения.
Насчет сервера, скорее всего ты ничего не выиграешь от передачи данных в JSON. Наоборот. при кривой реализации все будет работать медленее и требовать больше запросов, не знаю как сервер, а со стороны пользователя будет грузиться дольше.
Не генерируй новый токен. Это неправильно так как если открыть страницу во второй вкладке то сгенерируется новый токен, а токен с первой страниц устареет.
Архитектуры как раз пока и нет, пока я планирую и ищу наиболее оптимальный вариант.
>>433773
Дневник - иллюстрация структуры приложения. Пользоваться им будут 10-15 человек одновременно (смешно, да?), но запросы и изменения будут вноситься раз в минуту где-то, объём объектов в БД - несколько сотен.
>Насчет сервера, скорее всего ты ничего не выиграешь от передачи данных в JSON. Наоборот. при кривой реализации все будет работать медленее и требовать больше запросов, не знаю как сервер, а со стороны пользователя будет грузиться дольше.
Собственно, на сервере ответ, после получения массива из БД, например, будет посылаться возвращаться через аякс как echo json_encode($arr) куда уж проще сделать?
Если куки нет, то генерируем. Если есть то не генерируем, а выставляем куку со старым. Куку можно ставить на несколько часов (так как при каждом обновлении страницы она восстанавливается).
Если паранойя то при залогинивании/разлогинивании можно также принудительно менять токен.
Таким образом токен очистится как только пользователь на несколько часов уйдет с сайта. А пока он на сайте, токен не меняется и все формы работают.
Некоторые предлагают генерировать токен ан основе IP но это плохая идея так как при динамическом IP пользователь может загрузить страницу с одного IP, а отправить с другого. Так ты получишь труднообнаружимые баги.
Если у тебя миллионы пользователей найдутся те у кого куки отключены/блокируются/режутся и у них формы перестанут отправляться. Для таких можно доабвить проверку что куки включены (яндекс ее делает и выводит соотв. сообщение, попробуй отключить куки и авторизоваться, увидишь).
Также, ты можешь очистить куки, открыть отладчик (Ctrl + Shift + I) и изучить как сделаны токены на других сайтах, например, вконтакте (у них токен в страницу вписан и его легко найти), фейсбук (хотя у них там скриптов много накручено, трудно наверно понять), и аналогчиные.
И передавать её внутрь рекурсивной функции? Не совсем понял как реализовать то
Сейчас у тебя сделано так (если упростить код):
// сколько потрачено времени чтобы добраться до текущей точки
$time = 10;
// допустим это время пути из текущей точик в ссоедние
$points = array('b' => 1, 'c' => 2, 'd' => 3);
foreach ($points as $name => $pointTime) {
$time += $pointTime;
echo "t=$time чтобы добраться до $name\n";
}
То есть все время складывается в одну перемнную и выводится t = 11, t = 13, t = 16. Исправь, чтобы не складывалось и программа писала:
t = 11 до точки b
t = 12 до точки c
t = 13 до точки d
Прочитал мануал, так и не понял. Что у меня должно быть в скобках под array_flip. По ходу дела $code. Но тогда В расшифровке просто пишет Array.
http://ideone.com/VlcSYz
Эт я знаю, я только не понял как мне через временную переменную решить проблему
Ну ты код который я написал, можешь переделать чтобы он выводил 11, 12, 13 а не то что сейчас? Любым способом, который знаешь. Или нужна подсказка? Или сам знаешь как сделать?
Посомтри внимательно внизу на ideone:
> PHP Warning: array_flip() expects parameter 1 to be array, string given
В функцию array_flip надо передавать массив, а она вернет «перевернутую» копию, где ключи и значения поменяны местами. То есть ты даешь ей массив
[ x => 1, y => 'hello'] а она вернет [ 1 => 'x', 'hello' => 'y' ]
чтобы увидеть содержимое массива ($ras) используй var_dump($ras), echo не умеет выводить массивы.
Ты сделал, но очень неуниверсально. Смотри, ты прямо вписал проверки в код profile.php. Но было бы гораздо лучше вынести это в функцию с соотв. названием:
createXsrfCookie() — создает с нуля или продлевает XSRF-куку, и возвращает значение токена
Для проверки можно тоже сделать функцию, можно не делать.
Вместо «произошла ошибка» надо просить отправить форму еще раз.
Спасибо, я первый раз видимо жопой прочитал вот этот пост >>433797
>>433295
http://ideone.com/aq9trR
https://github.com/Si0n/phpandsoon
Вот, допилил финальную версию, надеюсь всё хорошо.
Код требует улучшений, конечно.
Там еще есть неточность. Непонятно, зачем lowerTime передается рекурсивно во все вызовы функции. Эта переменная не должна передаваться.
Ну или объясни зачем она нужна и почему без нее работать не будет.
Далее,
> $time = 0, $lowerTime = 5000, $pathDone)
Незачем тут давать значения по умолчанию, так как они не исопльзуются
Вместо 5000 можно использовать константу INF которая обозначает бесконечность (да, в компьютерной математике предусмотрена бесконечность): http://php.net/manual/ru/math.constants.php
Для проверки на бесконечность нельзя использовать == (то есть 2 бесконечночти не равны между собой, что логично) но есть функция: http://php.net/manual/ru/function.is-infinite.php
Далее, вот тут
> $result['path'] = $pathDone;
> $result['time'] = $time;
лучше написать return array('path' => ..., 'time' => ..) чтобы было более очевидно.
Далее, при остутсвии оптимального пути надо возвращать не пустой массив, а null.
Далее, непонятно зачем тут писать 2 строки
> $result = $shortest;
> return $result;
если можно записать сразу return.
далее, тут у тебя огромный иф:
> if (!in_array($stationName, $pathDone)) {
Надо его перевернуть таким образом:
Если (станция уже есть в пути) {
пропустить этот вариант;
}
Код требует улучшений, конечно.
Там еще есть неточность. Непонятно, зачем lowerTime передается рекурсивно во все вызовы функции. Эта переменная не должна передаваться.
Ну или объясни зачем она нужна и почему без нее работать не будет.
Далее,
> $time = 0, $lowerTime = 5000, $pathDone)
Незачем тут давать значения по умолчанию, так как они не исопльзуются
Вместо 5000 можно использовать константу INF которая обозначает бесконечность (да, в компьютерной математике предусмотрена бесконечность): http://php.net/manual/ru/math.constants.php
Для проверки на бесконечность нельзя использовать == (то есть 2 бесконечночти не равны между собой, что логично) но есть функция: http://php.net/manual/ru/function.is-infinite.php
Далее, вот тут
> $result['path'] = $pathDone;
> $result['time'] = $time;
лучше написать return array('path' => ..., 'time' => ..) чтобы было более очевидно.
Далее, при остутсвии оптимального пути надо возвращать не пустой массив, а null.
Далее, непонятно зачем тут писать 2 строки
> $result = $shortest;
> return $result;
если можно записать сразу return.
далее, тут у тебя огромный иф:
> if (!in_array($stationName, $pathDone)) {
Надо его перевернуть таким образом:
Если (станция уже есть в пути) {
пропустить этот вариант;
}
> https://github.com/Si0n/phpandsoon/blob/master/Navigate2.php#L198
> for ($i = 0; $i < count($path['path']); $i++) {
Для перебора массива удобнее (и код читается проще) использовать foreach
далее, эти 2 строчки:
> https://github.com/Si0n/phpandsoon/blob/master/Navigate2.php#L170
> $xTime = $time;
> $xTime += $pointTime;
Можно заменить на одну.
Если кука существует, надо продлить ей жизнь на 3 часа. а то у тебя она умирает через 3 часа после первой установки и может умереть в процессе взаимодействия пользователя с сайтом.
А ты проверял код?
> setcookie("studentscookie[token]", generateToken(), time()+60603, "/");
> return $_COOKIE['studentscookie']['token'];
setcookie по моему не заполняет массив COOKIE, это лишь массив пришедших от пользователя кук.
Чтобы не было повторов, надо time()+60603 вынести в переменную.
Если зайти незарегистрированным и без кук то на странице /profile.php выводится ошибка:
> Notice: Undefined variable: token in D:\mm\templates\profile.html on line 25
Выводится ли она у тебя? Если нет, то у тебя может быть отключено отображение ошибок. Надо включить display_errors = On либо смотреть ошибку в логах.
Ну и ошибка все же есть. Если зарегистрироватьяс, в отладчике удалить куку token (в Хроме куки удаляются в отладчике на вкладке resources) то при заходе на profile.php пишет:
> Notice: Undefined index: token in D:\mm\lib\functions.php on line 59
То есть setcookie не заполняет массив _COOKIE и код все же не совсем верный.
Теперь ошибок быть не должно, по крайней мере в логе я ничего не увидел.
В Апаче там только конфиг можно менять. Онобычно раскидан по файлам в /etc/apache2/
Почитать можно доки Апача про формат конфига: http://httpd.apache.org/docs/2.4/configuring.html
У Апача есть базовые директивы, а есть директивы настройки модулей, она доступны только если подключен тот или иной модуль. Базовые: http://httpd.apache.org/docs/2.4/mod/core.html
Остальные, по модулям: http://httpd.apache.org/docs/2.4/mod/
Про особенности того, как разложены файлы конфига надо читать документацию дистрибутива. Вот для дебиана например: http://debian-handbook.info/browse/stable/sect.http-web-server.html (нангуглено по debian apache config)
Если у тебя есть более конкретный вопрос, «как настроить чтобы при X появлялось Y» то гугли или спрашивай тут.
Действительно. Хотя если обновить ошибка пропадает. Честно говоря я в тупике. Не понимаю почему так происходит. Должно же ставится куки, если его не существует, и ставится ведь, но только если обновить страницу.
Еще, кстати, заметил, что при выходе куки с токеном не удаляются, хотя должны. Удаляются, только если нажать выход два раза. Очень странно.
Функция setcookie не меняет массив _COOKIE. Этот массив содержит только пришедшие из браузера до выполнения скрипта куки и не обновляется в дальнейшем. Попробуй проверить сам, поставив var_dump(COOKIE) до и после setcookie.
Итак единственное решение, пришедшее мне в голову, это переадресация в блоке else, но после того, как я добавил после Setcookie строчку header("Location: $currentPage"); мне выдает пикрелейтед
Решение неверное. Зачем делать редирект? Тебе вообще не нужен COOKIE в этом случае. Просто верни через return только что сгенерированный код.
И ведь лет 5 назад, когда фейсбук (или твиттер?) сделал впервые бесконечную прокрутку, подробно разобрали что там плохого и хорошего. Нет, дети хотят наступить на те же грабли еще разок.
Это мне почему-то напомнало случай, когда заказчик при разработке сайта просил добавить в угол часы. Да, это не выдумка, они действительно так просят сделать.
Мне нужна оценка на эту задачу! Я понимаю что все работает, но у меня есть подозрение, что можно было её через цикл решить или типа того. Я упустил какой-то хороший прием тут?
Что-то я пропустил эту задачу.
Все решено верно. Вместо mt_rand(0, count($words2)-1) можно использовать array_rand, но разницы особой, что именно использовать, нету.
Ну и стихи получились забавные.
Решай задачки дальше, там скоро регулярки будут, они чуть посложнее.
>Фаулера под названием "хранение информации на стороне сервера и на стороне клиента"
"Возвращаемая функция должна принимать любое количество аргументов и передавать их функции fn"
Я могу явно задать аргументы и передать их функции, но тогда их будет не любое количество.
Знаю, что есть arguments, но дальше ничего сделать с этим не могу. Нагуглил про "функции с переменным числом аргументов", но кажется, что это не то.
http://learn.javascript.ru/this#метод-apply
http://javascript.ru/Function/apply
Принимает массив с любым числом аргументов
> А что могут спрашивать на собеседовании?
Разное. Кратко вопросы можно разделить на типы:
- теория: что такое транзакция в БД? Что такое внешние ключи? что такое цикл?
- подвохи: что выведет код var_dump("x" == 0) ? Что выведет код if (array()) { echo "yes"; } ? Что выведет код $x = 'a'; $x++; echo $x; ? Какими функциями php можно выставить куку? Чтобы не бояться подвохов, стоит перечитать мануал.
- нормальные вопросы: как сделать X в языке Y?
- написать код/решить задачу
- ненормальные вопросы: кем вы видите себя через 5 лет? Почему мы должны взять именно вас? Почему люки круглые? почему у вас в X лет до сих пор нет опыта работы?
Залей код куда-нибудь на jsfiddle или codepen. Алсо, ты гуглил «центрирование по вертикали в CSS»? Это отдельная сложная тема.
Если высота блока известна можно просто сделать top 50%; margin-top: -200px; где 200px это половина высоты.
Ок, теперь все верно.
>>433462
Прочитал как «будет ли у меня сегодня свет» и пожалел автора.
>>433474
Молодец, все верно. Я вижу, ты там даже первую букву заглавной сделал.
>>433485
Есть такое понятие как «текущая директория». Ее можно увидеть функцией http://php.net/manual/ru/function.getcwd.php и поменять функцией http://php.net/manual/ru/function.chdir.php
Если ты не указываешь абсолютный путь к файлу (начинающийся со слеша или диска, например c:/hello или /hello.txt) то файл ищется в текущей директории.
Если ты запускаешь скрипт из командной строки то используется текущая директория которая была выбрана до запуска. Если через браузер и сервер то текущей директорией ставится та, в которой находится скрипт.
так что в твоем случае, если ты запускаешь через браузер то да,
> Только в директории где был вызван скрипт
http://dou.ua/lenta/columns/junior-middle-senior-kakimi-popugayami-meryaem/
https://toster.ru/q/124171
http://www.gamedev.ru/industry/forum/?id=143383
http://anton.shevchuk.name/project-management/developers-rank/
http://dev.by/lenta/main/junior-vs-intermediate-vs-senior
Разница в опыте, знании технологий уровне ответственности и самостоятельности.
В разных компаниях уровни разные, сеньор в одной компании может быть слабее миддла в другой.
Если у тебя 0 опыта, ты можешь претендовать только на должноть джуниор или стажер.
Наверно лучше спросить в одеск-треде у тех, кто получает эти 10 баксов? Скорее всего, как минимум нужно знать сам язык и какой-нибудь фреймворк.
Делал по этому мануалу http://www.if-not-true-then-false.com/2010/install-mysql-on-fedora-centos-red-hat-rhel/
комп подключен к роутеру, подключенный к роутеру ноут по идее должен видеть локалхост компа? Подключаюсь по ипу компа.
Сам начинал с пхп, и очень рад, что не стал в итоге макакой.
Мельком посмотрел, у тебя здесь ошибка наверное:
> trim($_GET['search'] != "")
Надо: trim($_GET['search']) != ""
не ОП
>сборка мусора
Референс каунтер c алгоритмом поиска циклических ссылок.
http://php.net/manual/ru/features.gc.php
>модель памяти
http://www.phpinternalsbook.com/zvals/memory_management.html
zval контейнры, copy-on-write и т.д. По управлению памятью ничего особо нет, на запуске скрипта резервируется кусман памяти указанный в php.ini, при выходе за его пределы - рантайм иксепшн. Вот ещё норм статья:
http://habrahabr.ru/post/134784/ там под ней тоже много хороших ссылок.
>жизненного цикла приложения (инициализация, обработка HTTP-запросов, завершение работы)
Пхп стоит за апачем как правило, хотя можно поднять php-fpm и поставить за nginx, но это уже сорт оф танцы с бубном. Т.е. http запрос идёт на вебсервер (в 90% случаев апаче), тот запускает php интерпретатор на каждый реквест в своём треде и запихивает ему в инпат распарсенные данные из запроса, в пыхе к ним уже можно обращаться через всякие $_REQUEST, $_POST, $_GET и т.д, хотя как правило фреймворки оборачивают это всё ещё одним слоем абстракции. Дальше пхп выполняет работу, выплёвывает в аутпут данные которые летят клиенту в качестве ответа (апач заголовки ответа генерит сам, хотя с пыхи можно в это дело вмешаться) и умирает. С использованием php-fpm можно сделать так, чтобы инстансы пхп не запускались на каждый реквест, а висели и ждали запросов, но это посложнее.
>многопоточности
Не стоит вскрывать эту тему. Обёрка pthreads есть, но весьма нирекамендую, там половина не работает. Многозадачность в пыхе обычно строится (на самом деле почти никогда этим никто не занимается) на процессовом взаимодействии со всякими лоу левел обёртками над posix или cntl типа proc_open, pcntl_fork и работу через пайпы, stream_select, posix_kill, а то и вообще голых вызовах exec/passthru/system но тоже не рекомендую, по понятным причинам.
Так вот, там указано
>>Надо использовать ООП
С ООП я знаком, но как именно присобачить его сюда на практике? И где прочитать про то, для чего как и где следует использовать ООП?
Выдели сущности, запили по ним классы.
https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a
Посмотри.
https://github.com/tokotun/matriculant
Ну, надеюсь верно я подправил.
Теперь пытаюсь с Твигом разобраться
Выводит ошибку Fatal error: Uncaught exception 'Twig_Error_Loader' with message 'The "/templates" directory does not exist.
Не может найти шаблон ни как не пойму почему.
https://github.com/tokotun/twig
Если буду постигать PHP каждый день по часику, глядишь лет через 15 стану джуниором
You don't have permission to access the requested object. It is either read-protected or not readable by the server.
If you think this is a server error, please contact the webmaster.
Error 403
localhost
Apache/2.4.10 (Win32) OpenSSL/1.0.1h PHP/5.4.31
В чём дело?
https://github.com/sqghub/TestHub
Распиши лучше подробно весь свой путь, начиная с первых шагов и до сегодняшнего дня, пришел ли к успеху?
>пришел ли к успеху?
Он занимается тем, что сидит на дваче и срет в пхп треде. Как ты думаешь, он пришел к успеху?
Алсо, после прохождения этого мини-учебника какую литературу почитать? (Ну или какой-нибудь интерактивный онлайн учебник, например)
Спасибо той няше, что сделала http://archive-ipq-co.narod.ru/
http://ideone.com/ZmxWeZ
На пикрелейтед было в аналогичной ситуации. Вот и пишу.
>после прохождения этого мини-учебника какую литературу почитать?
Бамп вопросу.
>>434468
Спасибо за ответы. Правда я сейчас задумался, может всё-таки на Питоне попробовать переписать.
Может потому, что у тебя условий на 9 чисел, а число может быть любым, от 0 до 99999?
http://ideone.com/u058sY
http://ideone.com/x9dG1R
http://ideone.com/ug2yag
Сделал. Возможно ли это было сделать как-то по-иному, чтобы сократить код?
А в чем суть программы вообще? Зачем вычислять остаток от деления? Что-то я не помню ничего такого в задачах опа.
В foreach после as идут временные переменные, любые действия с ними никак не влияют на оригинальный массив.
Не понимат. Гляди:
if ($roulette >= 99) // это если $рулетте БОЛЬШЕ ИЛИ РАВНО 99-ти (что странно, так работает), хотя по логике должно быть МЕНЬШЕ ИЛИ РАВНО (а так не работает, я проверял).
ЧЗХ?
Но там же написано, что чтобы найти последнюю цифру, нужен остаток от деления числа на 10. А у тебя и на 1000 делится и на 100, не понятно зачем.
>>434495-кун
Не надо ничего переделывать. Просто внутри foreach если ты хочешь изменить исходный массив, нужно к нему напрямую и обращаться. Допустим у нас есть массив array, мы хотим найти в нем значение яблоко и поменять на апельсин:
http://ideone.com/P2vSBh
У тебя там уже for стоит.
Во, огромное спасибо!
Это опять я. Не можешь подсказать, почему перед запятой пробел не убирается? Регулярка нормальная вроде.
У ОПа пхп-тредов наконец-то бомбануло?
Немного подделал, но пробел ПЕРЕД запятой все равно не хочет убираться. Halp!
http://ideone.com/gJQ19o
И там не надо было все знаки препинания вставлять. В 3м примере неправильно программа работала.
>>434011
Теперь все стало запутанно: https://github.com/MindiMakridi/Students/blob/master/profile.php
Например, найди здесь место где выставляется токен для незарегистрированного пользователя?
Все должно быть проще. Мы в начале файла profile.php выставляем токен в куках, а если форма отправлена, то заодно сверяем его с данными из POST. То есть должно быть в одном месте написано createXsrfCookie и в одном проверка $_POST['token']==$token. А у тебя там все как-то хаотично раскидано.
Ну и выход с сайты ты забыл защитить через проверку токена.
И еще, я просил вместо явной передачи $report в URL передавать коды, чтобы нельзя было вывести произвольное сообщение на сайте.
Тем более что ты неправильно формируешь тут URL:
> $report = "Вы успешно зарегистрировались";
> header("Location: http://students.ru/profile.php?msg=$report");
В URL не может быть пробелов. Когда ты подставляешь какие-то данные в query string ты должен экранировать спецсимволы с помощью urlencode() которая заменяет спецсимволы, в том числе пробел, на коды со знаком процента.
Давай доделаем уже, там немного осталось.
Еще тут непраивльно:
> https://github.com/MindiMakridi/Students/blob/master/templates/header.html#L13
> <input type='hidden' name="<?=$token ?>">
Все получилось. В "действие1" в цикле for я не знал чего вставить, тупо сделал то же самое, что и в 5 строке.
Поправьте, если что через жопу.
Этот анон >>434214 правильно заметил ошибку.
>>434226
Мануал наверно: https://php.net/manual/ru/langref.php
> Особенно интересуют вопросы модели памяти, многопоточности, жизненного цикла приложения (инициализация, обработка HTTP-запросов, завершение работы) и, немного, как там устроена сборка
Чтобы писать сайтик, тебе это не понадобится. Но рассказать могу, почему нет.
PHP обычно работает либо как плагин (динамически подключаемая библиоетка) в составе веб-сервера (Апач), либо как отдельный процесс (php-fpm организует пул таких процессов, соединяющихся с фронтенд сервером по протоколу FastCGI). Обработка HTTP запросов реализована в интерпретаторе таким образом, что пришедший запрос разбирается и данные из него заполняют глобальные массивы вроде GET/POST/COOKIE до запуска скрипта. Таким образом, тебе не нужен громоздкий стек для примера запросов и разбора HTTP: этот функционал уже встроен. Глобальные массивы подробно описаны в документации.
Фреймворки предлагают ООП-обертки для этого, например Symfony 2 содержит компонент HttpFoundation предлагающий классы Request и Response, аналоги которых ты наверняка видел в ява-фреймворках.
В PHP не используются должгоживущие серверные процессы, которые открывают порт, принимают Tcp-соединения, и т.д. Всем этим занимается веб-сервер, а твой скрипт запускается уже для обработки принятого и разобранного запроса, причем после отдачи пользователю ответа скрипт завершается. Это упрощает написание кода, так как можно не беспокоиться об освобождении ресурсов, организации разных пулов — все освобождается автоматически.
Фактически ты пишешь скрипт, который получает на вход разобранный HTTP запрос и все, что он выведет на stdout отправляется обратно в браузер, после чего скрипт завершается.
То, что на каждый пришедший HTTP-запрос запускается новый процесс PHP — миф. Один процесс может обработать много запросов, а вот приложение обычно запускается каждый раз заново, это верно. Обычно запускается либо несколько рабочих потоков, либо несколько рабочих процессов, что позволяет задействовать все ядра на сервере. Число рабочих процессов может регулироваться в зависимости от нагрузки.
В PHP также предельно упрощена конфигурация сервера: ты можешь просто создать файл, допустим hello.php и при обращении по адресу http;//example.com/hello.php сервер запустит твой скрипт. То есть создание нового обработчика сводится к созданию файла. Но фреймворки обычно используют единую точку входа (index.php), и систему роутинга, с которой ты тоже наверняка сталкивался в яве.
Я советую не писать с нуля, а использовать фреймворк, предлагающий готовые классы для реализации MVC приложения. Тебе может подойти Symfony 2: он хорошо организован, полностью сделан в ООП-стиле, хорошо документирован, включает в себя прекрасный шаблонизатор Twig (c синтаксисом питоновского jinja), ORM Doctrine 2 (похожий на Hibernate), роутер, поддержку конфиграции в YML, для него есть много готовых плагинов. Но он может быть сложен для начинающего, и требует времени на изучение.
Насчет многопоточности, сам код PHP потокобезопасен. Но скрипты традиционно пишутся однопоточно, хорошей библиотеки для организации многопоточности нет. Но это и не требуетя при разработке сайтов.
Насчет сборки мусора, там 2 механизма: reference counting для типов без циклических ссылок и простой сборщик мусора для сборки того что не собралось при подсчете ссылок. Опять же, это описано в мануале: http://php.net/manual/ru/features.gc.php
Я на практике не сталкивался с какими-то пробелмами со сборкой мусора. Один скрипт на тяжелом фреймворке может в пике потреблять 20-30 Мб, если же брать простые случаи то выходит 3-5 Мб. Это на время обработки запроса, после обработки эта память может быть использована для других скриптов.
Этот анон >>434214 правильно заметил ошибку.
>>434226
Мануал наверно: https://php.net/manual/ru/langref.php
> Особенно интересуют вопросы модели памяти, многопоточности, жизненного цикла приложения (инициализация, обработка HTTP-запросов, завершение работы) и, немного, как там устроена сборка
Чтобы писать сайтик, тебе это не понадобится. Но рассказать могу, почему нет.
PHP обычно работает либо как плагин (динамически подключаемая библиоетка) в составе веб-сервера (Апач), либо как отдельный процесс (php-fpm организует пул таких процессов, соединяющихся с фронтенд сервером по протоколу FastCGI). Обработка HTTP запросов реализована в интерпретаторе таким образом, что пришедший запрос разбирается и данные из него заполняют глобальные массивы вроде GET/POST/COOKIE до запуска скрипта. Таким образом, тебе не нужен громоздкий стек для примера запросов и разбора HTTP: этот функционал уже встроен. Глобальные массивы подробно описаны в документации.
Фреймворки предлагают ООП-обертки для этого, например Symfony 2 содержит компонент HttpFoundation предлагающий классы Request и Response, аналоги которых ты наверняка видел в ява-фреймворках.
В PHP не используются должгоживущие серверные процессы, которые открывают порт, принимают Tcp-соединения, и т.д. Всем этим занимается веб-сервер, а твой скрипт запускается уже для обработки принятого и разобранного запроса, причем после отдачи пользователю ответа скрипт завершается. Это упрощает написание кода, так как можно не беспокоиться об освобождении ресурсов, организации разных пулов — все освобождается автоматически.
Фактически ты пишешь скрипт, который получает на вход разобранный HTTP запрос и все, что он выведет на stdout отправляется обратно в браузер, после чего скрипт завершается.
То, что на каждый пришедший HTTP-запрос запускается новый процесс PHP — миф. Один процесс может обработать много запросов, а вот приложение обычно запускается каждый раз заново, это верно. Обычно запускается либо несколько рабочих потоков, либо несколько рабочих процессов, что позволяет задействовать все ядра на сервере. Число рабочих процессов может регулироваться в зависимости от нагрузки.
В PHP также предельно упрощена конфигурация сервера: ты можешь просто создать файл, допустим hello.php и при обращении по адресу http;//example.com/hello.php сервер запустит твой скрипт. То есть создание нового обработчика сводится к созданию файла. Но фреймворки обычно используют единую точку входа (index.php), и систему роутинга, с которой ты тоже наверняка сталкивался в яве.
Я советую не писать с нуля, а использовать фреймворк, предлагающий готовые классы для реализации MVC приложения. Тебе может подойти Symfony 2: он хорошо организован, полностью сделан в ООП-стиле, хорошо документирован, включает в себя прекрасный шаблонизатор Twig (c синтаксисом питоновского jinja), ORM Doctrine 2 (похожий на Hibernate), роутер, поддержку конфиграции в YML, для него есть много готовых плагинов. Но он может быть сложен для начинающего, и требует времени на изучение.
Насчет многопоточности, сам код PHP потокобезопасен. Но скрипты традиционно пишутся однопоточно, хорошей библиотеки для организации многопоточности нет. Но это и не требуетя при разработке сайтов.
Насчет сборки мусора, там 2 механизма: reference counting для типов без циклических ссылок и простой сборщик мусора для сборки того что не собралось при подсчете ссылок. Опять же, это описано в мануале: http://php.net/manual/ru/features.gc.php
Я на практике не сталкивался с какими-то пробелмами со сборкой мусора. Один скрипт на тяжелом фреймворке может в пике потреблять 20-30 Мб, если же брать простые случаи то выходит 3-5 Мб. Это на время обработки запроса, после обработки эта память может быть использована для других скриптов.
Если есть какие-то конкретные вопросы, можешь задавать.
>>434249
> на запуске скрипта резервируется кусман памяти указанный в php.ini, при выходе за его пределы - рантайм иксепшн
Неверно. Память выделяется по мере необходимости. То, что указано в php.ini это ограничение для защиты от ошибок в скриптах (также можно ограничить время выполнения).
> тот запускает php интерпретатор на каждый реквест в своём треде
Неверно, один процесс интерпретатора может обработать много запросов. Треды используются на winodws, на linux (подозреваю из-за того что там треды хуже работают) используются процессы-рабочие.
> С использованием php-fpm можно сделать так, чтобы инстансы пхп не запускались на каждый реквест, а висели и ждали запросов, но это посложнее.
Это называется слышал звон, да не знаю где он. С php-fpm модель та же самая, что и с Апачом, просто под Апачом PHP подключается в процесс сервера как динамическая библиотека и функции интерпретатора вызваются напрямую, а в случае с php-fpm он запущен как отдельный процесс и принимает запросы по FastCGI. По производительности разницы особой нет, php-fpm нужен например чтобы напрямую взаимодетсвтовать с nginx или любым другим fastCGI capable сервером.
>>434477
Я думаю, в любом случеа ты за выходные не перепишешь. Но если есть еще вопросы, я может быть могу что-то подсказать.
Так как ты не привел никаикх побробностей то подсказать не могу.
>>434374
Напиши тогда так как умеешь, а я потом скажу что надо исправить. Лучше показывать код как можно раньше, меньше придется переделывать.
> И где прочитать про то, для чего как и где следует использовать ООП?
Вроде бы в книгах которые указаны в ОП-посте (Зандстра и Шлосснейгл) это есть, но вообще, когда говорят «код должен быть на ООП» это значит что он должен состоять из классов, а не из функций. То есть использовать везде, где можно.
В частности, тут можно сделать объекта-абитуриента, объект-маппер для записи и загрузки абитуриентов из базы. Конечно, ООП надо применять без фанатизма и не пытаться пихать туда, где оно не требуется.
>>434404
> with message 'The "/templates" directory does not exist.
Написано же, папка не существует.
Когда ты указываешь /templates то это значит абсолютный путь, то есть путь от корня файловой системы (на linux) или корня текущего диска (на windows). То есть папка вроде c:/templates. Тебе надо писать _ _ DIR _ _ . '/templates' — как-то так примерно.
Чтобы не было путаницы, шаблоны лучше называть x.twig или x.html.twig (так вроде принято в Симфони)
О! Я тут баг просмотрел, даже странно что мне это в глаза не бросилось.
> https://github.com/tokotun/matriculant/blob/master/app/Pager.php#L39
> '&userSearch=' . $this->userSearch .
Это баг. Когда ты вставляешь данные в Query string, ты должен экранировать специсмволы с помощью процентов (это делает функция urlencode). Иначе что делать если в userSearch окажется знак & или пробел?
То есть должно быть так:
'?a=' . urlencode($a) . '&b=' . urlencode($b)
Вот тут подробнее описано:
http://ru.wikipedia.org/wiki/URL#.D0.9A.D0.BE.D0.B4.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_URL
http://php.net/manual/ru/function.urlencode.php
Но в твоем случае можно сделать еще умнее. В PHP есть стандартная функция для сборки query string из массива: http://php.net/manual/ru/function.http-build-query.php — используй ее.
Пройдись так же по коду и исправь если где-то еще есть этот баг. Ну и старайся использовать http_build_query в таких случаях.
Что-то я забыл сам про эту функцию и сразу не сказал.
И тут опечатка:
> header("Location: login.php?action=saved");
> if ($_GET['action'] == 'save'){
Надо проверять свой код.
А так, в остальном, все верно. У тебя неплохое мини-приложение в итоге поулчилось, и выглядит аккуратно, ну и надеюсь, что аналогичную задачу ты легко сможешь решить. Ну это так, была разминка, а теперь пора переходить к изучение фреймворков и библиотек.
Чтобы не было путаницы, шаблоны лучше называть x.twig или x.html.twig (так вроде принято в Симфони)
О! Я тут баг просмотрел, даже странно что мне это в глаза не бросилось.
> https://github.com/tokotun/matriculant/blob/master/app/Pager.php#L39
> '&userSearch=' . $this->userSearch .
Это баг. Когда ты вставляешь данные в Query string, ты должен экранировать специсмволы с помощью процентов (это делает функция urlencode). Иначе что делать если в userSearch окажется знак & или пробел?
То есть должно быть так:
'?a=' . urlencode($a) . '&b=' . urlencode($b)
Вот тут подробнее описано:
http://ru.wikipedia.org/wiki/URL#.D0.9A.D0.BE.D0.B4.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_URL
http://php.net/manual/ru/function.urlencode.php
Но в твоем случае можно сделать еще умнее. В PHP есть стандартная функция для сборки query string из массива: http://php.net/manual/ru/function.http-build-query.php — используй ее.
Пройдись так же по коду и исправь если где-то еще есть этот баг. Ну и старайся использовать http_build_query в таких случаях.
Что-то я забыл сам про эту функцию и сразу не сказал.
И тут опечатка:
> header("Location: login.php?action=saved");
> if ($_GET['action'] == 'save'){
Надо проверять свой код.
А так, в остальном, все верно. У тебя неплохое мини-приложение в итоге поулчилось, и выглядит аккуратно, ну и надеюсь, что аналогичную задачу ты легко сможешь решить. Ну это так, была разминка, а теперь пора переходить к изучение фреймворков и библиотек.
У тебя тут есть та же ошибка что у tokotun:
> https://github.com/MindiMakridi/Students/blob/master/index.php#L105
> $searchLink = htmlspecialchars($currentPage) . "?order=" . htmlspecialchars($sort, ENT_QUOTES) . "&direction=" . htmlspecialchars($order, ENT_QUOTES) . "&search=" . htmlspecialchars($search, ENT_QUOTES);
Неправильно формируется ссылка. параметры, которые ты подставляешь в ссылку, должны кодироваться процентным кодированием через urlencode, чтобы спецсимволы были заменены на коды со знаком процента:
$link = '...a=' . urlencode($a) . '&b=' . urlencode($b);
а уже потом через htmlspecialchars если их надо вывести в hTML коде:
$linkHtml = htmlspecialchars($link, ...);
Почитай
http://ru.wikipedia.org/wiki/URL#.D0.9A.D0.BE.D0.B4.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_URL
http://php.net/manual/ru/function.urlencode.php
Также, я советую не писать это все руками, а взять готовую удобную функцию http://php.net/manual/ru/function.http-build-query.php которая берет массив и формирует из него query string (но htmlspecialchars она разумеется не делает).
Linux? Может быть прав нету? Надо дать права на папку и файлы в веб-директории чтобы пользователь веб сервера (обычно это www-data) мог их читать. Например, поставить 0777. То есть файлы ты наверно заливаешь от своего пользователя и другим их читать получается запрещено. Почитай про права в линуксе:
http://ru.wikipedia.org/wiki/Chmod
http://www.linuxcenter.ru/lib/books/kostromin/gl_04_05.phtml
>>434410
> <input type="text" readonly value="http://testhub/t/{{ id }}">
Имя хоста надо либо брать из HTTP_HOST либо выносить в настройки. Так как иначе неудобно будет например настраивать тестовый сервер на отдельном домене.
Насчет таблицы answer_attempts — тут конечно есть сложный вопрос, а что должно храниться в answer? Просто число, текст или может ссылка на вариант ответа? Потому что если есть возможность использовать внешние ключи и ссылки то это конечно лучше чем не использовать. И второй вопрос — а что, если после прохождения тест будет отредактирован, например удалены вопросы или варианты ответа? Изменены критерии оценки или правльные ответы? Удалятся ли результаты прохождения? Изменятся ли?
Я думаю, во втором случае стоит запретить редактировать тест если его уже проходили. Ибо иначе мы можем получить расхождения в данных теста и прохождений.
С третьей стороны, а что если надо исправить опечатку в тесте или оказалось что правильный ответ был помечен неправильно? Ну, я думаю, в нашей задаче проще запретить редактирование, хотя в идеале конечно все должно работать корректно и перечитываться, но это очень усложнит систему.
То есть, я хочу сказать, что надо задумываться о таких вещах когда проектируешь БД. Что данные могут меняться и связи между ними нарушаться.
> Yii::$app->response->cookies->add(new \yii\web\Cookie([
> 'name' => "test[$testId][started]",
> 'value' => true
Лучше наверно 1 а не true, в куках же только строки можно хранить.
А зачем вообще ты ввел куки? Для защиты от случайного перезапуска теста? если так, то хорошо наверно, но ведь это можно и без кук проверить, по записи в базе данных? если можно без кук проверить то лучше наверно по БД проверять.
> возможно стоит просто добавить количество вопросов в таблицу,
> либо написать функцию мимо ActiveRecord, чтобы не брать весь массив ради одного количества
Есть такое http://stackoverflow.com/a/22752533 — это для Yii 1 правда
Там как я понимаю, есть либо метод count, либо можно SQL запросом сделать. Брать все записи ради подсчета действитеьно нехорошо как-то.
И есть вот такое: http://www.yiiframework.com/doc/guide/1.1/ru/database.arr#sec-9
Ну и еще, как вариант, ты можешь попробовать расширить класс ActiveRecord чтобы добавить в него универсаьный метод для подсчета числа связанных записей.
> $question = Question::find()->where(['test_id' => $testId])->limit(1)->offset($questionNumber-1);
Тут нужен еще order by иначе не будет работать как задумано
Linux? Может быть прав нету? Надо дать права на папку и файлы в веб-директории чтобы пользователь веб сервера (обычно это www-data) мог их читать. Например, поставить 0777. То есть файлы ты наверно заливаешь от своего пользователя и другим их читать получается запрещено. Почитай про права в линуксе:
http://ru.wikipedia.org/wiki/Chmod
http://www.linuxcenter.ru/lib/books/kostromin/gl_04_05.phtml
>>434410
> <input type="text" readonly value="http://testhub/t/{{ id }}">
Имя хоста надо либо брать из HTTP_HOST либо выносить в настройки. Так как иначе неудобно будет например настраивать тестовый сервер на отдельном домене.
Насчет таблицы answer_attempts — тут конечно есть сложный вопрос, а что должно храниться в answer? Просто число, текст или может ссылка на вариант ответа? Потому что если есть возможность использовать внешние ключи и ссылки то это конечно лучше чем не использовать. И второй вопрос — а что, если после прохождения тест будет отредактирован, например удалены вопросы или варианты ответа? Изменены критерии оценки или правльные ответы? Удалятся ли результаты прохождения? Изменятся ли?
Я думаю, во втором случае стоит запретить редактировать тест если его уже проходили. Ибо иначе мы можем получить расхождения в данных теста и прохождений.
С третьей стороны, а что если надо исправить опечатку в тесте или оказалось что правильный ответ был помечен неправильно? Ну, я думаю, в нашей задаче проще запретить редактирование, хотя в идеале конечно все должно работать корректно и перечитываться, но это очень усложнит систему.
То есть, я хочу сказать, что надо задумываться о таких вещах когда проектируешь БД. Что данные могут меняться и связи между ними нарушаться.
> Yii::$app->response->cookies->add(new \yii\web\Cookie([
> 'name' => "test[$testId][started]",
> 'value' => true
Лучше наверно 1 а не true, в куках же только строки можно хранить.
А зачем вообще ты ввел куки? Для защиты от случайного перезапуска теста? если так, то хорошо наверно, но ведь это можно и без кук проверить, по записи в базе данных? если можно без кук проверить то лучше наверно по БД проверять.
> возможно стоит просто добавить количество вопросов в таблицу,
> либо написать функцию мимо ActiveRecord, чтобы не брать весь массив ради одного количества
Есть такое http://stackoverflow.com/a/22752533 — это для Yii 1 правда
Там как я понимаю, есть либо метод count, либо можно SQL запросом сделать. Брать все записи ради подсчета действитеьно нехорошо как-то.
И есть вот такое: http://www.yiiframework.com/doc/guide/1.1/ru/database.arr#sec-9
Ну и еще, как вариант, ты можешь попробовать расширить класс ActiveRecord чтобы добавить в него универсаьный метод для подсчета числа связанных записей.
> $question = Question::find()->where(['test_id' => $testId])->limit(1)->offset($questionNumber-1);
Тут нужен еще order by иначе не будет работать как задумано
Вот этот вот код
> $question = Question::find()->where(['test_id' => $attempt->test_id])->limit(1)->offset($questionNumber-1);
Явно надо это вынести в метод у модели (полуить N-й вопрос теста)
И сразу же там сделать подгрузку вариантов ответов, чтобы лишних SQL запросов не было. Надо будет кстати как-нибудь потом еще с включенным отладчиком посмотреть нет ли где проблемы N + 1 запроса (эта пробелма упомянута тут http://www.yiiframework.com/doc/guide/1.1/ru/database.arr#sec-3 )
> + $attemptAnswer = new AttemptAnswer( );
> + $attemptAnswer->link('attempt', $attempt);
> + $attemptAnswer->link('question', $question);
Подумай, не стоит ли это тоже сделать методов вроде такого:
$attemptAnswer = $attempt->createAnswerAttempt($question);
>найди здесь место где выставляется токен для незарегистрированного пользователя?
Стоп, а зачем токен незарегестрированому пользователю? У незарегистрированного пользователя нечего красть.
>Ну и выход с сайты ты забыл защитить через проверку токена.
Но я же защитил, или так не правильно?
https://github.com/MindiMakridi/Students/blob/master/index.php#L25
Все верно, но после того как мы обнаружили расхождение, можно выходить из цикла — дальше смысла проверять нет.
>>434428
Что-то я смотрю, даблы часто выпадают. Надо условие усложнить видимо.
Так, задача решена верно, хотя exit в последних 3 случаях лишний— и без него будет работать.
В ОП-посте есть 2 книги, есть сайт phptherightway. Но я бы советовал больше упора сделать на практику — в ОП посте написано что учебник дает только основы и после него надо решать практические задачки на создание сайтов и приложений (там такие есть).
Там exit нужен так как if стоит отдельным блоком. Но в if в самом конце exit необязателен.
>>434458
Ты редактируешь переменную input, и думаешь что значение в массиве text тоже поменяется. А оно не меняется так как input это не элемент массива, а его копия. Ты меняешь копию.
Проще всего обработанные input складывать в новый массив и из него собирать результат.
> $roulette % 100000;
Эта команда ничего не делает. Ну то есть она находит остаток от деления на 10000 но никуда его не сохраняет. Чтобы сохранить результат, надо писать
$x = $x % 10000;
Иначе результат просто отбрасывается, а переменная не меняется.
Это то же самое что написать например команду
2 + 2;
PHP посчитает сумму, и выкинет результат так как он никуда не сохраняется.
>>434483
Та же ошибка что и выше. Строка $roulette % 10 ничего не делает.
>>434486
foreach дает тебе не ссылку на элемент массива, а копию. Меняя копию ты не меняешь сам элемент массива (это сделано ради читабельности и надежности кода, в общем для твоего же блага).
В твоем коде так же опечатка в строке 14:
> for ($i = 0; i < sizeof($text),$i++{
>>434487
Ты усложнил все. Чтобы получить последнюю цифру числа достаточно взять остаток от деления на 10 (так как остаток никак не может быть больше числа на которое делим).
$x = $y % 10;
Этого достаточно
> $roulette % 100000;
Эта команда ничего не делает. Ну то есть она находит остаток от деления на 10000 но никуда его не сохраняет. Чтобы сохранить результат, надо писать
$x = $x % 10000;
Иначе результат просто отбрасывается, а переменная не меняется.
Это то же самое что написать например команду
2 + 2;
PHP посчитает сумму, и выкинет результат так как он никуда не сохраняется.
>>434483
Та же ошибка что и выше. Строка $roulette % 10 ничего не делает.
>>434486
foreach дает тебе не ссылку на элемент массива, а копию. Меняя копию ты не меняешь сам элемент массива (это сделано ради читабельности и надежности кода, в общем для твоего же блага).
В твоем коде так же опечатка в строке 14:
> for ($i = 0; i < sizeof($text),$i++{
>>434487
Ты усложнил все. Чтобы получить последнюю цифру числа достаточно взять остаток от деления на 10 (так как остаток никак не может быть больше числа на которое делим).
$x = $y % 10;
Этого достаточно
Не надо через for, его читать тяжело из-за обилия запятых. Лучше всего просто склаыдвать обработанные строки в новый массив.
>>434501
$c = [];
foreach ($a as $b) {
$c[] = $a;
}
>>434539
Тут ошибка в регулярке:
> PHP Warning: preg_replace(): Compilation failed: missing ) at offset 14 in /home/YttfOF/prog.php on line 30
там скобок не хватает.
>>434544
Но ты же ничего и не разжевываешь
>>434553
Книга в плане PHP очень слабая, имей в виду, код там так себе, может быть ошибки или уязвимости. для ознакомления в общих чертах может подойти, не знаю.
>>434565
> $reg2 = '#(" ")(,(" "))#';
Двойная кавычка значит искать двойную кавычку. Чтобы искать пробел пиши либо просто пробел либо \\s (\\s ищет не только пробелы но и переводы строк и некоторые другие редкоиспользуемые пробельные символы вроде \\t, \\v или \\f).
Не надо через for, его читать тяжело из-за обилия запятых. Лучше всего просто склаыдвать обработанные строки в новый массив.
>>434501
$c = [];
foreach ($a as $b) {
$c[] = $a;
}
>>434539
Тут ошибка в регулярке:
> PHP Warning: preg_replace(): Compilation failed: missing ) at offset 14 in /home/YttfOF/prog.php on line 30
там скобок не хватает.
>>434544
Но ты же ничего и не разжевываешь
>>434553
Книга в плане PHP очень слабая, имей в виду, код там так себе, может быть ошибки или уязвимости. для ознакомления в общих чертах может подойти, не знаю.
>>434565
> $reg2 = '#(" ")(,(" "))#';
Двойная кавычка значит искать двойную кавычку. Чтобы искать пробел пиши либо просто пробел либо \\s (\\s ищет не только пробелы но и переводы строк и некоторые другие редкоиспользуемые пробельные символы вроде \\t, \\v или \\f).
Код потом покажи, когда доделаешь. тут явно нужна тщательная проверка.
>>434577
> а-я
Букву ё надо указзывать откдльно так как в юникоде она идет после а-я. То есть надо писать
[a-яё]
Посмотри сам: http://unicode-table.com/ru/#cyrillic
>>434642
Надо вывести общую сумму выплаченного по кредиту (должно быть около 61270)
> В "действие1" в цикле for я не знал чего вставить,
Можно ничего не вставлять если хочешь:
for ( ; $x < 10; $x ++) { .. }
Главное чтобы было ровно 2 точки с запятой, а что между ними не принципиально.
>>434653
> У незарегистрированного пользователя нечего красть.
Так-то да, но можно его заставить зарегистрироваться через XSRF, и проще закрыть все действия чем усложнять логику, в этом случае мы защищаемся, в это нет.
> Но я же защитил, или так не правильно?
Там еще в profile.php есть логаут
Код потом покажи, когда доделаешь. тут явно нужна тщательная проверка.
>>434577
> а-я
Букву ё надо указзывать откдльно так как в юникоде она идет после а-я. То есть надо писать
[a-яё]
Посмотри сам: http://unicode-table.com/ru/#cyrillic
>>434642
Надо вывести общую сумму выплаченного по кредиту (должно быть около 61270)
> В "действие1" в цикле for я не знал чего вставить,
Можно ничего не вставлять если хочешь:
for ( ; $x < 10; $x ++) { .. }
Главное чтобы было ровно 2 точки с запятой, а что между ними не принципиально.
>>434653
> У незарегистрированного пользователя нечего красть.
Так-то да, но можно его заставить зарегистрироваться через XSRF, и проще закрыть все действия чем усложнять логику, в этом случае мы защищаемся, в это нет.
> Но я же защитил, или так не правильно?
Там еще в profile.php есть логаут
То есть мне кажется, проще защитить обе формы, и редактирование, и добавление, и спать спокойно. А то завтра злоумышленник нам нарегистрирует кучу левых людей с реальных IP адресов. Надежнее все же защититься.И код проще получается.
На пхп редко пишут что-то серьезное. Если так и остаться пхпшником, то всю жизнь будешь писать гостевые и натягивать на джумлу. Шанс устроиться на нормальную работу с нормальными проектами и нормальной зарплатой - небольшой. Просто дело в том, что интересные вещи пишутся на других языках.
>>434418
>>434419
Ну, мне пока еще даже 20 нет, рано к успеху приходить. Очень недолго работал в вебговноконторе натягивал на джумлу. Сейчас чуть меньше полугода работаю в обычной джаваконторе, энтерпрайз, вся хуйня. Разница просто огромная, задачи разнообразные и интересные, приходится учить и использовать дохуя всяких технологий (задел на будущее хороший получается), клевый офис (футбол, иксбокс, бесплатный кофе и прочие плюшки). Вот только один минус - зарплата лично у меня сейчас такая же, как была бы в вебговноконторе, но это поправимо уходом в контору классом повыше, что я и планирую сделать через несколько месяцев, как наберусь опыта.
Про путь лениво все подробно расписывать. Купил книжку "Создаем динамические веб-сайты с помощью PHP, MySQL, CSS, JavaScript", прочитал ее, написал очень кривую и хуевую имиджборду открывающие и закрывающие теги в разных файлах и прочие радости. Потом в вузе C# был, ООП, вся хуйня. Некоторое время сидел и над шарпом, и над пхп, прочитал несколько умных статей, начал но дальше начала дело не пошло читать книжку по пхп Мэтта Зандстры, кстати, отличная книжка. Потом уже сам не помню почему подумал что надо чето уровнем повыше брать. Выбирал между джавой и сисярпом, выбрал первое, т.к. вакансий больше намного. В общем-то зная что-то одно из них, второе изучить недолго. Короче прочитал кусками первый том двухтомника Хорстманна по джаве и полное руководство Шилдта (ебать оно огромное, я наверное половину пропустил в нем). После такого объема информации у меня все в голове не уложилось, было дохуя пробелов, но я решил идти к успеху. Разослал письма в несколько контор, типа студент хочет стажироваться, в той где работаю сейчас пригласили на собеседование, им особо ничего сложного не надо было, спрашивали, умею ли в Swing, работу с бд и чето еще. Кстати со свингом так ни разу и не столкнулся на работе, лол. Дали тестовое задание, в котором было всего понемногу, и три дня срока. Я его начал делать только на второй день, за два дня в бешеном темпе закодил это все, вышло 1-1,5к строчек. Конечно косяки там были, как архитектурные, так и кодинговые, но в целом получилось довольно неплохо. Тут был мой эпичный фейл, что я до этого момента до сих пор нихуя не представлял себе про развертывание джава-приложений и послал в контору скомпилированный джарник без исходников, лол. Но в общем мне сказали, что все норм и я принят. На работе первые два месяца входил в курс дела, пиздецки тупил и заебывал тимлида дебильными вопросами. Если честно, сейчас тоже раз-два в день у него что-нибудь спрашиваю, но уже не такое очевидное и тупое, и мне кажется все так делают. Короче сейчас я познакомился с кучей базовых технологий (работа с БД, XML, сетью, узнал как использовать библиотеки, лол, понял что Apache Commons - это охуенно, и тд), и чувствую себя достаточно уверенно. Уровень наверное еще джуниор, но уже очень уверенный. Через полгода буду работать мидом в хорошей конторе и зарабатывать тыщ 25-30 (в мухосрани). Через года два понаеду в ДС 1/2/3 и устроюсь за 50-100к в какую-нибудь крутую контору, где надо говорить голосом по английски с заказчиками и прочие радости жизни.
Надеюсь кому-то это интересно и не зря катал эту простыню, (смех)
На пхп редко пишут что-то серьезное. Если так и остаться пхпшником, то всю жизнь будешь писать гостевые и натягивать на джумлу. Шанс устроиться на нормальную работу с нормальными проектами и нормальной зарплатой - небольшой. Просто дело в том, что интересные вещи пишутся на других языках.
>>434418
>>434419
Ну, мне пока еще даже 20 нет, рано к успеху приходить. Очень недолго работал в вебговноконторе натягивал на джумлу. Сейчас чуть меньше полугода работаю в обычной джаваконторе, энтерпрайз, вся хуйня. Разница просто огромная, задачи разнообразные и интересные, приходится учить и использовать дохуя всяких технологий (задел на будущее хороший получается), клевый офис (футбол, иксбокс, бесплатный кофе и прочие плюшки). Вот только один минус - зарплата лично у меня сейчас такая же, как была бы в вебговноконторе, но это поправимо уходом в контору классом повыше, что я и планирую сделать через несколько месяцев, как наберусь опыта.
Про путь лениво все подробно расписывать. Купил книжку "Создаем динамические веб-сайты с помощью PHP, MySQL, CSS, JavaScript", прочитал ее, написал очень кривую и хуевую имиджборду открывающие и закрывающие теги в разных файлах и прочие радости. Потом в вузе C# был, ООП, вся хуйня. Некоторое время сидел и над шарпом, и над пхп, прочитал несколько умных статей, начал но дальше начала дело не пошло читать книжку по пхп Мэтта Зандстры, кстати, отличная книжка. Потом уже сам не помню почему подумал что надо чето уровнем повыше брать. Выбирал между джавой и сисярпом, выбрал первое, т.к. вакансий больше намного. В общем-то зная что-то одно из них, второе изучить недолго. Короче прочитал кусками первый том двухтомника Хорстманна по джаве и полное руководство Шилдта (ебать оно огромное, я наверное половину пропустил в нем). После такого объема информации у меня все в голове не уложилось, было дохуя пробелов, но я решил идти к успеху. Разослал письма в несколько контор, типа студент хочет стажироваться, в той где работаю сейчас пригласили на собеседование, им особо ничего сложного не надо было, спрашивали, умею ли в Swing, работу с бд и чето еще. Кстати со свингом так ни разу и не столкнулся на работе, лол. Дали тестовое задание, в котором было всего понемногу, и три дня срока. Я его начал делать только на второй день, за два дня в бешеном темпе закодил это все, вышло 1-1,5к строчек. Конечно косяки там были, как архитектурные, так и кодинговые, но в целом получилось довольно неплохо. Тут был мой эпичный фейл, что я до этого момента до сих пор нихуя не представлял себе про развертывание джава-приложений и послал в контору скомпилированный джарник без исходников, лол. Но в общем мне сказали, что все норм и я принят. На работе первые два месяца входил в курс дела, пиздецки тупил и заебывал тимлида дебильными вопросами. Если честно, сейчас тоже раз-два в день у него что-нибудь спрашиваю, но уже не такое очевидное и тупое, и мне кажется все так делают. Короче сейчас я познакомился с кучей базовых технологий (работа с БД, XML, сетью, узнал как использовать библиотеки, лол, понял что Apache Commons - это охуенно, и тд), и чувствую себя достаточно уверенно. Уровень наверное еще джуниор, но уже очень уверенный. Через полгода буду работать мидом в хорошей конторе и зарабатывать тыщ 25-30 (в мухосрани). Через года два понаеду в ДС 1/2/3 и устроюсь за 50-100к в какую-нибудь крутую контору, где надо говорить голосом по английски с заказчиками и прочие радости жизни.
Надеюсь кому-то это интересно и не зря катал эту простыню, (смех)
Неплохо, а вообще мне кажется вместо реверса можно шафл использовать http://php.net/manual/ru/function.shuffle.php тогда результат будет не предсказуемым.
мимо не ОП
Я тоже в начале шафл поставил. Потом задачку повнимательнее прочитал, а там надо чтобы в обратном порядке слова стояли.
У нас есть две сущности ошибка и исключение. Ошибок есть куча видов: всякие notice, warning, eerror. Исключения можно отлавливать через try ... catch, а ошибки - нет. Можно отлавливать ошибки через функцию переданную в set_error_handler, кидая внутри неё исключение, а потом обрабатывая его, делая вид что кидается не какой-нибудь notice, а исключение.
Правильно ли я понял? И ещё:
set_error_handler не перехватывает сами исключения?
Почему в примере #1 здесь http://php.net/manual/ru/function.set-error-handler.php есть "!(error_reporting() & $errno)". Получается так, что $errno может становиться false и это значит, что ошибки нет? Почему тогда функция из set_error_handler вообще вызывается если ошибки нет?
Я — простая js-макака, с php знаком на уровне написания тем для wordpress.
Нужен простой php движок, желательно на файлах, потому что нет желания редактировать контент в базе.
Искаропки должны быть:
1. ЧПУ
2. Отправка писем Я как-то наебался с phpmailer, больше не хочу
3. Простая админка для редактирования контента.
Да, интересно, и ты молодец.
>нет желания редактировать контент в базе
А, ну раз так... У меня нет желания тебе советовать.
>желательно на файлах, потому что нет желания редактировать контент в базе
Ты с этим завязывай
Вот, очередная порция фиксов. Есть правда еще непонятки:
>>434640
>И еще, я просил вместо явной передачи $report в URL передавать коды, чтобы нельзя было вывести произвольное сообщение на сайте.
Вот этот момент не совсем понятен.
А есть более нормальные клиенты с GUI для работы с гитом?
Например как на битбаките TortouseHg?
error_reporting(-1);
echo "Бросаем кубик.../n";
$random = 0; /куда лепить функцию mt_rand()?/
echo "Выпало $random\n";
?>
По скрину непонятно где ошибка. Алсо, когда ты редактируешь файл на гитхабе, это коммит. Потом надо сделать pull -r локально
Разобрался сам, всем спасибо за внимание
<?php
error_reporting(-1);
echo "Бросаем кубик.../n";
$random = mt_rand(1,6);
echo "Выпало $random\n";
?>
Вот как-то так.
Сделай git status (я не знаю, есть ли это в GUI, если нет то сделай в консоли). Он пишут что у тебя есть незакомиченные изменения и надо либо их закомиттить либо отменить а только потом синхронизироваться.
Кстати, ты изучал работу с git в консоли? Начинающим надо именно там учитьяс, прочесть git book и сделать то что там описывается, а потом переходить к GUI программам.
TortoiseGit плохой и кривой. Я им только смотрю историю и диффы, а коммичу из консоли. Вообще, по моему GUI инструменты стоит использовать для просмотра и поиска, а важные операции вроде коммитов и переключения веток лучше из консоли делать.
А вообще есть куча клиентов: http://git-scm.com/download/gui/linux
Я начал читать, но у меня как то не задалось с командной строкой с самого начала. Во первых сама директория для гита установилась по умолчанию в мои документы. Я удалил её оттуда и перенес в папку моего проекта, но он там (в моих документах) заново появился. Поэтому у меня теперь как бы два директории с гитом, и командная строка видит по умолчанию ту, что в моих документах.
Ты передаешь в URL текст сообщения. Любой может туда подставить свое сообщение и оно выведется на сайте при открытии ссылки. Например, злоумышленник делает ссылку http://example.com/profile.php?msg=(для подтверждения регистрации заплатите 100 биткойнов на кошелек X) и каким-то образом подсовывает пользователю, и тот может поверить так как сообщение выводится на официальном сайте.
Это может использоваться для мошенничества, например.
Если использовать коды вроде ?msg=saved то подставить любое сообщение не получится. Да и ссылка будет короче.
Я понял в чем там проблема, мне не понятно, как именно её решить (кроме костыля с регулярками)
А, хотя, до меня вроде дошло. Через if или switch, проверять значение переменной и выводить сообщение в зависимости от значения get переменной.
Там происходит ошибка, но у тебя включен режим игнорирования ошибок и ты ее не видишь.
По умолчанию PDO не выводит сообщений об ошибках, что очень неудобно. Потому ты должен сразу после соединения включать режим вывода ошибок. Для этого надо выполнить такой код:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Мануал: http://php.net/manual/ru/pdo.error-handling.php
Проверить что все работает можно выполнив неправильный запрос например "SDASDADAA"
Более того, возможно что у тебя выключен режим отображения ошибок на экран (и они только пишутся в логи).
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
Ну и убери try/catch — он не нужен. Я знаю, что в некоторых учебниках и статьях есть такой код, он абсолютно неправильный и вредный. Почему:
- в PHP есть встроенный механизм обработки, логгирования и вывода исключений. Этот код его заменяет на вывод на экран, что не всегда требуется
- при этом способе пользователю при ошибке показывается непонятное и не нужное ему сообщение, в то время как в логи на сервере ничего не запишется и ты об ошибке не узнаешь. А надо делать ровно наоборот.
- исключение и так выведется на экран если у тебя display_errors = On
Вывод: автор кода, как и многие авторы статей и учебников по PHP сам не разбирается в программировании и берется учить других людей.
Вот мой мини-урок про исключения: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Там происходит ошибка, но у тебя включен режим игнорирования ошибок и ты ее не видишь.
По умолчанию PDO не выводит сообщений об ошибках, что очень неудобно. Потому ты должен сразу после соединения включать режим вывода ошибок. Для этого надо выполнить такой код:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Мануал: http://php.net/manual/ru/pdo.error-handling.php
Проверить что все работает можно выполнив неправильный запрос например "SDASDADAA"
Более того, возможно что у тебя выключен режим отображения ошибок на экран (и они только пишутся в логи).
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
Ну и убери try/catch — он не нужен. Я знаю, что в некоторых учебниках и статьях есть такой код, он абсолютно неправильный и вредный. Почему:
- в PHP есть встроенный механизм обработки, логгирования и вывода исключений. Этот код его заменяет на вывод на экран, что не всегда требуется
- при этом способе пользователю при ошибке показывается непонятное и не нужное ему сообщение, в то время как в логи на сервере ничего не запишется и ты об ошибке не узнаешь. А надо делать ровно наоборот.
- исключение и так выведется на экран если у тебя display_errors = On
Вывод: автор кода, как и многие авторы статей и учебников по PHP сам не разбирается в программировании и берется учить других людей.
Вот мой мини-урок про исключения: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Тебе надо было писать в наш тред и задавать вопросы, я бы ответил.
В командной строке есть такое понятие как текущая директория. По умолчанию, может быть, действительно, открываются твои документы. Git работает с тем репозиторием который находится в текущей директории (а как иначе? ведь на компьютере может быть много их).
Ты должен сначала перейти в нужную директорию, а потом выполнять там команды.
Вот простой гайд по командной строке (windows/linux), там описано как сменить директорию: https://gist.github.com/codedokode/10539568
К сожалению, git book видимо предполагает что ты уже умеешь пользоваться командной строкой и менять директории.
Если у тебя будут еще какие-то вопросы, задавай. Лучше разобраться чем каждый раз все делать наугад и сломать в итоге репозиторий — ты больше времени на исправление потратишь.
Консоль гита скорее всего и есть командная строка в которой может быть выставлены некоторые дополнительные переменные окружения.
Ну и если речь про msysgit под windows то там есть Git bash — это портированный на Windows bash (командная оболочка в линуксе) потому если у тебя консоль гита напоминает пикрелейтед https://msysgit.github.io/img/gw1.png то читай ту часть урока которая описывает командную строку в линуксе.
То есть в Msysgit «консоль git» или git bash это просто портированный на Windows аналог командной строки из linux (в котором доступен git и базовые линуксовые команды вроде cd, less, и т.д.).
Спасибо анончик протрезвев допер.
http://ideone.com/wdVVJX
Он тебе пишет что нет такого элемента в массиве. Алсо, проверят счетчик на соответствие какому-то интервалу с помощью регулярок - забивать гвозди микроскопом.
С ошибками в PHP все плохо. В других языках исплоьзуются только исключения, то есть если что-то не так, выбрасывается исключение. Но в PHP по историческим причинам используются еще и ошибки.
Ошибки (они включают и варнинги, и нотисы, и фатальные ошибки) — это такие штуки которые как правило (если они не фатальные) записываются в лог, выводятся на экран (если разрешено в php.ini) и выполнение продолжается. Это в общем-то плохо, так как нет смысла продолжать выполнять неправильную программу.
Вот директивы разрешающие запись в лог и вывод на экран:
http://php.net/manual/ru/errorfunc.configuration.php#ini.display-errors
http://php.net/manual/ru/errorfunc.configuration.php#ini.log-errors
http://php.net/manual/ru/errorfunc.constants.php
(до 5.4 в E_ALL входили не все виды ошибок и кто-то даже хотел ввести константу E_REALLY_ALL)
Что особо печально, через php.ini директивой error_reporting можно включить режим игнорирования некоторых видов ошибок (мануал: http://php.net/manual/ru/errorfunc.configuration.php#ini.error-reporting ). По умолчанию игнорирование отключено, но многие криворукие программисты разрабатывали свои продукты под настройку, что нотисы и варнинги игнорируются (то есть они писали кривой код и просто скрывали варнинги).
Фатальные ошибки в отличие от варнингов и нотисов завершают скрипт.
Есть также интересные виды ошибок E_DEPRECATED которые говорят о том что ты используешь устарвешую функцию.
Ты можешь ловить ошибки назначив свою функцию-обработчик (это наызвается неструктурная обработка ошибок, неструктурная потому что ты не указываешь в какой области ловить ошибки и какого типа - ловится все). В этом случае стандартные механизмы (запись в лог/вывод на экран) отключаются. мануал: http://php.net/manual/ru/function.set-error-handler.php
Некоторые фатальные ошибки не ловятся обработчиком, но их можно поймать хитрым костылем с register_shutdown_function (эта функция вызывается при завершении скрипта и может проверить не было ли ошибки).
Если тебе не хочется возиться с обработкой ошибок и хочется перевести все на исключения (тебе должно хотеться), в php предусмотрен стандартный класс для превращения всех ошибок (кроме фатальных) в исключения: http://php.net/manual/ru/class.errorexception.php
Что касается исключений, то это хороший и правильный подход к обработке ошибок. Он еще называется «структурная обработка исключений».
Про исключения у меня есть мини-урок: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Теория про структурную/неструктурную обработку исключений: https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B9
> Можно отлавливать ошибки через функцию переданную в set_error_handler, кидая внутри неё исключение, а потом обрабатывая его, делая вид что кидается не какой-нибудь notice, а исключение.
Да, для этого есть ErrorException. Но в теории ты можешь и без этого обрабатывать, в функции-обработчике пишешь что хочешь. Но лучше через исключения.
> set_error_handler не перехватывает сами исключения?
Нет но есть set_exception_handler для ловли непойманных исключений. Его можно использовать чтобы например отобразить страницу 500 ошибки для пользователя. Помни что в этом случае ты должен сам вручную залоггировать исключение и информацию о нем.
> Получается так, что $errno может становиться false и это значит, что ошибки нет? Почему тогда функция из set_error_handler вообще вызывается если ошибки нет?
Это нужно для того чтобы поддерживалась настройки error_reporting (которая позволяет игнорировать некоторые виды ошибок) и оператор тишины @: http://php.net/manual/ru/language.operators.errorcontrol.php
Если убрать if то @ и настрйока error_reporting не будут учитываться и все виды ошибок будут становитьяс исключениями, даже если они подавлены через @. Это не всегда хорошая идея, иногда @ необходима (там есть пара функций).
С ошибками в PHP все плохо. В других языках исплоьзуются только исключения, то есть если что-то не так, выбрасывается исключение. Но в PHP по историческим причинам используются еще и ошибки.
Ошибки (они включают и варнинги, и нотисы, и фатальные ошибки) — это такие штуки которые как правило (если они не фатальные) записываются в лог, выводятся на экран (если разрешено в php.ini) и выполнение продолжается. Это в общем-то плохо, так как нет смысла продолжать выполнять неправильную программу.
Вот директивы разрешающие запись в лог и вывод на экран:
http://php.net/manual/ru/errorfunc.configuration.php#ini.display-errors
http://php.net/manual/ru/errorfunc.configuration.php#ini.log-errors
http://php.net/manual/ru/errorfunc.constants.php
(до 5.4 в E_ALL входили не все виды ошибок и кто-то даже хотел ввести константу E_REALLY_ALL)
Что особо печально, через php.ini директивой error_reporting можно включить режим игнорирования некоторых видов ошибок (мануал: http://php.net/manual/ru/errorfunc.configuration.php#ini.error-reporting ). По умолчанию игнорирование отключено, но многие криворукие программисты разрабатывали свои продукты под настройку, что нотисы и варнинги игнорируются (то есть они писали кривой код и просто скрывали варнинги).
Фатальные ошибки в отличие от варнингов и нотисов завершают скрипт.
Есть также интересные виды ошибок E_DEPRECATED которые говорят о том что ты используешь устарвешую функцию.
Ты можешь ловить ошибки назначив свою функцию-обработчик (это наызвается неструктурная обработка ошибок, неструктурная потому что ты не указываешь в какой области ловить ошибки и какого типа - ловится все). В этом случае стандартные механизмы (запись в лог/вывод на экран) отключаются. мануал: http://php.net/manual/ru/function.set-error-handler.php
Некоторые фатальные ошибки не ловятся обработчиком, но их можно поймать хитрым костылем с register_shutdown_function (эта функция вызывается при завершении скрипта и может проверить не было ли ошибки).
Если тебе не хочется возиться с обработкой ошибок и хочется перевести все на исключения (тебе должно хотеться), в php предусмотрен стандартный класс для превращения всех ошибок (кроме фатальных) в исключения: http://php.net/manual/ru/class.errorexception.php
Что касается исключений, то это хороший и правильный подход к обработке ошибок. Он еще называется «структурная обработка исключений».
Про исключения у меня есть мини-урок: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Теория про структурную/неструктурную обработку исключений: https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B9
> Можно отлавливать ошибки через функцию переданную в set_error_handler, кидая внутри неё исключение, а потом обрабатывая его, делая вид что кидается не какой-нибудь notice, а исключение.
Да, для этого есть ErrorException. Но в теории ты можешь и без этого обрабатывать, в функции-обработчике пишешь что хочешь. Но лучше через исключения.
> set_error_handler не перехватывает сами исключения?
Нет но есть set_exception_handler для ловли непойманных исключений. Его можно использовать чтобы например отобразить страницу 500 ошибки для пользователя. Помни что в этом случае ты должен сам вручную залоггировать исключение и информацию о нем.
> Получается так, что $errno может становиться false и это значит, что ошибки нет? Почему тогда функция из set_error_handler вообще вызывается если ошибки нет?
Это нужно для того чтобы поддерживалась настройки error_reporting (которая позволяет игнорировать некоторые виды ошибок) и оператор тишины @: http://php.net/manual/ru/language.operators.errorcontrol.php
Если убрать if то @ и настрйока error_reporting не будут учитываться и все виды ошибок будут становитьяс исключениями, даже если они подавлены через @. Это не всегда хорошая идея, иногда @ необходима (там есть пара функций).
Если тебе еще что-то непонятно, задавай вопросы.
На мой взгляд удобнее всего превращать все ошибки в исключения, то есть фактически отключить устаревший механизм. Если ты используешь фреймворки, то многие включают такой режим по умолчанию (Slim, Symfony 2) и сами выводят 500-ю страницу.
Не забывай что при установке обработчика обязанность логгировать ошибку ложится на тебя.
Здравствуйте, я в общем-то к вам по такому вопросу. Научите меня пилить гостевуху на пхп. Сделал по гайду не получилось. Нужно комменты в текстовый файл записывать, а потом выводить (read, write?) или нужно это делать в базу данных?
Вот смотри, как я свою первую сделал за час
два файла в ней и база данных.
http://ideone.com/GrkT0S
http://ideone.com/XnKNy8
Сам попробуй разобраться, так как я ухожу.
Алсо может аноны оценят мой говнокод.
http://ideone.com/0WJq2h
Очень печально, что я не могу составить сразу схему всего скрипта в голове - оно само появляется по ходу написания кода.
и не не обязательно составлять в голове. можешь письменно описать на листочке.
Лучше нарисовать, квадратиками и стрелочками наверно. Да вообще, поначалу задачи простые, пиши как получается, и вкидывай в тред.
А вот и не правильно.
Когда у тебя как только остаётся на счету меньше 5000, школьник тут же неизвестно откуда достаёт ещё денег, что бы остатки погасить долг.
Хотя в задаче ясно сказано 5000 в месяц это всё что емё даёт мама.
Ещё >echo "12 месяц спустя: Кредит покрыт,
Это то же костыль. Тут у тебя не зависимо от того сколько анон брал кредита будет написано, что кредит он покрыл 12 месяцев спустя.
Ты смог разобраться в моем говне? В общем что бы это работало тебе еще нужно базу данных прикрутить. У меня там 1 таблица "posts", в ней
столбцы id, message, name, posttime.
id - накручиваются автоматически, заюзано autoincrement
message заносится из $_POST['text'];
name соответственно из name, ели пользователь оставил пустым то пишется Аноним.
Время вроде бы само заполняется, когда пост кидается в базу, то автоматом туда шлепается timestamp, потом берется и показывается у каждого поста.
Выглядит в итоге все пикрилейтед. Скажите аноны, рано еще джуном идти с такой хуетой? >>435079
Это опять я со своим многострадальным проектом.
Спасибо.
Ладно, первые вопросы справедливы, спасибо.
Ну я так понимаю, подобное можно вычитать в книге "PHP Собеседование в вопросах и ответах", да?
А вопросы с подвохом? Это ведь шуточки про hr, да?
Это вот всё на стажера нужно?
В резюме про что писать-то?
>что выведет код var_dump("x" == 0) ?
Сейчас проверил и удивился, если честно. 0 ведь эквивалентен false, а строка true. Но var_dump("x" == 0) почему-то выводит true.
С подвохом вопросы — прямо с собеседования убегать надо это когда, падаван юный.
Вот что я наделал:
https://ideone.com/aY91Dy
У тебя break; стоит в самом цикле, а не внутри условия которое его должно прекращать например.
Стало быть в процессе первой итерации он у тебя и прекращается.
http://sql-ex.ru
Я чет из-за него дропнул его пару месяцев назад, но сейчас после продолжительного ебланства решил взять себя в руки и прочитав к упражнению материал:
http://www.sql-tutorial.ru/ru/book_explicit_join_operations/page1.html
составил вот такой вот запрос:
SELECT product.maker, laptop.speed
FROM product INNER JOIN laptop
ON product.model = laptop.model
WHERE laptop.hd >= 10.0
но хоть оно и дает верные результаты, все равно не нравится сайту и кидает меня на faq: http://www.sql-tutorial.ru/book_exercise_6.html
В нем не могу понять объяснение.
Кто может пояснить что не так?
Есть какие-то общие рекомендации, ну или готовые решения? Интересует не сам механизм, а правильная реализация. Я делаю просто. ТЫ ему логин-пароль, он тебе в ответ случайную строку (токен). Далее все запросы в связке логин+токен.
Так вот меня настораживает тот факт, что практически все крупные api (amazon s3) используют заголовки, для передачи токена, логина. В php же так просто заголовок и не прочитаешь, нужно перебирать массив $_SERVER. В правильном ли я направлении?
http://ideone.com/xyjgRq
Боже я аутист не заметил спасибо
Можно вообще без токена, передавать логин + хеш пароля на каждый запрос. Это наверно более соответствует духу REST чем использование сессий и сильно упрощает систему.
Можно посмотреть в сторону OAuth/OAuth2, может быть можно использовать их? Там как раз токены есть.
Имей также в виду, что сам по себе REST идеальная абстракция, и реальные его имплементации могут не соответствовать ему на 100%.
Посмотри как сделана авторизация в других АПИ:
Google использует Oauth2 (раньше использовали велосипед): https://developers.google.com/accounts/docs/OAuth2
Яндекс использует Oauth: https://tech.yandex.ru/webmaster/doc/dg/concepts/About-docpage/
https://tech.yandex.ru/disk/api/concepts/quickstart-docpage/
> В php же так просто заголовок и не прочитаешь, нужно перебирать массив $_SERVER
Ничего перебирать не надо. Все заголовки есть в _SERVER, это описано в документации. А если ты используешь фреймворк то там скорее всего есть объект Request.
> Далее все запросы в связке логин+токен.
Логин тут лишний
Есть неплохие задачи на jQUery из нашего сборника задач на JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0#dom--jquery
Имей в виду что для их решения надо знать DOM. Если ты не знаешь DOM то ты все равно вряд ли нормально сможешь пользоваться jQuery.
$headersNumber = $queryResult -> num_rows;
А какой код ошибки или что-то типа того? Ты на попробовал сначала на локальной машине устаносить php + mysql и на ней запустить?
Спасибо, анон.
пхп у меня на локалке установился, а вот с мскл проблема. там настроек куча, нужно в километровых текстовых файлах рыться, и вообще я по-моему их много наустанавливал и хз, как и откуда удалять. так что пилю на хосте.
И вот я создал на хосте свою БД с именем пользователя, паролем, названием базы. Пытаюсь такой функцией вывести лист ДБ и вот что выводит. Что это значит? Там эта функция запрещена?
$link = mysqli_connect('localhost','юзернейм','пароль');
$db_list = mysql_list_dbs($link);
while($row=mysql_fetch_object($db_list))
{
echo $row->Database . "\n";
}
Warning: mysql_list_dbs() has been disabled for security reasons in /home/u209251236/public_html/php/index.php on line 15
Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource in /home/u209251236/public_html/php/index.php on line 17
Алсо попробуй установить для начала просто сборку типа Денвера: http://www.denwer.ru/ или EasyPHP: http://www.easyphp.org/
Далее заходишь в phpmyadmin, который входит в обе сборки, создаешь там базу с таким же именем пустую, после чего жмешь импортировать, и вставляешь из этого файла. Не забудь только подогнать везде пользователя и пароль к одному виду. Что бы в mysql у тебя был пользователь root без пароля, если ты ничего не менял в .php файлах, либо в этой строчке поменяй под своё:
>$db = array('host' => 'localhost', 'user' => 'root', 'pass' => '', 'name' => 'microboard');
Если сборки будут ругаться на занятый 80-й порт, то попробуй скайп выключить перед запуском, как-то так.
Теперь по функциям
>$db_list = mysql_list_dbs($link);
Пишет что запрещена на сервере, да и не нужна она тебе наверное, ты хочешь посмотреть успешно лл прошел коннект к базе? У тебя если просто
>$link = mysqli_connect('localhost','юзернейм','пароль');
сработало, то уже все норм, вроде, но ты можешь отправить туда запрос в духе:
$result = mysqli_query($link, "SHOW DATABASES");
Алсо mysql_... является устаревшей библиотекой и все такое, может быть ругается по этому
Минимум попробуй найти альтернативу в mysqli_...
Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource in /home/u209251236/public_html/php/index.php on line 17
Пишет что переданый в него ресурс неправилен, очевидно что ничего не работает, так как в него у тебя передается результат предыдущей функции, которая тоже не выполнена.
Еще у тебя идут мешанина из mysql и mysqli, возможно проблема в этом, никогда так не делал, но думаю что они могут конфликтовать.
Твой $link законнекченный через mysqli не подходит для работы с mysql, надеюсь понятно объясняю.
Здарова, макаки!
Стоит ли начинать учить РНР в 2015 почти с нуля? Под почти я подразумеваю наличие знаний о том, что такое переменная, массивы, циклы и т.д., в общем те начальные знания, что можно получить на каких-нибудь курсах codecademy по другим языкам.
И второй вопрос. РНРшников очень много, ОЧЕНЬ, т.е. на зп в 50-60к можно рассчитывать только если станешь убер синьёром лет через 20?
У нас тут пхпшник на 100к сидит. Надо бы тоже попросить что ли побольше бабла
В мухосрани самое большее, на что может рассчитывать пхпшник - 30к и то с потом и кровью.
Тоесть с момента открытия книги "делаем динамические сайты с помощью пхп, хтмл и цсс", при добросовестном обучении, через год можно будет работать за 50к в Москве?
Нашел где спросить.
Не понадобилось ошибка в коде была
Странное какое-то описание:
> 6.1 Тред, который подлежит удалению, переносится в nosql базу, где...
Такое ощущение что этот пункт доавлен только ради того чтобы использовать nosql базу.Чем SQL база не годится?
Насчет последних постов, чтобы выбирать их эффективно, надо в треде хранить ссылки на них. Можно сделать это реляцияонно, то есть таблицей связи latest_posts c колонками (thread_id, post_id, sort), можно нереляционно, храня id через запятую в таблице threads в отдельной колонке. При добавлении поста к треду обновляешь список последних постов.
Лучше наверно реляционно если это учебная задача.
>>434203
По идее должен. Но тут еще важно, слушает ли Апач на внешнем интерфейсе или нет. Там есть такая опция в httpd.conf, Listen: http://httpd.apache.org/docs/2.4/mod/mpm_common.html#listen
В ней ты можешь указать на каком интерфейсе принимать соединения. Если ты укажешь 127.0.0.1 то он будет слушать на внутреннем интерфейсе и снаружи будет не подключиться. Если укажешь IP сетевой карты то только на ней (это на случай если у тебя их несколько). А если указать 0.0.0.0 или не указывать котнкретный адрес, то на всех доступных.
То есть по умолчанию должно работать.
>>после прохождения этого мини-учебника какую литературу почитать?
> Бамп вопросу.
Книги есть в ОП-посте но я бы советовал решить практические задачки про стуентов и файлообменник.Так как учебник дает только сам язык PHP но не дает нужные навыки по написанию конкретных приложений, работой с БД, выводом html страниц и так далее.
>>434671
Значит папки или файла нету какого-то. Есои проблема еще не решилась, напиши какой адрес пытаешься открыть, что в httpd.conf, есть ли на диске файл который пытаешь открыть.
>>434664
На PHP примерно та же зарплата (хоят конечно зависит от уровня, может и меньше чем на Яве) и тоже можно говорить с заказчиками по английски. А можно работать в компании со своим продуктом.
>>434718
Молодец, все правильно решено.
Теперь верно
>>434718
То есть решено то конечно правильно, но код стоит улучшить, ибо как-то запутанно для такой простой задачи.
> foreach ($text as $key => $letter){
Неверно называны переменные.Должно быть не letter (буква) а sentence (предложение). лун не нужен
> $text[$key] = trim($text[$key]);
Вместо того чтобы копипастить text[$key] пиши так
$sentence = trim($sentence);
А в конце цикла ты можешь записать измененное предложение назад в массив.
> $text[$key] = preg_split('//u', $text[$key], -1, PREG_SPLIT_NO_EMPTY);
Не используй одну и ту же переменную для хранения и строки и массива, заведи новую, например letters, а еще лучше вынеси установку первой буквы заглавной в отдельную функцию.
Аналогично тут:
> foreach ($result as $key => $word){
переменная word названа неправильно
> $result[$key]
Не копипасть этот кусок 5 раз подряд, используй переменную
> $result = preg_replace($reg, "$1 ", $result);
Можно просто когда ты делаешь implode добавить к точке пробел и этот кусок не понадобится.
Теперь верно
>>434718
То есть решено то конечно правильно, но код стоит улучшить, ибо как-то запутанно для такой простой задачи.
> foreach ($text as $key => $letter){
Неверно называны переменные.Должно быть не letter (буква) а sentence (предложение). лун не нужен
> $text[$key] = trim($text[$key]);
Вместо того чтобы копипастить text[$key] пиши так
$sentence = trim($sentence);
А в конце цикла ты можешь записать измененное предложение назад в массив.
> $text[$key] = preg_split('//u', $text[$key], -1, PREG_SPLIT_NO_EMPTY);
Не используй одну и ту же переменную для хранения и строки и массива, заведи новую, например letters, а еще лучше вынеси установку первой буквы заглавной в отдельную функцию.
Аналогично тут:
> foreach ($result as $key => $word){
переменная word названа неправильно
> $result[$key]
Не копипасть этот кусок 5 раз подряд, используй переменную
> $result = preg_replace($reg, "$1 ", $result);
Можно просто когда ты делаешь implode добавить к точке пробел и этот кусок не понадобится.
В Оп посте есть 2 книги по php. Насчет HTML/CSS, не знаю, что именно посоветовать.
С книгами есть 2 проблемы:
- они устаревают и часто пока книгу переведут, ей уже года 3-4 исполнится
- книги по PHP/HTML часто пишут малограмотные авторы которые делают кучу ошибок. Пример — Никсон или книга Heads First PHP, там очень неграмотный код.
Но это что каается PHP, а что каается HTML, бери любую книгу поновее и прверь что там не ставят слеш в конце одиночных тегов, то есть пишут не
<img /><br />
А
<img><br>
И в начале стоит <!DOCTYPE html>
если ставят слеш — значит это старье, еще из эпохи когда везде пытались использовать XHTML (что характрено, зачастую с ошибками).
Считает верно, только эти строки
> \t$sum = 39999;
> $payment = 5000;
лучше бы вынести из функции, а то получилась неуниверсальная функция которая умеет считать кредит только на 39999 р, и не умеет считать на другие суммы.
>>435035
Я тут мимо проходил и напишу замечание:
> elseif(preg_match($from1to900, $number)){
preg_match предназначен для работы со строками. для чисел используй математические действия, например больше-меньше или деление с остатком.
>>435072
Математическими операциями вроде больше-меньше.
>>435075
Надо использовать базу данных. Нет смысла тратить время и придумывать свою систему хранения на файлах. а потом например решать проблему с одновременным доступом к ней из нескольких процессов. Используй MySQL например.
>>435079
Мимосоветы:
- не смешивай в кучу php и html, не выводи html код через echo, используй шаблоны: http://www.phpinfo.su/articles/practice/shablony_v_php.html (заодно так проще натягивать и править верстку, когда html в отдельном файле а не набит кусками внутри php)
- ты никак не проверяешь при работе с БД что произошла ошибка. соединение могло не сработать, запрос мог не выполниться. После каждой mysqli команды должна стоять проверка результата.
Кстати в PDO это не обязательно, можно просто включить режим выброса исключения при ошибке. А в mysqli обязательно так как такого режима нет.
- ты копипастишь параметры соединения:
> $db = array('host' => 'localhost', 'user' => 'root', 'pass' => '', 'name' => 'microboard');
Копипаста — зло.Надо вынести параметры в отдельный файл (обычно его называют config.php).
- вместо унылого цикла с for ($i=0; $i<$headersNumber; $i++) можно просто использовать mysqli_fetch_all
> echo "<p><b>№$row[0] $row[2] $row[3]
Это обсолютно нечитаемо. надо использовать названия колонок а не номера.
- у тебя SQL injection (погугли что это), то есть уязвимость позволяющая злодею выполнить произвольный SQL запрос. Потому что надо не вставлять переменные прямо в запрос:
> mysqli_query($link, "INSERT INTO `microboard`.`posts` (`name`, `message`) VALUES ('$username', '$text')");
А использовать плейсхолдеры:
http://php.net/manual/ru/mysqli.quickstart.prepared-statements.php
http://habrahabr.ru/post/141127/
(кстати в PDO это чуть короче пишется)
Вставляй данные в запрос только через плейсхолдеры, никогда не вставляй переменные напрямую.
- у тебя XSS уязвимость, то есть пользователь может вывести любой html код включая скрипт на страницу. Почитай урок: https://gist.github.com/anonymous/52adda0113428b274c64
- у тебя XSRF уязвимость то есть злоумышленник может заманив пользователя на свою страницу, отправлять посты на твой сайт от его имени. Надо использовать XSRF токен в куках и в форме для защиты от этого. Все формы должны быть защишены токеном (кстати большинство программистов этого не делают и если они не используют фреймворк с защитой то скорее всего сайт получается дырявый. не иди по их пути)
> !empty($_POST['username']) ? $username = $_POST['username'] : $username = "Аноним";
Не пиши так. Тут нужен if, не надо запутывать код.
- не верстай с помощью br, исплользуй CSS. Кстати у нас етсть хорошие задачки на HTML/CSS (в оп посте)
Я бы советовал тебе еще почитать сайт phptherightway, там много полезных советов по тому как писать правильно.
как видишь, ты сделал кучу ошибок в таком простом сайте. Если хочешь их исправить, я могу помочь советами, ответить на вопросы и проверить код.
Считает верно, только эти строки
> \t$sum = 39999;
> $payment = 5000;
лучше бы вынести из функции, а то получилась неуниверсальная функция которая умеет считать кредит только на 39999 р, и не умеет считать на другие суммы.
>>435035
Я тут мимо проходил и напишу замечание:
> elseif(preg_match($from1to900, $number)){
preg_match предназначен для работы со строками. для чисел используй математические действия, например больше-меньше или деление с остатком.
>>435072
Математическими операциями вроде больше-меньше.
>>435075
Надо использовать базу данных. Нет смысла тратить время и придумывать свою систему хранения на файлах. а потом например решать проблему с одновременным доступом к ней из нескольких процессов. Используй MySQL например.
>>435079
Мимосоветы:
- не смешивай в кучу php и html, не выводи html код через echo, используй шаблоны: http://www.phpinfo.su/articles/practice/shablony_v_php.html (заодно так проще натягивать и править верстку, когда html в отдельном файле а не набит кусками внутри php)
- ты никак не проверяешь при работе с БД что произошла ошибка. соединение могло не сработать, запрос мог не выполниться. После каждой mysqli команды должна стоять проверка результата.
Кстати в PDO это не обязательно, можно просто включить режим выброса исключения при ошибке. А в mysqli обязательно так как такого режима нет.
- ты копипастишь параметры соединения:
> $db = array('host' => 'localhost', 'user' => 'root', 'pass' => '', 'name' => 'microboard');
Копипаста — зло.Надо вынести параметры в отдельный файл (обычно его называют config.php).
- вместо унылого цикла с for ($i=0; $i<$headersNumber; $i++) можно просто использовать mysqli_fetch_all
> echo "<p><b>№$row[0] $row[2] $row[3]
Это обсолютно нечитаемо. надо использовать названия колонок а не номера.
- у тебя SQL injection (погугли что это), то есть уязвимость позволяющая злодею выполнить произвольный SQL запрос. Потому что надо не вставлять переменные прямо в запрос:
> mysqli_query($link, "INSERT INTO `microboard`.`posts` (`name`, `message`) VALUES ('$username', '$text')");
А использовать плейсхолдеры:
http://php.net/manual/ru/mysqli.quickstart.prepared-statements.php
http://habrahabr.ru/post/141127/
(кстати в PDO это чуть короче пишется)
Вставляй данные в запрос только через плейсхолдеры, никогда не вставляй переменные напрямую.
- у тебя XSS уязвимость, то есть пользователь может вывести любой html код включая скрипт на страницу. Почитай урок: https://gist.github.com/anonymous/52adda0113428b274c64
- у тебя XSRF уязвимость то есть злоумышленник может заманив пользователя на свою страницу, отправлять посты на твой сайт от его имени. Надо использовать XSRF токен в куках и в форме для защиты от этого. Все формы должны быть защишены токеном (кстати большинство программистов этого не делают и если они не используют фреймворк с защитой то скорее всего сайт получается дырявый. не иди по их пути)
> !empty($_POST['username']) ? $username = $_POST['username'] : $username = "Аноним";
Не пиши так. Тут нужен if, не надо запутывать код.
- не верстай с помощью br, исплользуй CSS. Кстати у нас етсть хорошие задачки на HTML/CSS (в оп посте)
Я бы советовал тебе еще почитать сайт phptherightway, там много полезных советов по тому как писать правильно.
как видишь, ты сделал кучу ошибок в таком простом сайте. Если хочешь их исправить, я могу помочь советами, ответить на вопросы и проверить код.
Не, неверно считает. Там должно получиться около 61270.
Смотри, у тебя в последний месяц анон платит 5000, и сразу же выплачивает 4139 остатка. А ведь он не может сразу это выплатить, он должен подождать месяц, за который набегут проценты и комиссии и итоговая сумма выйдет больше — не 49139, а около 61270.
Также, если поставить маленькую сумму кредита, например 1000, твоя программа не учтет это и все равно в первый месяц выплатит 5000, хотя достаточно заплатить 2030.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
Все правильно считает, молодец.
>>435138
> header("Content...
> ?>
> <?php
А зачем тут закрывающий и открывающий маркеры? Они же лишние явно и только добавляют пустую строку к выводу.
> return $result = array(
> ....
Не совмещай в одной строке присваивание ($x = 1) и return, это 2 команды и надо делать в 2 отдельных строках. А в данном случае переменная вообще не нужна и надо писать сразу return array( ....);
Непонятно зачем ты передаешь рекурсивно lowerTime. Ведь оно нужно только для выбора одного варианта из найденных внутри функции и не должно передаваться вглубь вызовов.
Ну сам подумай, функция makeOneStep ищет оптимальный путь от промежуточной (не начальной) до конечной точки. Соответственно, ей нужно знать промежуточную точку и конечную. Зачем ей передавать lowerTime? Или есть какая-то причина?
Также, нелогично в случае если путь не найден возвращать пустой массив. Логичнее null наверно.
Я там написал выше разбор, ошибок куча, наверно ты старый учебник читал где это не описано. Хотя может где-то с такими знаниями и возьмут, все зависит от компании.
>>435232
Не занимайся PHP, тогда проблемы не будет.
>>435236
О, почти все сделано. Только вот тут бросается в глаза:
> https://github.com/MindiMakridi/Students/blob/master/index.php#L105
> $searchLink = htmlspecialchars(urlencode($currentPage)) . "?order=" . ...
Длинные строки надо переносить, чтобы на том же гитхабе они не уехжали заправый край. Также, вместо того чтобы 4 раза писать htmlspecialchars проще применить его один раз ко всей ссылке (только amp; надо будет заменить на просто & в этом случае)
Также, вместо того чтобы 4 раза писать руками urlencode можно было использовать тут http_build_query которая составляет ссылку из массива параметров.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L72
> $token = createXsrfCookie( );
Второй раз наверно не надо вызывать уже функцию, достаточно один раз ее в самом верху поставить.
> https://github.com/MindiMakridi/Students/blob/master/lib/functions.php#L58
> ?>
Лучше не ставить этот маркер в конце файла, а то стоит поставит за ним хотя бы один пробел и куки перестанут высталвяться (так как отпралять заголовки и ставить куки нельзя если ты вывел хотя бы один символ)
Больше замечаний нет.
Ну и ты можешь не ждать меня, а потихоньку делать вторую задачу, на файлообменник с twig.
Я там написал выше разбор, ошибок куча, наверно ты старый учебник читал где это не описано. Хотя может где-то с такими знаниями и возьмут, все зависит от компании.
>>435232
Не занимайся PHP, тогда проблемы не будет.
>>435236
О, почти все сделано. Только вот тут бросается в глаза:
> https://github.com/MindiMakridi/Students/blob/master/index.php#L105
> $searchLink = htmlspecialchars(urlencode($currentPage)) . "?order=" . ...
Длинные строки надо переносить, чтобы на том же гитхабе они не уехжали заправый край. Также, вместо того чтобы 4 раза писать htmlspecialchars проще применить его один раз ко всей ссылке (только amp; надо будет заменить на просто & в этом случае)
Также, вместо того чтобы 4 раза писать руками urlencode можно было использовать тут http_build_query которая составляет ссылку из массива параметров.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L72
> $token = createXsrfCookie( );
Второй раз наверно не надо вызывать уже функцию, достаточно один раз ее в самом верху поставить.
> https://github.com/MindiMakridi/Students/blob/master/lib/functions.php#L58
> ?>
Лучше не ставить этот маркер в конце файла, а то стоит поставит за ним хотя бы один пробел и куки перестанут высталвяться (так как отпралять заголовки и ставить куки нельзя если ты вывел хотя бы один символ)
Больше замечаний нет.
Ну и ты можешь не ждать меня, а потихоньку делать вторую задачу, на файлообменник с twig.
>Не занимайся PHP, тогда проблемы не будет.
Лучшим советом, наверное, было бы не заниматься алкоголизмом.
>а потихоньку делать вторую задачу, на файлообменник с twig
Файлообменник, я так понял, можно уже использовать как портфолио, но с моей версткой будет стыдно такое показывать кому-либо. Хочу стать гуру разметки, ну или хотя бы, чтобы странички были приятны глазу.
> А вопросы с подвохом? Это ведь шуточки про hr, да?
Почему, некоторые любят вопросы на всякие тонкости преобразования типов.
> Это вот всё на стажера нужно?
Не факт, что нужно
> В резюме про что писать-то?
Погугли «как составить резюме». Надо писать образование и какие технологии на каком уровне ты знаешь.
>>435253
Потому что тут они приводятся не к bool а к int. 0 -> 0, 'x' -> 0
В мануале где-то есть правила приведения типов в таком случае.
>>435259
Если у тебя есть выбор, то можно и убегать. А так, можно на всяких сайтах типа antijob кучу кулстори на эту тему прочесть.
>>435262
Вот в этой строчке
> $creditBalance = ( $creditBalance * $percent ) + $servicePayment - $monthlyPayment;
Ты вычитытаешь monthlyPayment не глядя чему равен долг. А ведь может быть он меньше чем monthlypayment.
> $creditBalance == $monthlyPayment;
тут опечатка. == обозначает сравнение и используется внутри if, а ты наверно хотел написать просто =
> А вопросы с подвохом? Это ведь шуточки про hr, да?
Почему, некоторые любят вопросы на всякие тонкости преобразования типов.
> Это вот всё на стажера нужно?
Не факт, что нужно
> В резюме про что писать-то?
Погугли «как составить резюме». Надо писать образование и какие технологии на каком уровне ты знаешь.
>>435253
Потому что тут они приводятся не к bool а к int. 0 -> 0, 'x' -> 0
В мануале где-то есть правила приведения типов в таком случае.
>>435259
Если у тебя есть выбор, то можно и убегать. А так, можно на всяких сайтах типа antijob кучу кулстори на эту тему прочесть.
>>435262
Вот в этой строчке
> $creditBalance = ( $creditBalance * $percent ) + $servicePayment - $monthlyPayment;
Ты вычитытаешь monthlyPayment не глядя чему равен долг. А ведь может быть он меньше чем monthlypayment.
> $creditBalance == $monthlyPayment;
тут опечатка. == обозначает сравнение и используется внутри if, а ты наверно хотел написать просто =
Нет проблем, используй дефолтные компоненты из bootstrap. Они сами по себе довольно приятны глазу.
>Потому что тут они приводятся не к bool а к int. 0 -> 0, 'x' -> 0
>
>В мануале где-то есть правила приведения типов в таком случае.
По мне дак, за такой не очевидный код бить нужно. Или в реальном мире это знание всё таки может пригодится?
Это ты еще Жаваскрипт не видел.
Кстати, верно.
>>435299
Ты бы скопипастил текст вопроса, а то там регистрация же нужна.
Там в объяснении пишут что дложно быть условие type = 'laptop' а у тебя его нет, может в этом дело?
Если не в этом, то скопипасть пожалуйта текст задачи и описание таблиц product, laptop, так как я не очень понимаю, что в них и например являетяс ли колонка model уникальным ключом в laptop или нет.
>>435358
Время не надо увеличивать, там и полсекунды хватило бы. У тебя программа входит в бесконечный цикл и хоть сколько ты ей времени дай, она не завершится.
Смотри, у тебя условие продолжения записано как
> $firstInputMoney!=1000000
То есть продолжать цикл пока сумма не станет равна ровно миллиону. А что если там будет не миллион, а например миллион и 1 рубль? Тогда условие будет всегда выполняться и цикл никогда не завершится.
Также, это
> \t$firstInputMoney=$firstInputMoney+(($firstInputMoney/100)*10);
Надо упростить. Чтобы увеличить сумму на 10% достаточно просто умножить ее на 1.10 (вспоминай школьную математику).
И давай нормальные навазния переменным. Не $b, а $years например.
>>435413
Надо после каждой операции с mysqli делать проверку резудльтата через if, так как может произойти ошибка.
Код того анона очень неправильный, в нем куча ошибок, я выше написал.
Насчет вывода, там скорее всего выключено отображение ошибок. Посмотри логи сервера (они есть где-то в панели управления либо видны через FTP/SFTP) — в них хранится текст ошибки.
Если ты запускаешь код не на хостинге, а у себя то включи display_errors чтобы они выводились на экран. На хостинге включать не надо, смотри логи.
Кстати, верно.
>>435299
Ты бы скопипастил текст вопроса, а то там регистрация же нужна.
Там в объяснении пишут что дложно быть условие type = 'laptop' а у тебя его нет, может в этом дело?
Если не в этом, то скопипасть пожалуйта текст задачи и описание таблиц product, laptop, так как я не очень понимаю, что в них и например являетяс ли колонка model уникальным ключом в laptop или нет.
>>435358
Время не надо увеличивать, там и полсекунды хватило бы. У тебя программа входит в бесконечный цикл и хоть сколько ты ей времени дай, она не завершится.
Смотри, у тебя условие продолжения записано как
> $firstInputMoney!=1000000
То есть продолжать цикл пока сумма не станет равна ровно миллиону. А что если там будет не миллион, а например миллион и 1 рубль? Тогда условие будет всегда выполняться и цикл никогда не завершится.
Также, это
> \t$firstInputMoney=$firstInputMoney+(($firstInputMoney/100)*10);
Надо упростить. Чтобы увеличить сумму на 10% достаточно просто умножить ее на 1.10 (вспоминай школьную математику).
И давай нормальные навазния переменным. Не $b, а $years например.
>>435413
Надо после каждой операции с mysqli делать проверку резудльтата через if, так как может произойти ошибка.
Код того анона очень неправильный, в нем куча ошибок, я выше написал.
Насчет вывода, там скорее всего выключено отображение ошибок. Посмотри логи сервера (они есть где-то в панели управления либо видны через FTP/SFTP) — в них хранится текст ошибки.
Если ты запускаешь код не на хостинге, а у себя то включи display_errors чтобы они выводились на экран. На хостинге включать не надо, смотри логи.
> там настроек куча, нужно в километровых текстовых файлах рыться
Не надо, те что по умолчанию годятся.
> и вообще я по-моему их много наустанавливал
Должна быть только одан MySQL и один Апач
> Warning: mysql_list_dbs() has been disabled for security reasons
Да, функция запрещена администратором, так как расширение mysql устарело несколько лет назад.
>>435446
Функция запрещена администратором так как устарела.
Не надо начинающим ставить денвер. Это сборка для опытных разработчиков. Надо ставить руками Апач/PHP/mysql. У нас есть мини-уроки на эту тему:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Если ты не знаком с командной строкой вот урок:
https://gist.github.com/codedokode/10539568
> Далее заходишь в phpmyadmin, который входит в обе сборки, создаешь там базу с таким же именем пустую, после чего жмешь импортировать
Полезнее начинабщему делать это руками в консоли mysql. Импортировать дамп можно командой
mysql -u{имяюзера} -p {имя базы данных} < {имя файла с дампом}
Например
mysql -uanon -p database1 < c:\tmp\dump.sql
> то попробуй скайп выключить
Лучше зайти в настройки скайпа и снять галочку «занимать порт 80»
>>435446
Ой, я ошибся. Функция запрещена не потому что устарела (хотя она на самом деле устарела) а потому что администратор ее отключил (кстати вывести список баз все равно можно запросом SHOW DATBASES).
И анон прав, нельзя совместно использовать mysql и mysqli функции.
>>435466
Стоит учить наверно.
PHP-ников много, но грамотных мало (многие учатся по устаревшим видеокурсам и учебникам и ничего толком не понимают) потому не беспокойся.
>>435518
Удаленка, odesk
>>435519
Книга то слабая. Лучше год обучения в нашем треде, мы тебя гораздо лучше натренируем.
>>435520
Есть odesk тред в разделе /wrk
Вообще, не знаю, все зависит от компании. Если ты через odesk например работаешь, то проблем особых нет, договоров никаких нет, а деньги получашеь на карточку вроде payoneer (разве что в некоторых странах есть ответственность за владение иностранными счетами, а также уклонение от уплаты налогов). Большинство, как я понимаю, «партизанят» и никак официально о своей работе не рассказывают.
Теоретически наверно можно и официально как-то оформить это, но я подозреваю это геморройно.
>>435564
А у нас есть задачи на HTML/CSS, хорошие, в конце надо сверстать сайт. Как всегдя, я буду строго придиратся к каждой ошибочке и неточности в решении. Посмотри: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
Гуру не гуру, но крепкие навыки они тебе дадут и научат например позиционированию элементов, что далеко не везде изучают. Ну а если ты после этого еще лучше захочешь знать CSS, я может посоветую какие темы изучать (хотя наверно тебе это не понадобится).
Можно делать их параллельно с файлообменником, и вбрасывать сразу по несколько решений.
>>435446
Ой, я ошибся. Функция запрещена не потому что устарела (хотя она на самом деле устарела) а потому что администратор ее отключил (кстати вывести список баз все равно можно запросом SHOW DATBASES).
И анон прав, нельзя совместно использовать mysql и mysqli функции.
>>435466
Стоит учить наверно.
PHP-ников много, но грамотных мало (многие учатся по устаревшим видеокурсам и учебникам и ничего толком не понимают) потому не беспокойся.
>>435518
Удаленка, odesk
>>435519
Книга то слабая. Лучше год обучения в нашем треде, мы тебя гораздо лучше натренируем.
>>435520
Есть odesk тред в разделе /wrk
Вообще, не знаю, все зависит от компании. Если ты через odesk например работаешь, то проблем особых нет, договоров никаких нет, а деньги получашеь на карточку вроде payoneer (разве что в некоторых странах есть ответственность за владение иностранными счетами, а также уклонение от уплаты налогов). Большинство, как я понимаю, «партизанят» и никак официально о своей работе не рассказывают.
Теоретически наверно можно и официально как-то оформить это, но я подозреваю это геморройно.
>>435564
А у нас есть задачи на HTML/CSS, хорошие, в конце надо сверстать сайт. Как всегдя, я буду строго придиратся к каждой ошибочке и неточности в решении. Посмотри: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
Гуру не гуру, но крепкие навыки они тебе дадут и научат например позиционированию элементов, что далеко не везде изучают. Ну а если ты после этого еще лучше захочешь знать CSS, я может посоветую какие темы изучать (хотя наверно тебе это не понадобится).
Можно делать их параллельно с файлообменником, и вбрасывать сразу по несколько решений.
базу данный MySQL то он без сомнения поддерживает, а вот библиотеку пхпшную mysql_... он не поддерживает наверное, поэтому тебе нужна mysqli_.. это тоже вещь для работы с базой данных MySQL, только новее, лол.
Ну и да, чтобы выглядело аккуратно можно бутстрап использовать, а вообще чтобы уметь делать «красивые» страницы, нужна не столько верстка, сколько минимальные представления о дизайне.
Как оформлять текст, как выравнивать блоки, какие цвета лучше использовать/не использовать. Не знаю, где про это можно почитать.
А верстка это лишь процесс переноса дизайна на язык HTML/CSS. Но верстальщику полезно понимать принципы оформления текста.
Про оформление текста могу посоветовать «Недизайнерская книга о дизайне». Она маленькая, но рассказывает основные принципы оформления текста.
Вообще, «приятность» глазу как правило и основана на том, что текст правильно выровнен, шрифт читабельный, длина строк и межстрочное расстояние подобраны хорошо, блоки расположены по какой-то логике (например выровнены по сетке), цвета контрастные, поля и отступы достаточных размеров. Если нарушать эти правила, то сайт начинает выглядеть неаккуратно.
Например, на этом сайте есть такой косяк: длина строк не ограничена, из-за чего их не очень удобно читать. Возможно, тут расчет на то, что будут писать в основном одно-двух строчные посты, с которых вхгляд не соскакивает, но есть строчек больше, то лучше ограничивать ширину текста.
Также, цитаты оформлены довольно бледным текстом, который плохо заметен на сером фоне.
>>435567
Не надо сравнивать строки с числами, это да.
>>435572
Не, неаккуратное какое-то решение. Ты сначала в минус уходишь, а потом пытаешься исправить это. Но почему бы просто не переделать код, чтобы вычитать столько сколько осталось, а не 5000?
Вот в этой строке
> \t$creditBalance = ( $creditBalance * $percent ) + $servicePayment - $monthlyPayment;
Ты вычитаешь всегда ровно 5000, даже если осталось немного. надо бы это исправить.
mysql и mysqli это разные расширения. Почему денвер не поддерживает, не знаю, но если это так то надо либо поставить расширение самому (либо включить его в php.ini) либо ставить Апач/PHP с нуля.
Сделай файл 1.php c кодом
<?php phpinfo( );
И открой его через браузер. Там выведется список включенных расширений, проверь что там есть mysqli. Если нет то там выводится путь к php.ini, попробуй в нем разрешить mysqli.
>Не, неаккуратное какое-то решение.
Ты имеешь ввиду, что на одной строчке вычитается, а на другой сразу же прибавляется или что-то кардинально другой алгоритм? Если да, то признаю, проебал этот момент. А если нет, то хз, по мне так всё остальное уже будет шило на мыло.
> на одной строчке вычитается, а на другой сразу же прибавляется
Да, лучше не уходить в минус и не исправлять это костылями, а сделать проверку сколько осталось долга и не платить больше чем требуется.
>>435598
Спокойно, не нервничай, давай разберемся.
Ты явно не проходил курс для начинающих по mysql, так ведь? Сложно что-то понять если пропускать основы и сразу браться за сложное.
Значит, самое время пройти простой туториал который даже обезьянка осилит:
http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix-chast-3.html
(это третья часть, очевидно что перед ней надо пройти первые 2 части на которые там есть ссылки).
Также, дополнительно, чтобы закрепитть знания, советую решить 2-3 задачки на MySQL отсюда: https://gist.github.com/codedokode/10539213
Там же есть ссылка на учебник Пирамидина. Некоторые тут еще советую сайт sql-ex.ru но он требует регистрации.
Проходишь туториал под виндой, не работают русские буквы? Пиши SET NAMES cp866; в начале работы.
Первый раз в жизни видишь консоль и не понимаешь что это? Прочти инструкцию по командной строке https://gist.github.com/codedokode/10539568
Если что-то еще непонятно, задавай вопросы.
>>435595
Немного переделал, но хз, по мне так я не понял, что ты имеешь ввиду.
http://ideone.com/vMfEyo
А, перед прохождением туториала стоит почитать еще это: http://phpclub.ru/mysql/doc/tutorial.html
Про то как подсоединяться к серверу из командной строки. Да, начинабщему стоит начать с командной строки, а не phpmyadmin.
>Насчет таблицы answer_attempts — тут конечно есть сложный вопрос, а что должно храниться в answer?
Я планирую просто текст.
>Я думаю, во втором случае стоит запретить редактировать тест если его уже проходили.
Такой же план.
>С третьей стороны, а что если надо исправить опечатку в тесте или оказалось что правильный ответ был помечен неправильно?
Можно разрешить редактирование, но с обнулением всех результатов.
>А зачем вообще ты ввел куки? Для защиты от случайного перезапуска теста?
Чтобы как-то определить, кто какая попытка к какому пользователю относится. Пользователей же нет, так что просто пробить по айди не выйдет.
>Есть такое http://stackoverflow.com/a/22752533 — это для Yii 1 правда
Да, просто find()->where()->count() можно.
>>434652
>Явно надо это вынести в метод у модели (полуить N-й вопрос теста)
Да-да, унес.
>И сразу же там сделать подгрузку вариантов ответов, чтобы лишних SQL запросов не было.
В смысле, какую подгрузку? А про лишние SQL-запросы, там Yii сам же кеширует все, что кешируется.
>Подумай, не стоит ли это тоже сделать методов вроде такого:
Да надо было просто все это закинуть в конструктор. Попытка не существует вне теста, а ответы к попытке вне попытки же.
https://github.com/sqghub/TestHub
Чуть-чуть подправил. Подумываю начать делать сами страницы.
>Насчет таблицы answer_attempts — тут конечно есть сложный вопрос, а что должно храниться в answer?
Я планирую просто текст.
>Я думаю, во втором случае стоит запретить редактировать тест если его уже проходили.
Такой же план.
>С третьей стороны, а что если надо исправить опечатку в тесте или оказалось что правильный ответ был помечен неправильно?
Можно разрешить редактирование, но с обнулением всех результатов.
>А зачем вообще ты ввел куки? Для защиты от случайного перезапуска теста?
Чтобы как-то определить, кто какая попытка к какому пользователю относится. Пользователей же нет, так что просто пробить по айди не выйдет.
>Есть такое http://stackoverflow.com/a/22752533 — это для Yii 1 правда
Да, просто find()->where()->count() можно.
>>434652
>Явно надо это вынести в метод у модели (полуить N-й вопрос теста)
Да-да, унес.
>И сразу же там сделать подгрузку вариантов ответов, чтобы лишних SQL запросов не было.
В смысле, какую подгрузку? А про лишние SQL-запросы, там Yii сам же кеширует все, что кешируется.
>Подумай, не стоит ли это тоже сделать методов вроде такого:
Да надо было просто все это закинуть в конструктор. Попытка не существует вне теста, а ответы к попытке вне попытки же.
https://github.com/sqghub/TestHub
Чуть-чуть подправил. Подумываю начать делать сами страницы.
> https://github.com/sqghub/TestHub/blob/master/models/Question.php#L96
> \Yii::$app->getDb()->transaction(function () {
что это модель лезет куда-то в глобальные переменные? Из самого объекта AR никак нельзя получить ссылку на Db?
Ну я так понял $app действует как такой сервис-локатор. Хотя да, можно просто $this->getDb();
Сервис локатор это антипаттерн и плохая идея. Вот у меня был урок на эту тему: https://gist.github.com/codedokode/e1d31a31b37d5f635057
Хорошо когда объект получает зависимости через конструктор или сеттеры. Плохо когда используются глобальные переименные, прямое обращение по имени класса, статические методы, или передача сервис-локатора (так как в этом случае не очевидно от каких именно объектов зависит класс).
Конечно в Yii, я подозреваю, антипаттернов и так хоть отбавляй, но ты должен стараться не увеличивать их количество (если это не сложно; могут быть ситуации что по другому никак; либо смирись либо переходи на симфони 2).
>Хорошо когда объект получает зависимости через конструктор или сеттеры.
Он и получает. Просто если в конструкторе не указать бд, то он возьмет ту, что указана как db в сервис локаторе. Как-то так. В общем-то независимо от этого стоит брать бд из AR, а не из сервис локатора, я уже поменял.
Точнее не сам сервис локатор, а прямое обращение к нему. Вот так плохо:
$x = new X($serviceLocator); // надо передавать зависимости явно, чтобы было видно от каких классов зависит X
Так плохо:
function construct() {
$this->x = Locator::get('x'); // мы не можем подменить x на свой объект
}
Вот пример уместного использоваения servicelocator:
$a = $serviceLocator->getA( );
$b = $serviceLocator->getB( );
$x = new X($a, $b); // зависимости передаются явно, их можно поменить на что угодно
Обычно в таких случаях используют DI container, это класс который создает объекты по прописанным в коде или конфиге правилам:
// конфиг описывает что надо передать в конструктор для создания объекта
x:
class: 'X'
arguments: [@a, @b]
// использование
$x = $diContainer->get('x');
// Конструктор класса X
function construct(A $a, B $b) {
...
}
Так сделано например в Symfony 2:http://symfony.com/doc/current/book/service_container.html
Некоторые DI containers (в ZF2 например) пытаются сами угадать зависимости класса по тайп хинтам в конструкторе.
Точнее не сам сервис локатор, а прямое обращение к нему. Вот так плохо:
$x = new X($serviceLocator); // надо передавать зависимости явно, чтобы было видно от каких классов зависит X
Так плохо:
function construct() {
$this->x = Locator::get('x'); // мы не можем подменить x на свой объект
}
Вот пример уместного использоваения servicelocator:
$a = $serviceLocator->getA( );
$b = $serviceLocator->getB( );
$x = new X($a, $b); // зависимости передаются явно, их можно поменить на что угодно
Обычно в таких случаях используют DI container, это класс который создает объекты по прописанным в коде или конфиге правилам:
// конфиг описывает что надо передать в конструктор для создания объекта
x:
class: 'X'
arguments: [@a, @b]
// использование
$x = $diContainer->get('x');
// Конструктор класса X
function construct(A $a, B $b) {
...
}
Так сделано например в Symfony 2:http://symfony.com/doc/current/book/service_container.html
Некоторые DI containers (в ZF2 например) пытаются сами угадать зависимости класса по тайп хинтам в конструкторе.
Если ты возвращаешь null то можно просто написать
if ($newPath === null)
или, что короче, проверять что newPath пуст (а null это пустое значение):
if (!$newPath) {
...
}
Оу, там все иначе.
http://www.yiiframework.com/doc-2.0/yii-db-activerecord.html#getDb()-detail
Т.е. по умолчанию getDb() берет ту, что в сервис локаторе обозначена как db. А если мы хотим впихнуть другую, то мы переопределяем этот метод. Как-то глупо выходит, зависимость прямо в самом классе на уровне метода.
Ну это сделано на случай если у тебя например 2 базы и часть таблиц в одной, часть в другой, ты можешь в модели это прописать.
Да, это значит что ты не можешь создать объект и передать ему при создании какой-то экземпляр Db. Это делает код менее гибким. Видимо, это особо не требовалось (а для тестов они скорее всего подменяют глобальный объект db в service locator).
Аналогично сделано и в некоторых фреймворках на других языках, например ruby on rails, там тоже много статических вызовов.
Там в Yii много такого (в Yii 1 было хуже), это делается то ли ради упрощения (?) кода, то ли потому что не нужно, то ли потому что авторы немного велосипедисты. Точной причины я не знаю. Но большие фреймворки (ZF2, Symfony 2) используют DI и вообще новый код стараются писать в таком стиле, а цель нашего треда рассказать про то как принято делать.
Раз в Yii используется getDb, то используй ее.
Насчет почему Yii так устроен, у меня есть версия. Раньше был такой фремворк CodeIgniter (на который Yii 1 был нмного похож архитектурно), там тоже был доступен объект фреймворка через вызов функции
get_instance()->doSomething
Похоже на Yii::app()
Причем что особо адово, там нет отдельного объекта $app, get_instance() возвращает первый созданный контроллер (то есть этот контроллер являлся одновременно объектом $app, если ни одного контроллера не создано то get_instance возвращает null). так что в сравнении с ним Yii сделал шаг вперед.
Что исправить, что добавить?
http://ideone.com/1pDtpZ
> if(preg_match($end5, $last2Digits)){
Регулярные выражения используются для обработки текста. Для чисел используй математику.
> $from1to900 = '#^[1-9][0?0?]$#';
То же самое
>if(preg_match('#^([0-9])|([0-9]){2}|([11-19])|([0-9]{3})$#', $number)){
То же самое
> $first = 0; $second = 0; $third = 0;
Не стоит экономит место в ущерб читабельности
> $first = floor($number/10)10;
> $first = floor($number / 100)100;
У тебя одна и та же переменная обозначает разные вещи, это запутывает, лучше сделать одну переменную для сотен, другую для десятков и т.д.
> ." тыс "
Надо писать «тысяча». А так же миллионы добавить.
Во-первых. Как это происходит, если с нуля, - он дает уже готовый сервер с паролем-логином оплаченный, куда потом, после разработки, макаки сбрасывают плоды трудов своих(?) А если не с нуля?
Когда лепят сайт, допустим, магазин. Кто занимается наполнением со стороны клиента? Вебмастера или не всегда? Под это дело еще и "админку" делают, верно, для наполнения и управления? CMS? Сами макаки CMSки активно используют? Их нужно знать джуниору?
В чем пишет команда разработчиков? Большие IDE или могут и в простеньком редакторе? Их(ide) нужно знать? Насколько часто используются уже готовые шаблоны - свои/чужие? Как происходит разделение труда? Как делятся задания между работниками? Что по началу доверяют джуну?
> > ." тыс "
> Надо писать «тысяча». А так же миллионы добавить.
Я в конце планирую пройтись по результату, и в зависимости от цифры перед этим "тыс" добавить окончание.
Достаешь из штанов свой CMS, озалупливаешь БИТРИКС, водишь клиенту по губам, забираешь деньги.
http://jsfiddle.net/0spo8sog/
>>435670
http://ideone.com/ubPwTW
Странно, у меня в изначальном коде была строчка if($newPath) но кажется либо я сам, либо кто-то указал что она там не нужна и убрал её.
http://jsfiddle.net/qvm4725q/1/
Спасибо большое за такую рецензию. Вот начал исправлять по мелочам, кроме верстки с помощью css, её пока не касался, но уже в планах скоро. Вот файлы: http://ideone.com/rPazRD
Столкнулся со след проблемой пока:
когда захотел сделать index.php + post.php в 1 файл, то вылезала следующая болячка, после того как ты запостил что-то на борду, и жал f5, браузер снова пытался отправить на неё данные, и соответственно появлялся новый пост, копирующий предыдущий. Я пришел к выводу, что у меня после того как я отправил сообщение, ничего не происходит с масивом $_POST[], и соответственно, так как идет проверка на него через isset в начале, то результат оказывается положительным и опять постится сообщение в базу из него.
unset($_POST) или unset($_POST['text']); не помогали. Поэтому пока оставил два файла, один (index.php) под получение данных из базы, и формирования массива для внешнего вида, и второй (post.php) для занесения сообщения в базу.
Следует ли все таки дела это в одном файле или можно два?
Так же вопрос по поводу htmlspecialchars, не совсем ясно как и что ей нужно фильтровать? Всю инфу которую вводит юзер в формы и может послаь всякими post \ get методами? Или что?
Можешь пока ответить на вот эти вопросы
function check1($a, $b) {
\tif ($a='' || $b=''){//rabotai ska
\t\techo "11111";}
\telse {rnd($_GET['a'], $_GET["b"]);}
}
check1($_GET['a'], $_GET["b"]);
Естественно, при тесте выводит ошибку о том что "для функции рнд нужны параметры".
Внимание вопрос: что не так и как это исправить? Инбифо: жабаскрипт.
Сколько например по времени будет сделать сайт и сколько это будет стоить?
Если я сейчас начну изучать с нуля и начну с 1 января 2016 фрилансить на одеске, то $200 смогу сразу получать за месяц?
Все, уже не надо.
>он дает уже готовый сервер с паролем-логином оплаченный, куда потом, после разработки, макаки сбрасывают плоды трудов своих(?)
Нет, обычно это тоже пилить контора
>А если не с нуля?
it depends
>Кто занимается наполнением со стороны клиента? Вебмастера или не всегда?
Не всегда
>Под это дело еще и "админку" делают, верно, для наполнения и управления?
Да, можно сделать кастомную
> CMS?
CMS
>Сами макаки CMSки активно используют?
Зависит от конторы
> Их нужно знать джуниору?
Вообще нет, но мало ли какие требования у конторы твоего залупинска
>В чем пишет команда разработчиков? Большие IDE или могут и в простеньком редакторе?
В чем удобно в том и пишет
> Их(ide) нужно знать?
Нет, освоишься по ходу дела
>Насколько часто используются уже готовые шаблоны - свои/чужие?
Постоянно, гугл лучший друг макаки
>Как происходит разделение труда?
В разных конторах по разному. В конторе твоего залупинска вероятно все пилят всё, максимум кто на верстке + скрипты, кто то на похапе+мускуль
>Как делятся задания между работниками?
Какая блять, разница?
>Что по началу доверяют джуну?
То что никто больше не хочет делать
http://ideone.com/fork/NgH7eg
А зачем такой изврат?
http://ideone.com/zt8sKk
Неправильно. Ты должен был получить количество используя две другие переменные. Понимаешь?
Ты присвоил переменным значения - используй теперь сами переменные для подсчетов.
Так чтоли? Так что же можно написать в коментариях? Типо просто "Число долларов умножаем на курс ОБМЕНА"?
Комментарии там для тебя ОП-написаны. Ты можешь ничего не писать пока сам и другие понимают что происходит в программе.
Это понимаю. Просто я имел в виду, что я правильно понял или можно было коментарий совсем по другом изложить?
> он дает уже готовый сервер с паролем-логином оплаченный, куда потом, после разработки, макаки сбрасывают плоды трудов своих(?) А если не с нуля?
Бывает что у заказчика свой сервер, бывает что нет. Многие веб-конторы либо предоставляют свой хостинг, либо имеют партнерское соглашение с каким-то сторонним хостингом. Тебя это беспокоить не должно, этим занимается менеджер.
> Кто занимается наполнением со стороны клиента?
Иногда заказчик, иногда веб-студия. Занимается этим так называемый «контент-менеджер» (как правило студенты какие-нибудь), но разумеется при нехватке людей это могут поручить и тебе как самому молодому.
> Под это дело еще и "админку" делают, верно, для наполнения и управления? CMS?
Обычно студия ипользует либо CMS (допиленную) либо пишет свою (если старший программист увлекается велосипедостроением). CMS нужна, чтобы клиент мог сам через админку править сайт. Но я видел и примеры когда студия брала деньги с клиента «за поддержку» сайта и сама лениво и с большой задержкой выполняла просьбы по обновлению. В итоге, кстати мы отказались от клиента так как денег платил мало, а требовал много.
> Их нужно знать джуниору?
Может быть полезен опыт с какой-нибудь CMS, например, Drupal или Wordpress. Опыт со стороны разработчика разумеется, со стороны пользователя там вообще уметь ничего особо не надо.
> В чем пишет команда разработчиков? Большие IDE или могут и в простеньком редакторе?
Кто как хочет, но в IDE удобнее
> Их(ide) нужно знать?
Знание возможностей IDE может сделать тебя продуктивней. Я бы советовал полистать мануал и поискать скринкасты с примерами редактирования кода. Сами же производители IDE их выпускают, например для PhpStorm.
> Насколько часто используются уже готовые шаблоны - свои/чужие?
Часто
> Как делятся задания между работниками?
Старший программист распределеяет
> Что по началу доверяют джуну?
Баги, мелкие правки
Вообще, лучше бы ты беспокоился по поводу знания языка PHP, HTML, JS, ООП, фрейморков, а не думал о том кто арендует хостинг.
> он дает уже готовый сервер с паролем-логином оплаченный, куда потом, после разработки, макаки сбрасывают плоды трудов своих(?) А если не с нуля?
Бывает что у заказчика свой сервер, бывает что нет. Многие веб-конторы либо предоставляют свой хостинг, либо имеют партнерское соглашение с каким-то сторонним хостингом. Тебя это беспокоить не должно, этим занимается менеджер.
> Кто занимается наполнением со стороны клиента?
Иногда заказчик, иногда веб-студия. Занимается этим так называемый «контент-менеджер» (как правило студенты какие-нибудь), но разумеется при нехватке людей это могут поручить и тебе как самому молодому.
> Под это дело еще и "админку" делают, верно, для наполнения и управления? CMS?
Обычно студия ипользует либо CMS (допиленную) либо пишет свою (если старший программист увлекается велосипедостроением). CMS нужна, чтобы клиент мог сам через админку править сайт. Но я видел и примеры когда студия брала деньги с клиента «за поддержку» сайта и сама лениво и с большой задержкой выполняла просьбы по обновлению. В итоге, кстати мы отказались от клиента так как денег платил мало, а требовал много.
> Их нужно знать джуниору?
Может быть полезен опыт с какой-нибудь CMS, например, Drupal или Wordpress. Опыт со стороны разработчика разумеется, со стороны пользователя там вообще уметь ничего особо не надо.
> В чем пишет команда разработчиков? Большие IDE или могут и в простеньком редакторе?
Кто как хочет, но в IDE удобнее
> Их(ide) нужно знать?
Знание возможностей IDE может сделать тебя продуктивней. Я бы советовал полистать мануал и поискать скринкасты с примерами редактирования кода. Сами же производители IDE их выпускают, например для PhpStorm.
> Насколько часто используются уже готовые шаблоны - свои/чужие?
Часто
> Как делятся задания между работниками?
Старший программист распределеяет
> Что по началу доверяют джуну?
Баги, мелкие правки
Вообще, лучше бы ты беспокоился по поводу знания языка PHP, HTML, JS, ООП, фрейморков, а не думал о том кто арендует хостинг.
>Вообще, лучше бы ты беспокоился по поводу знания языка PHP, HTML, JS, ООП, фрейморков, а не думал о том кто арендует хостинг.
И зачем половина этого, если сайты пилят на CMS?
Точка с запятой.
А все нашел, забыл просто ; в конце поставить.
Ну всё я спать, завтра с новыми силами опять начну после работы, а то пока пневмания и лечиться/спать надо.
Я так понял прийдется вспоминать математику с 5 по 11 классы, а это очень, очень хуёво, так как я плохо это помню.
Так тоже можно. У меня и так и так получалось, ну твой вариант конечно красивее, но мой компактнее.
> и в зависимости от цифры перед этим "тыс" добавить окончание.
Только без строковых функций и регулярок
>>435861
Молодец, общий принцип ты понял, только сделай блоки повыше, отцентрируй текст и добавь рамку.
Также, у тебя есть ошибка:
> height: 10%
Ты можешь задавать height в процентах только если у родительского блока height задан в пикселях или процентах и определен. У тебя родитель это body и для него не задана высота. Следовательно, ты не можешь у детей задавать высоту в процентах.
Ты можешь прочесть об этом в стандарте CSS2 (англ.): http://www.w3.org/TR/CSS2/visudet.html#the-height-property под заголовком <percentage>
Или тут на русском: http://learn.javascript.ru/height-percent
Потому ты можешь задать высоту только в пикселях.
На практике, высоту задавать почти никогда не требуется, так как удобнее чтобы она определялась содержимым. В данной задаче проще добавить поля сверху/снизу и оставить вычисление высоты автоматическим.
>>435871
Ох, все рабоатет, но вот еще чуть-чуть надо код улучшить.
Строка 157,
> return $result = array(
Это ты не исправил. Перечитай замечание тут: >>435560\t
Строка 167,
> $xTime = $time;
> $xTime += $paths[$startPoint][$stationName]['time'];
Эти 2 строки можно (и нужно) объединить в одну.
> if (!isset($lowerTime)
Это очень плохо что переменная то есть, то нет. Как можно в таких условиях писать надежный код? Сделай чтобы переменная была всегда. Можешь ей в начале присвоить INF (бесконечность)
> и в зависимости от цифры перед этим "тыс" добавить окончание.
Только без строковых функций и регулярок
>>435861
Молодец, общий принцип ты понял, только сделай блоки повыше, отцентрируй текст и добавь рамку.
Также, у тебя есть ошибка:
> height: 10%
Ты можешь задавать height в процентах только если у родительского блока height задан в пикселях или процентах и определен. У тебя родитель это body и для него не задана высота. Следовательно, ты не можешь у детей задавать высоту в процентах.
Ты можешь прочесть об этом в стандарте CSS2 (англ.): http://www.w3.org/TR/CSS2/visudet.html#the-height-property под заголовком <percentage>
Или тут на русском: http://learn.javascript.ru/height-percent
Потому ты можешь задать высоту только в пикселях.
На практике, высоту задавать почти никогда не требуется, так как удобнее чтобы она определялась содержимым. В данной задаче проще добавить поля сверху/снизу и оставить вычисление высоты автоматическим.
>>435871
Ох, все рабоатет, но вот еще чуть-чуть надо код улучшить.
Строка 157,
> return $result = array(
Это ты не исправил. Перечитай замечание тут: >>435560\t
Строка 167,
> $xTime = $time;
> $xTime += $paths[$startPoint][$stationName]['time'];
Эти 2 строки можно (и нужно) объединить в одну.
> if (!isset($lowerTime)
Это очень плохо что переменная то есть, то нет. Как можно в таких условиях писать надежный код? Сделай чтобы переменная была всегда. Можешь ей в начале присвоить INF (бесконечность)
>Это очень плохо что переменная то есть, то нет. Как можно в таких условиях писать надежный код? Сделай чтобы переменная была всегда. Можешь ей в начале присвоить INF (бесконечность)
Я думал об этом, но если в начале присваивать INF - разве тогда при рекурсии переменная не будет перезаписываться при каждом самовызове?
> дальше хотел почитать о JScript'e но там завязка идет с CSS и HTML, так за что взяться далее? БД, CSS, HTML, JS или дальше PHP?
HTML/CSS конечно нужны. Ведь на этом языке верстаются странички которые ты видишь в своем браузере. Как ты будешь делать сайты без знания HTML?
Яваскрипт надо учить после HTML/CSS. Но если ты решаешь мои задачи, то первые задачи на JS не используют DOM (не взаимодействуют с версткой) и их по идее можно решать параллельно с изучением HTML. Но дальше он все равно понадобится.
Также, учебник дает только основы PHP. надо решать следующие задачи, например про абитуриентов, для получения практических навыков.
Так что советую изучить основы HTML (у тебя уйдет пара дней, он простой),а потом начинай решать задачу по PHP и параллельно решай задачи HTML/CSS.
По ходу решения тебе понадобится SQL, опять же, у меня есть задачи на него и там же список туториалов: https://gist.github.com/codedokode/10539213
Опять же, основы SQL выучить это несколько дней, а подробно можно изучить позже.
Если запутаешься опять, можешь попросить подсказку. Никто тебя не бросает один на один с неизвестной технологией. Также. чтобы не ждать ответа, можешь параллельно начинать решать другую задачу.
Тут у тебя ошибочка: если растянуть окно то блок шириной 600px должен быть по центру. А у тебя он смещен влево.
Также, добавь поля (padding) и рамку (border). А то у тебя сверху и снизу текст упирается в край блока.
Ну и я думаю, для такой простой задачи использовать 2 элемента (div и p) — перебор. Оставь только один.
Также, раз ты не знал какое свойство исплользовать, я напишу какие свойства ты должен знать для решения первых 2 задач:
- width, height, min/max-width/height
- padding, padding-left/top etc.
- margin, margin-left/top etc.
- border, border-width, border-style, border-color
- font, font-size, font-weight, font-style, line-height
- color, background-color
Прочитай про эти свойства и прочти про боксовую модель если еще не читал: http://softwaremaniacs.org/blog/2005/07/08/css-boxes/ (часть про IE5/6 устарела, не читай ее).
Для решения 3 задачи тебе надо будет прочесть про сущности (html entitites): http://htmlbook.ru/samhtml/tekst/spetssimvoly
Для 4-й: надо изучить свойство display, а также vertical-align (обрати внимание: оно работает только в 2 ситуациях, а именно выравнивает строчные боксы внутри строки и выравнивает содержимое ячейки таблицы).
Есть такой цикл статей: http://css-live.ru/css/vvedenie-v-inlajnovyj-kontekst-formatirovaniya-ikf-osnovnye-ponyatiya-1-ya-publikaciya-cikla-tajny-css2-1.html но он очень сложный и наверно не стоит его пока читать (не бойся, это знать особо не требуется).
Для 5-й: изучи как padding/margin/width/height работает на строчных боксах.
http://css-live.ru/css/vvedenie-v-inlajnovyj-kontekst-formatirovaniya-ikf-osnovnye-ponyatiya-2-ya-publikaciya-cikla-tajny-css2-1.html
Для 6-й придется изучить float и clear:
http://softwaremaniacs.org/blog/2005/12/01/css-layout-float/
http://softwaremaniacs.org/blog/2005/09/05/css-layout-flow-margins/
Ну и если этого недостаточно, напиши, я еще подсказку дам.
Если запутаешься опять, можешь попросить подсказку. Никто тебя не бросает один на один с неизвестной технологией. Также. чтобы не ждать ответа, можешь параллельно начинать решать другую задачу.
Тут у тебя ошибочка: если растянуть окно то блок шириной 600px должен быть по центру. А у тебя он смещен влево.
Также, добавь поля (padding) и рамку (border). А то у тебя сверху и снизу текст упирается в край блока.
Ну и я думаю, для такой простой задачи использовать 2 элемента (div и p) — перебор. Оставь только один.
Также, раз ты не знал какое свойство исплользовать, я напишу какие свойства ты должен знать для решения первых 2 задач:
- width, height, min/max-width/height
- padding, padding-left/top etc.
- margin, margin-left/top etc.
- border, border-width, border-style, border-color
- font, font-size, font-weight, font-style, line-height
- color, background-color
Прочитай про эти свойства и прочти про боксовую модель если еще не читал: http://softwaremaniacs.org/blog/2005/07/08/css-boxes/ (часть про IE5/6 устарела, не читай ее).
Для решения 3 задачи тебе надо будет прочесть про сущности (html entitites): http://htmlbook.ru/samhtml/tekst/spetssimvoly
Для 4-й: надо изучить свойство display, а также vertical-align (обрати внимание: оно работает только в 2 ситуациях, а именно выравнивает строчные боксы внутри строки и выравнивает содержимое ячейки таблицы).
Есть такой цикл статей: http://css-live.ru/css/vvedenie-v-inlajnovyj-kontekst-formatirovaniya-ikf-osnovnye-ponyatiya-1-ya-publikaciya-cikla-tajny-css2-1.html но он очень сложный и наверно не стоит его пока читать (не бойся, это знать особо не требуется).
Для 5-й: изучи как padding/margin/width/height работает на строчных боксах.
http://css-live.ru/css/vvedenie-v-inlajnovyj-kontekst-formatirovaniya-ikf-osnovnye-ponyatiya-2-ya-publikaciya-cikla-tajny-css2-1.html
Для 6-й придется изучить float и clear:
http://softwaremaniacs.org/blog/2005/12/01/css-layout-float/
http://softwaremaniacs.org/blog/2005/09/05/css-layout-flow-margins/
Ну и если этого недостаточно, напиши, я еще подсказку дам.
Еще ошибки:
> bottom:1px;
bottom работает только совместно с позиционированием (position), тут оно бесполезно
> font-size: 14px;
Если задаешь font-size всегда рядом задавай line-height иначе она унаследуется от родителя.
Слушай, можешь пояснить по поводу этого куска кода:
function addWorker(Employee $employee)
{
$this->workers[] = $employee;
}
Я немного не понял что выступает в качестве аргумента функции и в этом случае в массив $this->workers[] добавится уже посчитанные значения по кофе, зарплатам и страницам?
http://ideone.com/5uNo22
Файлы, если несколько, удобнее заливать на github, а если ты пока не освоил git (что плохо), то на gist.github.com — там можно добавлять файлы перетаскиванием.
Вот замечания по тому, что получилось:
Ты не исправил это: что когда ты вызываешь функции работы с mysqli, надо проверять результат который они возвращают. Ну например, возьмем mysqli_query и прочтем мануал по ней: http://php.net/manual/ru/mysqli.query.php
> Возвращаемые значения
> Возвращает FALSE в случае неудачи
Значит мы должны после вызова с помощью if проверить не получили ли мы false, и если получили то завершать скрипт с ошибкой (так как запрос выполнить не удалось).
Ну и я советовал бы освоить ООП-версию mysqli либо PDO ибо этот подход с вызовом функций никто сейчас не использует.
> \t$posts[] = mysqli_fetch_assoc($queryResult);
Есть же mysqli fetch all которая выбирает сразу все записи в массив, и цикл можно убрать.
> mysqli_query($link, "INSERT INTO `microboard`.`posts` (`name`, `message`) VALUES ('$username', '$text')");
Не вставляй переменные в текст запроса, используй плейсхолдеры. htmlspecialchars тут вообще не причем — они нужны когда ты выводишь данные на HTML страницу и они не защищают от SQL инъекций.
htmlspecilachars надо использовать не тут, а при выводе в шаблоне.
Никогда не используй echo а шаблоне, так как html код внутри кавычек писать и читать неудобно. Используй тег <?= ... ?>
В шаблоне используй версии операторов с двоеточием вместо фигурных скобок ради читабельности. Посмотри пример кода тут: http://www.phpinfo.su/articles/practice/shablony_v_php.html в конце статьи.
> \tfor($i=0; $i<$headersNumber; $i++) {
Для перебора массива короче и читабельнее использовать foreach
> после того как ты запостил что-то на борду, и жал f5, браузер снова пытался отправить на неё данные, и соответственно появлялся новый пост, копирующий предыдущий.
Для решения этой проблемы надо делать после добавления поста редирект например на страницу просмотра постов. Тогда браузер загрузит ее методом GET и при нажатии F5 только обновит эту страницу, не отправляя форму.
Редирект делается через header(location:...)
> Я пришел к выводу, что у меня после того как я отправил сообщение, ничего не происходит с масивом $_POST[], и соответственно, так как идет проверка на него через isset в начале, то результат оказывается положительным и опять постится сообщение в базу из него.
Неверно. Если ты не делаешь редирект, а вместо этого добавляешь запись в базу и сразу выводишь список постов то у тебя отображается страница полученная методом POST (отправкой формы), соответсвтенно при ее обновлении браузер отправляет форму повторно — а как иначе получить эту страницу? Потому надо после добавления записи делать редирект.
После редиректа не забудь сделать die ()
> Следует ли все таки дела это в одном файле или можно два?
В одном удобнее если ты хочешь чтобы при ошибке (например слишком мало или много букв) выводилась форма с вкведенным текстом в ней.
> Так же вопрос по поводу htmlspecialchars, не совсем ясно как и что ей нужно фильтровать?
Используй htmlspecialchars в шаблоне при выводе любых данных. Она превращает (ты читал мануал? прочитай) символы вроде < в спецсимволы и если злоумышленник передаст html-теги то после экранированяи они превратятся в обычный текст и XSS не произойдет. Ну и перечитай мой урок про XSS если не читал.
То есть надо выводить переменные через
<?= htmlspecialchars($x, ENT_QUOTES ?>
и ты будешь защищен от XSS.
Файлы, если несколько, удобнее заливать на github, а если ты пока не освоил git (что плохо), то на gist.github.com — там можно добавлять файлы перетаскиванием.
Вот замечания по тому, что получилось:
Ты не исправил это: что когда ты вызываешь функции работы с mysqli, надо проверять результат который они возвращают. Ну например, возьмем mysqli_query и прочтем мануал по ней: http://php.net/manual/ru/mysqli.query.php
> Возвращаемые значения
> Возвращает FALSE в случае неудачи
Значит мы должны после вызова с помощью if проверить не получили ли мы false, и если получили то завершать скрипт с ошибкой (так как запрос выполнить не удалось).
Ну и я советовал бы освоить ООП-версию mysqli либо PDO ибо этот подход с вызовом функций никто сейчас не использует.
> \t$posts[] = mysqli_fetch_assoc($queryResult);
Есть же mysqli fetch all которая выбирает сразу все записи в массив, и цикл можно убрать.
> mysqli_query($link, "INSERT INTO `microboard`.`posts` (`name`, `message`) VALUES ('$username', '$text')");
Не вставляй переменные в текст запроса, используй плейсхолдеры. htmlspecialchars тут вообще не причем — они нужны когда ты выводишь данные на HTML страницу и они не защищают от SQL инъекций.
htmlspecilachars надо использовать не тут, а при выводе в шаблоне.
Никогда не используй echo а шаблоне, так как html код внутри кавычек писать и читать неудобно. Используй тег <?= ... ?>
В шаблоне используй версии операторов с двоеточием вместо фигурных скобок ради читабельности. Посмотри пример кода тут: http://www.phpinfo.su/articles/practice/shablony_v_php.html в конце статьи.
> \tfor($i=0; $i<$headersNumber; $i++) {
Для перебора массива короче и читабельнее использовать foreach
> после того как ты запостил что-то на борду, и жал f5, браузер снова пытался отправить на неё данные, и соответственно появлялся новый пост, копирующий предыдущий.
Для решения этой проблемы надо делать после добавления поста редирект например на страницу просмотра постов. Тогда браузер загрузит ее методом GET и при нажатии F5 только обновит эту страницу, не отправляя форму.
Редирект делается через header(location:...)
> Я пришел к выводу, что у меня после того как я отправил сообщение, ничего не происходит с масивом $_POST[], и соответственно, так как идет проверка на него через isset в начале, то результат оказывается положительным и опять постится сообщение в базу из него.
Неверно. Если ты не делаешь редирект, а вместо этого добавляешь запись в базу и сразу выводишь список постов то у тебя отображается страница полученная методом POST (отправкой формы), соответсвтенно при ее обновлении браузер отправляет форму повторно — а как иначе получить эту страницу? Потому надо после добавления записи делать редирект.
После редиректа не забудь сделать die ()
> Следует ли все таки дела это в одном файле или можно два?
В одном удобнее если ты хочешь чтобы при ошибке (например слишком мало или много букв) выводилась форма с вкведенным текстом в ней.
> Так же вопрос по поводу htmlspecialchars, не совсем ясно как и что ей нужно фильтровать?
Используй htmlspecialchars в шаблоне при выводе любых данных. Она превращает (ты читал мануал? прочитай) символы вроде < в спецсимволы и если злоумышленник передаст html-теги то после экранированяи они превратятся в обычный текст и XSS не произойдет. Ну и перечитай мой урок про XSS если не читал.
То есть надо выводить переменные через
<?= htmlspecialchars($x, ENT_QUOTES ?>
и ты будешь защищен от XSS.
Ну если ты собрался всю жизнь сидеть в студии своего зажопинска и пилить визитки для местых ооо вектор, то незачем.
>На вашем счету ноль один миллион сто девяносто пять тысяч девятьсот двадцать пять (1195925) рублей
Вот из-за чего?
Нет ну я серьезно спрашиваю. Вы говорите, что все пилят на CMS, а затем вы же наезжаете на мой зажопинск.
Давай я тебя научу как проверить любую форму (в том числе твою гостевуху) на XSS. Введи туда текст вроде такого:
<b>hello
то есть HTML тег + текст, отправь форму и проверь, что выведется. Если текст на странице стал жирным (то есть <b> вставился как HTML тег а не как текст) то сайт уязвим (часто самописные сайты уязвимы, а вот сайты на CMS как правило защищены). Затем, попробуй второй вариант:
">'>©<b>hello
Этот текст тоже должен вывестись как есть. Если он вывелся, то все ок. Если нет (например © превратился в © или часть символов потерялась) — на сайте XSS.
Делай такие проверки только на своих сайтах или с разрешения владельца сайта. ну или хотя бы позаботься об анонимности[/spolier]
Уязвимость XSS за счет вставки на страницу произвольных HTML тегов позволяет воровать данные, других пользователей, менять внешний вид сайта (дефейс), выполнять действия от имени других пользователей сайта (например отправлять сообщения или добавлять посты), входить на сайт под другим пользователем, перенаправлять посетителей на любую другую страницу.
Для проверки на SQL инъекцию можно вводить (только на своем сайте или с разрешения владельца) такие строчки:
' OR 1=1 # (это может сработать в неправильно написанной форме логина)
" OR 1=1 #
а также комбинации кавычек разных видов и бекслешей. Если на сайте уязвимость то выведется либо много лишних данных, либо сайт упадет с ошибкой.
Вики: https://ru.wikipedia.org/wiki/%D0%92%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_SQL-%D0%BA%D0%BE%D0%B4%D0%B0
Школофорум: http://forum.antichat.ru/thread43966.html
# это символ комментария, используемый чтобы закомментировать остаток запроса
Во многих случаях одна SQL инъекция позволяет вытянуть всю важную информацию из базы, а зачастую и из файлов на диске и взломать сайт.
Давай я тебя научу как проверить любую форму (в том числе твою гостевуху) на XSS. Введи туда текст вроде такого:
<b>hello
то есть HTML тег + текст, отправь форму и проверь, что выведется. Если текст на странице стал жирным (то есть <b> вставился как HTML тег а не как текст) то сайт уязвим (часто самописные сайты уязвимы, а вот сайты на CMS как правило защищены). Затем, попробуй второй вариант:
">'>©<b>hello
Этот текст тоже должен вывестись как есть. Если он вывелся, то все ок. Если нет (например © превратился в © или часть символов потерялась) — на сайте XSS.
Делай такие проверки только на своих сайтах или с разрешения владельца сайта. ну или хотя бы позаботься об анонимности[/spolier]
Уязвимость XSS за счет вставки на страницу произвольных HTML тегов позволяет воровать данные, других пользователей, менять внешний вид сайта (дефейс), выполнять действия от имени других пользователей сайта (например отправлять сообщения или добавлять посты), входить на сайт под другим пользователем, перенаправлять посетителей на любую другую страницу.
Для проверки на SQL инъекцию можно вводить (только на своем сайте или с разрешения владельца) такие строчки:
' OR 1=1 # (это может сработать в неправильно написанной форме логина)
" OR 1=1 #
а также комбинации кавычек разных видов и бекслешей. Если на сайте уязвимость то выведется либо много лишних данных, либо сайт упадет с ошибкой.
Вики: https://ru.wikipedia.org/wiki/%D0%92%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_SQL-%D0%BA%D0%BE%D0%B4%D0%B0
Школофорум: http://forum.antichat.ru/thread43966.html
# это символ комментария, используемый чтобы закомментировать остаток запроса
Во многих случаях одна SQL инъекция позволяет вытянуть всю важную информацию из базы, а зачастую и из файлов на диске и взломать сайт.
Выпускникам матфака тут будет скучно. Ты бы взял и попробовал почитать учебник, порешать задачки для начала.
>>435947
>>435960
Открой fl.ru, odesk, freelance (без минуса) и сделай исследование. Надеюсь, учить пользоваться поиском на сайте тебя не надо.
> Сколько например по времени будет сделать сайт и сколько это будет стоить?
Смотря какой. Обычно стоимость определяется как число_часов × стоимость_часа + надбавка, а сделать сайт может занять от нескольких часов (используя стандартную CMS) до месяцев и лет.
> Если я сейчас начну изучать с нуля и начну с 1 января 2016 фрилансить на одеске, то $200 смогу сразу получать за месяц?
Все зависит от тебя. Даже при ставке $6 в час (полный ноль) 200 долларов это всего лишь 33 часа работы.
Алсо, в /wrk есть odesk тред. Изучи его.
Используй Гугл, введя туда «сайт_про_IT odesk» (плохо если ты не догадался это сделать):
http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=habr+odesk
http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=dou.ua+odesk
http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=dev.by+odesk
На одеске расценки от $1 в час (индия, пакистан, иогда в заказах прямо пишут: не просите больше 2 долларов) до 40-50 (есть наверно и больше но я не знаю как они уговаривают заказчиков столько заплатить).
Еще есть заказы с фиксированной суммой. Их можно брать если ты можешь сделать что-то быстро или сделать одну работу для нескольких заказчиков (а деньги взять с каждого) или перепродать заказ кому-нибудь за меньшую сумму.
>>435820
Разделение труда в больших богатых конторах. В маленькой студии лучше уметь все (но уровень умений там соответствующий).
>>436016
Так, работает неплохо. Но к коду есть замечания:
Мне кажется, chief было бы удобнее сделать не параметром в конструкторе, а изменяемым свойством. чтобы можно было сделать работника начальником или разжаловать. А по умолчанию все обычные работники.
> if ($this->chief) {
> $this->pages = 0;
Это нехорошо как-то, незачем менять свойство класса, лучше просто сделать return 0, а то в твоем варианте при разжаловании из дложности начальника pages не восстановится.
> $count = count($this->workers);
> return $count;
А что сразу не написать не return count(..)?
> return round($sum, 1);
Это лучше делать при выводе, а не в Department, а департамент пусть вернет точное значение. А то вдруг в другом отчете понадобится выводить с большей точностью.
> function totalCoffee()
Имя функции должно начинаться с глагола, сделайЧтоТо, напрмер getToatlCoffee или getTotalCoffeeConsumption().
> $string = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
> while (count($string) <= $lenght) {
Чтобы добавить несколько пробелов сразу, есть str_repeat, чтобы найти длину строки есть mb_strlen, а ты как-то переусложнил все.
> for ($i = 0; $i <= count($departments) - 1; $i++) {
> ... $departments[$i]..
используй тут foreach $departments as $department
> foreach ($departments as $value) {
Почитай статью: http://learn.javascript.ru/write-unmain-code#будьте-абстрактны-при-выборе-имени
Не исплоьзуй бессмысленные имена вроде value, tmp, data и так далее.
Ну а вообще неплохо, я вижу, ты ООП более-менее понимаешь.
На одеске расценки от $1 в час (индия, пакистан, иогда в заказах прямо пишут: не просите больше 2 долларов) до 40-50 (есть наверно и больше но я не знаю как они уговаривают заказчиков столько заплатить).
Еще есть заказы с фиксированной суммой. Их можно брать если ты можешь сделать что-то быстро или сделать одну работу для нескольких заказчиков (а деньги взять с каждого) или перепродать заказ кому-нибудь за меньшую сумму.
>>435820
Разделение труда в больших богатых конторах. В маленькой студии лучше уметь все (но уровень умений там соответствующий).
>>436016
Так, работает неплохо. Но к коду есть замечания:
Мне кажется, chief было бы удобнее сделать не параметром в конструкторе, а изменяемым свойством. чтобы можно было сделать работника начальником или разжаловать. А по умолчанию все обычные работники.
> if ($this->chief) {
> $this->pages = 0;
Это нехорошо как-то, незачем менять свойство класса, лучше просто сделать return 0, а то в твоем варианте при разжаловании из дложности начальника pages не восстановится.
> $count = count($this->workers);
> return $count;
А что сразу не написать не return count(..)?
> return round($sum, 1);
Это лучше делать при выводе, а не в Department, а департамент пусть вернет точное значение. А то вдруг в другом отчете понадобится выводить с большей точностью.
> function totalCoffee()
Имя функции должно начинаться с глагола, сделайЧтоТо, напрмер getToatlCoffee или getTotalCoffeeConsumption().
> $string = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
> while (count($string) <= $lenght) {
Чтобы добавить несколько пробелов сразу, есть str_repeat, чтобы найти длину строки есть mb_strlen, а ты как-то переусложнил все.
> for ($i = 0; $i <= count($departments) - 1; $i++) {
> ... $departments[$i]..
используй тут foreach $departments as $department
> foreach ($departments as $value) {
Почитай статью: http://learn.javascript.ru/write-unmain-code#будьте-абстрактны-при-выборе-имени
Не исплоьзуй бессмысленные имена вроде value, tmp, data и так далее.
Ну а вообще неплохо, я вижу, ты ООП более-менее понимаешь.
А что конкретно у тебя не получается?
ууу, платина
Ни в коем случае. А зачем тебе это? Приведи пример кода?
>>436048
first/second лучше бы заменить на hundreds/tens/units. У тебя же в редакторе есть поиск/замена? Поучись заодно ей пользоваться, тут поменять имена дело на полторы минуты.
В функции smallNumberToText($number, $isFemale) очень сложный код. Упрости его, чтобы было примерно так:
слова = пусто;
если (в числе есть сотни) {
добавляем в слова сотни;
}
если (есть десятки) {
добаляем десятки;
}
...
> function Thousand($number){
названия функций пишутся с маленькой буквы и начинаются с глагола, сделайЧтоТо().
Функции Thousand и Million очень похожи на inclineWord($number), согласись? То есть получается ты сделал 3 копии одной функции. Так, разумеется, не пойдет. Копипасты не должно быть.
> if(((((floor($number / 1000000)%10>= 5) && (floor($number / 1000000)%10 <= 9 || floor($number / 1000000)%100 >= 10 && floor($number / 1000000)%100 <= 19)||floor($number / 1000000) % 10 == 0)))){
Это же невозможно читать, такую сложную и длинную строку. Ну как я проверю, правильно тут написано или нет если пока я дойду до конца, я забуду что было в начале. Посмотри насколько проще и красивее сделано в inclineWord.
> PHP Warning: Missing argument 2 for smallNumberToText(), called in /home/ICHKgN/prog.php on line 135 and defined in /home/ICHKgN/prog.php on line 29
аргумент забыл передать
> Пока только тысячи.
а я все равно все проверил
Ни в коем случае. А зачем тебе это? Приведи пример кода?
>>436048
first/second лучше бы заменить на hundreds/tens/units. У тебя же в редакторе есть поиск/замена? Поучись заодно ей пользоваться, тут поменять имена дело на полторы минуты.
В функции smallNumberToText($number, $isFemale) очень сложный код. Упрости его, чтобы было примерно так:
слова = пусто;
если (в числе есть сотни) {
добавляем в слова сотни;
}
если (есть десятки) {
добаляем десятки;
}
...
> function Thousand($number){
названия функций пишутся с маленькой буквы и начинаются с глагола, сделайЧтоТо().
Функции Thousand и Million очень похожи на inclineWord($number), согласись? То есть получается ты сделал 3 копии одной функции. Так, разумеется, не пойдет. Копипасты не должно быть.
> if(((((floor($number / 1000000)%10>= 5) && (floor($number / 1000000)%10 <= 9 || floor($number / 1000000)%100 >= 10 && floor($number / 1000000)%100 <= 19)||floor($number / 1000000) % 10 == 0)))){
Это же невозможно читать, такую сложную и длинную строку. Ну как я проверю, правильно тут написано или нет если пока я дойду до конца, я забуду что было в начале. Посмотри насколько проще и красивее сделано в inclineWord.
> PHP Warning: Missing argument 2 for smallNumberToText(), called in /home/ICHKgN/prog.php on line 135 and defined in /home/ICHKgN/prog.php on line 29
аргумент забыл передать
> Пока только тысячи.
а я все равно все проверил
Помести кнопку внутрь формы. Дополнительные данные можно передать через скрытый input type=hidden. Тогда при нажатии будет отправляться форма.
>>436056
Комментарий можно не писать. Но задачу ты решил не совсем правильно, так как если мы поменяем исходные данные (строчку $dollars = 200), результат не поменяется, а должен поменяться.
>>436061
Комментарий можно удалить, ты не обязан их писать тем более в такой простой (надеюсь для тебя она простая) программе.
Также, вместо или вместе со скриншотом стоит постить ссылку на ideone, так удобнее, если я например захочу что-то попробовать поменять.
>>436063
Можно вообще удалить комментарий.
>>436069
В некоторых случаях для CMS надо делать и натягивать верстку (нужен HTML/CSS, скорее всего JS), а иногда сделать какой-то свой модуль или подправить существующий (нужен PHP/SQL). Но делать примитивные однообразные кривые сайты тебе скоро надоест и захочется перебраться в компанию покрупнее и попрофейсиональнее, работющую на запад или делающую свой продукт. А там на собеседовании тебя будут спрашивать про MVC, ООП и фреймворки. Кстати, в нашем треде всему перечисленному учат.
Это не проблема так как \ не может быть частью имени переменной и php это понимает.
>>436074
Вспомнишь, тут сложнее процентов ничего нет, и в одной задаче надо будет синус с косинусом вставить (формулу дадут готовую хотя мог бы и сам ее составить).
>>436076
Там есть хитрость, ты можешь указать любой верхний предел, но mt_rand генерирует только числа типа int (причем наверняка только 32 битные), а они не могут быть меньше - 2 млрд или больше +2 млрд (примерно). тут есть примеры: http://php.net/manual/ru/language.types.integer.php
>>436078
Локальные (созданные внутри функции) переменные создаются при каждом вызове и изолированы друг от друга, то есть одна и та же переменная может иметь разные значения в разных вызовах функции. То есть ничего перезаписыватья не будет.
То есть если ты имеешь код
function x() {
$a = 1; // создали локальную переменную
... действия с a ...
x( ); // рекурсия
...
то изменение переменной $a в одной функции никак не влияет на переменную $a в другой. Ты можешь поменять локальную переменную только внутри того вызова функции, который ее создал, и снаружи никак на нее не повлиять (и это делает код надежнее).
И если функция рекурсивно вызвана несколько раз, то существует несколько независимых переменных $a, каждая внутри своего вызова функции.
Это не проблема так как \ не может быть частью имени переменной и php это понимает.
>>436074
Вспомнишь, тут сложнее процентов ничего нет, и в одной задаче надо будет синус с косинусом вставить (формулу дадут готовую хотя мог бы и сам ее составить).
>>436076
Там есть хитрость, ты можешь указать любой верхний предел, но mt_rand генерирует только числа типа int (причем наверняка только 32 битные), а они не могут быть меньше - 2 млрд или больше +2 млрд (примерно). тут есть примеры: http://php.net/manual/ru/language.types.integer.php
>>436078
Локальные (созданные внутри функции) переменные создаются при каждом вызове и изолированы друг от друга, то есть одна и та же переменная может иметь разные значения в разных вызовах функции. То есть ничего перезаписыватья не будет.
То есть если ты имеешь код
function x() {
$a = 1; // создали локальную переменную
... действия с a ...
x( ); // рекурсия
...
то изменение переменной $a в одной функции никак не влияет на переменную $a в другой. Ты можешь поменять локальную переменную только внутри того вызова функции, который ее создал, и снаружи никак на нее не повлиять (и это делает код надежнее).
И если функция рекурсивно вызвана несколько раз, то существует несколько независимых переменных $a, каждая внутри своего вызова функции.
Теперь все верно.
>>436092
Есть годный учебник learn.javascript.ru и задачи от ОПа: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
Для первых 10 задач есть робот-проверялка: http://dkab.github.io/jasmine-tests/
>>436094
Это пример кода на ООП. Если ты не знаком с ООП, в моем учебнике он объясняется в последнйе главе.
> Я немного не понял что выступает в качестве аргумента функции
Объект, на который указывает переменная $employee. Объекты можно хранить в переменных и передавать так же как и числа, строки или массивы. Разница только в том, что команда
$a = $b;
для объектов не делает в $a копию объекта $b, а копирует ссылку и 2 переменные укаызвают на тот же самый объект (в отличие от чисел, строк и массивов, для которых эта команда делает копию).
Заметь что там стоит тайп-хинт Employee который гарантирует что в функцию будет передан только объект класса Employee или его наследник. Тайп-хинты делают твой код надежнее и читаьельнее, используй их! Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> и в этом случае в массив $this->workers[] добавится уже посчитанные значения по кофе, зарплатам и страницам?
В массив добавляется объект, который внутри хранит информацию о работнике. зарплата нигде не хранится, она вычисляется функцией исходя из ранга и профессии работника.
Теперь все верно.
>>436092
Есть годный учебник learn.javascript.ru и задачи от ОПа: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
Для первых 10 задач есть робот-проверялка: http://dkab.github.io/jasmine-tests/
>>436094
Это пример кода на ООП. Если ты не знаком с ООП, в моем учебнике он объясняется в последнйе главе.
> Я немного не понял что выступает в качестве аргумента функции
Объект, на который указывает переменная $employee. Объекты можно хранить в переменных и передавать так же как и числа, строки или массивы. Разница только в том, что команда
$a = $b;
для объектов не делает в $a копию объекта $b, а копирует ссылку и 2 переменные укаызвают на тот же самый объект (в отличие от чисел, строк и массивов, для которых эта команда делает копию).
Заметь что там стоит тайп-хинт Employee который гарантирует что в функцию будет передан только объект класса Employee или его наследник. Тайп-хинты делают твой код надежнее и читаьельнее, используй их! Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> и в этом случае в массив $this->workers[] добавится уже посчитанные значения по кофе, зарплатам и страницам?
В массив добавляется объект, который внутри хранит информацию о работнике. зарплата нигде не хранится, она вычисляется функцией исходя из ранга и профессии работника.
Упрощай код, он же у тебя сложный получился. А так, можешь попробовать в smallNumberToText натыкать echo и посмотреть чему какая переменная равна и какие ветки if выполняются.
Также, попробуй упростить ситуацию. Например пере дай ей число 1 миллион и посмотри, будет ли ошибка или нет.Если будет то проблема в выводе числа миллионов.
>>436133
В некоторых случаях (например нужен сайт со стандартным функционалом который реализован в CMS) лучше подходит CMS, в некоторых самописный на фреймворке. Студии обычно делают на CMS так как оплачивать разработку на фреймворке (а это тысячи челочекочасов) заказчик не согласится и у маленьких студий нет нужных специалистов.
Заказчики в регионах предпочитают низкобюджетные простые сайты на CMS. Но есть например компании, делающие сложные приложения — там CMS не подходит.
1) Например в строке аа11134+54477+7-654+
регулярка preg_match_all("/[0-9]+[+0-9]+/", $str, $var);
не должна выдавать в конце +или -.
2) Туже самую строку нужно разбить на массив: число, +-, число, +- число...
> не должна выдавать в конце +или -.
перепиши регулярку чтобы было так:
(цифры-и-знаки)(цифра)
то есть чтобы в концце всегда была цифра.
Либо же исплоьзуй утверждения: http://php.net/manual/ru/regexp.reference.assertions.php
> Туже самую строку нужно разбить на массив: число, +-, число, +- число...
Напиши правильную регулярку. preg_split умеет с помощью специального флага сохранять разделители, то есть то что попало в регулярку.
Я понятия не имею, что нужно писать в массиве, для того чтоб
выполнить проверку на палиндром.
http://ideone.com/7iCe3f
Это то что я накатал.
Это сама ссылка, чтоб долго не искать.
http://archive-ipq-co.narod.ru/l1/strings.html
Пикча для привлечения внимания.
Сделал через ООП,
http://ideone.com/OMmQGE
но насколько я понял, чтобы высчитать вероятность как задано в задачке нужно повторить этот цикл большое количество раз и каждый раз высчитывать среднее арифметическое между старыми и новым результатом?
Код так кидать?
<script src="http://ideone.com/e.js/IHlAEo" type="text/javascript" ></script>
Зачем так извращаться? Берешь урл из адресной строки и вставляешь сюда
http://ideone.com/IHlAEo
>PHP Fatal error: Call to undefined function eror_reporting() in /home/HIQDz9/prog.php on line 3
Всегда смотри на сообщения об ошибках.
>on line 3
На третьей строке ошибка.
>Call to undefined function eror_reporting()
Обращаешься к неизвестной функции eror_reporting(). Нет такой функции, есть функция error_reporting(), а ты написал с одной r
На айдеоне в stderr прямо под stdout. Сотри точку с запятой где-нибудь в коде и сам увидишь.
http://ideone.com/IHlAEo
< - это знак меньше. У тебя в условии стоит $anonSum < $compSum
если сумма анона меньше суммы компьютера, анон победил.
А понял, но там такая проблема, я уже переделал, там абсолютно всегда была победа анона, даже когда у него меньше было.
Что теперь не так?
И когда я в прямом эфире редактирую по этой ссылке, то у вас тоже редактируется в прямом эфире или как?
?> в конце не нужно.
>>>W4.2 Сделай рулетку, то есть генерируется 6-значный номер поста, и, в зависимости от последней цифры, что-то пишется (что, придумай сам).
Это надо в этой же программе что то менять или писать полностью новый код другой?
>И когда я в прямом эфире редактирую по этой ссылке, то у вас тоже редактируется в прямом эфире или как?
Когда ты нажимаешь редактировать и затем запускаешь код, то да, у нас он изменяется, если обновить страницу. Чтобы код оставался прежним, нужно вместо редактирования жать fork.
Я имел в виду, что чтобы решить вторую задачу можно просто кое что поменять в этой или это совсем другая задача?
Ну а сам как думаешь? Начни делать, а там ясно будет.
У тебя там куча мелких ошибок, например отсутствует открывающая скобка, или нету закрывающей фигурной скобки. Смотри лог ошибок внизу, исправляй. Потом спросишь, что не понятно.
Да с этим я разберусь. Я просто логичесски "словами" не могу допереть как сравнивать буквы попарно.
Чтото вроде if $1=$-1 или что
Ты берешь первый символ с начала строки (это у тебя уже есть в коде), и первый символ с конца (чтобы понять как, еще раз прочитай про функцию mb_substr в уроке Опа) потом сравниваешь их друг с другом. Если они равны, цикл продолжается, если нет прерываешь его в результат записываешь, что строка не палиндром.
В чем проблема няши?
Проверка на равенство это ==, а = это присваивание. У тебя там в условиях переменная приравнивается к числу, а не сравнивается с ним.
Неужели я это сделал? Я!!! Обычное заводобыдло написал код!!! КРУТИМ РУЛЕТКУ
>(цифры-и-знаки)(цифра)
тогда в начали будет пропускать знак, с утверждениями буду разбираться,
> preg_split умеет с помощью специального флага сохранять разделители
не нашел нужный флаг
http://ideone.com/6jj9fm
Берешь первый с начала и первый с конца символы, сравниваешь. Если не совпали — не палиндром, если совпали — сравниаем дальше.
Берешь 2й с начала и 2й с конца символы, сравниваешь. Если не совпали — не палиндром, если совпали — сравниаем дальше.
....
Берешь N-й с начала и N-й с конца символы, сравниваешь. Если не совпали — не палиндром, если совпали — сравниаем дальше.
Если дошли до середины строки не несовпадений не было — значит палиндром.
>>436282
> чтобы высчитать вероятность как задано в задачке нужно повторить этот цикл большое количество раз и каждый раз высчитывать среднее арифметическое между старыми и новым результатом?
Как я понимаю (я слаб в матстатистике, увы), матожидание — это если мы повторим эксперимент бесконечное число раз и возьмем среднее. На практике выполнить эксперимент бесконечное число раз невозможно и мы получаем не точную величину, а (ответ ± погрешность) и погрешность зависит от числа выполненных экспериментов. Чем больше, тем точнее.
То есть мы проходим игру с нуля допустим 1000 раз и берем среднее из заработанных в каждом случае денег, это и будет примерное матожидание. Оно будет не точным, а с погрешностью.
Альтернативный метод — не проводить эксперимент, а рассчитать матожидание математически. Ну например в задаче «определите матожидание числа выпавшего на кубике» вместо проведения реального эксперимента можно заметить, что цифры 1-6 выпадают с равной веростностью и матожидание будет равно (1 + 2 .... + 6) / 6 = 3.5. Это точный ответ, а если бы мы проводили эксперимент (попробуй сам), то мы бы получили неточное число вроде 3.5012
В условии задачи сказано:
> Ответ считается правильным, если его относительная или абсолютная погрешность не превосходит 10^ 9.
Очевидно что чтобы поулчить такую точность экспериментально надо провести огромное число экспериментов и мы не уложимся по времени. Значит, задачу нужно решать математиечскими методами.
Ну к примеру, давай найдем матожидание заработанных денег после одного хода. В начале мы имеем k вещей 1-го уровня:
1 1 1 1 ... 1
После первого хода мы убиваем монстра и получаем одну вещь случайного типа случайного уровня из диапазона [1, 2], то есть либо первого либо второго уровня.
— если мы получаем вещь первого уровня, мы ее продаем за одну монету
— если второго уровня, то оставляем ее себе и продаем имеющуюся за 1 монету
Таким образом после первого хода мы имеем всегда ровно одну монету. В половине случаев мы получим вещь второго уровня (назовем эту вещь L2), в половине останемся с существующим набором.
Я бы изобразил это так:
1×0.5 + 2×0.5 1 1 1 ... 1
1 × 0.5 + 2 x 0.5 здесь значит что в половине случаев там вещь 1-го уровня, в половине 2-го.
Теперь рассчитаем ситуацию после второго хода. Убив монстра, мы получаем вещь случайного типа. В 1/2k случаев вещь такого типа (L2) у нас есть, причем 2-го уровня, и в оставшихся (2k - 1)/2k случаев у нас есть такая вещь первого уровня.
Таким образом после второго хода есть такие исходы:
Если у нас есть L2 и нам выпадает вещь такого же типа:
- мы получаем вещь типа L 3-го уровня (L3) и продаем имеющуюся L2 за 2 монеты. Это происходит в (1/2k / 3) случаев.
- мы получаем новую вещь 2-го уровня и продаем L2 за 2 монеты
- мы получаем новую вещь 1-го уровня и продаем ее за 1 монету
Если у нас нет L2 или есть, но выпадает вещь другого типа:
- мы либо получаем вещь 1 уровня и продаем ее за 1 монету
- либо получаем вещь 2 уровня и продаем существующую за 1 монету
То есть у нас после 2 хода есть уже 5 вариантов исходов с разной вероятностью. Перемножив и сложив их, мы получим матожидание числа монет после 2-го хода.
Что касается вещей, то большинство вещей у нас будут 1-го уровня, и только 2 вещи могут быть 2-го, либо одна вещь 3-го уровня.
Как мы видим, на каждом ходе число возможных исходов увеличивается (есть наука комбинаторика, которая может посчитать сколько исходов будет через N ходов). Так как вещей K и к N-му ходу у нас могут быть вещи не выше N + 1 уровня, то для хранения информации о вероятностях обладания вещью понадобится массив размером k × (n + 1) что приемлемо (с учетом ограничения в 1 ≤ n ≤ 10^5; 1 ≤ k ≤ 100 в массиве не может быть более 10 ^ 5 × 100 = 10 млн элементов).
Очевидно, программа должна работать по такой логике и рассчитывать итоговую ситуацию через N ходов. Я не уверен, сколько действий надо сделать для расчета всех вариантов и нужны ли здесь какие-то оптимизации или решение «перебрать и сложить все варианты» в лоб подойдет. Для этого надо анализировать задачу дополнительно. Скорее всего нужны, так как если у нас есть массив k × N то чтобы его обновить надо сделать k × N действий и за N ходов это будет k × N ^ 2 действий, что довольно много.
Продолжу в след. посте.
Берешь первый с начала и первый с конца символы, сравниваешь. Если не совпали — не палиндром, если совпали — сравниаем дальше.
Берешь 2й с начала и 2й с конца символы, сравниваешь. Если не совпали — не палиндром, если совпали — сравниаем дальше.
....
Берешь N-й с начала и N-й с конца символы, сравниваешь. Если не совпали — не палиндром, если совпали — сравниаем дальше.
Если дошли до середины строки не несовпадений не было — значит палиндром.
>>436282
> чтобы высчитать вероятность как задано в задачке нужно повторить этот цикл большое количество раз и каждый раз высчитывать среднее арифметическое между старыми и новым результатом?
Как я понимаю (я слаб в матстатистике, увы), матожидание — это если мы повторим эксперимент бесконечное число раз и возьмем среднее. На практике выполнить эксперимент бесконечное число раз невозможно и мы получаем не точную величину, а (ответ ± погрешность) и погрешность зависит от числа выполненных экспериментов. Чем больше, тем точнее.
То есть мы проходим игру с нуля допустим 1000 раз и берем среднее из заработанных в каждом случае денег, это и будет примерное матожидание. Оно будет не точным, а с погрешностью.
Альтернативный метод — не проводить эксперимент, а рассчитать матожидание математически. Ну например в задаче «определите матожидание числа выпавшего на кубике» вместо проведения реального эксперимента можно заметить, что цифры 1-6 выпадают с равной веростностью и матожидание будет равно (1 + 2 .... + 6) / 6 = 3.5. Это точный ответ, а если бы мы проводили эксперимент (попробуй сам), то мы бы получили неточное число вроде 3.5012
В условии задачи сказано:
> Ответ считается правильным, если его относительная или абсолютная погрешность не превосходит 10^ 9.
Очевидно что чтобы поулчить такую точность экспериментально надо провести огромное число экспериментов и мы не уложимся по времени. Значит, задачу нужно решать математиечскими методами.
Ну к примеру, давай найдем матожидание заработанных денег после одного хода. В начале мы имеем k вещей 1-го уровня:
1 1 1 1 ... 1
После первого хода мы убиваем монстра и получаем одну вещь случайного типа случайного уровня из диапазона [1, 2], то есть либо первого либо второго уровня.
— если мы получаем вещь первого уровня, мы ее продаем за одну монету
— если второго уровня, то оставляем ее себе и продаем имеющуюся за 1 монету
Таким образом после первого хода мы имеем всегда ровно одну монету. В половине случаев мы получим вещь второго уровня (назовем эту вещь L2), в половине останемся с существующим набором.
Я бы изобразил это так:
1×0.5 + 2×0.5 1 1 1 ... 1
1 × 0.5 + 2 x 0.5 здесь значит что в половине случаев там вещь 1-го уровня, в половине 2-го.
Теперь рассчитаем ситуацию после второго хода. Убив монстра, мы получаем вещь случайного типа. В 1/2k случаев вещь такого типа (L2) у нас есть, причем 2-го уровня, и в оставшихся (2k - 1)/2k случаев у нас есть такая вещь первого уровня.
Таким образом после второго хода есть такие исходы:
Если у нас есть L2 и нам выпадает вещь такого же типа:
- мы получаем вещь типа L 3-го уровня (L3) и продаем имеющуюся L2 за 2 монеты. Это происходит в (1/2k / 3) случаев.
- мы получаем новую вещь 2-го уровня и продаем L2 за 2 монеты
- мы получаем новую вещь 1-го уровня и продаем ее за 1 монету
Если у нас нет L2 или есть, но выпадает вещь другого типа:
- мы либо получаем вещь 1 уровня и продаем ее за 1 монету
- либо получаем вещь 2 уровня и продаем существующую за 1 монету
То есть у нас после 2 хода есть уже 5 вариантов исходов с разной вероятностью. Перемножив и сложив их, мы получим матожидание числа монет после 2-го хода.
Что касается вещей, то большинство вещей у нас будут 1-го уровня, и только 2 вещи могут быть 2-го, либо одна вещь 3-го уровня.
Как мы видим, на каждом ходе число возможных исходов увеличивается (есть наука комбинаторика, которая может посчитать сколько исходов будет через N ходов). Так как вещей K и к N-му ходу у нас могут быть вещи не выше N + 1 уровня, то для хранения информации о вероятностях обладания вещью понадобится массив размером k × (n + 1) что приемлемо (с учетом ограничения в 1 ≤ n ≤ 10^5; 1 ≤ k ≤ 100 в массиве не может быть более 10 ^ 5 × 100 = 10 млн элементов).
Очевидно, программа должна работать по такой логике и рассчитывать итоговую ситуацию через N ходов. Я не уверен, сколько действий надо сделать для расчета всех вариантов и нужны ли здесь какие-то оптимизации или решение «перебрать и сложить все варианты» в лоб подойдет. Для этого надо анализировать задачу дополнительно. Скорее всего нужны, так как если у нас есть массив k × N то чтобы его обновить надо сделать k × N действий и за N ходов это будет k × N ^ 2 действий, что довольно много.
Продолжу в след. посте.
Продолжу свою мысль о решении. чтобы понять мой метод, нарисуем (на бумаге или в екселе) таблицу размером K в ширину и N + 1 в высоту. По горизонтали мы откладываем тип вещи, по вертикали ее уровень, а в клеточк пишем вероятность обладать данной вещью на текущем ходе.
Вещь я буду обозначать так: B3 - вещь второго типа 3-го уровня.
Я буду рисовать таблицу из 4 вещей максимум 3 уровня.
До первого хода мы имеем все вещи 1-го уровня и таблица имеет вид:
0 0 0 0
0 0 0 0
1 1 1 1
A B C D
То есть у нас есть 4 вещи 1-го уровня. Вероятность иметь вещь второго уровня равна нулю.
После первого хода мы с вероятностью 0.5 имеем одну из вещей второго уровня и с вероятностью 0.5 остаемся со старой. Для простоты предположим что эта вещь всегда первого типа (то есть мы назовем первую полученную вещь A). То есть мы получаем либо A1 либо A2 с равной вероятностью. Таблица выглядит так:
0.0 0 0 0
1/2 0 0 0
1/2 1 1 1
-A- B C D
То есть в половине случаев мы имеем 1 вещь 2 уровня и 3 вещи первого, и в половине у нас все вещи первого уровня.
После второго хода, мы можем получить вещь такого же как в прошлый раз (A) или другого (B) типа. И она может быть 1-3 уровней для первого типа, и 1-2 уровней для второго. Получается более сложная картина:
- в 1/4 случаев мы получаем вещь A, такую же как и в первый ход. При этом она может быть 1, 2, 3 уровня с разной вероятностью. Вероятность получить вещь A имея A1 равна 1/8. Вероятночть получить A имея A2 равна 1/8. Если у нас есть A2, мы можем получить A1-A3 (вероятность 1/8 распределяется поровну на эти 3 варианта), а если нету то только A1 или A2 (1/8 делится на 2 варианта).
Поделив вероятности получаем в итоге после второго хода вероятность получить:
A1 имея A1 = 1/16
A2 имея A1 = 1/16
A1 имея A2 = 1/24
A2 имея A2 = 1/24
A3 имея A2 = 1/24
B1 или 2 имея A1 = 3/4/ 2= 3/8
B1 или 2 имея A2 = 3/8
Так как мы выбираем лучшую вещь то мы будет владеть (я просто сложил вероятности когда у нас остается указанная вещь):
A1 c вероятностью 1/16 + 3/8
A2 с вероятностью 1/16 + 1/24 + 1/24 + 3/8
A3 c вероятностью 1/24
Что каается вероятности получить B2, она равна 3/4 /2 = 3/8
Таким образом мы можем составить таблицу вероятности владеть вещью определенного уровня после 2 хода (я посчитал сумму дробей на wolphram alpha):
https://gist.github.com/anonymous/95aeedeac668c9b15737
Наверно, это сложно, но главное что можно понять:
- мы можем составить таблицу вероятности иметь какую-то вещь какого-то уровня к N ходу
- мы можем каждый ход проходиться по таблице и пересччитывать вероятности, заодно находя матожидание прибыли от продажи вещей
Соответственно на такой логике можно попробовать сделать программу. Единтвенное, что мне кажется, тут могут понадобиться дальнейшие оптимизации, так как иначе действий придется сделать очень много и можно не уложиться по времени. Может быть можно найти какую-то особенность и упростить расчет.
Продолжу свою мысль о решении. чтобы понять мой метод, нарисуем (на бумаге или в екселе) таблицу размером K в ширину и N + 1 в высоту. По горизонтали мы откладываем тип вещи, по вертикали ее уровень, а в клеточк пишем вероятность обладать данной вещью на текущем ходе.
Вещь я буду обозначать так: B3 - вещь второго типа 3-го уровня.
Я буду рисовать таблицу из 4 вещей максимум 3 уровня.
До первого хода мы имеем все вещи 1-го уровня и таблица имеет вид:
0 0 0 0
0 0 0 0
1 1 1 1
A B C D
То есть у нас есть 4 вещи 1-го уровня. Вероятность иметь вещь второго уровня равна нулю.
После первого хода мы с вероятностью 0.5 имеем одну из вещей второго уровня и с вероятностью 0.5 остаемся со старой. Для простоты предположим что эта вещь всегда первого типа (то есть мы назовем первую полученную вещь A). То есть мы получаем либо A1 либо A2 с равной вероятностью. Таблица выглядит так:
0.0 0 0 0
1/2 0 0 0
1/2 1 1 1
-A- B C D
То есть в половине случаев мы имеем 1 вещь 2 уровня и 3 вещи первого, и в половине у нас все вещи первого уровня.
После второго хода, мы можем получить вещь такого же как в прошлый раз (A) или другого (B) типа. И она может быть 1-3 уровней для первого типа, и 1-2 уровней для второго. Получается более сложная картина:
- в 1/4 случаев мы получаем вещь A, такую же как и в первый ход. При этом она может быть 1, 2, 3 уровня с разной вероятностью. Вероятность получить вещь A имея A1 равна 1/8. Вероятночть получить A имея A2 равна 1/8. Если у нас есть A2, мы можем получить A1-A3 (вероятность 1/8 распределяется поровну на эти 3 варианта), а если нету то только A1 или A2 (1/8 делится на 2 варианта).
Поделив вероятности получаем в итоге после второго хода вероятность получить:
A1 имея A1 = 1/16
A2 имея A1 = 1/16
A1 имея A2 = 1/24
A2 имея A2 = 1/24
A3 имея A2 = 1/24
B1 или 2 имея A1 = 3/4/ 2= 3/8
B1 или 2 имея A2 = 3/8
Так как мы выбираем лучшую вещь то мы будет владеть (я просто сложил вероятности когда у нас остается указанная вещь):
A1 c вероятностью 1/16 + 3/8
A2 с вероятностью 1/16 + 1/24 + 1/24 + 3/8
A3 c вероятностью 1/24
Что каается вероятности получить B2, она равна 3/4 /2 = 3/8
Таким образом мы можем составить таблицу вероятности владеть вещью определенного уровня после 2 хода (я посчитал сумму дробей на wolphram alpha):
https://gist.github.com/anonymous/95aeedeac668c9b15737
Наверно, это сложно, но главное что можно понять:
- мы можем составить таблицу вероятности иметь какую-то вещь какого-то уровня к N ходу
- мы можем каждый ход проходиться по таблице и пересччитывать вероятности, заодно находя матожидание прибыли от продажи вещей
Соответственно на такой логике можно попробовать сделать программу. Единтвенное, что мне кажется, тут могут понадобиться дальнейшие оптимизации, так как иначе действий придется сделать очень много и можно не уложиться по времени. Может быть можно найти какую-то особенность и упростить расчет.
Теперь разберем твое решение.
Видно что твоя программа делает ровно 1 эксперимент и потому погрешность будет огромная, явно больше чем 10 ^ -9 . Мне кажется, так ты задачу за разумное время не решишь. Тут нужен математический подход.
Насчет ООП: ООП использовать можно, но в олимпиадных задачах его обычно не используют. Почему? Потому,что задачи обычно в плане числа переменных простые и там на всю задачу хватает пары массивов и нескольких переменных, и сама программа заниамет 20-30 строк, заводить объекты незачем. Ну например в предложенном мной алогритме нужен всего лишь один массив для хранения таблицы вероятностей.
Насчет codeforces: там у каждой задачи указано число человек которые ее решили. Вот можно отсортировать список по количеству: http://codeforces.ru/problemset?order=BY_SOLVED_DESC
А вещь твою задачу решили всего 166 человек. Я бы советовал начинать с тех что решили хотя бы 3000 человек.
То есть тебе надо начинать с простых задач и параллеьно почитывать книги по олимпиадным задачам, а потом переходить к более сложным. А ты взялся за очень сложную задачу, пропустив простые.
Ну и по коду, примерно такие замечания:
> public $hero;
Переходи на protected/private свойства, public исплоьзовался только в первых задачах ради простоты, а дальше стоит исплоьзовать закрытые свойства.
> \tpublic $gold=0;
Число золота — это наверно свойство героя, а не игры?
get значит «получить». Не надо его к каждой функии приписывать:
getKillMonster -> killMonster
getChangeItem -> changeItem, replaceItem, sellItem
> $monsters = $this->monsters; //копия переменной монстров
Незачем делать копию
Строки 22-28 стоит перенести в класс Hero.
> \t$item = new Item($i);
> $items[] = $item;
Тут можно ключом массива сделать тип вещи, для более удобного поиска.
> getOldItem($numberItem)
Удобнее если функцию будет возвращать объект-вещь, а не уровень.Это гибче.
> public function getChangeItem($numberItem, $itemLvl)
тут тоже логичнее сделать replaceItem(Item $old, Item $new)
> function getGame($n, $k)
Не нужна
В общем, подведу итог:
- если ты хочешь решать олимпиадные задачки, начни с более простых и читай теорию (если не уверен, дай ссылки на статьи/учебники я скажу какой больше тебе подойдет)
- если хочешь помучать ООП, решай кошки-мышки
Теперь разберем твое решение.
Видно что твоя программа делает ровно 1 эксперимент и потому погрешность будет огромная, явно больше чем 10 ^ -9 . Мне кажется, так ты задачу за разумное время не решишь. Тут нужен математический подход.
Насчет ООП: ООП использовать можно, но в олимпиадных задачах его обычно не используют. Почему? Потому,что задачи обычно в плане числа переменных простые и там на всю задачу хватает пары массивов и нескольких переменных, и сама программа заниамет 20-30 строк, заводить объекты незачем. Ну например в предложенном мной алогритме нужен всего лишь один массив для хранения таблицы вероятностей.
Насчет codeforces: там у каждой задачи указано число человек которые ее решили. Вот можно отсортировать список по количеству: http://codeforces.ru/problemset?order=BY_SOLVED_DESC
А вещь твою задачу решили всего 166 человек. Я бы советовал начинать с тех что решили хотя бы 3000 человек.
То есть тебе надо начинать с простых задач и параллеьно почитывать книги по олимпиадным задачам, а потом переходить к более сложным. А ты взялся за очень сложную задачу, пропустив простые.
Ну и по коду, примерно такие замечания:
> public $hero;
Переходи на protected/private свойства, public исплоьзовался только в первых задачах ради простоты, а дальше стоит исплоьзовать закрытые свойства.
> \tpublic $gold=0;
Число золота — это наверно свойство героя, а не игры?
get значит «получить». Не надо его к каждой функии приписывать:
getKillMonster -> killMonster
getChangeItem -> changeItem, replaceItem, sellItem
> $monsters = $this->monsters; //копия переменной монстров
Незачем делать копию
Строки 22-28 стоит перенести в класс Hero.
> \t$item = new Item($i);
> $items[] = $item;
Тут можно ключом массива сделать тип вещи, для более удобного поиска.
> getOldItem($numberItem)
Удобнее если функцию будет возвращать объект-вещь, а не уровень.Это гибче.
> public function getChangeItem($numberItem, $itemLvl)
тут тоже логичнее сделать replaceItem(Item $old, Item $new)
> function getGame($n, $k)
Не нужна
В общем, подведу итог:
- если ты хочешь решать олимпиадные задачки, начни с более простых и читай теорию (если не уверен, дай ссылки на статьи/учебники я скажу какой больше тебе подойдет)
- если хочешь помучать ООП, решай кошки-мышки
Ошибки:
- цвет не тот. Определить цвет можно инструментом пипетка в графическом редакторе по скриншоту либо еще как-то. Верстальщик должен уметь это делать.
- Шрифт у тебя с засечками, а надо без (например Arial подойдет или Trebuchet MS)
- Максимальная ширина блока должна быть 600 px а у тебя 622 (это можно проверить инспектором Ctrl + Shift + I на вкладке Elements, там есть схема с размерами блока) так как width задает ширину без учета паддинга и border. Читал ли ты внимательно статью? http://htmlbook.ru/samlayout/blochnaya-verstka/blochnaya-model
>>436340
Ок, хорошо, я бы конечно буквы покрпнее сделал, но так сойдет.
>>436378
Покажи код
@
Попроси подсказку
>>436379
Я не дам готовый ответ. Так вообще, лучше конечно самому дойти, чем готовый ответ переписать.
Не понял условие — уточни.
>>436385
Да, только почему у тебя побеждает тот у кого очков меньше?
>>436388
Гуд, (теперь) все верно.
>>436393
Они выводтся в пункте stderr, но если ты нажал edit и запускаешь программу там, то там ошибки не выводятся. Жми fork вместо edit и все будет нормально.
Отписал про баг разработчикам ideone.
Ошибки:
- цвет не тот. Определить цвет можно инструментом пипетка в графическом редакторе по скриншоту либо еще как-то. Верстальщик должен уметь это делать.
- Шрифт у тебя с засечками, а надо без (например Arial подойдет или Trebuchet MS)
- Максимальная ширина блока должна быть 600 px а у тебя 622 (это можно проверить инспектором Ctrl + Shift + I на вкладке Elements, там есть схема с размерами блока) так как width задает ширину без учета паддинга и border. Читал ли ты внимательно статью? http://htmlbook.ru/samlayout/blochnaya-verstka/blochnaya-model
>>436340
Ок, хорошо, я бы конечно буквы покрпнее сделал, но так сойдет.
>>436378
Покажи код
@
Попроси подсказку
>>436379
Я не дам готовый ответ. Так вообще, лучше конечно самому дойти, чем готовый ответ переписать.
Не понял условие — уточни.
>>436385
Да, только почему у тебя побеждает тот у кого очков меньше?
>>436388
Гуд, (теперь) все верно.
>>436393
Они выводтся в пункте stderr, но если ты нажал edit и запускаешь программу там, то там ошибки не выводятся. Жми fork вместо edit и все будет нормально.
Отписал про баг разработчикам ideone.
ого, я смотрю, что-то часто даблы выпадают.
>>436428
Если ты жмешь edit то редактируется у всех
Если fork то создается новый код по новой ссылке.
Лучше жать fork.
>>436430
> elseif ($anonSum = $compSum) {
Ошибка:
= значит поместить значение в переменную
== сравнить 2 значения
Ты не сравниваешь, а копируешь в anonSum значение переменной compSum
Всегда пиши == внутри if, а не =
Ну и в данном случае можно просто написать else без условия так как 4-го варианта не дано.
Можешь там немного поменять код. Главное чтобы ответ был правильный и код аккуратный.
>>436440
Ну а ты попробуй и посмотри что получится.
>>436447
Реши заново. Второй раз быстрее же будет.
>>436452
Начало неплохое
>>436463
написал тут >>436596
>>436474
Да, все верно.
PHP же один из самых простых языков. Продолжай решать задачки, и ты гораздо более сложные вещи научишься делать.
Ну и решения на проверку не забывай показывать.
>>436517
>> preg_split умеет с помощью специального флага сохранять разделители
> не нашел нужный флаг
Посмотри код, все разделители попали в массив: http://ideone.com/r3sdx8
>>436521
Нет, он сам сделал, а ты наверно просто завидуешь.
>>436561
Посмотри внизу куча ошибок:
> PHP Warning: Missing argument 2 for smallNumberToText(), called in /home/Oueapy/prog.php on line 107 and defined in /home/Oueapy/prog.php on line 29
> PHP Notice: Undefined variable: isFemale in /home/Oueapy/prog.php on line 48
Их надо исправить.
Также надо исправить все замечания из поста: >>436147
Если что-то непонятно, задавай вопросы.
Можешь там немного поменять код. Главное чтобы ответ был правильный и код аккуратный.
>>436440
Ну а ты попробуй и посмотри что получится.
>>436447
Реши заново. Второй раз быстрее же будет.
>>436452
Начало неплохое
>>436463
написал тут >>436596
>>436474
Да, все верно.
PHP же один из самых простых языков. Продолжай решать задачки, и ты гораздо более сложные вещи научишься делать.
Ну и решения на проверку не забывай показывать.
>>436517
>> preg_split умеет с помощью специального флага сохранять разделители
> не нашел нужный флаг
Посмотри код, все разделители попали в массив: http://ideone.com/r3sdx8
>>436521
Нет, он сам сделал, а ты наверно просто завидуешь.
>>436561
Посмотри внизу куча ошибок:
> PHP Warning: Missing argument 2 for smallNumberToText(), called in /home/Oueapy/prog.php on line 107 and defined in /home/Oueapy/prog.php on line 29
> PHP Notice: Undefined variable: isFemale in /home/Oueapy/prog.php on line 48
Их надо исправить.
Также надо исправить все замечания из поста: >>436147
Если что-то непонятно, задавай вопросы.
Ну и конечно яндекс не забыл добавить пункт про эллиптические функции. Вряд ли их там кто-то использует, просто видимо повыпендриваться хотят какие они умные.
> $monsters = $this->monsters; //копия переменной монстров
>Незачем делать копию
Если не делать - у меня ниже идет цикл где использовано это свойство:
for ($i = 1; $i <= $this->monsters; $i++)
А в теле цикла декремент использован на это свойство $this->monsters. То-бишь мне надо либо использовать копию свойства либо переделывать цикл.
Если свойствами одного объекта является массив двух и больше объектов - можно ли как нибудь напрямую обращаться к одному из объектов без перебора всего массива через foreach ?
Ну вот к примеру у меня есть экземпляр объекта
$game, внутри объекта есть массив $players в котором находятся экземпляры объектов $player.
я пробовал обращаться к ним через $game->players->0 - не выходит.
$game->players[0]
[] используются для выбора элемета из массива
-> для обращения к свойсту или методу
И наоборот, если у тебя массив объектов то пиши
$palyers[0]->doSmth( );
>>436718
Спасибо.
Сделал тут симулятор боя из браузерной игрушки
http://ideone.com/wpVMXX
нужна критика.
Копипаста — зло.
Нельзя ли функции makeOneHitFirstHero и makeOneHitSecondHero которые почти одинаковы, заменить на одну универсальную, в которую передается кто кого атакует?
Это был обходной путь - выше я как раз спрашивал как обратиться к объектам напрямую так как не знал, эт уже позже переделаю.
Еще мне кажется, если урон нанести не удалось, то надпись
> DoctorS наносит 0 урона.
можно не выводить.
http://ideone.com/lIOFhk
Всё парюсь с зад чей про палиндром. Почти додумался но теперь выходит непонятная хрень портящая всю малину.
Почему при разборе по буквам фразы с конца два раза проверяется буква А.
Внимательнее посмотри на $symbol2. Какой символ будет при каждой итерации цикла выводится?
Еще по идее можно было бы сделать классы для оружия и щитов, то есть ты создаешь персонажа, создаешь оружие и даешь ему. Это позволило бы сделать для разных видов оружия разные алгоритмы нанесения урона, например. Но это конечно усложнение.
Плохо, что в конструкторе очень много параметров. Ты не должен делать в функции больше 4-5 аргументов. Это неудобно так как когда ты смотришь на код
> new Hero('DoctorS', 504, 563, 19520, 225, 276, 39, 25, 51, 1276);
Непонятно, какая цифра что значит. В такой ситуации лучше сделать создание героя в несколько шагов:
$doctor = new Hero('DoctorS', 19520);
$doctor->setAttackRange(503, 563);
$doctor->setArmorRange(100, 200);
Или, можно использовать запись в виде цепочки если в конце функций сделать return $this:
$doctor->setAttackRange(...)->
setArmor(...)->
setBlockProbability(...);
Но у этого подхода есть недостаток. В случае конструктора с кучей аргументов ты не можешь их не передать, а здесь ты можешь не вызвать метод.
Еще одним способом сделать код понятнее будет передача массива в конструктор:
$doctor = new Hero('DoctorS', [
'attackLow' => 100,
'attackHigh' => 200,
'armorLow' => 100,
...
]);
За счет массива видно какая цифра что обозначает.
Разумеется, ты должен тогда проверять что все ключи в массиве правильные и ничего не пропущено. Это поможет защититься от ошибок из-за опечаток или забытого параметра.
> $critAmplify = 1;
> return $critAmplify;
Не проще ли написать return 1; не заводя переменную? Аналогично, тут:
> $reduction = mt_rand($this->armorLow, $this->armorHigh);
> return $reduction;
можно сразу писать return mt_rand....
> onstruct($heroFirst, $heroSecond)
Исплоьзуй тайп хинты везде где можно: http://php.net/manual/ru/language.oop5.typehinting.php
Они делают твой код понятнее и надежнее.
Непонятна логика почему getCrit возвращает 1 или 2, а getBlock 0 или 1. Если у тебя результат вида да/нет то лучше всего использовать значения false/true которые специально для этого придуманы ( http://php.net/manual/ru/language.types.boolean.php ) ну или хотя бы 0/1.
Тогда вместо непоянтного
if ($crit == 2)
можно написать читабельное
if ($isCriticalAttack) ...
Метод getAverageDmgReduction лучше переделать, чтобы он не возвращал на сколько ументьшается урон, а получал бы урон на вход и возращал измененное значение:
$damage = $target->reduceDamage($damage);
Тогда можно было бы делать не только вычитаение, а уменьшать урон по другими алгоритмам, например делить на 2 в некотоырх случаях.
> $block = $this->heroFirst->getBlock( );
Тут по моему должно быть heroSecond? Он же удар блокирует.
> $this->heroSecond->doubleHit
Это неправильно сделано, это должно быть не свойство героя (которое вычисляется перед боем в fillDoubleHitString), а метод который принимает второго героя и отвечает на вопрос, может ли первый ударить по второму еще раз:
if ($hero->canHitAgain($target)) ...
Ты не должен хранить doubleHit как свойство, так как это не свойство одного героя, а величина которая получается при сравнении характеристик 2 героев. Ее неправильно хранить как свойство.
> if (!isset($damage2)) {
Неправильно, что переменная может существовать, а может и нет. как в таких условиях вообще писать надежный код?
> $this->heroFirst->health -= $secondDmg;
Лучше сделать метод $hero->takeDamage($damage)
Также, лучше исплоьзовать свойства c доступом private/protected, то есть закрыть их от доступа извне. Это делает код надежнее и получается меньше бардака, так как в этом случае свойства можно менять только через методы.
Соответственно вместо этого
> if ($this->heroFirst->health == 1) {
Лучше написать if ($hero->isDead()) так как это переносит алгоритм определения смерти в класс героя и позволяет сделать его более гибким. Ну и читается праивльнее. Кстати, в мое время герои умирали при достижении 0 HP, а не 1.
> if ($firstFullDmg > $secondFullDmg) {
Странно, ты проверяешь кто победил по тому кто нанес больше урона, а надо проверять у кого осталось меньше HP. А ничья если оба живы остались наверно?
Еще по идее можно было бы сделать классы для оружия и щитов, то есть ты создаешь персонажа, создаешь оружие и даешь ему. Это позволило бы сделать для разных видов оружия разные алгоритмы нанесения урона, например. Но это конечно усложнение.
Плохо, что в конструкторе очень много параметров. Ты не должен делать в функции больше 4-5 аргументов. Это неудобно так как когда ты смотришь на код
> new Hero('DoctorS', 504, 563, 19520, 225, 276, 39, 25, 51, 1276);
Непонятно, какая цифра что значит. В такой ситуации лучше сделать создание героя в несколько шагов:
$doctor = new Hero('DoctorS', 19520);
$doctor->setAttackRange(503, 563);
$doctor->setArmorRange(100, 200);
Или, можно использовать запись в виде цепочки если в конце функций сделать return $this:
$doctor->setAttackRange(...)->
setArmor(...)->
setBlockProbability(...);
Но у этого подхода есть недостаток. В случае конструктора с кучей аргументов ты не можешь их не передать, а здесь ты можешь не вызвать метод.
Еще одним способом сделать код понятнее будет передача массива в конструктор:
$doctor = new Hero('DoctorS', [
'attackLow' => 100,
'attackHigh' => 200,
'armorLow' => 100,
...
]);
За счет массива видно какая цифра что обозначает.
Разумеется, ты должен тогда проверять что все ключи в массиве правильные и ничего не пропущено. Это поможет защититься от ошибок из-за опечаток или забытого параметра.
> $critAmplify = 1;
> return $critAmplify;
Не проще ли написать return 1; не заводя переменную? Аналогично, тут:
> $reduction = mt_rand($this->armorLow, $this->armorHigh);
> return $reduction;
можно сразу писать return mt_rand....
> onstruct($heroFirst, $heroSecond)
Исплоьзуй тайп хинты везде где можно: http://php.net/manual/ru/language.oop5.typehinting.php
Они делают твой код понятнее и надежнее.
Непонятна логика почему getCrit возвращает 1 или 2, а getBlock 0 или 1. Если у тебя результат вида да/нет то лучше всего использовать значения false/true которые специально для этого придуманы ( http://php.net/manual/ru/language.types.boolean.php ) ну или хотя бы 0/1.
Тогда вместо непоянтного
if ($crit == 2)
можно написать читабельное
if ($isCriticalAttack) ...
Метод getAverageDmgReduction лучше переделать, чтобы он не возвращал на сколько ументьшается урон, а получал бы урон на вход и возращал измененное значение:
$damage = $target->reduceDamage($damage);
Тогда можно было бы делать не только вычитаение, а уменьшать урон по другими алгоритмам, например делить на 2 в некотоырх случаях.
> $block = $this->heroFirst->getBlock( );
Тут по моему должно быть heroSecond? Он же удар блокирует.
> $this->heroSecond->doubleHit
Это неправильно сделано, это должно быть не свойство героя (которое вычисляется перед боем в fillDoubleHitString), а метод который принимает второго героя и отвечает на вопрос, может ли первый ударить по второму еще раз:
if ($hero->canHitAgain($target)) ...
Ты не должен хранить doubleHit как свойство, так как это не свойство одного героя, а величина которая получается при сравнении характеристик 2 героев. Ее неправильно хранить как свойство.
> if (!isset($damage2)) {
Неправильно, что переменная может существовать, а может и нет. как в таких условиях вообще писать надежный код?
> $this->heroFirst->health -= $secondDmg;
Лучше сделать метод $hero->takeDamage($damage)
Также, лучше исплоьзовать свойства c доступом private/protected, то есть закрыть их от доступа извне. Это делает код надежнее и получается меньше бардака, так как в этом случае свойства можно менять только через методы.
Соответственно вместо этого
> if ($this->heroFirst->health == 1) {
Лучше написать if ($hero->isDead()) так как это переносит алгоритм определения смерти в класс героя и позволяет сделать его более гибким. Ну и читается праивльнее. Кстати, в мое время герои умирали при достижении 0 HP, а не 1.
> if ($firstFullDmg > $secondFullDmg) {
Странно, ты проверяешь кто победил по тому кто нанес больше урона, а надо проверять у кого осталось меньше HP. А ничья если оба живы остались наверно?
>Непонятна логика почему getCrit возвращает 1 или 2, а getBlock 0 или 1. Если у тебя результат вида да/нет то лучше всего использовать значения false/true
Я их там дальше при подсчете одной атаки использую в качестве множителей.
Крит умножает атаку на 2, в то же время блок врага умножает атаку на 0. На выходе получаю либо либо х2 либо х1 урон если блока не было, если блок был - получаю 0.
Может это программисты поленились.
>>436757
> Тут меня беспокоит, что я ввёл 2 новые
> переменные можноли их не вводить?
Можно не вводить, можно положить текст назад в ту же переменную:
$text = str_replace($text, ....);
Но если ты вводишь новые переменные, надо давать им понятные имена. Вот полезный урок на тему как (не) надо называть переменные: http://learn.javascript.ru/write-unmain-code#именование
В твоем случае новая переменная содержит текст без пробелов и ее уместно назвать textWithoutSpaces (или просто положить результат назад в text)
> А тут я понятия не имею что делать?
Сравни буквы, и если они не совпадают, выходи из цикла — слово не палиндром. Если же все буквы совпали, слово палиндром.
Посмотри у тебя там код не проверяет действительно ли $symbol равняется $symbol2 и в результате просто пишет, что они одно и то же.
Ввод данных для создания экземпляра класса Hero да большой, но это идет не как часть самой браузерки, это скорее как сторонний скрипт который поможет определить - стоит ли нападать либо нет, если цикл боев повторить раз 100-1000 можно получить средний шанс на победу с большой погрешностью конечно. В принципе можно в html создать окно для ввода необходимых параметров своего и вражеского персонажа и на выходе получить вероятность победы. А остальные замечанию постараюсь поправить, благодарю.
>>>Выполни код на картинке
Всмысле просто перепечатать?
>>>Как-нибудь его поменяй
Например как?
Так сойдет? Я справился с заданием?
А нет
Поставил if($i=0) и ракета не запустилась
Ты неправильно пишешь. Внутри if надо писать ==, а не = для сравнения. В твоем случае проще вообще без if написать echo.
Что теперь не так?
Почему >=1 не работает с 1, а только когда стоит 0, ведь 1=1
http://ideone.com/zOliGn
$i >= 1 не работает с if($i == 1), а
$i >= 1 работает с if($i == 0)
Ведь 1=1
Поставь перед
> if($i == 1) {
Команду echo "i=$i\n"; чтобы увидеть чему равно i перед выполнением if.
Это ты просто выводишь чему равно i, "i=" это текст, а $i это имя переменной. Посмотри, там внизу написано
i = 0
Это происходит потмоу что после цикла i равно 0. Почему? надо разобрать, как работает цикл.
Допустим, что сейчас i = 2. Разберем что происходит в цикле:
- проверяется выполнено ли условие $i >= 1 (да)
- выполняется тело цикла
- выполняется команда $i-- и $i становится равным 1
- проверяется выполнено ли условие $i >= 1 (да)
- выполняется тело цикла
- выполняется команда $i-- и $i становится равным 0
- проверяется выполнено ли условие $i >= 1 (нет)
- цикл завершен, а в $i хранится 0
так как после завершения цикла i равно нулю, условие
> if($i == 1) {
Не срабатывает.
В твоем случае, по моему проще вообще убрать if и просто написать
echo "Поехали";
Я об этом писал ранее, твой вариант как бы неживой. Ну типо слово поехали будет в любом случае. А я хочу, чтобы слово поехали было именно тогда когда выполняется команда $i >= 1
Тогда поставь if внутри тела цикла (то ест внутри скобочек for { ... }), а не после. Внутри цикла на последнем шаге $i как раз равно единице и условие сработает.
потому что ты написал: выводить пуск когда i=1. А у тебя там i после цикла равняется 0.
Как оно может равняться нулю, ведь когда 1=1 то цикл должен завершиться.
на самом деле нет.
от сюда -> http://php.net/manual/ru/control-structures.for.php
>В начале каждой итерации оценивается выражение expr2. Если оно принимает значение TRUE, то цикл продолжается, и вложенные операторы будут выполнены.
После того как запостишь код на идеоне. Больше не меняй ни чего в нём по этому адресу. А создавай новый.
То есть цикл закончиться, не когда он должен закончиться, а когда он сломается/не сможет быть выполнен?
>То есть цикл закончиться, не когда он должен закончиться, а когда он сломается/не сможет быть выполнен?
Нет, это я на секунду затупил. Цикл не начинается если условие не выполнилось.
У тебя тут в выражении for ($i = 10; $i >= 1; $i--)
выполняется последний раз когда i = 1, но после проверки условия, идёт выражение $i--
i становится равна 0 и цикл идёт дальше.
Жду подсказки друг.
http://ideone.com/XlltxP
Осталось решить проблему с 11 месяцем, чтобы он был двенадцатым. Но как?
У тебя в последнем месяце. Выплата идёт дважды. Это противоречит условию, выплата делается каждый месяц единожды.
Сделай так.
Сначала, Анон проверяет сколько ему осталось платить.
Если долг больше 5000, то пусть платит ровно 5000.
Если долг меньше 5000, то гасит весь долг. Выбирает что то одно, а не всё сразу.
Так делать нехорошо же? Или типо сойдет?
У тебя ошибка в коде
> \tif($i == 1);
> }
if надо писать в в виде
if (..) {
...
}
А ты не поставил тело if (то что в фигуных скобках).
Цитккл завершается когда нарушено условие цикла то есть $i >= 1. При i = 1 он еще продолжается, при i = 0 завершается.
Сделай без if тогда. Или с if, но правильно.
>>436846
Должно быть около 61270 всего выоплачено. Твоя программа выводит другие числа.
Смотри, у тебя в последний месяц анон платит 5000, и сразу же выплачивает 4139 остатка. А ведь он не может сразу это выплатить, он должен подождать месяц, за который набегут проценты и комиссии и итоговая сумма выйдет больше — не 49139, а около 61270.
Также, если поставить маленькую сумму кредита, например 1000, твоя программа не учтет это и все равно в первый месяц выплатит 5000, хотя достаточно заплатить 2030.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
Это сложная задача, на ней все спотыкаются.
Сделай без if тогда. Или с if, но правильно.
>>436846
Должно быть около 61270 всего выоплачено. Твоя программа выводит другие числа.
Смотри, у тебя в последний месяц анон платит 5000, и сразу же выплачивает 4139 остатка. А ведь он не может сразу это выплатить, он должен подождать месяц, за который набегут проценты и комиссии и итоговая сумма выйдет больше — не 49139, а около 61270.
Также, если поставить маленькую сумму кредита, например 1000, твоя программа не учтет это и все равно в первый месяц выплатит 5000, хотя достаточно заплатить 2030.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
Это сложная задача, на ней все спотыкаются.
Да, не хорошо.
И к тому же, выплата всё равно происходит в 11 месяце, хоть ты и написал, что прошло 12 месяцев.
Я ж говорю. После выплаты 5000, на счету осталось 4138. Должен пройти ещё месяц(цикл). Должны быть на эти 4138 начислены проценты. И вот уже , когда мама Анону даст ещё 5000, он пойдёт гасить долг.
Я не ОП, могу не очень понятно обьяснять. Переспроси если что.
> и итоговая сумма выйдет больше — не 49139, а около 61270.
Исправлюясь: и итоговая сумма выйдет больше — не 59139, а около 61270.
>>436852
11-й месяц не может стать 12-м.
Тебе надо поменять алгоритм, чтобы платить не ровно 5000 каждый раз, а смотреть чему равен остаток долга и если он меньше 5000 то платить меньше.
>>436858
Так делать неправильно, потому что если мы поменяем сумму кредита например на 4000 или 1000, то число 12 не поменяется.
если кредит 40 000 всего вылачено 61270
если 4000 то всего выплачено 6123
если 1000 то всего выплачено 2030
Проверь что ответ совпадает.
W5.1 Исправь и переделай программу, чтобы она работала нормально. Например, эта версия позволяет школьнику переплатить за кредит, так, что банк ему становится должен — это плохо!
ОП, с твоею помощью добрался до файлообменика.
https://github.com/tokotun/uppy
Глянь на набросок беглым взглядом, верной ли дорогой иду?
А так - у меня есть пара вопросов, если кто-то сможет дать на них хороший ответ, то это будет просто замечательно.
Первый вопрос - а почему, собственно, PHP для сайтиков? Почему не какой-либо другой язык? Какие принципиальные преимущества PHP? Наверняка сейчас можно назвать большое количество всяких фреймворков, но ведь это было же не всегда, не так ли?
Второй же вопрос - чисто практический. Итак, допустим у меня есть написанная настольная игрушка. С возможностью игры по сети, ботом. Но хотелось бы сделать так, чтобы можно было играть в нее в браузере. Ну это ведь гораздо удобнее, чем качать исполняемый файл + всякие библиотеки, не так ли? Но тут наступает проблема: веб для меня - совершенно незнакомая область, единственное, что я когда-то делал веб-релейтед - запилил скриптик на джаваскрипте, чтобы генерились таблицы с теми параметрами, которые я даю, лол.
Вот я и вообще не понимаю, куда копать, даже не очень понимаю как это должно быть устроено. Наверняка, у клиента это все страница с каким-нибудь джаваскриптом, который может в отрисовку всего чего надо и в общение с сервером. А сам сервер, вероятнее всего, уже написан на каком-нибудь PHP. Но это все, что я могу предположить, что делать - не понимаю. А в идеале - чтобы еще можно было к этому делу как-то прикрутить уже написанного бота написан на плюсах, быстродействие, все дела
В общем, жду ваших ответов
Переписываю одну небольшую функцию с джавы на php, и не могу понять почему так получается.
В php я совсем ньюфаг, плиз хелп.
В java long это 64битный тип.
В php integer может быть 32- или 64- битным на рахных платформах. запусти свой код в 64 битной ОС и получишь то же самое.
int32 может быть только от -2 млрд до + 2 млрд, а у тебя 5 млрд.
Ты также можешь использовать библиотеку gmp которая не имеет огранчений по разрядности:
http://php.net/manual/ru/book.gmp.php
Спасибо, теперь понятно. А можно как-то указать в php что число 5265657653 не integer, а float например?
Или единственный вариант использовать библиотеку gmp для этого?
Хотя нет, оператор XOR не работает с типом данных float.
xor принудительно преобразует float к int. Да и float неточный тип, он может не сохранить часть цифр. Используй gmp.
Первый шаг по получению html с помощью url все получается норм. Но вот дальше я не могу разобраться в том как управлять этой библиотекой.
Например есть общий для всех тредов контейнер:
<form id="posts form">
Как мне выпарсить только содержимое этой формы?
Как потом пройтись по её содержимому в виде:
<div id="" class="thread"> и далее к оп-постам?
Структуру сосачерской страницы я например понял примерно. Но вот работу с этой библиотекой что-то не могу въехать. Осложняется еще тем, что я привык каждый шаг проверять, особенно когда не понимаешь что делаешь, и дампить все переменные которые есть на выходе, а там дамп такой, что крашит мой браузер.
Есть язык Xpath на котором пишутся условия для поиска узлов в xml-дереве (ну у нас HTML, в не XML, но суть та же). Ну например, «найди мне узел с определенным классом внутри которого есть минимум 2 элемента div».
https://ru.wikipedia.org/wiki/XPath
http://www.zvon.org/xxl/XPathTutorial/General_rus/examples.html
Ой, это я тебе про SimpleXML написал. Что касается SimpleHTMLDom там все понятно из примеров если ты знаешь CSS селекторы и работал с jQuery.
Первое создает переменную ( http://php.net/manual/ru/language.variables.basics.php ), второе константу ( http://php.net/manual/ru/language.constants.php ). Кстати, имена констант принято писать большими буквами.
В общем прикрутил gmp. Теперь при превышении значения integer, выдает ошибку что не может сконвертировать в переменную в GMP и выдает первую переменную в результате. А если вторая переменная не превышает максимальное значение integer, то вычилсяет нормально. Как добиться того, чтобы GMP понимал значения больше чем максимальное значение integer?
То есть переменную еще можно поменять, а константу нет?
Например:
define("B",1)
$b = 3
То константа не измениться. Или это совершенное разное?
Проблема решена. Надо было вместо $b = gmp_init(5265657653);
написать $b = gmp_init("5265657653", 0);
А в gmp есть фунция сдвига битов влево? Посмотрел тут http://php.net/manual/ru/ref.gmp.php , что-то не могу найти.
Вопрос актуален.
Бббамп!
> а почему, собственно, PHP для сайтиков?
А почему нет? Думаю, в гугле при желании можно найти конкретные аргументы в пользу php, это и постота и большое число разаботчиков знакомых с языком и инфраструктура, библиотеки и фреймворки.
> Наверняка, у клиента это все страница с каким-нибудь джаваскриптом, который может в отрисовку всего чего надо и в общение с сервером. А сам сервер, вероятнее всего, уже написан на каком-нибудь PHP
Можно php, но если нужно максимальное бытродейтсвие то нужен java/си++ (например на асинхронных сокетах). Для крупных игр используют именно масштабируемые решения на си++ или java чтобы выжать максимум из железа.
Если пользователей и запросов не очень много, то php подойдет. Ведь на нем сделать будет гораздо быстрее чем на низкоуровневых языках или яве.
> А в идеале - чтобы еще можно было к этому делу как-то прикрутить уже написанного бота
Бот может слать запросы на сервер, в чем проблема?
> Вот я и вообще не понимаю, куда копать, даже не очень понимаю как это должно быть устроено
Да, у клиента html страница с яваскриптом, которая шлет запросы на сервер. Или можно использовать вебсокеты, если обмен данными интенсивный и нужна маленькая задежрка.
На сервере есть 2 модели:
- если запросов не много, то можно запустить прилождение на php в обычном режиме. Приложение получает запрос, запускается скрипт, берет данные из хранилища (MySQL, Redis например), обрабатывает, кладет назад, выдает ответ и умирает. Так работают php-скрипты по умолчанию, это просто и удобно, но не очень быстро.
- если нагрузка высока то пишется демон, который принимает http-соединения от клиентов, обрабатывает их запросы. Демон может держать данные либо в памяти либо в внешнем хранилище. В памяти мы имеем максимальную скокрость доступа, но не можем так просто масштабироваться на несколько процессов или серверов. С хранилищем имеем возможность, но там появляются проблемы вроде блокировок и хранилище становится узким местом.
Иногда, если данные можно разбить на независимые группы (например отдельные миры), можно их хранить в памяти, так что каждый экзепляр приложения хранит и обрабаытвает свою часть данных. Это назвыается шардинг.
Также, если ты держишь данные в памяти, тебе придется самому решать проблему их сохранения на диск (персистенстности). Ребята из ВК тут разобрали возможные подходы: https://github.com/vk-com/kphp-kdb/blob/master/docs/ru/DBMS_Storage_Comparison.wiki
При использовании хранилища проблему соханения решать не надо.
Обычно делают однопоточную асинхронную обработку, так как с ней проще поддерживать большое число соединений.
В общем что тебе стоит изучить, так это работу с сокетами, асинхронную работу с сокетами, протокол HTTP, хранилища вроде MySQl/Redis — это если ты хочешь делать по сложному варианту. На php можно сделать по простому, но с оганичением по нагрузке и без вебсокетов.
Если в задачу подставить сумму кредита 40 000 (которая там стоит по умолчанию), то должно получится что всего выплачено 61270.
Если подставить сумму кредита 4000 то должно получитьься что всего выплачено 6123.
И тд.
Если у тебя получаются другие числа то где-то неправильно считает.
>>436884
Ну попробуй, если надо я могу придумать доолнительную задачку на какую-то тему.
>>436895
Лучше помучать и решить. На ней все спотыкаются, ее по 3 дня и больше решали.
>>436907
У тебя в последний месяц анон выплачивает 5000 и сразу же 4139, то есть в сумме 9139. А он не может столько вылатить сазу, он должен ждать еще месяц и за этот месяц банк накидает процентов на 4139 и там выйдет больше сумма.
>>436930
Ответ должен быть 61270 а не 59 000
Если в задачу подставить сумму кредита 40 000 (которая там стоит по умолчанию), то должно получится что всего выплачено 61270.
Если подставить сумму кредита 4000 то должно получитьься что всего выплачено 6123.
И тд.
Если у тебя получаются другие числа то где-то неправильно считает.
>>436884
Ну попробуй, если надо я могу придумать доолнительную задачку на какую-то тему.
>>436895
Лучше помучать и решить. На ней все спотыкаются, ее по 3 дня и больше решали.
>>436907
У тебя в последний месяц анон выплачивает 5000 и сразу же 4139, то есть в сумме 9139. А он не может столько вылатить сазу, он должен ждать еще месяц и за этот месяц банк накидает процентов на 4139 и там выйдет больше сумма.
>>436930
Ответ должен быть 61270 а не 59 000
Советы и замечания
Где sql дамп базы данных?
> "twig/twig": "1.18
Лучше наверно так жестко к версии не привязываться, а написать ~1.18 например (это значит любая между 1.18 и 2.0)
Да и зачем @dev указывать? Это же нестабильная версия, с которой работают разработчики.
> $app->get('/', function () {
> require "uppy/upload.php";
Тут принято не подключать файл, а писать код прямо в функции. Естественно он должен быть небольшим, не более 20 строчек.
> x.twig
Лучше назвать templates
> base.html
Лучше base.twig или base.html.twig
> <div style="margin:0;padding:0;display:inline">
Не пиши стили в style, используй классы. Чтобы скрыть блок, используй display none
> id="search"
Если ты не собирешься обращаться к элементу из JS лучше не ставь id. Он неудобен тем что не может повторяться. Для CSS удобнее использовать только классы и никогда не использовать id.
Имя хоста лучше вообще не писать либо вынести в конфиг так как у меня например имя будет другое. В данном случае можно не указывать имя хоста.
> $loader = new Twig_Loader_Filesystem('uppy/x.twig');
Это надо интегрировать в Slim чтобы при вызове слимовского $app->render вызывался Twig. Как это сделать? Надо создать слимовский вью использующий твиг и задать чтобы он использовался по умолчанию. Это можно нагуглить. Есть документация: http://docs.slimframework.com/#Custom-Views
Более того, есть уже готовая библиотека интегирующая twig в slim таким образом.
> // Try to delete the temporary file
Не надо удалять временный файл, созданный php, он сам удаляется если его не переместили.
> https://github.com/tokotun/uppy/blob/master/uppy/app/File.php#L17
> if (isset($_FILES['file'])) {
Это ужасно. С какой стати объект File, представляющий собой информацию о файле, лезет в глобальный массив FILES при создании, причем это никак не отключить? C какой стати в нем жестко захардкодено имя file? Что мне делать если у меня файл в с другими именем?
Класс File занимается не своим делом. Он не должен сам в себя прописывать свойства из FILES. должна быть какая-то внешняя функция которая берет на вход FILES и создает File.
> $numChars = strlen($chars);
Понятно что там латинница. но почему бы не использовать mb_strlen всегда?
> https://github.com/tokotun/uppy/blob/master/uppy/app/FileMapper.php#L36
> public function loadFile($key)
У нас же есть замечательный класс File, почему эта функция возвращает какой-то безликий массив?
> appvars.php
> connectvars.php
Что-то многовато конфигов. Сделай один конфиг, и без констант. желательно использовать для хранения конфига возможности Слим: http://docs.slimframework.com/#Configuration-Overview
> bootstrap.php
Код отсюда надо перенести в index.php так как у нас не будет других точек входа. получение $db надо сделать через Slim Sinleton: http://docs.slimframework.com/#DI-Overview
> https://github.com/tokotun/uppy/blob/master/uppy/app/autoloader.php
Убери этот файл и используй автозагузку средствами композера. Это описано тут например:
https://getcomposer.org/doc/04-schema.md#autoload (англ )
http://habrahabr.ru/post/149678/
Заметь что если ты используешь для именования классов и файлов стандарт PSR-0 или PSR-4 то добавление автозаргрузки делается одной строчкой в composer.json (видишь как полезно следовать стандартам). Описание стандартов есть тут
http://www.php-fig.org/psr/psr-0/ru/
http://www.php-fig.org/psr/psr-4/ru/
(там немного едет верстка, если что есть еще копия на гитхабе https://github.com/php-fig/fig-standards/tree/master/accepted )
Научись использовать автозагрузку композером и никогда больше не пиши свой автозагрузчик.
Советы и замечания
Где sql дамп базы данных?
> "twig/twig": "1.18
Лучше наверно так жестко к версии не привязываться, а написать ~1.18 например (это значит любая между 1.18 и 2.0)
Да и зачем @dev указывать? Это же нестабильная версия, с которой работают разработчики.
> $app->get('/', function () {
> require "uppy/upload.php";
Тут принято не подключать файл, а писать код прямо в функции. Естественно он должен быть небольшим, не более 20 строчек.
> x.twig
Лучше назвать templates
> base.html
Лучше base.twig или base.html.twig
> <div style="margin:0;padding:0;display:inline">
Не пиши стили в style, используй классы. Чтобы скрыть блок, используй display none
> id="search"
Если ты не собирешься обращаться к элементу из JS лучше не ставь id. Он неудобен тем что не может повторяться. Для CSS удобнее использовать только классы и никогда не использовать id.
Имя хоста лучше вообще не писать либо вынести в конфиг так как у меня например имя будет другое. В данном случае можно не указывать имя хоста.
> $loader = new Twig_Loader_Filesystem('uppy/x.twig');
Это надо интегрировать в Slim чтобы при вызове слимовского $app->render вызывался Twig. Как это сделать? Надо создать слимовский вью использующий твиг и задать чтобы он использовался по умолчанию. Это можно нагуглить. Есть документация: http://docs.slimframework.com/#Custom-Views
Более того, есть уже готовая библиотека интегирующая twig в slim таким образом.
> // Try to delete the temporary file
Не надо удалять временный файл, созданный php, он сам удаляется если его не переместили.
> https://github.com/tokotun/uppy/blob/master/uppy/app/File.php#L17
> if (isset($_FILES['file'])) {
Это ужасно. С какой стати объект File, представляющий собой информацию о файле, лезет в глобальный массив FILES при создании, причем это никак не отключить? C какой стати в нем жестко захардкодено имя file? Что мне делать если у меня файл в с другими именем?
Класс File занимается не своим делом. Он не должен сам в себя прописывать свойства из FILES. должна быть какая-то внешняя функция которая берет на вход FILES и создает File.
> $numChars = strlen($chars);
Понятно что там латинница. но почему бы не использовать mb_strlen всегда?
> https://github.com/tokotun/uppy/blob/master/uppy/app/FileMapper.php#L36
> public function loadFile($key)
У нас же есть замечательный класс File, почему эта функция возвращает какой-то безликий массив?
> appvars.php
> connectvars.php
Что-то многовато конфигов. Сделай один конфиг, и без констант. желательно использовать для хранения конфига возможности Слим: http://docs.slimframework.com/#Configuration-Overview
> bootstrap.php
Код отсюда надо перенести в index.php так как у нас не будет других точек входа. получение $db надо сделать через Slim Sinleton: http://docs.slimframework.com/#DI-Overview
> https://github.com/tokotun/uppy/blob/master/uppy/app/autoloader.php
Убери этот файл и используй автозагузку средствами композера. Это описано тут например:
https://getcomposer.org/doc/04-schema.md#autoload (англ )
http://habrahabr.ru/post/149678/
Заметь что если ты используешь для именования классов и файлов стандарт PSR-0 или PSR-4 то добавление автозаргрузки делается одной строчкой в composer.json (видишь как полезно следовать стандартам). Описание стандартов есть тут
http://www.php-fig.org/psr/psr-0/ru/
http://www.php-fig.org/psr/psr-4/ru/
(там немного едет верстка, если что есть еще копия на гитхабе https://github.com/php-fig/fig-standards/tree/master/accepted )
Научись использовать автозагрузку композером и никогда больше не пиши свой автозагрузчик.
У меня короче php не интерпретируется и выводится валом прямо на страницу. libphpтратата подключено, php стоит и сопутствующие библиотеки, ubuntu.
Чому?
Ну и еще, давай для улучшения архитектуры вынесем из File свойства с ошибками. Все же ошибка загрузки — это отдельная сущность и удобно тут сделать ее отдельным классом.
> https://github.com/tokotun/uppy/tree/master/uppy/container
Это надо удалить из репозитория, закоммитить, а потом добавить содержимое папки в gitignore
> Как мне выпарсить только содержимое этой формы?
> Как потом пройтись по её содержимому в виде:
Сделай css селектор выбирабщий нужные элементы и пройдись через foreach по найденным узлам, как в документации.
> а там дамп такой, что крашит мой браузер.
Посмотри может там есть встроенная функция для дампа. Или можно выводить какой-нибудь innerHTML.
>>437168
Да. Константу менять нельзя. Также, перед переменной надо писать знак доллара. Также, константы суперглобальны. Также в константы нельзя класть массив или объекты.
При этом константа A и переменная $A разные вещи.
>>437157
Потому что если ты пишешь число больше 2 млрд то оно становится float, и при этом теряется часть знаков. Потому gmp отказывается его принимать. Передавай как строку.
Причем исходный код отображается не с самого начала, а спустя какое-то количество символов. Довольно странно
Плохо подлючено. Вообще, если в Убунте ставить php стандартными средствами (apt-get install ) то он не только установит php но и в папку /etc/apache2/conf.d/ закинет файлик который подключает php к Апачу для обработки своих файлов.
Ты как ставил, чем?
Также, вопрос 2: ты в коде не забыл поставить <?php в начале?
Вопрос 3: что менял руками в конфигурации Apache или php (то есть из /etc/apache2/ и /etc/php5/)?
Отмена, не смотрите, я исправил уже случайно.
>Для крупных игр
Но это не про меня, лол
>Бот может слать запросы на сервер, в чем проблема?
Да ни в чем кроме того, что я вообще не понимаю, как все это должно быть устроено
>>437280
>нужна маленькая задежрка
Ну а без вебсокетов какая будет задержка? Игрушка простенькая, настольная, не думаю, что там это будет уж очень принципиально, в конце концов
То есть, правильно ли я понимаю, что сервер это, по сути, скрипт на пыхе, который ожидает каких-то запросов, получает их, обрабатывает(например, в моем случае - как-то передает их программе боту), получает результат обработки, после чего пересылает его по сети?
То есть, в принципе, для достижения моей цели достаточно просто покурить php + основы js+html, всяких навороченных штук и не надо, так?
Тогда спасибо большое за ответики, буду постепенно вливаться в ваш дружелюбный тред
Решите пожалуйста полностью за меня, а я сам посмотрю как это должно быть.
А еще если исходный код страницы посмотреть, то часть кода как будто php, а часть - черная, как текст. Граница не ясна, на скриншоте есть.
Сейчас с теми же настройками запустил другой проект, все хорошо работает, только здесь какая-то ерунда - не полностью интерпретируется php.
>Умножить на 2 в степени N не вариант?
Что-то не могу понять что нужно умножать на 2 в степени N?
Допустим есть 5719407308<<12 на джаве.
Получается надо записать как 5719407308*212 на PHP?
Может быть в htaccess что-то прописано что отключает php? Если на этом же компютере другой проект работает?
И еще раз спрошу, там <?php в начале стоит? Или может <?
То, что раскрашено на скриншоте нважно так как это лишь браузер пытается php как html раскрасить.
Котаны, пытаюсь в данный момент на сайте реализовать примитивную систему общения. Суть заключается в том что есть Админ и он может присылать всем сообщения, причём есть возможность отсылать одно сообщение сразу нескольким людям. Я предполагаю что каждое сообщение надо записывать в базу данных, где в особенном поле должно храниться id того кому это сообщение предназначено (по которому оно будет выводиться в аккаунте у того, кому оно предназначено). Но если есть надобность отправить например 5 или больше людям одно и тоже сообщение, как лучше поступить? Записать 5 одинаковых сообщений в базу данных но с разными id для каждого пользователя? Или вписать в одно поле все id тех пользователей (через запятую) кому предназначено сообщение. В первом случае засоряем таблицу базы данных, во втором делаем много проблем себе для организации правильного вывода сообщений в аккаунте у тех кому они предназначены. Или может куда более лучший третий вариант?
.htaccess скопирован с другого сервера, где изначально крутился этот проект, так что вряд ли там ошибка. В начале не было php, только <?. Добавил, перезапустил - выводимый код немного изменился, но суть осталась той же - не обрабатывает. Хотя появилась среди строк голой выдачи какая-то ошибка:
Problem encountered: $error.
Недоинтерпретированный кусок.
Направьте на путь истинный.
Ты каждую итерацию цикла пишешь в $dohod одно и то же число, а тебе надо прибавлять к тому что уже есть
Переменная $dohod должна присутствовать и в левой и в правой части уравнения.
Чё он не жирный?
<? по умолчанию отключен. Надо всегда использовать <?php
В твоем случае надо либо включить short_tags либо, что правильнее, всюду поменять <? на <?php
Мануал http://php.net/manual/ru/language.basic-syntax.phptags.php
> .htaccess скопирован с другого сервера, где изначально крутился этот проект, так что вряд ли там ошибка.
Тут дело не в нем, но в общем ты мыслишь неправильно. Код не обязательно переносим между серверами так как там могут быть жестко прописаны пути и имена.
>>437378
Можно сделать таблицу сообщений и связь многие-ко-многие между сообщениями и пользователями.
>>437506
> $dohod = ($vklad * $procent) + $vklad;
Это примерно то же самое что
$dohod = 11000;
То есть всегда пишется одно и то же. Надо увеличивать доход, например так:
$dohod = $dohod + 10;
(или что то же самое , $dohod += 10; )
Это увеличивает число в переменной на 10.
Ну и поменяй русские имена на английские, если не знаешь английский то можешь использовать google translate или slovari.yandex.ru .По руссски не принято переменныенаывать.
<? по умолчанию отключен. Надо всегда использовать <?php
В твоем случае надо либо включить short_tags либо, что правильнее, всюду поменять <? на <?php
Мануал http://php.net/manual/ru/language.basic-syntax.phptags.php
> .htaccess скопирован с другого сервера, где изначально крутился этот проект, так что вряд ли там ошибка.
Тут дело не в нем, но в общем ты мыслишь неправильно. Код не обязательно переносим между серверами так как там могут быть жестко прописаны пути и имена.
>>437378
Можно сделать таблицу сообщений и связь многие-ко-многие между сообщениями и пользователями.
>>437506
> $dohod = ($vklad * $procent) + $vklad;
Это примерно то же самое что
$dohod = 11000;
То есть всегда пишется одно и то же. Надо увеличивать доход, например так:
$dohod = $dohod + 10;
(или что то же самое , $dohod += 10; )
Это увеличивает число в переменной на 10.
Ну и поменяй русские имена на английские, если не знаешь английский то можешь использовать google translate или slovari.yandex.ru .По руссски не принято переменныенаывать.
Тут есть ошибки:
> $dohod = (($vklad * $procent) + $vklad + $dohod);
Надо увеличивать доход каждый год на процент. То есть если сейчасв банке 200000 то надо прибавить 10% от этой суммы. То есть находи чему равна надбавка каждый год, и прибавляй ее к сумме на счету.
>if ($dohod = 1000000) {
Неправильно. Для сравнения надо писать $dohod == 100000. В if всегда надо использовать ==.
= обозначает не сравнение, а присваивание, то есть присвоить $dohod значение 1000000.
Ну и имена хорошо бы на английские поменять.
>>437520
Он и не должен быть жирным. ideone не интерпретирует html код как браузер, а просто выводит как есть. То же самое будет если ты запустишь программу например в консоли. Теги работают только в браузере.
>>>То есть находи чему равна надбавка каждый год, и прибавляй ее к сумме на счету.
Надбавка каждый год будет увеличиваться, так как сумма на счету тоже каждый год увеличивается. Я низнаю.
Помогите плиз.
Я всё правильно сделал, или можно было проще?
Спасибо ^^
Только надо миллион накопить, а не 100 000. Но идея правильная.
И еще,
$a = $a × $b;
можно записать короче как
$a ×= $b;
Вроде бы и всё понимаю, но пока не получается. Мне "стоп" нужно заключить в функцию, или прописывать отдельно после нее?
Вот то что нашкрябал. Пока до отрицательных значений долга не доходишь вроде как пашет.
Первую задачку с массивами сделал за 5 минут. А еботня с циклами и кредитами так и не закончилась.
Хочу удостовериться, правильно сделано?
Следовательно, теперь я должен переправить пользователя на страницу, которая примет его id и отобразит данные его профиля на странице. Но как в данном случае лучше передать данные? Вернее как вообще их передать на следующую страницу? Через ссылку? В этом случае пользователю придётся нажимать на ссылку которая появиться после правильного ввода параметров, а это как то неудобно, очень мало где такое видел. Единственное что придумал это записать id в сессию и потом вывести всё необходимое по этому id, но мне кажется это как-то кривовато.
Форму у меня обрабатывает та же страница на которой она и находиться, вероятно именно в этом моменте я чего то не пойму.
Вот пытаюсь сделать "Еще одна задачка. Дан рост школьника и рост его одноклассников. Надо найти, сколько человек в классе выше, чем наш герой."
Заведи переменную, положи в нее 0. затем проходишь по списку одноклассников и если текущий одноклассник выше анона то увеличиваешь переменную на один. В итоге в ней будет число высоких одноклассников.
>>437721
Все правильно
>>437639
> Мне "стоп" нужно заключить в функцию, или прописывать отдельно после нее?
Не понял вопрос. Что за стоп?
Тебе надо в функции посчитать общую сумму выплат по кредиту. Так как банков 3 и они предоставляют кредиты на разных условиях, то ты три раза вызываешь функцию с разными аргументами и получаешь в итоге 3 суммы выплат, по одной для каждого банка.
Код по моему у тебя не дописан, обрывается на полуслове.
Не знаю как это правильно называется, но я использую:
Header("Location: catalog.php");
В том случае если правильно введены все данные
>Можно сделать таблицу сообщений и связь многие-ко-многие между сообщениями и пользователями.
Но в любом случае, одно и тоже сообщения но только предназначенное для двух разных пользователей, будет занимать две строки в таблице, правильно?
Провожу по работе часов 6 в день в дороге, хочу годную среду разработки под ведроид, а то постоянно по возвращении домой забиваю на обучение и в итоге даже стартовые задачи еще не сделал.
Короче посоветуйте под чем кодить на планшете, пожалуйста.
посоветуйте как лучше сверстать этот блок с видео, может есть шаблон который можно допилить? спасибо
посоветуйте как лучше сверстать этот блок с видео, может есть шаблон который можно допилить? спасибо
Не совсем понял, что там верстать-то?
> http://php.net/manual/ru/language.oop5.overloading.php#object.get
Это аналог рубийного attr_accessor ?
Когда добавляю group строка перестаёт вставляться в таблицу, без group всё работает?
Какое сообщение об ошибке? Если сообщения нет то это значит что включен режим игнорирования ошибок от базы данных.
По умолчанию PDO не выводит сообщений об ошибках, что очень неудобно. Потому ты должен сразу после соединения включать режим вывода ошибок. Для этого надо выполнить такой код:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Мануал: http://php.net/manual/ru/pdo.error-handling.php
Проверить что теперь ошибки выводятся можно, попытавшись выполнить неправильный запрос:
$pdo->exec("SDASDASDASDASDA");
Также, если у тебя даже после добавления этого кода не выводится сообщений об ошибке, то у тебя отключен вывод ошибок на экран.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
Под андроид есть редакторы кода и есть возможность запускать PHP. Весь наш учебник можно прорешать на нем (а также дополнительные задачи на создание сайтов). Чтобы решать задачи, тебе нужно несколько вещей:
- веб-сервер + PHP который будет выполнять php код
- редактор которым ты будешь редактировать код (редактор должен поддерживать ввод разных значков, которые неудобно вводить со стандартной клавитаутры, подсветку кода)
- браузер которым будешь подсоединяться к серверу, запускать код и смотреть результат его работы (в качестве браузера очевидно подойдет встроенный браузер)
Эти компоненты можно ставить как по отдельности, так и найти IDE которая их включает в себя.
Если искать по словам PHP IDE то вываливаются в основном платные IDE. Но там все уже идет в комплекте + есть например тот же MySQL.
Но можно и ставить по отдельности. Вот например что гуглится:
- http://droidphp.github.io/ (бесплатный сервер, включает php и mysql)
- https://play.google.com/store/apps/details?id=com.esminis.server.php (MySQL нету)
- https://play.google.com/store/apps/details?id=com.ayansoft.androphp
- https://play.google.com/store/apps/details?id=com.alfanla.android.pws
Посмотри их, почитай отзывы. Я ими не пользовался, так что про подвохи рассказать не могу.
Если есть сомнения, задавай уточняющие вопросы.
Также я советую скачать мануал по PHP: http://php.net/download-docs.php если тебе неудобно пользоваться мануалом через интернет.
Он доступен либо в виде CHM файла (и для его просмотра наверно нужно приложение) либо в виде архива HTML файлов которые непонятно как просматривать на устройстве.
>>437901
AIDE для Java и С++ как следует из описания
Под андроид есть редакторы кода и есть возможность запускать PHP. Весь наш учебник можно прорешать на нем (а также дополнительные задачи на создание сайтов). Чтобы решать задачи, тебе нужно несколько вещей:
- веб-сервер + PHP который будет выполнять php код
- редактор которым ты будешь редактировать код (редактор должен поддерживать ввод разных значков, которые неудобно вводить со стандартной клавитаутры, подсветку кода)
- браузер которым будешь подсоединяться к серверу, запускать код и смотреть результат его работы (в качестве браузера очевидно подойдет встроенный браузер)
Эти компоненты можно ставить как по отдельности, так и найти IDE которая их включает в себя.
Если искать по словам PHP IDE то вываливаются в основном платные IDE. Но там все уже идет в комплекте + есть например тот же MySQL.
Но можно и ставить по отдельности. Вот например что гуглится:
- http://droidphp.github.io/ (бесплатный сервер, включает php и mysql)
- https://play.google.com/store/apps/details?id=com.esminis.server.php (MySQL нету)
- https://play.google.com/store/apps/details?id=com.ayansoft.androphp
- https://play.google.com/store/apps/details?id=com.alfanla.android.pws
Посмотри их, почитай отзывы. Я ими не пользовался, так что про подвохи рассказать не могу.
Если есть сомнения, задавай уточняющие вопросы.
Также я советую скачать мануал по PHP: http://php.net/download-docs.php если тебе неудобно пользоваться мануалом через интернет.
Он доступен либо в виде CHM файла (и для его просмотра наверно нужно приложение) либо в виде архива HTML файлов которые непонятно как просматривать на устройстве.
>>437901
AIDE для Java и С++ как следует из описания
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group) VALUES ('23', '23', '23', '23')' at line 1' in Z:\home\test.ru\www\testsql\lib\pdo.php:71 Stack trace: #0 Z:\home\test.ru\www\testsql\lib\pdo.php(71): PDOStatement->execute() #1 Z:\home\test.ru\www\testsql\index.php(19): DataMapper->addStudent(Object(Profile)) #2 {main} thrown in Z:\home\test.ru\www\testsql\lib\pdo.php on line 71
Синтаксическая, но я не понимаю что не так.
Ведь когда три параметра всё норм.
Ты же уже пару недель назад спрашивал как верстать этот сайт. За это время можно было выучить CSS и не мучаться.
Не знаю, как насчет шаблонов, но по моему расположить блоки вертикально можно с помощью простого CSS.
>>437913
Так-то верно, но ты используешь 2 дива, неоптимально, тут можно обойтись одним. Подумай, как.
>>437959
Наверно, не знаю. Он вызывается при обращении к несуществующему или недоступному свойству.
>>437994
Не надо там никаких стопов. Там должен быть примерно такой алгоритм:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
>>438031
Используя маргины ты усложняешь себе жизнь. Поля делаются с помощью паддинга. Если у тебя у синего блока поля 10px то надо просто поставить паддинг 10px и не мучаться.
> \tmargin-bottom: 6px;
Это у меня косяк, картинка криво нарисована. На самом делел 3-й блок выровнен нижним краем с первым блоком о высоте.
> потом обнаружил, что последний блок не на одной линии должен находиться, с первыми двумя, пришлось добавлять маржинов.
Это у меня криво нарисовано. Должен быть на одной линии нижней частью с первым блоком.
> Сначала сделал без отступов, с полями
Так и надо было
По горизонтали у тебя не 10px, вот я даже квадратик нарисовал для сравнения: https://jsfiddle.net/kejsdrfe/1/
Посмотри подсказки к заданию, там есть полезная ссылка на тему почему там не 10px получается.
Ты же уже пару недель назад спрашивал как верстать этот сайт. За это время можно было выучить CSS и не мучаться.
Не знаю, как насчет шаблонов, но по моему расположить блоки вертикально можно с помощью простого CSS.
>>437913
Так-то верно, но ты используешь 2 дива, неоптимально, тут можно обойтись одним. Подумай, как.
>>437959
Наверно, не знаю. Он вызывается при обращении к несуществующему или недоступному свойству.
>>437994
Не надо там никаких стопов. Там должен быть примерно такой алгоритм:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
>>438031
Используя маргины ты усложняешь себе жизнь. Поля делаются с помощью паддинга. Если у тебя у синего блока поля 10px то надо просто поставить паддинг 10px и не мучаться.
> \tmargin-bottom: 6px;
Это у меня косяк, картинка криво нарисована. На самом делел 3-й блок выровнен нижним краем с первым блоком о высоте.
> потом обнаружил, что последний блок не на одной линии должен находиться, с первыми двумя, пришлось добавлять маржинов.
Это у меня криво нарисовано. Должен быть на одной линии нижней частью с первым блоком.
> Сначала сделал без отступов, с полями
Так и надо было
По горизонтали у тебя не 10px, вот я даже квадратик нарисовал для сравнения: https://jsfiddle.net/kejsdrfe/1/
Посмотри подсказки к заданию, там есть полезная ссылка на тему почему там не 10px получается.
Тут все верно. Главная цель этой задачи понять как работает padding на inline элементах.
>>438044
Попробуй погуглить по словам типа «вопросы с php собеседования» может найдешь.
>>438042
GROUP это зарезервированное слово (там есть опция GROUP BY)/ . Надо писать его в косых кавычках, аналогично с другими резервированными словами.Вот мануал, выучи наизусть:
http://www.mysql.ru/docs/man/Reserved_words.html
http://makefuture.net/article/mysql-all-reserved-words/
http://spec-zone.ru/RU/mysql/5.7/language-structure_reserved-words.html
Ок, насчет выучить наизуcть я поушутил. Не надо учить ничего
>ты используешь 2 дива, неоптимально, тут можно обойтись одним. Подумай, как
Ты имеешь ввиду -webkit-box-sizing: border-box?
спасибочки
Нет, я предлагаю просто вычесть из 600 паддинг и бордер и прописать как max-width.
Кстати, в новых браузерах надо писать
box-sizing: ...
-moz-box-sizing: ...
-webkit-box-sizing: ...
Вендорные рефиксы работают только в старых версиях браузеров. Сейчас они признаны дурной идеей и не исплоьзуются (но ставить их стоит для старых браузеров).
Это копия, сохраненная 4 марта 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.