Вы видите копию треда, сохраненную 21 декабря 2016 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это не чат! Высказывайтесь одним большим постом, а не цепочкой мелких
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут: >>864640 (OP)
Мейруч лежит? Есть запасной тред: http://dobrochan.org/s/res/23225.xhtml#i46467
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост, прежде чем писать код).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
- для начала прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- установи Апач + PHP (советы выше и ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, PDO, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a
- Если ты все решил, переходи к Symfony 2/Doctrine 2
- Почитать про паттерны http://designpatternsphp.readthedocs.org/ru/latest/README.html (если ты не изучил ни одного фреймворка, то это будет рановато), тут с примерами кода http://designpatternsphp.readthedocs.org/ru/latest/README.html . Имей в виду что без примеров использования их учить бесполезно - не поймешь, хочешь увидеть примеры использования паттернов - ковыряй исходники Симфони, например Symfony Forms. Не заучивай паттерны - смотри код и думай, зачем тут они использованы.
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Может тебе понадобится пользоваться командной строкой, вот гайд https://github.com/codedokode/pasta/blob/master/soft/cli.md
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://github.com/codedokode/pasta/blob/master/db/databases.md
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
Платиновые вопросы
- Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.
- Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета)
- Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев
- Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm
- Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
- Что самое главное для программиста? Умение аккуратно оформлять код.
- ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
- Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.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/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md
------------------
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Давай удочку, а не рыбу
Лучше не давать готовое решение проблемы, а рассказать как его искать. Может дать ключевые слова для гугла или ссылку. Но помогай, а не пытайся показать превосходство. Если даешь ссылки на нерусскоязычные статьи, упомяни об этом.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского или русского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
Если тебе лень выравнивать код руками, закачай его на 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/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md
------------------
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Давай удочку, а не рыбу
Лучше не давать готовое решение проблемы, а рассказать как его искать. Может дать ключевые слова для гугла или ссылку. Но помогай, а не пытайся показать превосходство. Если даешь ссылки на нерусскоязычные статьи, упомяни об этом.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского или русского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
Например как примерно выглядит функция, которой я кормлю
скажем
$a = some_func('2016-09-28, '2016-11-23');
и в а в итоге лежал последовательный массив вида:
[
'2016-09-28',
'2016-09-29',
'2016-09-30',
'2016-10-01',
'2016-10-02',
...
'2016-10-30',
'2016-10-31',
'2016-11-01',
'2016-11-02',
...
'2016-11-22',
'2016-11-23'
]
может быть есть уже какое-то готовое решение в самой пхп? Нужно для построения графиков в общем, что бы потом к к каждому элементу с датой какую-то инфу добовлять.
Если тебе нужен именно массив и дата окончания включительно, то вряд ли получится что-то короче этого: http://ideone.com/GtvENn
А так хватит следущих строк:
$period = new DatePeriod(
____new DateTime($from),
____new DateInterval('P1D'),
____new DateTime($to)
);
На русскоязычном форуме чет не густо.
У Макарова на гитхабе (samdark)
Если вы не знаете, что такое XSS, у меня есть урок по ней: https://github.com/codedokode/pasta/blob/master/security/xss.md
Ну и разумеется, вам надо знать основы HTML и JS (из JS нужна функция alert).
Размеры макета конечны?
Шапка высотой 200px на экране с большим разрешением -- смех, а буквы не читаются: как исправить?
Возможно ли проставить высоту в% без потери возможности скроллить вниз?
Если возможно - пару комментариев
>не используй <a href="#" или <a href="javascript:void(0)" никогда. Для этого есть кнопки или <span>
if(a1==a2 && a3==a4)
if(a1==a2)&&(a3=0a4)
Как правильней и как грамотней?
да, я один из тех, которые не дочитали второй пост. Сорян, ухожу из программирования
<?php
error_reporting(-1);
for ($i = 1; $i<=10; $i++) {
$b =$i$i;
echo "$i$i = $b \n";
}
Вот данный код, возводит каждое следующее число в квадрат. До 10 включительно.
Но как сделать так, чтобы цикл работал до того момента, пока результат квадрата числа меньше 1000 например.
задай условие типа если результат равен н выход или же пока н меньше условия сорян в синтаксе пхп не очень как именно не могу точно написать
там еще знак умножения между $i*$i
Все, понял .Спасибо огромное
<?php
error_reporting(-1);
for ($i = 1; $b<10; $i++) {
$b =$i$i;
echo "$i$i = $b \n";
}
Вот результат этого :
Успешноtime: 0.01 memory: 52488 signal:0
11 = 1
22 = 4
33 = 9
44 = 16
.
А как сделать так, чтобы на 9 заканчивался цикл? Понять не могут ? В принципе, логика понятно, почему 16 получается . 33 = 9;, проверяется это условие , потом выполняется действие и выводится 16. А как сделать так, чтоб на 33 цикл заканчивался ?
Сори за спам
дак задай конкретное условие
если известен результат то укажи в условии
если нет то сделай типа пока b!=i
хз че первое в голову пришло
Правильней if (($a1 === $a2) && ($a3 === $a4)) (если тебе нужно зачем-то сравнивать с автоприведением типов, то используй ===)
Ну а совсем правильно будет книжки читать.
._.
А вы бы обратили внимание на чебокс, старательно замаскированный под серую галочку? Это же прекрасно. Впрочем, что еще ждать от убогой устаревшей системы платежей с технологиями транзисторной эры, которая позволяет такие трюки. Я бы никогда не стал платить настоящей картой в интернете.
То-есть хранить в data/categoryX/product_id уже не выйдет из за того что в среднем будет 500к+ товаров в одной категории. Есть так же производители, но неизвестно есть ли приозводитель со 100к+ товаров и будет ли в будущем.
Ну то-есть я не прошу за меня придумать это, у меня есть пару идей к примеру: "категория > производитель > [0] > photo.png" по достижению первой директории лимита ( к примеру 1к фото ) создавать вторую и заливать туда.
Просто может есть какие то паттерны общепринятые или идеи, я конечно поискал, но ничего занимательного не нашел.
1) делать папки по дате загрузки
2) делать папки по первым цифрам id товара, например id 12345678 -> 123/123456/12345678.png. Тут правда надо помнить, что мы обязаны сохранять картинку до записи информации в базу и придется изворачиваться с транзакциями, чтобы это обеспечить.
Или 123/123456/12345678-телевизор-самсунг.jpg если ты хочешь читабельные имена которые возможно улучшат позицию в поиске по картинкам.
Антоши, элементарный для вас, знатоков, вопрос: как красиво вывести данные из БД в html в виде таблицы, чтоб без <tr><td>? Без шаблонизаторов специальных не обойтись?
>>882288
Ты хочешь разделить HTML разметку и PHP код? Хорошая мысль, для этого можно использовать шаблонизатор вроде Twig. Если не хочешь, можно использовать сам PHP, он имеет встроенный шаблонизатор. Почитай советы в пасте про список студентов из ОП-поста, там были ссылки на статьи в которых объяснялось как это работает.
нашел этот сайт https://smashballoon.com/custom-facebook-feed/access-token/ который как бы поясняет как его получить и в конце статьи показывает его ( что мне показалось сомнительным). Получил , значит, этот токен доступа, вставил в положенное место и в итоге получил такое сообщение
"An active access token must be used to query information about the current user."
в общем реквестую помощь. Как справиться с этим говном, как мне без жопоболи работать с этим приложением?
По аналогии с тестовыми токенами все нормально работает, только вот их каждый день нужно новые постить
Спасибо, анончик. Изучаю.
После смены работы на полнодневную, в конце рабочего дня просто убитый. Весь месяц кое-как занимаюсь на гитаре и кое-как программирую. Часик в день по будням и по три в выходные остались в прошлом. Не думал, что курьерить 6-8 часов зимой будет так сложно, хоть платят очень хорошо.
Теперь вот задумываюсь над тем, чтобы начать искать работу сейчас или после НГ. Задачи на студентов и файлхостинг у меня сделаны на хорошем уровне. На тестхаб, видимо, придётся забить. Надо подтянуть CSS, JS, подготовиться к вопросам собеседований и вперёд
https://github.com/TheSidSpears/
http://dkab.github.io/jasmine-tests/?spec=4
Чёт сложно
> Возвращаемая функция должна принимать любое количество аргументов и передавать их функции fn
Это как можно сделать?
Школьник решил купить айфон и для этой цели взял кредит. Сумма кредита — 40000 р., банк в начале каждого месяца (включая первый) начисляет 3% от остатка долга за пользование кредитом и 1000 р. комиссии (да, а ты думал, обойдешься процентами?). После этого, в конце каждого месяца, наш герой идет в банк и пытается выплатить долг, но он не может заплатить более 5000 р за раз (сэкономленных на школьных завтраках). Вопрос, когда он избавится от долга? Во сколько школьнику обошелся айфон?
<?php
error_reporting(-1);
$creditBalance = 4000; / Долг анона перед банком /
$percent = 1.03; / Банк начисляет 3% в месяц от суммы /
$servicePayment = 1000; / А также 1000 рублей в месяц комиссии за обслуживание счета /
$monthlyPayment = 5000; / Анон платит 5000 р в месяц, это все, что ему дает мама на завтраки /
$paymentTotal = 0; / Сколько всего отдал банку анон /
/ Посчитаем расходы 20 раз на 20 месяцев вперед /
for ($month = 1; $month <= 20; $month ++) {
$creditBalance = ( $creditBalance $percent ) + $servicePayment - $monthlyPayment;
$paymentTotal = ($paymentTotal + $monthlyPayment)+$creditBalance;
echo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n";
/ Если баланс отрицательный — хватит считать */
if ($creditBalance < 5000) {
echo "С меня хватит!\n";
break;
}
}
Вы пока выучите пыхапы, он устареет окончательно и исчезнет с рынка.
Функция в JS это объект. И у него есть полезные методы: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype
Поищи там.
Я это слышу с 2002 года.
Код в тред не кидай. Читай внимательнее оппост и задачник, там всё расписано для новичков. Или посмотри как местные код кидают хоть.
Ты за последний месяц не доплачиваешь, у тебя если сумма меньше 5000, то программа завершается.
Чтобы не уходить в минус, надо перед тем как платить, посмотреть, какая сумма долга, если маленькая, то платить не 5000, а сколько осталось.
Пока изучал не по ОП мануалам, но блииин.
Какой-же MVC сложный. Просто ужос. Я не могу понять буквально ничего. Ну то-есть я понимаю как всё работает, как всё теоретически устроено, но как например прикрутить сбор данных из БД - это для меня загадка, прикрутить новый функционал - тоже. Вообще не понимаю как происходит наследование в некоторых случаях. Не могу понять как происходит передача данных по структуре от POST.
Антоны, я последню неделю я только и делал что ковырял всякие MVC по мануалам с сайтов и ютюбов, но я уже просто отчаялся.
Неужели я просто тупой и не судьба мне в программирование?
Не ссы, продолжай учить, пока осознание не придёт само.
вот примерно до этого я дошел, но не знаю как выразить оплату только остачи. гуглил, но по теме не нашел
>перед тем как платить, посмотреть, какая сумма долга, если маленькая, то платить не 5000, а сколько осталось.
вот это я и не понимаю.
додумался до такого костыля, но он не работает
if ($creditBalance < 0) {
$paymentTotal = $paymentTotal + $creditBalance;
$creditBalance = 0;
echo "С меня хватит!\n";
break;
И совсем не в том местеспрашиваю, но сколько времени займет путь от "полный 0" до создание сайта по шаблонам?
чисто для вёрстки - нет. для создания возможности общения между клиентом и сервером - да.
Итак, нихуя я и не нашёл как вывести таблицу без смешивания кода html с php. Придётся хуячить по воробьям с ионной пушки.
Например,
@$array[z]=round($array[x]/$array[y]);
До такого и я додумался, а как со строками быть? Предполагается, что количество строк динамическое.
HTML-таблица состоит из тегов <tr>, строк таблицы, и <td>, колонок таблицы. Есть двумерный массив, которым эту таблицу нужно заполнить. Предполагается, что массив расширяемый.
Как создать таблицу, не выводя тегов в php, а используя шаблон максимально эффективно? Или таблица в хтмл - это настолько рудиментарное говно, что даже и пытаться не стоит?
Почему бы не почитать мануал ОПа? https://github.com/codedokode/pasta/blob/master/arch/mvc.md
>>882653
Мануал: http://php.net/manual/ru/language.operators.errorcontrol.php
Вообще это плохая штука и ее использование в твоем примере неправильно. Видимо там кривой код иногда переменная или элемент массива отсутствует. Чтобы не исправлять код, поставили оператор игнорирования любых ошибок.
>>882673
Прочитай http://www.phpinfo.su/articles/practice/shablony_v_php.html
Как-то так.
<table>
<?php for($i=0;$i<$colls;$i++){?>
<tr><td>{$data}</td><td>{$data2}</td><td>{$data3}</td>
</tr>
<?php } ?>
</table>
Насколько я понял вопрос, у него не та ситуация, когда шаблоны можно было-бы применить.
Таки кошерно.
Премного благодарю. До сих пор плохо понимаю что в альтернативном синтаксисе писать можно, а что нельзя.
> Вообще не понимаю как происходит наследование в некоторых случаях.
А какое отношение это имеет к MVC? Наследование изучают в теме про ООП. Если что, в моем учебнике в главе про ООП это немного изучается.
> Не могу понять как происходит передача данных по структуре от POST.
Удобно данные из POST внести в объект-модель и дальше работать с ней. Хотя некоторые предпочитают гонять туда-сюда большие массивы.
Какие шаблоны нельзя применить? Шаблоны на PHP? Шаблоны на twig? Оба этих варианта решают его проблему.
Или ты имел в виду какие-то придуманные тобой самодельные шаблоны? Ну значит, они плохо продуманы, если не могут решить такую задачу.
>>882696
МАнуал объясняет http://php.net/manual/ru/control-structures.alternative-syntax.php
>Или ты имел в виду какие-то придуманные тобой самодельные шаблоны?
Я имел ввиде что у человека наверное MVC вообще нет.Иначе-бы такие вопросы он не стал задавать.
>Удобно данные из POST внести в объект-модель и дальше работать с ней.
Я про то, что POST теряется пока до модели доходит. И не могу понять почему.
>А какое отношение это имеет к MVC?
Делаю модель с подключением к бд, наследую параметры подключения чтобы получить результат запроса. Должен ли я наследовать всё это для того, чтобы выполнить запрос? Во многом именно это и непонятно.
>>882691
Как ни странно времени не было, сейчас уже буду его усиленно учить.
Да, mvc там и рядом не валялось. Это простецкая визитка с вау-вау, динамическим выводом прайслиста. Тупо нужно быстрее сделать, но чтобы я это потом ещё мог поддерживать и допиливать туда разные элементы, не дёргая верстальщика по пятнадцать раз в день.
Можно сложнее сделать, с div и прочее. Но с таблицей вариант очень хорош тем, что его я тебе накидал за минуту и он работает вообще во всех браузерах одинаково. Даже в IE 4.5!
Вот я и говорю, что наикошернейше. Благодарю вас, товарищ.
<form>
<input type="file"/>
</form>
на сервере? Пытаюсь сделать по инструкции с w3school
if (move_uploaded_file($_FILES["filename"]["tmp_name"], $target_file))
echo "done";
Но у меня move_uploaded_file ничего не возвращает, ну и файл не появляется, разумеется. В php.ini file_uploads=On.
$target_file
А тут что? Скорее всего в этой переменой проблема.
if (move_uploaded_file($_FILES["filename"]["tmp_name"], $target_file)){
echo "Загрузилось";
}else{
echo "Сообщение об ошибке";
}
В $target_file - путь к файлу, который составляется следующим образом:
$target_file="/"."uploads/" . basename($_FILES["filename"]["name"]);
Папка "uploads" лежит в папке с .php файлом, в котором происходят описанные выше действия, да.
echo $classInstance['propertyName'];
Но именно такой синтаксис у меня не работает. Или для того, чтобы он работал, нужно кастовать объект к массиву, и только потом уже брать значения свойств по ключу-названию свойства?
mysql_escape_string
Дак оно и так совпадало. Потом я сменил имя файла в инпуте и в пхп файле, и только тогда заработало. Скорее всего, я еще помимо этого делал какие то мелкие изменения, которые повлияли на результат, но чё то в голове из последних действий отложилось только изменение атрибута name
да не должно быть. datDB было, FUCKTHAT стало.
Через какое-то время допишу о знаниях JS и CSS, как доделаю задачки в ОП-посте
буду писать ломатель куков на пхп ^^
пока что только для фейсбука но мы будем расширяться.
#kill firefox
PROCNAME = "firefox.exe"
def kill_firefox():
for proc in psutil.process_iter():
try:
if proc.name() == PROCNAME:
proc.kill()
except:
pass
kill_firefox()
О нем пишут, что он работает без использования базы данных.
Отзываются о нем так, например:
>>Pico is another really simply CMS. It doesn't have a backend to edit (there is a plugin to enable that). It doesn't use database queries therefore making it super fast.
>>It doesn't use database queries therefore making it super fast.
Неужели использование базы данных медленне, чем использование файлов?
Толстота.
>если и возьмут джуниором чистить вилкой легаси пхп4
Тут тебе не Java уже везде где только можно 7 версия, и 7.1 на подходе.
Их есть несколько версий? Срисли? А как же обратная совместимость? Или у JS с этим совсем беда?
Пару месяцев кручусь в веб-разработке. Учил PHP сам, методом проб и ошибок(не было денег на курсы какие-то, да и курсов полноценных в моем мухосранске нету). Так что, если у тебя есть шанс пойти на такие курсы, я рекомендую сделать это. Это в том случае, если ты всерьез хочешь заняться веб-разработкой. Мне, например, сейчас иногда аукается мое самообучение, иногда не в очень хорошую сторону.
>>883306
NetBeans, Eclipse из бесплатных.
PhpStorm от JetBrains из платных (для студентов бесплатно, при желании можно взять торрент-эдишен).
По поводу отладчика - для PHP это xdebug и необязательно для его использования иметь ИДЕ.
Я всегда пользовался атомом, для него есть пакет php-debug который добавляет функционал отладчика в редактор.
https://atom.io/packages/php-debug
По поводу других редакторов вроде Sublime Text когда-то в треде писали что дополнения тоже существуют.
Благодарю.
>функционала как на visual studio
Там же был бесплатный плагин к ней. По крайней мере в 2011 году. А сейчас все на PHPStorm перекатились. Удобнее ничего не найти.
Реализуешь интерфейс ArrayAccess для класса: http://php.net/manual/en/class.arrayaccess.php
>>883206
В PHP нет, так как обычно достаточно встроенных функций. Если не достаточно, то есть обёртки-коллекции, предоставляющие как раз нужные тебе методы, пример: https://laravel.com/docs/5.3/collections#method-avg
Но конкретно в твоём случае, если я правильно понял, хватит функций array_filter и count. Вбрось на ideone пример исходного массива и то, что тебе нужно из него получить.
>>883466
http://php.net/manual/en/function.realpath.php
Может это?
Что значит последняя часть поддиректории? Просто вбрось пример.
Например, есть такой путь.
C:/Users/Dima/AppData/Mozilla/Firefox/Profiles/kslj498/cookies.sqlite
Я точно знаю, что AppData/Mozilla/Firefox/Profiles и cookies.sqlite должны быть в поддиректории, а другие папки, например Dima и kslj498 находятся динамически. из них строится путь до файла
мне придется все директории и поддиректории в диске С обходить?
Есть вопросцы, в юношеском запале клепал магазины на wp и woocommerce, но потом очнулся и понял что это раковник. Вкатился в yii2 (пара успешных крупных проектов и куча опыта) и для своего бизнеса (оптовый портал с 1000+ позиции (раковый webasyst - достался в наследство, от предыдущего хозяина) и розничный(wp+woo)) делаю новый магаз с преферансом и куртизанками. Работают у меня макаки на кассах которые и вордпресс ложили на пол, поэтому неубиваемая трехкнопочная система - это мой выбор. В целом я добрался до отличного результата с rbac, виджетами, но все равно ощущение что что-то забыл. Точнее, что можно больше.
Что посоветуешь, анончик? Как бы ты аноний сделал магазин для розничной и оптовой сети и как бы ты его писал, что использовал? Как не обосраться и сделать магазин 10 из 10? Что тебе кажется нужным, а что нет?
Больше мотивационно хочется пообщаться, а то очень иногда грустно одному сидеть в тоске.
>$Frame::getInstance()->startDynamicWithID("delivery-info");
Заранее спасибо.
Первое статический метод вызывает
Есть функция glob: http://php.net/manual/en/function.glob.php
Но она не умеет в рекурсивный поиск, чтобы найти cookies.sqlite нужно точно знать на каком уровне вложенности находится файл, т.е. писать как-то так: glob('folder/✱/✱/cookies.sqlite')
Для произвольной вложенности нужно всё обходить ручками. Но есть готовые итераторы из SPL: http://php.net/manual/en/class.recursivedirectoryiterator.php
Использовать как-то так: http://stackoverflow.com/a/36912410
А на линуксе есть find, с помощью которого задача решается одной короткой строчкой.
Вопрос - можно ли как-то так заюзать тернарный оператор, что бы сократить немного этот код? Думал что это будет что-то такое (empty($_COOKIE['user_id'])) ? $this->actionRegistr() : $this->action(), но не работает.
Граммар Наци
http://ideone.com/uNsBBv - первое задание с выделением текста. У меня сложилось ощущение, что тут нужно больший кусок текста выводить с ошибкой, но я без понятия как это сделать. В голову приходит работа с флагом PREG_OFFSET_CAPTURE, но как на деле это все применить - хз...
http://ideone.com/XHg06L - вторая часть с тихим исправлением полегче.
Нет такого этапа, каждый раз когда я думал, что все самое тяжелое уже позади и дальше осталось только попивать смузи, читая хабр, меня настигала еще большая жопа и осознание того, что я нихуя не знаю.
>Ребят, есть интересный вопрос. Какой самый тяжелый этап в изучении программирования? Может есть какая-то тяжелая тема, или тяжелый этап это теория и тд.
Архитектурные всякие дела, ну и всякие алгоритмы сложные. Если освоишь это - считай ты понял программирование как таковое.
Что бы стать таким фрилансером надо сначала минимум пару лет бичпакетами питаться.
$x = $somearray[$i]->SomeFunction();
ругается, что не найдена функция SomeFunction();
Я так понимаю, надо кастовать элемент массива к классу, и потом только вызывать функцию?
> $x = $somearray[$i]->SomeFunction();
Ничего кастовать не нужно, такой код должен работать, если в массиве под индексом $i действительно есть объект с методом SomeFunction().
Ты лучше вбрасывай код на ideone, а не рассказывай что там IDE показывает. IDE не знает, что добавится в массив во время выполнения программы.
Можно использовать докблоки для помощи IDE: http://stackoverflow.com/a/29999292
"W5.2 Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня ему 16 лет?"
Решаю так:
for ($l=1000;$l<1000000;$l=$l+$l*0.1) {
echo "l=$l\n";
}
Получаю столбец результатов.
Собсн вопрос: как вывести в конце число строк (лет)?
И является ли решение правильным, если крайнее число в столбце равно l=955593.81772732 ?
зачем кучу раз выводить, сколько денег и когда?
невыводи ничего, а сделай counter на года типа кол-во год депозита ++
for ($l=1000;$l<1000000;$l=$l+$l0.1) {
$goda ++;
$babki =$l;
}
if $babki<1kk {
$goda ++;
$babk=$babki+$babki0.1
}
echo $goda;
echo $babki;
это хоть и говнокод, но получше твоего варианта
Девушка с оппика позожа на мою коллегу просто 1 в 1!
Код не пашет даже после исправления опечаток. Я только начинаю, не мог бы подробнее расписать что к чему? Просто ума не приложу что делает вот эта команда "$goda ++;" (ну кроме того что с каждым разом эта переменная должна расти) во второй строке, этой переменной даже начальное значение не присваивалось, не говоря уже о том, что она никак не связана с основным вычислением.
<?php
$goda =0; //ставишь сколько изначально лет вкладчику этк. это входное значение годов.
for ($l = 1000 ;$l < 1000000; $l=$l+$l0.1) {
$goda ++;
$babki =$l;// после конца цикла переменная $l превратится в тыкву(на нормальных языках, на пхп останется, собственно этот костыль необязателен)
}
if ($babki < 1000000) {// при значении меньше 1кк цыкл выше перестает работать, потому как делать надо было через do while, фиксим это проверкой, если мы вышли из предыдущего цыкла, а бабки меньше ляма, нада еще на 1 год оставить на депозите.
$goda ++ ; //увеличит на 1 значения года
$babki = $babki + ($babki 0.1) ; //добавит бабки заработаные за этот дополнительный год
}
echo $goda;
echo $babki;
?>
Потому-что у тебя неправильное решение например.
Почему ^[+7|8][ --()]{1,}[0-9]{10}$ не пашет?
http://codepad.org/JrKDe8It
выводит 2 раза одно и тоже, а надо чтобы разное.
Сначала первую строку выводишь, затем рандомишь опять и снова выводишь
Напомню себе, что надо будет глянуть https://github.com/never3ver/students_list из >>873486 >>873545 и там почти все готово.
Напомню, что надо глянуть https://github.com/someApprentice/maintaskforlayout из >>874239 .
Подождите еще немного, доберусь и до вас.
Вот, в частности, последние ответы:
>>884783 - тут https://bitbucket.org/learningacc/file-downloader/
>>884472 - про аякс и почему не работает класс alert-success
>>884470 - про ООП, и что значит атрибут form action
спасибо
https://web2033.com/strrev-php/
Нет. Программа должна вывести, является ли слово палиндромом или нет. Программа по ссылке этого не делает.
Также, код избыточен и его можно упростить.
Ты можешь объяснить, какие недостатки имеет используемый тобой подход? Ну например, будет ли работать проверка на палиндром для любого текста в кодировке utf-8 или не для любого? Если нет, то для каких входных данных программа будет работать правильно?
Важно понимать, что ты делаешь, а не просто скопировать откуда-то кусок кода. В поиске кода в интернете нет ничего плохого, но важно понимать, как он работает, и какие у того или иного подхода есть особенности.
Я бы сам предложил либо разюивать текст на буквы через mb_substr, либо хаком с preg_split. У этого метода тоже кстати есть определенный недостаток, основанный на особенностях юникода, если ты можешь его назвать - было бы вообще замечательно.
> function strrev_enc($text2)
Надо писать названия не через подчеркивания, а кемел кейсом. Название функции желательно начинать с глагола. Переменную надо назвать не text2, а просто text, так как в этой функции нет text1 и это просто выглядит нелогично.
Обычно в этом нет необходимости. PHP скрипты предназначены для запуска в первую очередь на веб-сервере, где уже есть интерпретатор PHP. Соответственно, никто их в исполняемый файл не компилирует. Это ведь только замедлит разработку, вынуждая делать новую компиляцию после каждой правки.
Но я встречал упаковщики, которые упаковывают PHP скрипт и интерпретатор в один файл. Но они мутные, например на них может ругаться антивирус (что само по себе подозрительно), а также там ты ограничен в настройке PHP и подключении его расширений.
Если ты хочешь писать консольные скрипты (или тем более десктопные программы), которые надо запускать без PHP, я бы советовал использовать другие языки. Для десктопных программ хорош C# (но ему нужен дотнет) или Java (тоже надо сначала саму Яву ставить), еще можно писать на C++, но это намного сложнее и неудобнее.
Для консольных программ можно использовать Го, но не уверен, что у него все хорошо с поддержкой винды. Он в первую очередь на Линукс ориентирован.
Или я не понял вопрос и ты просто хочешь чтобы Апач с PHP в составе запускался сам при загрузке ОС? Тогда достаточно просто добавить Апач как службу.
Чистый PHP самозапускать немного странно - зачем? Если ты используешь его как сервер, то можно записать код запуска сервера в bat-файл и перетащить этот файл в раздел "автозагрузка" в меню Пуск -> Программы.
> Размеры макета конечны?
Размеры окна браузера могут быть любые. Мы не знаем, какие мониторы с каким разрешением будут популярны в будущем. Но с другой стороны, растягивать текст до бесконечности в одну длинную строку тоже смысла нет. Потому стоит сделать так:
- зафиксировать максимальную ширину содержимого (например 1200-1400px), если окно шире то центрировать содержимое, добавив поля с краев
- на ширине от ~600-800 до максимальной - сделать верстку резиновой, чтобы содержимое растягивалось на эту ширину. Ну например, блок с картинками может на узкой ширине превращаться в 3 колонки вместо 4, а на большой - в 5.
- на ширине меньше 600-800 переходить на мобильную верстку - обычно там все содержимое выводится в 1-2 колонки
Вот в помощь таблица размеров экранов мобильных устройств: http://mydevice.io/devices/
Если ты не знаком с адаптивной версткой, то погугли "примеры адаптивных сайтов", или просто используй кнопку "тестирование адаптивной верстки" в инструментах разработчика в Хроме/ФФ (Ctrl + SHift + I).
> Шапка высотой 200px на экране с большим разрешением -- смех, а буквы не читаются: как исправить?
Почему не читаются? Они довольно большие в макете. И как на этом экране выглядят другие сайты, например Хабр?
> Возможно ли проставить высоту в% без потери возможности скроллить вниз?
Я думаю, не стоит. Высота шапки определяется не размером экрана, а текстом в ней. Добавлять пустое место особого смысла нет.
>>не используй <a href="#" или <a href="javascript:void(0)" никогда. Для этого есть кнопки или <span>
Ссылка должна куда-то вести, то есть в href должен быть указан URL. Ссылку можно открыть в новом окне, скопировать. Если ты не можешь указать URL - у тебя не ссылка. Скорее всего у тебя кнопка, для которой есть тег button.
Если есть какие-то еще вопросы - задавай.
>>885037
Нет, я с помощью пхп хочу создать и записать на компе юзера ехе файл. Это можно сделать, вот только как его запустить - не знаю. Можно сделать так, чтобы юзер кликнул на этот файл, но как сделать шоб .ехе файл запустился без клика.
Выражение в if (а также в for, while, switch) всегда должно быть заключено в скобки, так что второй вариант неправильный.
>>881676
Я из скриншота вижу, что правило в файле uploader-master.css перекрывает правила в бутстрапе. Приоритет у них равный, скорее просто причина в том что тот файле позже подключен.
Почитай про приоритеты селекторов. Также, не стоит переопределять бустраповские правила, лучше сделать свой класс.
>>881710
Тебе надо вместо $i <= 10 написать кое-что другое.
>>881722
У тебя в коде есть ошибка. Условие $b < 10 проверяется в первый раз до того, как переменная будет создана, и происходит ошибка обращения к несуществующей переменной.
Также, условие фактически проверяет значение переменной с предыдущего шага. То есть сначала выводится 4x4 = 16, а только потом идет проверка и обнаруживается, что из цикла пора выходить. Посмотри в моем учебнике картинку с порядком выполнения цикла.
>>881760
Код для любых слов пишет, что это палиндром: http://ideone.com/Uw7SWV
Ведь фактически ты проверяешь только средние 2 буквы. У тебя в коде вообще нет слова "не палиндром".
>>881835
Боюсь, что у нас не тред поиска работы. Чтобы быть востребованным для работодателей, я советую изучать разные языки и технологии (в том числе решив например все наши задачки), а также делать учебные проекты (вроде тех что в ОП посте).
Выражение в if (а также в for, while, switch) всегда должно быть заключено в скобки, так что второй вариант неправильный.
>>881676
Я из скриншота вижу, что правило в файле uploader-master.css перекрывает правила в бутстрапе. Приоритет у них равный, скорее просто причина в том что тот файле позже подключен.
Почитай про приоритеты селекторов. Также, не стоит переопределять бустраповские правила, лучше сделать свой класс.
>>881710
Тебе надо вместо $i <= 10 написать кое-что другое.
>>881722
У тебя в коде есть ошибка. Условие $b < 10 проверяется в первый раз до того, как переменная будет создана, и происходит ошибка обращения к несуществующей переменной.
Также, условие фактически проверяет значение переменной с предыдущего шага. То есть сначала выводится 4x4 = 16, а только потом идет проверка и обнаруживается, что из цикла пора выходить. Посмотри в моем учебнике картинку с порядком выполнения цикла.
>>881760
Код для любых слов пишет, что это палиндром: http://ideone.com/Uw7SWV
Ведь фактически ты проверяешь только средние 2 буквы. У тебя в коде вообще нет слова "не палиндром".
>>881835
Боюсь, что у нас не тред поиска работы. Чтобы быть востребованным для работодателей, я советую изучать разные языки и технологии (в том числе решив например все наши задачки), а также делать учебные проекты (вроде тех что в ОП посте).
> Я про то, что POST теряется пока до модели доходит. И не могу понять почему.
Ставь везде var_dump и смотри, в каком именно месте данные теряются. Если у тебя IDE, то можно попробовать настроить и использовать отладчик, чтобы пройти код по шагам.
> Делаю модель с подключением к бд, наследую параметры подключения
Выглядит странно. Наследование не для этого придумано.
По поводу работы с БД - у меня есть урок - https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md - читал? Если да, то напиши какой паттерн используешь.
Проверь с помощью var_dump, что в переменных ($_FILES и других). Проверь, что возвращает функция move_uploaded_file и прочти мануал по ней, а также это целиком: http://php.net/manual/ru/features.file-upload.php
Открой отладчик в браузере (Ctrl +Shift + I) и проверь на вкладке Network, отправляется ли файл вообще.
Проверь лог ошибок PHP, нет ли ошибок.
> ничего не возвращает
Что значит "ничего"? Проверь с помощью var_dump что именно.
>>882731
Что значит "у нас"? Кривой код у тебя, а не у нас.
>>882737
Надо реализовать ArrayAccess.
>>882741
Без кода помочь не могу. Могу предположить, что ты неправильно работаешь с базой данных и тебе стоит подробнее про это почитать.
>>882762
2017 год рано писать.
>>882958
Твой вопрос неудачно сформулирован. Что значит "можно"? В теории на PHP сделать такое можно, на практике не факт что есть нужная библиотека. Ну например, под виндой можно использовать утилиту pskill или как-то так от Русиновича. Но это уже не совсем PHP.
>>882963
Нет. Ты вызываешь функцию N раз, передавая ей 1 аргумент, а надо вызвать 1 раз, передав все аругменты.
Ты почитал про apply() и call() ? Сделай-ка пример кода для каждой функции, если не пробовал.
>>882978
Откуда ты пытаешься прочитать эти директивы? Куда ты пытаешься вывести их названия? В браузер?
В браузере воспринимаемая кодировка зависит от тега meta charset и HTTP заголовка Content-Type.
Проверь с помощью var_dump, что в переменных ($_FILES и других). Проверь, что возвращает функция move_uploaded_file и прочти мануал по ней, а также это целиком: http://php.net/manual/ru/features.file-upload.php
Открой отладчик в браузере (Ctrl +Shift + I) и проверь на вкладке Network, отправляется ли файл вообще.
Проверь лог ошибок PHP, нет ли ошибок.
> ничего не возвращает
Что значит "ничего"? Проверь с помощью var_dump что именно.
>>882731
Что значит "у нас"? Кривой код у тебя, а не у нас.
>>882737
Надо реализовать ArrayAccess.
>>882741
Без кода помочь не могу. Могу предположить, что ты неправильно работаешь с базой данных и тебе стоит подробнее про это почитать.
>>882762
2017 год рано писать.
>>882958
Твой вопрос неудачно сформулирован. Что значит "можно"? В теории на PHP сделать такое можно, на практике не факт что есть нужная библиотека. Ну например, под виндой можно использовать утилиту pskill или как-то так от Русиновича. Но это уже не совсем PHP.
>>882963
Нет. Ты вызываешь функцию N раз, передавая ей 1 аргумент, а надо вызвать 1 раз, передав все аругменты.
Ты почитал про apply() и call() ? Сделай-ка пример кода для каждой функции, если не пробовал.
>>882978
Откуда ты пытаешься прочитать эти директивы? Куда ты пытаешься вывести их названия? В браузер?
В браузере воспринимаемая кодировка зависит от тега meta charset и HTTP заголовка Content-Type.
Базы данных в конечном итоге тоже хранят данные в файлах. Где тут выигрыш? Разве что могут быть накладные расходы на передачу данных из приложения в СУБД по сети.
Я думаю, что "super fast" это маркетинговое заявление. Там есть примеры тестов, показывающих разницу в скорости с обычными СУБД? Нет. Ну а слово "super fast", как ты понимаешь, может значить что угодно.
Я не сравнивал, но Бд вроде MySQL не медленные, я добивался там тысяч вставок в секунду при грамотном использовании, Бд поддерживают язык SQL , транзакции, параллельный доступ. Я сильно сомневаюсь что самописный движок на PHP будет работать лучше чем отлаживаемый годами профессиональный продукт.
Скорее автор просто хотел сэкономить, используя дешевый хостинг без доступа к БД. Не советую.
Если тебе надо хранить базу в файле для каких-то целей (например для простоты установки или переноса), есть SQlite - это однопользовательская БД на файлах. Она используется в iOs, андроиде, Хроме (хранить историю и закладки), скайпе. Но она рассчитана на "встраиваемое" использование, когда ей пользуется только одна программа, а веб - это много параллельно работающих скриптов и там она не так эффективна как отдельная БД.
Какой ответ ты ожидаешь? Надо либо модифицировать код, либо найти другой. Если есть более конкретные вопросы, уточняй.
>>883087
Изучи, чем отличается от PHP5, что нового, какую выгоду это дает.
>>883104
Забили на нее. Если у тебя андроид 2-летней давности то хипстеров твои проблемы не волнуют.
Я конечно советую пока писать на ES3.
Также есть транспайлеры, которые могут транслировать код в более раннюю версию, но они пока умеют только превращать ES6 -> ES5. Никто не хочет попробовать в ES3 транспайлер написать? Тут конечно надо понимать, что часть кода все равно преобразовать не удастся.
>>883199
Стену кода тяжеловато читать, инициализацию стоило засунуть в функцию.
Эхо сервер должен читать 1 строку (до первого \n). Ты вместо этого читаешь 1 пакет, это может быть несколько строк или кусок строки.
socket_close может выдать ошибку.
> $buf = trim($buf);
> if ($buf == "\r\n") {
Это никогда не сработает. Догадайся, почему.
Советую не требовать наличия \r для совместимости с теми кто использует только \n (но при этом слать \r\n в ответе).
Какой ответ ты ожидаешь? Надо либо модифицировать код, либо найти другой. Если есть более конкретные вопросы, уточняй.
>>883087
Изучи, чем отличается от PHP5, что нового, какую выгоду это дает.
>>883104
Забили на нее. Если у тебя андроид 2-летней давности то хипстеров твои проблемы не волнуют.
Я конечно советую пока писать на ES3.
Также есть транспайлеры, которые могут транслировать код в более раннюю версию, но они пока умеют только превращать ES6 -> ES5. Никто не хочет попробовать в ES3 транспайлер написать? Тут конечно надо понимать, что часть кода все равно преобразовать не удастся.
>>883199
Стену кода тяжеловато читать, инициализацию стоило засунуть в функцию.
Эхо сервер должен читать 1 строку (до первого \n). Ты вместо этого читаешь 1 пакет, это может быть несколько строк или кусок строки.
socket_close может выдать ошибку.
> $buf = trim($buf);
> if ($buf == "\r\n") {
Это никогда не сработает. Догадайся, почему.
Советую не требовать наличия \r для совместимости с теми кто использует только \n (но при этом слать \r\n в ответе).
А кстати, ты изучал генераторы? Я подумал, код чтения строк удобно сделать генератором, который выплевывает строку на каждой итерации. Попробуй.
Ну или предложи свой способ сделать функцию, которая при каждом вызове возвращает 1 прочитанную строку. Генератор тут по моему удобнее всего.
>>883206
Нет, но можно написать цикл, либо array_filter, либо использовать array_reduce с анонимной функцией.
>>883310
У меня в саблайме был отладчик, но он показался мне глючным. Времени особо разобраться не было. Проверьте, у кого он есть, только на чем-нибудь посложнее проекта из 1 файла.
>>883410
А как еще хранить набор объектов, если не класть их в массив? Ну например, список новостей?
Можно составить индекс (список всех путей) заранее и искать в нем.
>>883563
http://php.net/manual/ru/language.oop5.paamayim-nekudotayim.php
http://php.net/manual/ru/language.oop5.basic.php
это из ООП. Изучи его сначала.
>>883621
find как раз не панацея, на мой взгляд это все усложняет, например как ошибку от find передать в стандартный логгер? Как поставить таймаут на время выполнения? Как получить имена файлов с нестандартными символами? Как остледить, что find раньше времени?
Я не думаю, что тут будет 1 строка. Я обычно исплоьзую Symfony Process для запуска внешних команд, а тут выгоднее написать все на PHP.
>>883720
Тут нужен именно иф, сокращать нечего, код станет хуже читаемым.
>>883745
Отвител тут >>884790
>>883810
Надо полностью прочесть этот раздел http://php.net/manual/ru/language.references.php
Ссылки в общем усложняют код и создают риск всяких неожиданных эффектов, потому лучше ими не злоупотреблять.
>>883894
Класс не может быть элементом массива. Правильно писать "объект класса X хранится в массиве/является значением элемента массива"
Твой код должен работать.
Кастовать объекты нельзя.
>>883980
Надо завести переменную и увеличивать ее на 1 каждый год, тогда в конце в ней будет возраст вкладчика.
Требуется вывести возраст, когда на счету будет миллион или более.
>>884036
Не надо писать переменные русскими словами. Используй Гугл транслейт.
Иф в коде лишний - зачем он?
>>884250
$x++ равносильно $x += 1 или $x = $x + 1
>>884272
Иф не нужен.
>>884303
у всех других решение совпало, так что ответ в учебнике скорее всего правильный.
>>884323
Потому что это мощный инструмент и надо читать и писать регулярки без лишних раздумий.
Пригодятся они не раз. даже в редакторе кода в поиске их можно использовать.
>>884396
Ну так ты выводишь одну и ту же переменную 2 раза. Или ты думаешь, она сама по себе поменяет значение? Переменная - это просто хранилище, что ты в нее кладешь, то в ней и останется лежать, пока не поменяешь.
Можно составить индекс (список всех путей) заранее и искать в нем.
>>883563
http://php.net/manual/ru/language.oop5.paamayim-nekudotayim.php
http://php.net/manual/ru/language.oop5.basic.php
это из ООП. Изучи его сначала.
>>883621
find как раз не панацея, на мой взгляд это все усложняет, например как ошибку от find передать в стандартный логгер? Как поставить таймаут на время выполнения? Как получить имена файлов с нестандартными символами? Как остледить, что find раньше времени?
Я не думаю, что тут будет 1 строка. Я обычно исплоьзую Symfony Process для запуска внешних команд, а тут выгоднее написать все на PHP.
>>883720
Тут нужен именно иф, сокращать нечего, код станет хуже читаемым.
>>883745
Отвител тут >>884790
>>883810
Надо полностью прочесть этот раздел http://php.net/manual/ru/language.references.php
Ссылки в общем усложняют код и создают риск всяких неожиданных эффектов, потому лучше ими не злоупотреблять.
>>883894
Класс не может быть элементом массива. Правильно писать "объект класса X хранится в массиве/является значением элемента массива"
Твой код должен работать.
Кастовать объекты нельзя.
>>883980
Надо завести переменную и увеличивать ее на 1 каждый год, тогда в конце в ней будет возраст вкладчика.
Требуется вывести возраст, когда на счету будет миллион или более.
>>884036
Не надо писать переменные русскими словами. Используй Гугл транслейт.
Иф в коде лишний - зачем он?
>>884250
$x++ равносильно $x += 1 или $x = $x + 1
>>884272
Иф не нужен.
>>884303
у всех других решение совпало, так что ответ в учебнике скорее всего правильный.
>>884323
Потому что это мощный инструмент и надо читать и писать регулярки без лишних раздумий.
Пригодятся они не раз. даже в редакторе кода в поиске их можно использовать.
>>884396
Ну так ты выводишь одну и ту же переменную 2 раза. Или ты думаешь, она сама по себе поменяет значение? Переменная - это просто хранилище, что ты в нее кладешь, то в ней и останется лежать, пока не поменяешь.
PHP обычно выполняется на веб-сервере, а не у пользователя на компьютере - ты это понимаешь? Запустить можно например через exec, но там много своих тонкостей.
Ну и это плохая идея, писать инсталляторы на PHP. Есть гораздо более подходящие для этого средства.
JNDI-запросы сервиса, когда объект запрашивает сервис по имени, реализуют внедрение зависимости лишь частично."
Перечитываю и перечитываю раз за разом, это какой-то мертвый язык? Как это можно понимать вообще?
Почитай у меня: https://github.com/codedokode/pasta/blob/master/arch/di.md
Или у Фаулера (он очень умный) (англ): http://www.martinfowler.com/articles/injection.html
Перевод не очень читабельного качества: http://yugeon-dev.blogspot.ru/2010/07/inversion-of-control-containers-and_21.html
Также предлагаю, если есть желающие, составить нормальное определение для Вики, желательно опирающееся на труды Фаулера.
переделал 13 задачу по JS: http://ideone.com/7lG98j
Теперь элементы сети наследуются от общего класса, и DepartmentOfEnergy получил метод добавления элемента сети.
>> @param {сonst} timesOfDay - Константы класса DepartmentOfEnergy
>Мне стало интересно, а можно ли описать как-то что тут константы, с помощью jsdoc? Я нашел такое:
>Но это по моему все не то. В TypeScript вроде есть enum для этого.
Для обозначения констант решил сделать так:
* @param {(PowerDepartment.DAY|PowerDepartment.NIGHT)}
Так как, данная конкретная константа сама по себе является новым, определенным типом данных,
я указываю ее название в качестве этого типа данных. А варианты показаны как Multiple types (type union) http://usejsdoc.org/tags-type.html
Хотя, если констант больше двух, запись будет очень длинной. Но зато, название константы сообщает о том, что она константа, и дополнительно то, в каком месте кода она объявлена. А ее значение {string}, не важно для метода класса, который с ней непосредственно работает, т. к. значение может поменяться в том месте, где она объявляется, без нарушений в работе данного метода.
Не могу понять как решить задачу с годовыми процентами.
http://ideone.com/wmAd6C
Намекните что делать.
что происходит при использовании следующей конструкции:
http://ideone.com/IYyjOd
Вот я создал database handler, и вот мне нужно запросить с БД х строк из представления. На W3schools я прочел, что в контексте работы с БД рекомендуется запрашивать хэндлер подгатавливать некий стейтмент (чё вообще возвращает DBH->prepare()?), после чего указанный в prepare() запрос компилируется на сервере
и тут вопрос номеро один: только компилируется запрос, не подгатавливаются никакие данные? Сколько потом на сервере хранится скомпилированный скрипт, и вообще, важно ли это, что он там хранится с какой либо другой точки зрения, кроме как серверу не придется парсить текст запроса и компилировать запрос по новой и той, что подготовленные запросы якобы уменьшают риск сикуль инъекций?
Далее, вот есть объект, возвращенный prepare()'ом - некоторый statement. Далее, на w3schools'е в примерах его тут же вызывали через
$statement->execute();
тут вопрос нумеро дос. Что происходит при вызове execute()? Интуитивно из названия функции мне казалось, что execute() тут же выполняет подготовленный запрос в БД и, следовательно, если это селект-запрос, то сервер тут же предоставляет мне информацию в полном объеме
Но тут я наткнулся на $statement->fetch(...)
И здесь вопрос нумеро трес - что происходит при вызове функции fetch()? Как я понял, считывается одна строка из результирующей таблицы, ну и интерпретируется в соответствии с аргументами. Но что происходит с точки зрения взаимодействия с БД? fetch каждый раз обращается к БД за очередной строчкой, или извлекает из результата работы (не возвращаемого значения) $statement->execute() строку?
И ещё, если после $statement->execute() данные всё таки в полном объеме берутся из БД, то где и как они хранятся после этого, когда удаляются?
а как же основной баланс?
function test_global_ref() {
global $obj;
$obj = &new stdclass;
}
>$obj = &new stdclass;
Что, черт возьми, это значит?
Я понимаю, что "$obj = new stdclass;" - это создать экземпляр класса и присвоить его переменной $obj. Но если перед new стоит &, как это понимать? Ссылка на экземпляр класса? Но ведь он еще не создан и ничему не присвоен.
Пример взят из справочника с php.net.
Я тебе еще раз объясняю, с помощью пхп я смогу создать на компе юзера файл с расширением ехе, который будет написан на крестах или шарпе. Вопрос как с помощью пхп или того яп, на котором он написан, сделать, чтобы файл с расширением ехе самозапустился. Или ты других яп кроме пхп не знаешь?
Это ссылка и я подозреваю, что это устаревший пример кода, так как в PHP5 объекты передаются как бы по ссылке и & не нужен:
- http://php.net/manual/ru/language.references.php
- http://php.net/manual/ru/language.oop5.references.php
>>885351
Но что тебе мешает сделать нормальный инсталлятор? Некоторые программы позволяют создать инсталлятор даже без программирования. Я не вижу смысла городить какую-то сложную схему с установкой PHP, затем установкой через него программы - это слишком переусложнено.
огоспади. смотри, я вешаю скрипт на сервер в публичный доступ. сторонний юзер переходит по ссылке и у него на компе (не на моем) создается файл екзешник. теперь мне надо чтобы у него на компе этот файл самозапустился. не на моем. грубо говоря, вирусняк хочу через ссылку юзеру закинуть.
Тогда уходи. Наш тред не для создателей вирусов. Ну и дополню, чтобы ты не тратил время, юный вирусописатель, что с помощью PHP екзешник ты создать можешь разве что на сервере.
не правда, я могу создать файл с помощью fopen и присвоить ему расширение .ехе. Причем на компе у того, кто открыл ссылку
for($age=16, $money = 10000;$money<1000000;$age++,$money+=$money*0.1){
}
echo $age."\n";
echo $money;
Перечитай теорию про то, как взаимодействует браузер и сервер.
>>885374
А номер поста?
>>885263
Для начала почитай мануал по PDO::prepare http://php.net/manual/ru/pdo.prepare.php
Там написано, что возвращается объект PDOStatement.
Этот объект обозначает собой запрос (как выполненный, так и еще не выполненный), и также позволяет получить результаты (для выполненного запроса). prepare создает пока еще не выполеннный запрос. Выполненным он становится после успешного выполнения execute().
> Сколько потом на сервере хранится скомпилированный скрипт
В мануале не написано явно: "так как позволяет драйверу кэшировать на клиенте и/или сервере план выполнения запроса и метаданные". Это потому что у разных баз данных могут быть разные принципы работы, PDO ведь несколько видов баз поддерживает.
Но важно знать, что PDO поддерживает 2 вида подготовленных запросов - настоящие, реализуемые с помощью БД, и эмуляцию, когда ничего не подготавливается, а просто PDO сам подставляет в запрос знаечния и отправляет на сервер. Эмуляция используется если сервер БД не поддерживает подготовленные запросы или поддерживает, но не полностью. Эмуляцию можно включить опцией принудительно и тогда ничего сохраняться естественно не будет. Также, как я помню, MySQL поддерживает только плейсхолдеры-вопросики и с двоеточиями автоматически включается эмуляция.
Далее нам надо обратиться к документации MySQL. MySQL включает в себя как сервер (отдельная программа), так и клиентскую библиотеку. В случае PDO, в PDO встроена нужная клиентская библиотека (но не та, что распространяется с MySQL, а своя, совместимая, написанная, чтобы не зависеть от владельца MySQL). Соответственно, имеет смысл почитать документацию по MySQL, либо по серверу, либо по клиентской библиотеке.
Идем на сайт MysQL: http://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
Видим там пункт "Prepared Statements in Application Programs" - это как раз наш случай, речь о подготовке запроса клиентом. Конечно, там описана поставляемая с MySQL библиотека-клиент, но я думаю что та что в PHP работает аналогично. По крайней мере она использует тот же протокол и серверный код одинаков. Идем по ссылке и находим статьи
1) http://dev.mysql.com/doc/refman/5.7/en/c-api-prepared-statements.html
2) http://dev.mysql.com/doc/refman/5.7/en/c-api-prepared-statement-problems.html
Открываем 1 и там мы видим " For more information, see Section 9.10.4, “Caching of Prepared Statements and Stored Programs”." и снова идем по ссылке http://dev.mysql.com/doc/refman/5.7/en/statement-caching.html
Видим: "The max_prepared_stmt_count system variable controls the total number of statements the server caches. (The sum of the number of prepared statements across all sessions.)" - то есть есть ограничение на общее число закешированных в памяти подготовленных запросов. Можешь просмотреть эту переменную запросом SHOW VARIABLES LIKE 'max_prepared%';
> The server maintains caches for prepared statements and stored programs on a per-session basis. Statements cached for one session are not accessible to other sessions. When a session ends, the server discards any statements cached for it.
Кеш свой для каждого соединения с БД. Он очищается при отсоединении от нее.
Я как-то тестировал (советую тебе тоже сделать это), у меня получилось что выигрыш от подготовки запроса очень маленький.
Их используют в основном ради плейсхолдеров.
Перечитай теорию про то, как взаимодействует браузер и сервер.
>>885374
А номер поста?
>>885263
Для начала почитай мануал по PDO::prepare http://php.net/manual/ru/pdo.prepare.php
Там написано, что возвращается объект PDOStatement.
Этот объект обозначает собой запрос (как выполненный, так и еще не выполненный), и также позволяет получить результаты (для выполненного запроса). prepare создает пока еще не выполеннный запрос. Выполненным он становится после успешного выполнения execute().
> Сколько потом на сервере хранится скомпилированный скрипт
В мануале не написано явно: "так как позволяет драйверу кэшировать на клиенте и/или сервере план выполнения запроса и метаданные". Это потому что у разных баз данных могут быть разные принципы работы, PDO ведь несколько видов баз поддерживает.
Но важно знать, что PDO поддерживает 2 вида подготовленных запросов - настоящие, реализуемые с помощью БД, и эмуляцию, когда ничего не подготавливается, а просто PDO сам подставляет в запрос знаечния и отправляет на сервер. Эмуляция используется если сервер БД не поддерживает подготовленные запросы или поддерживает, но не полностью. Эмуляцию можно включить опцией принудительно и тогда ничего сохраняться естественно не будет. Также, как я помню, MySQL поддерживает только плейсхолдеры-вопросики и с двоеточиями автоматически включается эмуляция.
Далее нам надо обратиться к документации MySQL. MySQL включает в себя как сервер (отдельная программа), так и клиентскую библиотеку. В случае PDO, в PDO встроена нужная клиентская библиотека (но не та, что распространяется с MySQL, а своя, совместимая, написанная, чтобы не зависеть от владельца MySQL). Соответственно, имеет смысл почитать документацию по MySQL, либо по серверу, либо по клиентской библиотеке.
Идем на сайт MysQL: http://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
Видим там пункт "Prepared Statements in Application Programs" - это как раз наш случай, речь о подготовке запроса клиентом. Конечно, там описана поставляемая с MySQL библиотека-клиент, но я думаю что та что в PHP работает аналогично. По крайней мере она использует тот же протокол и серверный код одинаков. Идем по ссылке и находим статьи
1) http://dev.mysql.com/doc/refman/5.7/en/c-api-prepared-statements.html
2) http://dev.mysql.com/doc/refman/5.7/en/c-api-prepared-statement-problems.html
Открываем 1 и там мы видим " For more information, see Section 9.10.4, “Caching of Prepared Statements and Stored Programs”." и снова идем по ссылке http://dev.mysql.com/doc/refman/5.7/en/statement-caching.html
Видим: "The max_prepared_stmt_count system variable controls the total number of statements the server caches. (The sum of the number of prepared statements across all sessions.)" - то есть есть ограничение на общее число закешированных в памяти подготовленных запросов. Можешь просмотреть эту переменную запросом SHOW VARIABLES LIKE 'max_prepared%';
> The server maintains caches for prepared statements and stored programs on a per-session basis. Statements cached for one session are not accessible to other sessions. When a session ends, the server discards any statements cached for it.
Кеш свой для каждого соединения с БД. Он очищается при отсоединении от нее.
Я как-то тестировал (советую тебе тоже сделать это), у меня получилось что выигрыш от подготовки запроса очень маленький.
Их используют в основном ради плейсхолдеров.
сам почитай. я прямо сейчас так и делаю.
> тут вопрос нумеро дос. Что происходит при вызове execute()? Интуитивно из названия функции мне казалось, что execute() тут же выполняет подготовленный запрос в БД
Да, в случае эмуляции PHP собирает и отправляет запрос на сервер, в случае реальных подготовленных запросов - PHP посылает только значения плейсхолдеров. Сервер начинает выполнять запрос и скорее всего возвращает какой-то идентификатор, по которому можно позже получать результаты.
Далее, возможны вариации. Сервер обычно старается вернуть данные как можно раньше, по мере выполнения запроса. Но с PHP не все так просто. Он может прочитать результат полностью, а может не дожидаться окончания и возвращать данные тоже по мере поступления. Это называется буферизация результата. Отсутствие буферизации ограничивает наши возможности: к примеру, мы не можем узнать общее число результатов и не можем вернуться к уже полученному ранее результату. Мы не можем запустить второй запрос, не дождавшись окончания первого. Но зато это позволяет обрабатывать огромные результаты, не занимая много памяти и не дожидаясь окончания запроса.
Библиотека mysqli умеет работать с небуферизованными данными ( http://php.net/manual/ru/mysqlinfo.concepts.buffering.php ). Умеет ли PDO?
Тут http://php.net/manual/ru/ref.pdo-mysql.php есть константа PDO::MYSQL_ATTR_USE_BUFFERED_QUERY. Я предлагаю тебе выяснить, работает ли она?
Выяснить, какой способ используется, можно так:
- сделать огромный запрос, который вернет миллионы записей. Прочитать их в цикле. Померять потребление памяти в середине процесса
- попробоваь сделать медленный запрос, который возвращает строки с задержкой, так:
SELECT 1
UNION ALL
SELECT SLEEP(3)
UNION ALL
SELECT 2
UNION ALL
...
ну ты понял идею, думаю. И померять точно, с какой задержкой возвращаются строки. Если запрос буферизованный, то задержка будет пока весь запрос не выполнится и потом все строки вернутся разом.
Попробуй потестировать, интересно, что получится.
> И здесь вопрос нумеро трес - что происходит при вызове функции fetch()? Как я понял, считывается одна строка из результирующей таблицы, ну и интерпретируется в соответствии с аргументами
При буферизации PHP прочитает весь ответ в память во время execute (я так думаю, надо проверять) и вернет ответ из памяти. При отсутствии буферизации fetch должна ждать прихода следующей строки результата от MySQL и сразу возвращать ее.
> данные всё таки в полном объеме берутся из БД, то где и как они хранятся после этого, когда удаляются?
В полном объеме в БД данные не хранятся так как это не позволяет возвращать много результатов. Как я понимаю, они шлются клиенту (в PHP), если он их не спешит забирать, то запрос приостанавливается, пока он их не примет: http://stackoverflow.com/questions/33573434/how-does-mysql-server-retrieve-and-send-data-to-clients/33573678#33573678
Сетевой протокол TCP имеет небольшой буфер и имеет обратную связь, то есть MySQL знает, сколько именно данных успешно передано в PHP, и знает, если он приостановил их прием.
Казалось бы, при такой схеме памяти много в MYSQL не израсходуется. Но не все так просто. Для некоторых запросов MySQL придется создавать буфера в памяти. Ну например, для сортировки не по индексу
мы должны выбрать все нужные данные в память mysql, отсортировать их там и только после этого можем передавать. также, огромные временные таблицы могут получаться при использовании JOIN без индексов + сортировка. Для временного хранения исплоьзуется либо буфер в памяти либо временный файл:
- http://dev.mysql.com/doc/refman/5.7/en/memory-use.html
- https://dev.mysql.com/doc/refman/5.7/en/internal-temporary-tables.html
> Most requests that perform a sort allocate a sort buffer and zero to two temporary files depending on the result set size. See Section B.5.3.5, “Where MySQL Stores Temporary Files”.
> All joins are executed in a single pass, and most joins can be done without even using a temporary table. Most temporary tables are memory-based hash tables. Temporary tables with a large row length (calculated as the sum of all column lengths) or that contain BLOB columns are stored on disk.
Обрати внимание, что в этих случаях PHP не причем и это особенности самого сервера MySQL. Потому важно уметь писать такие запросы, которые будут выполняться быстро.
Большинство ссылок на английском, но ты написал что читаешь w3schools, а на русском ты нигде эту ценную информацию не найдешь. Советую собраться с силами и почитать.
> тут вопрос нумеро дос. Что происходит при вызове execute()? Интуитивно из названия функции мне казалось, что execute() тут же выполняет подготовленный запрос в БД
Да, в случае эмуляции PHP собирает и отправляет запрос на сервер, в случае реальных подготовленных запросов - PHP посылает только значения плейсхолдеров. Сервер начинает выполнять запрос и скорее всего возвращает какой-то идентификатор, по которому можно позже получать результаты.
Далее, возможны вариации. Сервер обычно старается вернуть данные как можно раньше, по мере выполнения запроса. Но с PHP не все так просто. Он может прочитать результат полностью, а может не дожидаться окончания и возвращать данные тоже по мере поступления. Это называется буферизация результата. Отсутствие буферизации ограничивает наши возможности: к примеру, мы не можем узнать общее число результатов и не можем вернуться к уже полученному ранее результату. Мы не можем запустить второй запрос, не дождавшись окончания первого. Но зато это позволяет обрабатывать огромные результаты, не занимая много памяти и не дожидаясь окончания запроса.
Библиотека mysqli умеет работать с небуферизованными данными ( http://php.net/manual/ru/mysqlinfo.concepts.buffering.php ). Умеет ли PDO?
Тут http://php.net/manual/ru/ref.pdo-mysql.php есть константа PDO::MYSQL_ATTR_USE_BUFFERED_QUERY. Я предлагаю тебе выяснить, работает ли она?
Выяснить, какой способ используется, можно так:
- сделать огромный запрос, который вернет миллионы записей. Прочитать их в цикле. Померять потребление памяти в середине процесса
- попробоваь сделать медленный запрос, который возвращает строки с задержкой, так:
SELECT 1
UNION ALL
SELECT SLEEP(3)
UNION ALL
SELECT 2
UNION ALL
...
ну ты понял идею, думаю. И померять точно, с какой задержкой возвращаются строки. Если запрос буферизованный, то задержка будет пока весь запрос не выполнится и потом все строки вернутся разом.
Попробуй потестировать, интересно, что получится.
> И здесь вопрос нумеро трес - что происходит при вызове функции fetch()? Как я понял, считывается одна строка из результирующей таблицы, ну и интерпретируется в соответствии с аргументами
При буферизации PHP прочитает весь ответ в память во время execute (я так думаю, надо проверять) и вернет ответ из памяти. При отсутствии буферизации fetch должна ждать прихода следующей строки результата от MySQL и сразу возвращать ее.
> данные всё таки в полном объеме берутся из БД, то где и как они хранятся после этого, когда удаляются?
В полном объеме в БД данные не хранятся так как это не позволяет возвращать много результатов. Как я понимаю, они шлются клиенту (в PHP), если он их не спешит забирать, то запрос приостанавливается, пока он их не примет: http://stackoverflow.com/questions/33573434/how-does-mysql-server-retrieve-and-send-data-to-clients/33573678#33573678
Сетевой протокол TCP имеет небольшой буфер и имеет обратную связь, то есть MySQL знает, сколько именно данных успешно передано в PHP, и знает, если он приостановил их прием.
Казалось бы, при такой схеме памяти много в MYSQL не израсходуется. Но не все так просто. Для некоторых запросов MySQL придется создавать буфера в памяти. Ну например, для сортировки не по индексу
мы должны выбрать все нужные данные в память mysql, отсортировать их там и только после этого можем передавать. также, огромные временные таблицы могут получаться при использовании JOIN без индексов + сортировка. Для временного хранения исплоьзуется либо буфер в памяти либо временный файл:
- http://dev.mysql.com/doc/refman/5.7/en/memory-use.html
- https://dev.mysql.com/doc/refman/5.7/en/internal-temporary-tables.html
> Most requests that perform a sort allocate a sort buffer and zero to two temporary files depending on the result set size. See Section B.5.3.5, “Where MySQL Stores Temporary Files”.
> All joins are executed in a single pass, and most joins can be done without even using a temporary table. Most temporary tables are memory-based hash tables. Temporary tables with a large row length (calculated as the sum of all column lengths) or that contain BLOB columns are stored on disk.
Обрати внимание, что в этих случаях PHP не причем и это особенности самого сервера MySQL. Потому важно уметь писать такие запросы, которые будут выполняться быстро.
Большинство ссылок на английском, но ты написал что читаешь w3schools, а на русском ты нигде эту ценную информацию не найдешь. Советую собраться с силами и почитать.
на почте, но вот: " ^[\+]?[\ ]?(7|8)([-]?[ ]?[(]?[)]?){1,}[0-9]{10}$ почему пробел\скобка\- в номерах не ищутся между цифрами? Кучу вариантов перепробовал пиздос"
Потому, что [0-9]{10} значит "10 идущих подряд цифр". Минусы и скобки у тебя разрешены только между цифрой 7/8 и второй цифрой номера.
Я советую написать так:
- 10 раз повторить: "1 любая цифра, за ней любое число минусов/скобок в любом порядке"
Кстати, у тебя заложен порядок знаков (что минус идет до пробела и до скобок). Не советую так делать. Лучше написать "любое число знаков в любом порядке". Для этого надо использовать либо квадратные скобки, либо вертикальную черту.
Анон, я ща сдохну нахуй, почему вместо всей строчки вывод заканчивается на арозаупала а не полной фразе!?
$str обращается к байту строки под номером i. Юникод строка использует 2 байта для хранения символа. Поэтому выводится первые $length-1 байт сроки. Используй mb_substr например.
Чет пол сообщения пропало. Ну надеюсь ты понял куда копать.
Ой лол, спасибо анон, я дебил
$str[$i] возвращает i-й байт, а не букву. Урок: https://gist.github.com/codedokode/ff99e357e9860ea169b8
Зашел на фтп, слил себе папку сайт\паблик_хтмл на локалку.
сделал локальный домен, залил её туда.
Захожу значит на локальный домен - меня редиректит на основной сайт.
до index.php даже не доходит дело.
.htacess вообще удалял, всё равно редиректит.
Дошло до того, что я вырубил локальынй сервер и всё равно всё редиректит. Что это за пакость прописалась у меня?
http://ideone.com/ZULwK4
Во-первых, твоя функция makeFirstLetterUppercase ничего не возвращает. Она принимает строку, делает её копию, изменяет эту копию и всё.
Во-вторых цикл foreach работает с копиями элементов массива $matches. То есть ты в foreach'е изменяешь копию элемента, а не сам элемент массива, следовательно все твои изменения сохраняются в копиях и на исходный массив никак не влияют. Плохой способ решения проблемы - использовать ссылки - &, выше вбрасывали где почитать о них. Способ получше - добавлять новые апперкейсные значения в другой массив. В PHP есть удобная функция array_map, но тебе наверное будет проще циклом сделать. Если ты зачем-то хочешь менять именно исходный массив $matches, то тебе нужен цикл for и обращения по индексу.
Ты че, сука, думаешь тебе весь мир должен?
Просто в ахуе, таких родителей стерилизовать нужно. Нарожают бля трутней.
Длинный текст писал, потом подумал и решил не удалять, мало ли. В коротком тексте вроде короче и понятней
У меня некоторые проблемы с ООП и я решил попробовать реализовать получение данных через API, чтобы понять некоторые особенности этого самого ООП. Данные получаются по ссылке с непостоянным количеством параметров, которое указано в методе, и в xml.
Нужно:
1. Получить с помощью CURL файл
2. Получить объект SimpleXML и отдать его.
Это самое минимальное.
У меня есть:
Класс со всеми доступными вызовами в виде методов, ни от кого не наследуется.
Как я представляю работу:
1. Вызывается метод $api->accountData(); Это один из возможных вызовов в API.
2. Он должен взять BASE_URL(адрес api), которую я не знаю где объявить, присоединить к нему адрес конкретного метода, BASE_URL.'/account_info.xml', получить это по CURL и через SimpleXML вернуть объект с данными. Причем к ссылке должен быть постоянно подставлен id и password, которые я думаю передавать в конструктор при создании экземпляра объекта
Пока писал, продумал часть.
$api = new Api($login,$password);
Api ничего не наследует.
Такой вызов $api->get('accountData'); Возвращает просто готовую ссылку на xml, как сделать так, чтоб он возвращал объект? То есть обрабатывался тем же CURL и SimpleXML?
Знакомый так устроился 1ass ковырять. Но это не программирование.
Вот, вот оно! И почему дядьки стараются писать заумно? Оп-няшка, #спасибо_что_живой. Разжевано, понравилось, почитал еще твои статьи, кто-нибудь пробовал делать задание на браузерный проект (рассчитанный на 2-3 месяца): https://github.com/codedokode/pasta/blob/master/js/spa.md ?
у нас в новосибе есть noveo среди таких, но там надо хотя бы учебник из этого треда знать да, прям блядь так и спрашивают, прошел ли ты учебник из пхп треда на дваче нет
В общем примитивы самые учишь и дуешь к ним на стажировку.
if($www == true) {
echo $correctNumbers[$i];
echo "verno ";
почему перед Иф элемент массива показывает, а в иф уже нет? через foreach тоже
http://sandbox.onlinephpfunctions.com/code/fe037e0a55113cfd26d1699ec29f03295d2d27f9
Я так сделал
/8|(\+ *7)/
в идеале оно должно ловить начало либо с 8 либо с +, потом любое кол-во пробелов, потом 7рка?
Сейчас уже есть примерно такой регексп, не пойму только как сделать, что б любое колво пробелов черточек и дужек между цифрами не ловилось =(
^(8|(\+ *7))[0-9]{10}$
Тут почти правильно, только нет привязки к началу строки так что он будет искать цифру 8 или + не только в начале, но и в середине.
>>885852
[0-9]{10} значит 10 идущих подряд цифр
Напиши выражение "ровно 1 минус, скобка или пробел". Затем сделай из этого "любое число минусов/скобок/пробелов в любом порядке". затем сделай "1 цифра, за ней любое число минусов/скобок/пробелов" . затем добавь, что это должно повторяться ровно 10 раз.
>>885813
заходи через логин с паролем.
>>885801
Есть. В одном из банков должно получиться около 61270. Срок выплаты по моему там 13 месяцев.
Алгоритм у тебя верный, хотя заголовок цикла довольно громоздкий, может часть переменных стоит оттуда вынести.
В твоем коде число 5000 повторяется много раз. Что если мы захотим его поменять на другое? Надо вынести его в переменную, чтобы оно передавалось при вызове функции.
Такой тип комментариев не приносит никакой пользы нашему треду. Выражай свое разочарование где-нибудь в другом месте.
>>885777
Можешь дать пример кода на ideone или аналогичном сайте, чтобы видно было, в чем проблема? Я пока не очень понял, что не так.
>>885761
Смелых не нашлось. Перед этой задачей надо пройти задачник по JS и ОП поста, и дойдя до середины, аноны переполняются уверенностью в своих силах и пропадают из треда.
>>885713
Это мусорный комментарий не по теме.
>>885699
В общем, ты мыслишь в верном направлении. Для работы с АПИ действительно удобно сделать объект, методы которого соответствуют вызовам АПИ. Единственное, что имена методов принято начинать с глагола и вместо accountData логичнее писать getAccountData(...), но и странно, что у этого метода нет аргументов - надо же указать, чьи данные мы хотим получить.
По поводу конфигурации. Действительно, у АПИ может быть конфигурация - например, адрес сервера, на который надо отправлять запросы. Очевидно, без этой конфигурации АПИ скорее всего использовать невозможно. Раз так, ее можно передать через конструктор, например:
$apiClient = new TradingApiClient('http://www.api.dev/endpoint');
Если у АПИ есть необязательные настройки (например, использовать сжатие данных или задать таймаут для запроса) - их обычно либо меняют с помощью методов, либо передают как необязательный аргумент:
$apiClient->setTimeout(3);
$apiClient = new TradingApiClient('http://', ['timeout' => 3]);
Далее, у АПИ часто бывает авторизация. Как ее реализовать? Тут есть 2 варианта.
- если без авторизации в принципе нельзя пользоваться АПИ, то можно передавать ее в конструктор
- если часть методов доступна без авторизации, а также есть желание перелогиниваться и разлогиниваться, то можно добавить методы для этого
Ошибки в АПИ (при передаче данных итд) обычно принято показывать с помощью исключений. Разные классы исключений соотвествуют разным видам ошибок.
Ну и еще. В простом варианте конечно можно вписать работу с курлом прямо в класс АПИ, но это в общем плохая идея. Например, как задать дополнительные опции курла, если вся работа с курлом спрятана внутри класса? Очевидно, что здесь имеет смысл разделить код на 2 класса:
- низкоуровневый HTTP клиент
- высокоуровневый API клиент, использующий объект HTTP клиента
(когда ты начнешь писать HTTP клиент, классы запросов и ответов, тебе может придти в голову мысль что наверно такие клиенты уже написаны. И действительно, поиск выдаст тебе множество библиотек, например, Guzzle)
Это позволяет нам делать интересные вещи. Ну например мы можем сделать логгирование запросов, кеширование ответов, подмену ответов для тестирования не меняя код классов. То есть это дает нам большую гибкость.
Насчет SimpleXML - я бы не советовал особо обольщаться названием simple, у него куча неудобных моментов, наверно удобнее с XML работать через DOM, хотя это твое дело.
Такой тип комментариев не приносит никакой пользы нашему треду. Выражай свое разочарование где-нибудь в другом месте.
>>885777
Можешь дать пример кода на ideone или аналогичном сайте, чтобы видно было, в чем проблема? Я пока не очень понял, что не так.
>>885761
Смелых не нашлось. Перед этой задачей надо пройти задачник по JS и ОП поста, и дойдя до середины, аноны переполняются уверенностью в своих силах и пропадают из треда.
>>885713
Это мусорный комментарий не по теме.
>>885699
В общем, ты мыслишь в верном направлении. Для работы с АПИ действительно удобно сделать объект, методы которого соответствуют вызовам АПИ. Единственное, что имена методов принято начинать с глагола и вместо accountData логичнее писать getAccountData(...), но и странно, что у этого метода нет аргументов - надо же указать, чьи данные мы хотим получить.
По поводу конфигурации. Действительно, у АПИ может быть конфигурация - например, адрес сервера, на который надо отправлять запросы. Очевидно, без этой конфигурации АПИ скорее всего использовать невозможно. Раз так, ее можно передать через конструктор, например:
$apiClient = new TradingApiClient('http://www.api.dev/endpoint');
Если у АПИ есть необязательные настройки (например, использовать сжатие данных или задать таймаут для запроса) - их обычно либо меняют с помощью методов, либо передают как необязательный аргумент:
$apiClient->setTimeout(3);
$apiClient = new TradingApiClient('http://', ['timeout' => 3]);
Далее, у АПИ часто бывает авторизация. Как ее реализовать? Тут есть 2 варианта.
- если без авторизации в принципе нельзя пользоваться АПИ, то можно передавать ее в конструктор
- если часть методов доступна без авторизации, а также есть желание перелогиниваться и разлогиниваться, то можно добавить методы для этого
Ошибки в АПИ (при передаче данных итд) обычно принято показывать с помощью исключений. Разные классы исключений соотвествуют разным видам ошибок.
Ну и еще. В простом варианте конечно можно вписать работу с курлом прямо в класс АПИ, но это в общем плохая идея. Например, как задать дополнительные опции курла, если вся работа с курлом спрятана внутри класса? Очевидно, что здесь имеет смысл разделить код на 2 класса:
- низкоуровневый HTTP клиент
- высокоуровневый API клиент, использующий объект HTTP клиента
(когда ты начнешь писать HTTP клиент, классы запросов и ответов, тебе может придти в голову мысль что наверно такие клиенты уже написаны. И действительно, поиск выдаст тебе множество библиотек, например, Guzzle)
Это позволяет нам делать интересные вещи. Ну например мы можем сделать логгирование запросов, кеширование ответов, подмену ответов для тестирования не меняя код классов. То есть это дает нам большую гибкость.
Насчет SimpleXML - я бы не советовал особо обольщаться названием simple, у него куча неудобных моментов, наверно удобнее с XML работать через DOM, хотя это твое дело.
Открой инструменты разработчика (Ctrl + Shift + I) на вкладке Network. Ввведи в адресную строку УРЛ локального сайта и нажми Enter. Посмотри что появится в инструментах разработчика.
>>885690
На хабре врод было что-то https://www.google.ru/search?q=habr+php+анонимные+функции&newwindow=1&gbv=1&sei=N39AWMbjHILN6QSfoqLYCQ
Анонимные функции удобно использовать, когда надо передать какое-то условие, записанное в виде кода. Ну например вместе с array_map, array_filter, preg_replace_callback.
У тебя шапка цикла получилась громоздкой и из-за этого более тяжело читаемой. Лучше часть кода все же вынести в тело цикла.
>>885908
Если это переменная в шаблоне layout, то подозреваю, что в ней отрендеренный в HTML строку шаблон серединки страницы. Ты код самого Юи смотреть не пробовал и поискать там по этому слову?
>>885497
Есть. Например:
- Школа Анализа Данных Яндекса
- Java школа Дойче Банка
Подробнее https://habrahabr.ru/company/tceh/blog/250333/
Вот например про Дойче Банк (это было в 2013 году, может сейчас поменялось): https://habrahabr.ru/company/changellenge/blog/196664/
> Во время обучения каждый студент получает заработную плату в размере 100 тысяч рублей. Лучшие ученики по окончании Школы приглашаются на работу в Центр Разработки Дойче Банка.
Некоторые из этих курсов даже платят стипендию (которая иногда больше чем средняя зарплата в провинциальном российском городке), но там обычно есть входные экзамены. То есть они рассчитаны на талантливых и трудолюбивых. Сами задания или примеры часто доступны на их офиц. сайтах, так что можешь зайти и оценить свои силы.
При желании на Хабре можно найти отзывы тех, кто например, в ШАД учился.
Ты очень плохой человек. И злой
Вот это регекс!
>>885970
Спасибо тебе за такой полный ответ. SimpleXML был выбран просто как пример. Имя Api знаю что не сильно хороший выбор, но пока это не имеет значения.
Я понял твои мысли насчет разделения и думаю действительно так и сделать, я просто не понимаю как мне использовать другие классы в моем. Мне просто создать где-нибудь вне методов объект того-же HTTP клиента и DOM? Или наследовать? Если наследовать то что? Мне нужен и HTTP и DOM одновременно. Вернее последовательно, сначала первое, потом второе.
Есть файл, в котором csv-данные. Есть задача - перенести данные в MySQL-БД. Запихиваю данные через подготовленные запросы с параметрами (пробовал как именованные, так и анонимные) посредством PDO. Всё бы хорошо, но один из столбцов в csv-файле - дата в формате "дд.мм.гггг", и эта сука постоянно делает дату 0000:00:00 (вот что то меня немного напрягает, что формат другой - не ДД.ММ.ГГГГ, как в csv-файле, а ГГГГ,ДД,ММ или ГГГГ.ММ.ДД). Так вот, вопрос - как запихать в MySQL строковое представление даты в столбец с типом Date?
php.net не читай, функцию применяй
yii, laravel, symfony, 1с битрикс
Каким образом формируются веб-странички для каждого из элементов списка?
Например интернет-магазин. Есть список товаров, для каждого товара отдельная страничка формируется. Но я так понимаю на сервере для каждого элемента не создается файл "id12344567.php", а как-то динамически туда данные идут. В какую сторону копать?
Это и есть так сказать эссенция веб-разработки, и то чем мы тут занимаемся.
Есть сервер, на котором верится скрипт, в нашем случае это пхп.
И например там есть "страничка", которая называется show_item.php в которой будет лежать скрипт, ответственный за то, что ты сказал.
Например так же у тебя есть база, в которой лежат товары, у них есть id, name, price например
Когда пользователь бегает по каталогу, ему опять же скрипт, формирует хитрые ссылки, по которым можно пройти на каждый товар.
ссылка будет вида shop.sru/show_item.php?id=123
Чувак кликает по этой ссылке, скрипт который сидит в show_item.php видит что прилетел get запрос: https://ru.wikipedia.org/wiki/HTTP#GET
(бывают и другие способы спросить что-то у сервера)
И он значит понимает (потому что программист так запрограммировал заранее), что нужно из базы спросить инфу о товаре с таким id
он отправляет в базу запрос что-то вида ВЫБРАТЬ ИЗ таблица_товаров, ГДЕ id = 123.
Прилетает ответ от базы с информацией о товаре с нужным id которая лежит в полях name и price (полей может туча)
далее скриптик берет заранее заготовленную html-ку (шаблон) и подставляет в нужные места всю информацию в этот шаблон.
Так же и в каких-нибудь социальных сетях отрисовывается всё. Тупо нужен 1 шаблон, 1 скрипт, и куча инфы в базе, и ты можешь посмотреть совершенно разные странички разных людей.
В теории всё будет примерно так. Даже на дваче всё на этом же принципе. Посты хранятся в базе. Спрашиваешь у базы все посты такого-то треда. Он собирает их в кучу и отрисовывает тебе по порядку циклом.
Да, база есть, но я именно на могу понять как формируются отдельные странички для каждого элемента. Я могу тупо выгрузить, скажем, в индекс, табличку с базы, можно там с определенными параметрами.
Могу также допустим к тексту позиции присобачить уникальный урл(ну можно по тому же айдишнику)
Но как сделать так, чтобы кликая на этот урл я переходил бы на страничку, где отображалась конкретная информация по определенной записи?
Какой модуль копать? Или может есть какие примеры? Как ни гуглю, а найти не могу.
Или вот пример. Могу сделать блог, с добавлением записей. Но как сделать так, чтобы каждая запись была доступна отдельно? То есть получается на ходу формируется страничка, а там уже выгрузка по определённым параметрам?
А, прости, не развернулся полностью пост. Значит скрипт и шаблон. Будем копать
Конкретные пункты:
1) Можно ли написать класс, с помощью которого, передавая различные аргументы - опции подключения через __construct() мы будем создавать и возвращать PDO-подключения с нужными параметрами, а также закрывать их когда хотим (как раньше $mysqli->close())? Или это черезчур?
2) Если: $a = new PDO(); $b = $a; $a = null; , экземпляр подключения сохраняется, так как есть на него ссылка $b. Как реально убить подключение (ведь, возможно, у нас десятки таких ссылок разбросаны по программе).
3) Не париться, ибо все подключения завершаются по окончании скрипта (все ли?), а вручную закрывать вредно в принципе. Есть ли какие подводные камни?
>>886353
ты можешь хоть самим скриптом генерировать html после того как собрал все нужные тебе данные, тупо через примерно такой вот способ:
echo '<html>';
echo '<head>';
...
и потом подставляя переменные где нужно прям в это всё
echo '<p>наименование товара: ' . $name . ' </p>;
...
echo '</body>;
echo '</html>;
//конец скрипта
?>
Но это самый примитивный способ, что бы ты просто понял как это работает.
продуктивнее и проще это инклудить по факту html-файл, но с расширением .php
и где ты в нужных местах выводишь нужные тебе данные через такие вот теги:
//отдельный_документ-шаблон.php
<html>
.....
.....
<p>Наименование товара: <?=$item_name?></p>
...
если бы у тебя в родительском классе было бы больше полей/свойств, да ещё и часть из них были бы private, то тогда тебе было бы более выгодно/пришлось бы вызывать родительский конструктор, которому ты бы передал соответствующие параметры из конструктора класса-наследника.
Спасибо, тебе вспомнилось
> Можно ли написать класс, с помощью которого, передавая различные аргументы - опции подключения через __construct() мы будем создавать и возвращать PDO-подключения с нужными параметрами,
Этот класс уже написан, он называется PDO. Ему в конструктор как раз передаются параметры соединения. Зачем писать еще один?
> Если: $a = new PDO(); $b = $a; $a = null; , экземпляр подключения сохраняется, так как есть на него ссылка $b. Как реально убить подключение (ведь, возможно, у нас десятки таких ссылок разбросаны по программе).
Обычно это не делают, так как при завершении php скрипта переменные будут уничтожены. Если тебе по каким-то причинам надо сделать явное отсоединение, придется делать (или найти) класс-обертку, который будет внутри держать экземпляр PDO и сможет его уничтожить. Но я не думаю, что это так уж нужно.
Вообще, наличие метода вроде close - как раз не очень хорошо. Представь, один класс закрыл соединение, а другие классы не знают об этом и думают что их экземпляр PDO все еще работоспособный. Нелогично.
Бывают случаи, когда приложение обрабатывает не один запрос, а много, в цикле, не умирая. Ну например приложения на Яве или на ReactPHP так работают. В таких случаях надо подсоединяться/отсоединяться от БД. Обычно для этого реализуют так называемый "пул". Пул позволяет как создавать каждый раз новое соединение, так и вместо закрытия возвращать соединение в пул и использовать позже.
Вот пример (англ) пула соединений на Яве:
http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#How_to_use
(JDBC это Ява-библиотека для взаимодействия с разными БД, напоминающая PDO)
(кстати ниже, под заголовком "And here is an example on how to configure a resource for JNDI lookups" ты можешь увидеть пример XML-конфигурации для DI контейнера в Яве).
Вот ключевое место кода на Яве:
// создаем объект настроек пула
PoolProperties p = new PoolProperties();
....
// создаем пул и задаем его настройки
DataSource datasource = new DataSource();
datasource.setPoolProperties(p);
try {
// получаем из пула новое или, может быть, старое соединение (аналог PDO)
con = datasource.getConnection();
// создаем объект запроса (аналог PDOStatement)
Statement st = con.createStatement();
// выполняем запрос
ResultSet rs = st.executeQuery("select * from user");
...
// освобождаем результат и запрос
rs.close();
st.close();
} finally {
// в любом случае (даже при выбросе исключения) закрываем соединение
if (con!=null) {con.close();}
}
Здесь con.close() либо закроет соединение, если оно одноразовое, либо вернет его в пул, если он настроен на переиспользование соединений. Переиспользование соединений используют, чтобы сэконмить время на установку. Насколько я знаю, на MySQL она и так довольно быстрая, хотя возможно, когда идет счет на миллисекунды, это имеет значение.
В некоторых языках, вроде C#, можно обойтись без ручного написания этих close(), там есть конструкция using ( https://msdn.microsoft.com/ru-ru/library/yh598w02.aspx ), которая говорит что объект нужно "очистить" при выходе из блока:
using (con = datasource.GetConnection()) {
using (st = con.createStatement()) {
...
}
}
Это упрощает код и защищает от ошибок, когда что-то забыли закрыть.
В PHP для этого вместо пулов можно использовать persistent connections. Надо помнить, что хотя ты экономишь время на установку соединения, у этого подхода есть недостатки. Что если один процесс PHP оставит соединение в каким-то измененном состоянии, например оставит незакрытую транзакцию или поменяет какую-то переменную MySQL? Может быть баг. В Яве это чуть упрощается за счет того, что там ведется учет открытых/закрытых транзакций.
> ведь, возможно, у нас десятки таких ссылок разбросаны по программе
Возможно, не стоит их разбрасывать тогда по программе, если тебе нужно только временно подсоединится и отсоединиться.
> Не париться, ибо все подключения завершаются по окончании скрипта (все ли?), а вручную закрывать вредно в принципе. Есть ли какие подводные камни?
Никаких, так и делают. Просто это не работает, если ты обрабатываешь не один, а много запросов в цикле. Тогда тебе понадобятся пулы и явное закрытие соединения. Тут конечно в PDO отсутствие close не очень удобно и возможно стоит использовать что-то на основе mysqli.
> Можно ли написать класс, с помощью которого, передавая различные аргументы - опции подключения через __construct() мы будем создавать и возвращать PDO-подключения с нужными параметрами,
Этот класс уже написан, он называется PDO. Ему в конструктор как раз передаются параметры соединения. Зачем писать еще один?
> Если: $a = new PDO(); $b = $a; $a = null; , экземпляр подключения сохраняется, так как есть на него ссылка $b. Как реально убить подключение (ведь, возможно, у нас десятки таких ссылок разбросаны по программе).
Обычно это не делают, так как при завершении php скрипта переменные будут уничтожены. Если тебе по каким-то причинам надо сделать явное отсоединение, придется делать (или найти) класс-обертку, который будет внутри держать экземпляр PDO и сможет его уничтожить. Но я не думаю, что это так уж нужно.
Вообще, наличие метода вроде close - как раз не очень хорошо. Представь, один класс закрыл соединение, а другие классы не знают об этом и думают что их экземпляр PDO все еще работоспособный. Нелогично.
Бывают случаи, когда приложение обрабатывает не один запрос, а много, в цикле, не умирая. Ну например приложения на Яве или на ReactPHP так работают. В таких случаях надо подсоединяться/отсоединяться от БД. Обычно для этого реализуют так называемый "пул". Пул позволяет как создавать каждый раз новое соединение, так и вместо закрытия возвращать соединение в пул и использовать позже.
Вот пример (англ) пула соединений на Яве:
http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#How_to_use
(JDBC это Ява-библиотека для взаимодействия с разными БД, напоминающая PDO)
(кстати ниже, под заголовком "And here is an example on how to configure a resource for JNDI lookups" ты можешь увидеть пример XML-конфигурации для DI контейнера в Яве).
Вот ключевое место кода на Яве:
// создаем объект настроек пула
PoolProperties p = new PoolProperties();
....
// создаем пул и задаем его настройки
DataSource datasource = new DataSource();
datasource.setPoolProperties(p);
try {
// получаем из пула новое или, может быть, старое соединение (аналог PDO)
con = datasource.getConnection();
// создаем объект запроса (аналог PDOStatement)
Statement st = con.createStatement();
// выполняем запрос
ResultSet rs = st.executeQuery("select * from user");
...
// освобождаем результат и запрос
rs.close();
st.close();
} finally {
// в любом случае (даже при выбросе исключения) закрываем соединение
if (con!=null) {con.close();}
}
Здесь con.close() либо закроет соединение, если оно одноразовое, либо вернет его в пул, если он настроен на переиспользование соединений. Переиспользование соединений используют, чтобы сэконмить время на установку. Насколько я знаю, на MySQL она и так довольно быстрая, хотя возможно, когда идет счет на миллисекунды, это имеет значение.
В некоторых языках, вроде C#, можно обойтись без ручного написания этих close(), там есть конструкция using ( https://msdn.microsoft.com/ru-ru/library/yh598w02.aspx ), которая говорит что объект нужно "очистить" при выходе из блока:
using (con = datasource.GetConnection()) {
using (st = con.createStatement()) {
...
}
}
Это упрощает код и защищает от ошибок, когда что-то забыли закрыть.
В PHP для этого вместо пулов можно использовать persistent connections. Надо помнить, что хотя ты экономишь время на установку соединения, у этого подхода есть недостатки. Что если один процесс PHP оставит соединение в каким-то измененном состоянии, например оставит незакрытую транзакцию или поменяет какую-то переменную MySQL? Может быть баг. В Яве это чуть упрощается за счет того, что там ведется учет открытых/закрытых транзакций.
> ведь, возможно, у нас десятки таких ссылок разбросаны по программе
Возможно, не стоит их разбрасывать тогда по программе, если тебе нужно только временно подсоединится и отсоединиться.
> Не париться, ибо все подключения завершаются по окончании скрипта (все ли?), а вручную закрывать вредно в принципе. Есть ли какие подводные камни?
Никаких, так и делают. Просто это не работает, если ты обрабатываешь не один, а много запросов в цикле. Тогда тебе понадобятся пулы и явное закрытие соединения. Тут конечно в PDO отсутствие close не очень удобно и возможно стоит использовать что-то на основе mysqli.
Конструктор подготавливает объект к работе, инициализирует его свойства. Если ты наследуешь класс, логично что стоит в начале вызвать конструктор родителя, чтобы тот инициализировал свои свойства, а потом уже инициализировать свойства наследника.
Если ты определил в наследнике конструктор, то автоматически конструктор предка не вызывается.
>>886353
- пользователь набирает в браузере УРЛ http://example.com/product/123
- браузер отправляет на HTTP сервер HTTP-запрос
- сервер запускает PHP скрипт
- скрипт смотрит на УРЛ и видит что надо показать страницу товара № 123
- он берет из БД свойства этого товара
- он берет HTML шаблон страницы и подставляет туда свойства товара
- отдает ответ в браузер
> Да, база есть, но я именно на могу понять как формируются отдельные странички для каждого элемента.
Ты думаешь, что URL всегда указывает на файл на сервере. Это так только для статических сайтов. В динамических сайтах обработка URL может настраиваться произвольно. Например, все URL, для которых нет соответствующего файла, передаются на обработку в index.php
Прочти например это: https://github.com/codedokode/pasta/blob/master/soft/web-server.md
> можно через наследника спокойно задать все необходимые свойства
- это будет бессмысленная копипаста. А что если логика в конструкторе класса-предка изменится, ты будешь заодно и во всех наследниках код переписывать?
- класс-предок может быть частью сторонней библиотеки и поменять его нельзя
- свойства могут быть приватные и недоступны из наследника
>>886183
Ты читал урок по DI? Прочитай: https://github.com/codedokode/pasta/blob/master/arch/di.md
"HTTP клиент" - это зависимость для класса Api и урок как раз разбирает, как их связать.
Наследование используют только тогда когда можно сказать "A является разновидностью B". ApiClient это не разновидность HTTP клиента или DOM и наследование тут применять нельзя.
Где htmlspecialchars? Вот люди по таким примерам учатся, а потом оставляют XSS.
>>886196
С таким количество параметров удобнее использовать плейсхолдеры с двоеточием и передавать массив в execute.
>>886183
Объект DOM, я думаю, тут не зависимость, так как он просто создается заново на каждый документ через new.
>>886054
> {1,}
Это то же самое, что и плюс
> ((-| )?[()]?){1,}
переусложнено. Ты можешь написать "ровно один пробел, минус или скобка"? Есть вертикальная черта или квадратные скобки для этого.
Вместо повторения выражения 10 раз надо использовать {10}.
> Я из скриншота вижу, что правило в файле uploader-master.css перекрывает правила в бутстрапе. Приоритет у них равный, скорее просто причина в том что тот файле позже подключен.
Я понял. В скачаном плагине был такой же селектор, как и в бутстрапе
Конечно возможно, для этого функция должна возвращать функцию. Можно даже строить цепочки произвольной длины.
У Кантора, например, об этом написано.
>>886734
Посмотри, на что спрос у тебя в городе или сделай на каждом из фреймворков тех же студентов и выбери, что больше понравится.
>>885926
Ещё есть на архиваче: https://arhivach.org/thread/213097/
>Посмотри, на что спрос у тебя в городе
ни на что, я в мухосрани живу. Планирую перекатываться в столицы.
Хочу чтобы анон сказал с аргументами а я подчинился пусть и субъективное мнение
^[ ]?(8|(\+ 7))(([-]|[(]|[)]|[ ])[0-9]([-]|[(]|[)]|[ ])*){10}$
Я даун или маладца?
хотел скачать дистрибутив себе для винды что бы научиться в халоворлд, а хуй там плавал, архивы в формате tgz, ладно няши из 7zip предусмотрели это и с их помощью можно открыть архив, но хуй там плавал и внутри был лишь TAR файл. Хотя и его вроде как можно открыть. Но блин, что это за флагман такой, который не может иметь дистрибутив под винду :(
gz - это сжатие, но gzip умеет сжимать только один файл
tar - это формат для сборки нескольких файлов в один (с сохранением имен и других метаданных), но без сжатия
Вместе получается возможность сжимать несколько файлов в один архив.
Форматы довольно старые, им лет 20, если не больше.
И кстати, зачем делать дистрибутив под винду, если
- PHP в принципе кроссплатформенный и не нужна отдельная версия под винду
- на сервере обычно стоит Линукс
http://lurkmore.to/Копипаста:Программирование#.D0.92.D1.8B.D1.81.D1.88.D0.B5.D0.B5_.D0.BE.D0.B1.D1.80.D0.B0.D0.B7.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_.D0.B2_IT_.D1.81.D0.B2.D0.BE.D0.B8.D0.BC.D0.B8_.D1.80.D1.83.D0.BA.D0.B0.D0.BC.D0.B8_v2
>PHP Notice: Undefined variable: totalPayed2 in /home/SWobaS/prog.php on line 28
>PHP Notice: Undefined variable: totalPayed3 in /home/SWobaS/prog.php on line 28
неопределенные переменные в строке 28, так так что же там у нас???
>$totalPayed1=credit($balance, $monthly, $percents[0], $comission[0]);
>//$totalPayed2=credit($balance, $monthly, $percents[1], $comission[1]);
>//$totalPayed3=credit($balance, $monthly, $percents[2], $comission[2]);
>echo "first: $totalPayed1 second: $totalPayed2 third: $totalPayed3 \n";
Ну всё очевидно блядь, эти переменные неопределятся потому, что должны быть определены в тех строчках которые закоменченны, элементрано.
Я уже разобрался, это я сейчас редактирую код просто вот и закомментил эти строки. Все равно спасибо.
Если что задача про айпад из раздела "Функции".
Вопрос : смогу ли я через месяц обучения написать движок для имиджбода?
Сможешь, но будешь долго ковыряться и учиться в процессе написания. И это не плохо, так как практика. Только через полгода-год тебе будет стыдно за этот код.
Чет почитал и расстроился посоны.
А чего расстроился? Вообще похуй что там пишут.
знать как пользоваться гуглом
вот про неймспейсы хорошо, например, почти как у опа. https://habrahabr.ru/post/212773/
Вдруг кому поможет.
http://pastebin.com/mJd4vdxz
Чего расстроился-то? Мы быдлокодеры, гордись этим!
Какая-то критика на самом деле странная. Ну вот например
>Основные функции встроены прямо в интерпретатор вместе со всей поебенью, которая может «понадобиться впердь». Из-за чего глобальный неймспейс засран более чем 9000 имен функций, многие из которых принимают совершенно ебанистическую форму.
Ну и что? По моему это плюс. К тому-же у Objective-C, Swift, и С++ тоже самое, но никто не жалуется. Я уже не говорю про JAVA, где вообще можно всю программу написать вызовом стандартных функций.
>Отсутствует проверка на уровне интерпретатора типов для значений параметров, передаваемых в функции. Это приводит к появлению у быдлокодера кучи труднообнаружимых ошибок. Например, при сравнении лучше везде использовать ===. Иначе можно подхватить лулз типа такого:
>var_dump($php == "хуита");
Написал говнокод.
@
Это PHP виновато что он работает не так, как я хочу.
>Переменные по умолчанию могут быть не объявлены;
Вообще не проблема.
>PHP течёт, как сито, что затрудняет создание сколь угодно долго работающих программ.
Потому-что PHP не предназначен для написания программ. Есть C++ и C#, нет мы хотим страдать.
>Отсутствует такая кошерная вещь, как CPAN в perl, которая позволяет огромному числу разработчиков по всему миру писать новые либы в составе комьюнити. Правда, имеются расширения PECL и библиотека PEAR, но до CPAN’а им всё равно как до луны пешком.
Вообще бред чистой воды. PHP стал популярен только потому, что может в расширения, и под него написано 100500 расширений. А CPAN удобен только если им долго учиться пользоваться.
>Всё-таки отсутствует многопоточность — потоков как таковых нет
Чтобы многопоточно отдавать данные из БД одному юзеру? Что?
>Большие проблемы с реализацией utf-8.
Одна единственная проблема, в том, что он по дефолту не UTF-8 и надо явно указывать кодировки. 1 строка кода это недостаток?
http://ideone.com/rW81Hw
Вообще, там много устаревшей информации, видимо написано это лет 10 назад. Думаю, что аноны, знающие PHP, сразу видят несоответствия.
> Отсутствует проверка на уровне интерпретатора типов для значений параметров, передаваемых в функции. Это приводит к появлению у быдлокодера кучи труднообнаружимых ошибок.
Это возможно было верно во времена PHP4. В PHP5 появились тайп-хинты для классов и массивов, а в PHP7 и для обычных типов вроде строк. Да, они не совершенные, и например, для массива пока нельзя указать тип содержимого, но это лучше, чем ничего.
В то время как в популярных языках Питон, Руби, Лисп, Яваскрипт вообще их нету. Но про них почему-то такую критику не пишут. Свое бревно не видят.
> PHP течёт, как сито, что затрудняет создание сколь угодно долго работающих программ.
Это было акутально до появления сборщика мусора в 5.3.
> Отсутствует такая кошерная вещь, как CPAN в perl, которая позволяет огромному числу разработчиков по всему миру писать новые либы в составе комьюнити. Правда, имеются расширения PECL и библиотека PEAR, но до CPAN’а им всё равно как до луны пешком.
Опять же информация устарела. Есть PECL, (старый) PEAR и новый composer. С этим как раз все в порядке.
> Большие проблемы с реализацией utf-8.
Это скорее идеология, что в PHP нет кодировки по умолчанию и разработчик должен сам везде указывать, как интерпретировать строку.
А вообще, вот набор претензий для троллинга других языков: https://habrahabr.ru/post/315152/
>Вообще, там много устаревшей информации, видимо написано это лет 10 назад. Думаю, что аноны, знающие PHP, сразу видят несоответствия.
Двачую.
http://ideone.com/Mc3n1q
есть код jQuery, который через ajax обращается к PHP скрипту с некоторыми параметрами посредством гет-запроса (https://jsfiddle.net/x9no97vd/1/).
Дак вот, что мне нужно сделать так, чтобы при определенном условии в ходе работы php скрипта я отсылал ошибку ajax'овой функции, причем вызывалась бы именно функция - параметр "error:" ajax-овой функции. Как это сделать? Пока что я знаю только о следующем способе обмена информацией между сервером и клиентом посредством связи PHP-AJAX: на PHP при вызове некоторо скрипта ajax'ом весь вывод от "echo 'somehtml';" попадает в параметр result у AJAX'а.
Тебе это не надо. error() говорит об ошибке на транспортном уровне (уровне передачи данных между браузером и сервером), ошибки приложения надо возвращать другим способом.
Удобно возвращать в JSON-ответе либо поле success = true если все ок (а в поле html - HTML-код), либо такой ответ при ошибке:
{
"success": false,
"error": "....."
}
Но в твоем случае, как я понимаю, там даже не ошибка, а признак, что данных больше нет. Раз так, надо возвращать с ответом флаг "haveMore": true/false. Узнать, есть ли еще данные, просто: надо просто выбирать из БД на 1 запись больше, чем просят.
У тебя вроде нет блокировок. Что, если пользователь прокруткой отправит несколько параллельных запросов, и данные придут в другом порядке? Надо блокировать отправку запросов на время загрузки.
Также, "вечная" прокрутка это в общем плохой UI паттерн с недостатками, зря ты его используешь, как мне кажется.
Также, совет по коду: не пиши длинные простыни и не вкладывай функции в функции по много раз. Разбивай код на отдельные функции.
> $("#tableDIV").find("table").find("tbody").find("tr:last-child")
Это можно написать одним выражением. table и tbody не нужно указывать.
> '../phps/database stuff/GetTablePage.php?page='+ CurrentPage++ + "&FetchType=2"
Не стоит совмещать в одной строке увеличение переменной и сборку URL. Также вместо ручной сборки лучше параметры передавать в свойстве data функции $.ajax
> FetchType=2
Магические числа
> if (data!="")
А что если равно пустой строке? Это никак не обрабатывается.
> if (errorThrown=="ALL_DATA_LOADED")
Это еще что? errorThrown это же вроде объект исключения
Кстати, у нас есть задачки по JS и JQuery в ОП посте.
Тебе это не надо. error() говорит об ошибке на транспортном уровне (уровне передачи данных между браузером и сервером), ошибки приложения надо возвращать другим способом.
Удобно возвращать в JSON-ответе либо поле success = true если все ок (а в поле html - HTML-код), либо такой ответ при ошибке:
{
"success": false,
"error": "....."
}
Но в твоем случае, как я понимаю, там даже не ошибка, а признак, что данных больше нет. Раз так, надо возвращать с ответом флаг "haveMore": true/false. Узнать, есть ли еще данные, просто: надо просто выбирать из БД на 1 запись больше, чем просят.
У тебя вроде нет блокировок. Что, если пользователь прокруткой отправит несколько параллельных запросов, и данные придут в другом порядке? Надо блокировать отправку запросов на время загрузки.
Также, "вечная" прокрутка это в общем плохой UI паттерн с недостатками, зря ты его используешь, как мне кажется.
Также, совет по коду: не пиши длинные простыни и не вкладывай функции в функции по много раз. Разбивай код на отдельные функции.
> $("#tableDIV").find("table").find("tbody").find("tr:last-child")
Это можно написать одним выражением. table и tbody не нужно указывать.
> '../phps/database stuff/GetTablePage.php?page='+ CurrentPage++ + "&FetchType=2"
Не стоит совмещать в одной строке увеличение переменной и сборку URL. Также вместо ручной сборки лучше параметры передавать в свойстве data функции $.ajax
> FetchType=2
Магические числа
> if (data!="")
А что если равно пустой строке? Это никак не обрабатывается.
> if (errorThrown=="ALL_DATA_LOADED")
Это еще что? errorThrown это же вроде объект исключения
Кстати, у нас есть задачки по JS и JQuery в ОП посте.
Спасибо за совет по поводу JSON, сейчас пока ждал ответа тоже наткнулся на него в похожих вопросах на SO.
>У тебя вроде нет блокировок. Что, если пользователь прокруткой отправит несколько параллельных запросов, и данные придут в другом порядке? Надо блокировать отправку запросов на время загрузки.
Блокировку ajax'а достаточно реализовать переменной-флагом, который переключаю в false в ajax'овском параметре-функции beforesent и в true в параметре-функции complete?
>также, "вечная" прокрутка это в общем плохой UI паттерн с недостатками, зря ты его используешь, как мне кажется.
Та це не мой каприз, так поставлена задача в лабораторной. Я думал, что было бы неплохо реализовать выгрузку лишних первых 100 строк данных из html при прокрутке вниз на 500-600 строк, ну и соответственно их обратную подгрузку при скроллинге вверх а потом посмотрел на аналогичную систему в вконтактике и подумал, что для лабораторной и так сойдёт. Будет ли такой вариант сильно плох, если в таблице не предусмотрена возможность редактирования, то есть не нужно хранить состояние измененных строк при их выгрузке?
>Это можно написать одним выражением. table и tbody не нужно указывать.
разве не лучше сужать пространство для работы each()? Она же вроде как собирает ссылки на все соответствующие html-элементы, следовательно, ей надо пробежать по всему document'у для этого, типа лишние задачи вседела тыры-пыры.
>Не стоит совмещать в одной строке увеличение переменной и сборку URL. Также вместо ручной сборки лучше параметры передавать в свойстве data функции $.ajax
це я знаю, просто только изучаю ajax, ну и реализовал все способы его использования, которые смог найти $("element").load(), $.get(),$.ajax() у jQuery, XMLHttpRequest с чистого js c различными параметрами.
>Магические числа
Вот тут не понял, типа плохой тон передавать неименованными константами какую либо информацию?
> Я думал, что было бы неплохо реализовать выгрузку лишних первых 100 строк данных из html при прокрутке вниз на 500-600 строк
Взаимодействие с DOM не бесплатное, неизвестно, как это повлияет на производительность, это надо мерять и тестировать. Ну и смотреть надо, чтобы ничего не съехало.
Вообще, на мой взгляд бесконечная прокрутка это неудобно. Типичный пример - твиттер - кликнешь, уйдешь на другую страницу, жмешь назад и с вероятностью 50% оказваешьтся в начале списка постов. Какой-то даун-дизайнер решил что без пагинации красивее и все теперь так делают.
> Блокировку ajax'а достаточно реализовать переменной-флагом, который переключаю в false в ajax'овском параметре-функции beforesent и в true в параметре-функции complete?
Да.
Кстати, ты тестировал на мобильных устройствах, там подгрузка будет работать?
> ну и реализовал все способы его использования, которые смог найти ... c различными параметрами.
Это разве все? Ты официальный мануал jQuery не пробовал открыть? Там еще куча функций и параметров.
> Вот тут не понял, типа плохой тон передавать неименованными константами какую либо информацию?
Глядя на код трудно понять, что значит эта цифра. Текст был бы лучше, а константа - еще лучше.
>Кстати, ты тестировал на мобильных устройствах, там подгрузка будет работать?
Nyet, а что может пойти не так? Для мобильных браузеров как то иначе обрабатываются scrollTop() или document.height() и window.height() расчитываются не так, как на десктопных браузерах?
>Это разве все? Ты официальный мануал jQuery не пробовал открыть? Там еще куча функций и параметров.
я про вышеперечисленные ajax'овские собсно на http://api.jquery.com/ и смотрел. Просто, возможно, под мою задачу мне приглянулись именно те функции, сейчас уже не вспомню.
В задаче "echo server" есть функция readSocket, как она должна работать по задумке? Я вижу там yield, как это должно использоваться?
По идее соединение не должно закрываться после передачи первой строки. echo-сервер должен постоянно возвращать обратно строки, пока соединение не закроют.
Во второй задаче, почему не используешь функции socketRead/Write из первой?
> (.*)[;\r\n]
Чтобы сделать звездочку нежадной, удобнее просто поставить после нее вопрос (а то я сначала подумал что тут ошибка и не обратил внимания на U)
> $response = preg_split('/\r\n\r\n/', $response);
Тут проще было использовать ограничение на число частей, которое есть у preg_split.
> $file = fopen(__DIR__ . '/test' . $extension, 'wb');
есть file_put_contents
Также, ты не учел что ответ может быть передаваться с кодировкой вроде Transfer-Encoding: chunked. Или это не требовалось в задании?
> while ($out = socket_read($socket, 2048)) {
Это неправильный код, так как при чтении пакета с байтом "0" он примет его за конец данных.
Также не проверяются ошибки которые могут возникнуть в процессе чтения.
1. На сервере подготавливать информацию в json-объект, и отсылать клиенту его, и чтобы на стороне клиента посредством JSON.Parse() распарсить json-пакет и модифицировать информацию внутри json-пакета по необходимости ну, например, в случае работы с таблицами - добавлять для каждого объекта <tr></tr>, и для каждого параметра - <td></td>
2. Прям в php подготавливать информацию и обрамлять её соответствующими html-элементами и посылать пользователю уже готовый блок html-разметки, только вставляй её в нужное место.
Подозреваю, что особой разницы нет. А так, можешь сделать и сравнить.
Первый вариант называется "шаблонизация на клиенте" и на практике там просто дописать tr/td будет недостаточно. Как миниумм надо еще спецсимволы экранировать.
Ты читать не умеешь? Ясно же написано "не используется" - это значит не считывается нигде. Ты ее только пишешь, а не читаешь.
Ну и еще у тебя проблема, что ты используешь какие-то магические числа вместо констант. И еще вдобавок глобальные переменные. Да еще и большими буквами написанные.
for (int i = 0; i < 26; i++) alphabet = i + 65;
и оно работало.
А в php везде в ручную забивают. Как-то поуебански, не?
Тоесть ты не знаешь способа забить автоматом, и в этом, по твоему виноват язык? Ты вообще нормальный?
>А в php везде в ручную забивают.
Где везде то? В учебнике опа 100500 примеров автоматического забивания.
Ебать дибил.
Очевидно они хотят человека который знает О нотацию и умеет разработать или выбрать оптимальный алгоритм для поставленой задачи.
>О нотацию и умеет разработать или выбрать оптимальный алгоритм
На этом месте поподробнее объяснить можешь?или информацию какую-то скинуть.
ну чо пехепач, бампчик, как дальше развивацо то епт, а то скурвлюсь и пойду битрикс макакой от безысходности, выручайти. Потом сами спасибо скажите, когда мой код перенимать на поддержку будете.
покури cms, modx, вордпресс. Вкатись к кому-нибудь джуниором, да задай вопросы.
разбери чужой код и посмотри как там устроено.
раскуривал уже, дак чо просто копировать чужой код? точнее его логику? Был жуном, хз все отвечают абстрактно в стиле все абстрактно и зависит от ситуации.
Вротпрес помоему не самая лучшая архитектура.
Раскуривал исходники ларавели кодигнайтера юи, да там все круто, но типа как самому хотябы на 1% так же писать.
>Напомню, что надо глянуть https://github.com/someApprentice/maintaskforlayout из >>874239 .
У меня вроде бы всё проверенно. Только сейчас начну всё исправлять из прошлого треда, так что с этим можно не торопиться.
http://ideone.com/lpZyA8
массивы с именами text и value?
Как их декодировать в вид обычного php-массива??
Потому что в первом случае ты выводишь значение выражения $a x $a в переменной $b, а во втором выводишь строку "$a x $a". Переменная $b так же преобразуется в строку,потому что ты берешь её в кавычки "$b", и переменные $a, они тоже становится строкой. А в строковом значении выражения не выполняются, потому что, привычные для нас операторы, операторы, это тоже строки, т.е. просто символ, например, + или -.
К сожалению нету.
и до чего же ты дошел?
ну тип я в детстве написал еще файло объебник, говнокодище говнокодское, недавно пытался сделать коменты типа с ветвями как на хубре, у сука напилил там дата маперов , моделей, контролеров, дбконекторов, еще пару синглетонов. Сказать что я ахуел ниче не сказать бошка готова была взорваться. Я начал путаться среди этого говна и сходить с ума. Поэтому дропнул.
Как избежать такого дерьма?
и нет я не шизик
http://ideone.com/OAyQXi
быдлокод
Конечно. Достаточно не преобразовывать выражение в строку (не ставить кавычки): echo $a + $b;
Если нужно что-то ещё вывести можно разделить с помощью разделителя . : echo "$a + $b = " . $a + $b . "\n";
Спасибо большое, получилось.
array (size=2)
0 =>
array (size=1)
'foo' => string 'Test' (length=4)
1 =>
array (size=1)
'bar' => string 'Test' (length=4)
Как мне проверить и вывести тру, если значения у foo и bar cовпадают?
["0"=>["foo"=>"test"], "1" => ["bar"=>"test"]]
как мне проверить, что значения foo and bar совпадают?
ты дебил что ли? массив формируется динамически таких значений там может и не быть. для этого есть проверка.
эт ты дебил,как ты спросил так тебе ответили, пшел нах отсюда щенок
пздц докатились да? Изучал пхп думал буду супер сеньером архитектором пхп, и вот сижу дрочу шляпу и ковыряю инфаблохи
почаще говори про папку локал на собеседовании они это любят ты сразу в глазах чуваков гуру битрикса становишся
бля я не могу средствами пхп распарсить джейсон, они че прикалываются такие тестовые присылать? на жаве или жс это вообще легко библиотеками делается. пиздец какой-то уже второе такое тестовое.
да это лучше чем джейсон пхп парсить. наверное.
алсо решите мне задачку на собес плз
https://2ch.hk/pr/res/882422.html#888476 (М)
тоисть ты не можешь http://php.net/manual/ru/function.json-decode.php
сделать? скожи сколько процентов мозга у тебя ампутировали и пощему?
и чо там решать юзаешь >>888872
потому по масиву гоняешь лысого чекаешь, либо регулярку пилишь которая в этом жисоне ищет фу и блять бар ебаный
>бля я не могу средствами пхп распарсить джейсон
>на жаве или жс это вообще легко библиотеками делается
>Библиотеками
>парсить json
>библиотеками
Лучше-бы мозги подключили вместо библиотек. Так рекурсивная функция строк на 5 всего.
не слушайте его он тролит, надо поставить ларавель, запустить через доктрину, когда все настроите на локальном хоместед вагранте, у вас не составит парсить жсон через пхп, возможно нужно смотреть в сторону композера
>уровня 7Б
если тебя твои однокласники из паралельного 7б загнобили это не повод тут высказывать свое недовольство бедненький, смирись тряпка
это не работает, там видно на глаз что это массивы зашиты в строках, но формат какой-то странный. Всё еще нужна помощь.
спасибо, разобрался, костыль который мне пришлось применить:
$json = "{" . $string . "}";
- это конечно же кек.
Внезапно. Но примерно это я и имел ввиду. Хоть и не думал что это так повернётся у тебя в коде. Удачи.
В общем условие такое.
На вход подается массив монет.
Монет может быть от 0 до 10, номинал монет может быть от 1 до 9, монеты могут повторяться, то есть входной массив может выглядеть: 1,2,2,3,7 например.
Нужно написать функцию, которая выдает минимальную положительную сумму, которую нельзя оплатить этими монетами без сдачи.
Например, если у нас есть монеты 1,2,5, то ответом должно быть 4. Потому что суммы в 1,2,3 - можно оплатить имеющимися монетами, а вот что бы оплатить 4, то придется дать 5, и получить сдачу 1.
Если есть монеты 2,5, то ответ должен быть 1.
В галере в котрую я ходил нужно такое решить "на бумаге" То есть пишешь код без гугла по памяти и без возможности запускать скрипт, и у тебя всё должно сразу заработать считаю это тупостью, ну да ладно, ведь ца такой конторки как раз студенты-олимпиадники. Дерзайте.
> Что оплатить то?
минимальную положительную сумму, которую нельзя оплатить этими монетами без сдачи.
Если я оплачиваю товар за 6 рублей, я плачу 6 рублей без сдачи. Очевидно же. Откуда мне знать будет сдача или нет, если я не знаю цену товара?
речь в этой задаче не о цене покупки, а о том что у тебя есть мелочь в кармане, и ты приходишь в киоск на котором висит табличка "НЕТ СДАЧИ, ВООБЩЕ"
И ты смотришь на товары, все все они стоят от 1 рубля до бесконечности по нарастающей. И должен назвать мне первый товар, который ты не сможешь купить на свои монетки, потому что у тебя нету нужной комбинации, понимаешь???
>все они стоят от 1 рубля до бесконечности по нарастающей.
Тогда в киоске есть все цены, на любое количество денег без сдачи.
да, но у тебя например в кармане есть монетки с номиналом в 1, 2 и 5.
И ты должен мне сказать, что не можешь купить хуйню за 4 рубля. Потому что из твоих монет можно скомбинить только 1,2,3,5,6,7,8 ясно?
Как ты определил что я не могу купить хуйню за 4 рубля а не за 8? Я не понимаю.
ты не можешь купить за 4, 9, 10, 11...
но ты должен назвать минимальное из этих.
В общем мне кажется что ты толстишь, так что больше я на твои вопросы не отвечаю, думай сам. Если ты тебе надо настолько разжевать задачу, то иди решай лучше учебник опа уебок жирный
иди ты нахуй с такими задачами уровня ебанутой /b/изнес логики, за решение и расшифровку таких задач бабло должны платить. Постоянно такое встречается, Хотим чтобы скидка была у каждого третьего товара притом что каждый 4 товар имел уменьшеную скидку от предыдущего товара на 3 процента. Плюс вычитать ндс когда полнолуние и марс заходит за юпитер.
Я бы просто встал и ушел нахуй, если им нужен даун который это будет решать за наносекунду, это либо аутист математик ебанутый, либо чел который задрочил подобные задачи. В остальном все нормальные люди решают кто сколько может.
Ну и хуй на них с их олимпиадниками. Такую задачу юзают просто чтоб отсеять простых людей, а зазвать каких нибудь сампутер саенс магистров и прочих матановедов.
Да пригорело у меня знатно сука.
Аа регулярку. попробую
на жаве есть удобные библиотеки по работе с джейсоном, даунидзе. а тут регулярки какие-то, рекурсии по массиву. вообще ахуеть.
то есть например у тебя если есть массив [1,3,4], то на выходе ты должен дать массив вида: [1,3,4,5,7,8], ну а дальше всё легко, ты просто проходишь циклом от 1 до 91 и находишь первую дырку.
https://2ch.hk/pr/res/882422.html#888476 (М)
http://ideone.com/1oqh9Z
нужна кровь девственицы
Допустим пост на форуме, в форме открывается уже готовый текст, его можно отредактировать.
Это просто идет селект текста и он заново пересобирается?
Лучше запостить ссылку на код и написать что именно непонятно. Что касается задачи с айфном, на ней все спотыкаются.
Один раз выучил, могу не работать год, и снова писать на нём. Никаких затруднений, максимум - освежить в памяти какие-то тонкие вопросы, это легко сделать из того же мануала.
Разделил методы на категории и создал для каждой категории класс. Один из классов: http://pastebin.com/dw2uaFCH
Base класс: http://pastebin.com/AvsCw8Ar
Создание объекта и вызов выглядят так:
$server = new Server($keyId,$vCode);
$url = $server->get('ServerStatus');
В $url идет ссылка со всеми параметрами, которые передаются в get вторым параметром массивом. Собственно вопрос остался тот же - как мне правильно получить файл с помощью того же Guzzle и обработать с помощью DOM?
Это прочитал https://github.com/codedokode/pasta/blob/master/arch/di.md но ничего не изменилось, я все равно не понимаю как это сделать. Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл и еще ниже сразу же объявить DOM и обработать, но это неправильно, или я не прав?
В результате я хочу двумя строчками получить массив данных.
А в цикле во втором действии можно столько вычислений проводить за раз?
ну у тебя прилетает $_POST, когда пользователь заполнил поля.
Пробегаешь форичем по этому массиву и проверяешь каждый элемент на !empty
$bdUpdate = [];
for ($_POST as $key => $value) {
____if(!empty($value)) {
________$bdUpdate[$key] = $value;
____}
}
и им уже апдейтишь базу.
Дык а если это не добавление объекта, а редактирование уже существующего? У меня же в посте все поля прилетят, и мне нужно как то дифференцировать измененные от неизмененных.
схерали нельзя? ты же сам ответил на свой вопрос? у тебя есть эти переменные. Скажем человек перешел на вторую страницу. Стало быть в контроллере ты оперируешь тем что у тебя $page = 2, и передаешь потом эту инфу во вьюху, и стало быть все ссылки, которые в пределах этой страницы строишь с гет-параметром &page=2, хули сложного? Отсортировал он по какому-то столбцу, sort=name, стало быть у тебя появилась переменная, что $sort = "name" и допустим ты знаешь что у тебя по дефолту стоит $defaultOrder = "ASC";
значит ты прямо в мускуль и отправишь эти сортить по name ASC, и хуяришь на выходе уже ссылки вида sort=name&order=asc&page=2
Кароче чет меня повело, прост блядь переменные гоняй через гет запрос и себе же их передавай и во вьюхе с их использованием берешь и строишь переменные прост.
что мешает апдейтить всю запись в базе? Ну или тогда если хочешь апдейтить только часть, то селекти перед апдейтом и сравнивай 2 массива.
>делать невидимый инпут внизу формы
мм, вкусно, уже заапдейтил в твоей базе пароль админу)))
ЗАВИСТЬ
Можно создать объект СтрокаЗапроса, который будет хранить все возможные параметры запроса, вроде sort, page и т.д. Каждый раз, при переходе по ссылке, меняется только один параметр. Т.е. пользователь может либо кликнуть на заголовок столбца - изменится порядок сортировки, либо перейти на другую страницу - изменится номер страницы, но не сортировка. Начинает он всегда с первой страницы, т.е. все начальные параметры строки тебе известны.
А ссылки будет формировать класс СсылкоФормировщик, который получает на вход объект СтрокаЗапроса.
Не очень понял о чем ты. http://ideone.com/ppPhO0 вот мой шаблон, чую я вообще не с той стороны захожу.
>что мешает апдейтить всю запись в базе? Ну или тогда если хочешь апдейтить только часть, то селекти перед апдейтом и сравнивай 2 массива.
Ну а если всю запись обновлять слишком затратно в плане объема информации? Следовательно, и селектить лишний раз нежелательно.
И в чем заключается уязвимость невидимого инпута? Я же с него только считываю информацию
http://ideone.com/ppPhO0 тащемта сделал вот так, просто передаю во вью параметры сорт и пейдж и показываю их в ссылке. Работает как надо, только вот все равно не покидает ощущение того, что можно сделать куда лучше, слишком уж это на наебку похоже.
Можно сделать функцию для генерации ссылок, вроде такой
generateTableLink($sort, $dir, $search, $page)
Там еще надо учесть что повторный клик по заголовку должен менять направление сортировки.
>>889269
Можно, но тут наверно проще функцией сделать.
>>889247
Надо либо апдейтить все, либо делать селект и сравнивать. Также нужно иметь список разрешенных для редактирования полей.
Кстати, ORM вроде Доктрины умеют сравнивать сами.
>>889286
Что там затратного? Ты по 10 мегабайт текста каждый раз выбираешь? По моему ты сам себе придумываешь усложнение. Можно сделать список полей, но не забудь проверить его по списку разрешенных полей.
>>889235
Можно, но читабельность страдает и лучше лишнее перенести в тело цикла.
Ну и второе действие у тебя никуда не сохраняет результат вычисления.Ну и код по моему не очень правильный ответ даст.
>>889279
> $tdg->getBalance(); / $tdg->getBalance(0); / $tdg->getBalance(NULL);
Не должно быть 3 варианта сделать одно и то же. Надо строже определить тип данных.
> $tdg->getBalance(); --> если в базе 0 записей, выбрасывает исключение
не понятна логика, почему исключение
По моему, ты переусложнил код. Зачем ты совмещаешь 2 разных действия (получить баланс одного счета и всех счетов) в одной функции? Это неудобно, удобнее сделать 2 функции. Это позволит четко определить типы получаемых и возвращаемых данных, а сейчас у тебя сложно понять что и когда возвращается.
Ну например если мы хотим получить баланс одного счета, то мы хотим получить на выходе число, а не массив. Зачем делать массив ради одного элемента?
>>889271
Символ & в HTML тексте или атрибуте надо писать как & amp ;
Можно сделать функцию для генерации ссылок, вроде такой
generateTableLink($sort, $dir, $search, $page)
Там еще надо учесть что повторный клик по заголовку должен менять направление сортировки.
>>889269
Можно, но тут наверно проще функцией сделать.
>>889247
Надо либо апдейтить все, либо делать селект и сравнивать. Также нужно иметь список разрешенных для редактирования полей.
Кстати, ORM вроде Доктрины умеют сравнивать сами.
>>889286
Что там затратного? Ты по 10 мегабайт текста каждый раз выбираешь? По моему ты сам себе придумываешь усложнение. Можно сделать список полей, но не забудь проверить его по списку разрешенных полей.
>>889235
Можно, но читабельность страдает и лучше лишнее перенести в тело цикла.
Ну и второе действие у тебя никуда не сохраняет результат вычисления.Ну и код по моему не очень правильный ответ даст.
>>889279
> $tdg->getBalance(); / $tdg->getBalance(0); / $tdg->getBalance(NULL);
Не должно быть 3 варианта сделать одно и то же. Надо строже определить тип данных.
> $tdg->getBalance(); --> если в базе 0 записей, выбрасывает исключение
не понятна логика, почему исключение
По моему, ты переусложнил код. Зачем ты совмещаешь 2 разных действия (получить баланс одного счета и всех счетов) в одной функции? Это неудобно, удобнее сделать 2 функции. Это позволит четко определить типы получаемых и возвращаемых данных, а сейчас у тебя сложно понять что и когда возвращается.
Ну например если мы хотим получить баланс одного счета, то мы хотим получить на выходе число, а не массив. Зачем делать массив ради одного элемента?
>>889271
Символ & в HTML тексте или атрибуте надо писать как & amp ;
Класс неправильно назван. У тебя не сервер, а клиент. Сервер - это тот, кто отвечает на запросы, а клиент - тот, кто отправляет. Также, неправильно писать просто "сервер", надо писать, для чего этот сервер или клиент.
> namespace libs;
Название тоже не по PSR-4 выбрано.
> $this->$api($params);
Зачем это? Динамические вызовы только усложняют понимание кода и их не стоит использовать без необходимости.
> $url = $server->get('ServerStatus');
Чем это лучше чем $client->getServerStatus() ? Какой смысл вместо вызова метода напрямую как-то это все усложнять? Ну например в случае с отдельными методами мы можем писать тайп-хинты, а как это сделать в твоем случае? Да даже просто комментарий к методу непонятно, как написать. как узнать, какие методы доступны?
Класс работы с АПИ должен делать работу с ним удобной, скрывая ненужные подробности, ну например, притворяясь что это обычный объект с методами. Ты же вместо скрытия особенностей АПИ наоборот заставляешь в них разбираться, предоставив единственную функцию.
Зачем использовано наследование? Я пока не вижу смысла писать в виде 2 классов то, что можно написать в одном. Наследование иногда используют для возможности расширения пользователем стороннего кода, но вряд ли имеет смысл расширять клиент АПИ, так как он жестко привязан к функционалу сервера.
Ты должен выбирать подход не по принципу "использовать не менее 1 паттерна в коде", а оценивая преимущества того или иного варианта.
> В $url идет ссылка со всеми параметрами, которые передаются в get вторым параметром массивом.
Ну так это получается не клиент АПИ, а HTTP клиент. Ты с таким же успехом можешь дать пользователю Гуззл, и пусть он сам делает там запросы.
> Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл и еще ниже сразу же объявить DOM и обработать, но это неправильно, или я не прав?
DI используется для передачи объектов-сервисов, которые могут использоваться многократно. Пользователь может выбирать, какую именно версию объекта передать. DOM это не сервис (он каждый раз создается заново) и его передавать через конструктор не надо, да и нет смысла, непонятно, зачем? Что ты в нем можешь поменять? DOM объекты ты просто создаешь и используешь.
Если ты читал урок про DI, там есть в конце пример, показывающий сценарий использования DI.
Что касается Guzzle, то его как раз можно передавать с помощью DI. Ты передаешь в конструктор объект, с помощью которого потом будут делаться HTTP-запросы. Соответственно сам класс не создает и не настраивает этот HTTP клиент, а использует тот, что ему дали. Можно передать объект-заглушку, можно настроить какие-то параметры объекта (ну например, таймаут).
> В результате я хочу двумя строчками получить массив данных.
Это тоже не всегда хорошая идея, так как ответ может быть удобнее представить в виде объектов, а не массивов неизвестной структуры в которых любые поля могут отсутствовать. Хотя, конечно, это требует больше труда.
> Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл
Это будет не DI.
>>889313
А в школах до сих пор пишут буквы прописью.
Класс неправильно назван. У тебя не сервер, а клиент. Сервер - это тот, кто отвечает на запросы, а клиент - тот, кто отправляет. Также, неправильно писать просто "сервер", надо писать, для чего этот сервер или клиент.
> namespace libs;
Название тоже не по PSR-4 выбрано.
> $this->$api($params);
Зачем это? Динамические вызовы только усложняют понимание кода и их не стоит использовать без необходимости.
> $url = $server->get('ServerStatus');
Чем это лучше чем $client->getServerStatus() ? Какой смысл вместо вызова метода напрямую как-то это все усложнять? Ну например в случае с отдельными методами мы можем писать тайп-хинты, а как это сделать в твоем случае? Да даже просто комментарий к методу непонятно, как написать. как узнать, какие методы доступны?
Класс работы с АПИ должен делать работу с ним удобной, скрывая ненужные подробности, ну например, притворяясь что это обычный объект с методами. Ты же вместо скрытия особенностей АПИ наоборот заставляешь в них разбираться, предоставив единственную функцию.
Зачем использовано наследование? Я пока не вижу смысла писать в виде 2 классов то, что можно написать в одном. Наследование иногда используют для возможности расширения пользователем стороннего кода, но вряд ли имеет смысл расширять клиент АПИ, так как он жестко привязан к функционалу сервера.
Ты должен выбирать подход не по принципу "использовать не менее 1 паттерна в коде", а оценивая преимущества того или иного варианта.
> В $url идет ссылка со всеми параметрами, которые передаются в get вторым параметром массивом.
Ну так это получается не клиент АПИ, а HTTP клиент. Ты с таким же успехом можешь дать пользователю Гуззл, и пусть он сам делает там запросы.
> Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл и еще ниже сразу же объявить DOM и обработать, но это неправильно, или я не прав?
DI используется для передачи объектов-сервисов, которые могут использоваться многократно. Пользователь может выбирать, какую именно версию объекта передать. DOM это не сервис (он каждый раз создается заново) и его передавать через конструктор не надо, да и нет смысла, непонятно, зачем? Что ты в нем можешь поменять? DOM объекты ты просто создаешь и используешь.
Если ты читал урок про DI, там есть в конце пример, показывающий сценарий использования DI.
Что касается Guzzle, то его как раз можно передавать с помощью DI. Ты передаешь в конструктор объект, с помощью которого потом будут делаться HTTP-запросы. Соответственно сам класс не создает и не настраивает этот HTTP клиент, а использует тот, что ему дали. Можно передать объект-заглушку, можно настроить какие-то параметры объекта (ну например, таймаут).
> В результате я хочу двумя строчками получить массив данных.
Это тоже не всегда хорошая идея, так как ответ может быть удобнее представить в виде объектов, а не массивов неизвестной структуры в которых любые поля могут отсутствовать. Хотя, конечно, это требует больше труда.
> Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл
Это будет не DI.
>>889313
А в школах до сих пор пишут буквы прописью.
47 лет прошло, люди все еще не могут передать некоторые заглавные буквы.
Сперва это и были две разные функции, но так как в них много общего, были объединены в одну. Выходит, меньше кода не всегда хорошо? Ну а вообще, концепция правильная? Передавать в этот класс pdo-объект, а в методы все условия и ничего более, а внутри только операции с базой данных, никакой внешней логики? (Супер удобно, в общем, получается на самом деле! Если надо что-то изменить, трогаешь только один метод, блин, это вообще...).
Концепция, что вся работа с определенной сущностью в Бд собрана в одном классе - да, именно для этого TDG и придуман. Но объединение методов в один только ухудшило код.
А что насчет проверок на правильность вставляемых / запрашиваемых данных, можно ли их (эти проверки) держать внутри методов или нужно обрабатывать до того, как передадим данные в метод TDG?
Например:
1) внешний файл
if (условия, что данные правильны) {
$tdg->функция(данные);
} else {
...
}
2) внешний файл
$tdg->функция(данные);
наш класс
функция(данные)
{
if (условия, что данные правильны) {
манипуляции с бд
} else {
исключение
}
}
А что насчет проверок на правильность вставляемых / запрашиваемых данных, можно ли их (эти проверки) держать внутри методов или нужно обрабатывать до того, как передадим данные в метод TDG?
Например:
1) внешний файл
if (условия, что данные правильны) {
$tdg->функция(данные);
} else {
...
}
2) внешний файл
$tdg->функция(данные);
наш класс
функция(данные)
{
if (условия, что данные правильны) {
манипуляции с бд
} else {
исключение
}
}
В маленьких приложениях в простых случаях можно совмещать все в TDG (хотя конечно получается не очень чисто и уже не совсем TDG), в больших обычно делают более высокоуровневый сервис, который делает проверки/преобразования и после вызывает TDG.
Сам по себе & может являться служебным символом для других символов ( , < , ©). Поэтому для самого символа & пишем & - так мы точно определим, что этот & набранан для текста.
Лол, вот и оно, & lt; поменялось на кавычку.
https://school-php.com/tasks
какой-то ппц, как будто шизик писал, условия понять не могу.
>ИГРА НА СЕССИЯХ (БИТВА АЛКОГОЛИКОВ)
>СОРТИРОВКА МНОГОМЕРНОГО МАССИВА
Реально, человеку нужно научиться выражать свои мысли.
>ORDER BY `age` ASC
Зачем там sql?
йА думаю што существуют стандарты кодирования, и надо их соблюдать. Вот и всё.
И ещё, дайте ссылку на хорошийгодный мануал по формам типа советы, практические рекомендации, рекомендуемые правила построения и обработки данных, если таковой имеется.
В сессии пользователя, например.
Зачем извращаться? Проверь после сабмита есть ли права на редактирование переданного id у текущего юзера.
У меня тоже подгарело от задачи. Но я отдаю себе отчет что отчасти это потому что я не могу её решить так сразу.
Суть такова: не могу добиться работы из-за того, что Мейлеру не нравится статический вызов.
ЧЯДНТ?
Забыл: там если ещё монету прибавить номиналом 1 - считает неверно.
Из-за того, что исключает единицу при прибавлении к другим монетам - и первую, и вторую.
>>889638
Просто мы веб макаки, а эта задача расчитанна на выпускников вузов которые на сях дрочили алгоритмы несколько курсов. Если свести эту задачу к совсем простой теме, то там будет что-то комбинаторное, и надо написать лагоритм который выдает нам все возможные варианты суммы этихмонет, при которых у тебя монета принимает либо 0, либо своё значение. Вот так как-то.
То есть покажу пример для монет в 1, 2, 5.
В общем варианты:
1 + 0 + 0 = 1
0 + 2 + 0 = 2
1 + 2 + 0 = 3
0 + 0 + 5 = 5
1 + 0 + 5 = 6
0 + 2 + 5 = 7
1 + 2 + 5 = 8
Вот так как-то надо вложенным циклом или еще чем пройтись и получить массив, портом по этому массиву циклом до первой дыры и выдать ответ 4.
Для монет в 1,3 это
1 + 0 = 1
0 + 3 = 3
1 + 3 = 4
Ответ соотстввенно 2
для 1, 2, 2
1 + 0 + 0 = 1
0 + 2 + 0 = 2
0 + 2 + 2 = 2
1 + 2 + 0 = 3
1 + 0 + 2 = 3
0 + 2 + 2 = 4
1 + 2 + 2 = 5
Ответ - 6.
обосравшийся на собесе
Ща напишу еще вторую зщадачку отдельным постом. На обе давался 1 час, для написания "на бумажке"
Ну и что еще могу сказать, так на самом деле это лотерея, потому что я ходил в эту контору уже второй раз, и в первый раз мне выпали на рандоме другие задачи, которые в тот раз я обе решил минут за 50, но завалил уже устное собеседование после этого :(
>>889638
Просто мы веб макаки, а эта задача расчитанна на выпускников вузов которые на сях дрочили алгоритмы несколько курсов. Если свести эту задачу к совсем простой теме, то там будет что-то комбинаторное, и надо написать лагоритм который выдает нам все возможные варианты суммы этихмонет, при которых у тебя монета принимает либо 0, либо своё значение. Вот так как-то.
То есть покажу пример для монет в 1, 2, 5.
В общем варианты:
1 + 0 + 0 = 1
0 + 2 + 0 = 2
1 + 2 + 0 = 3
0 + 0 + 5 = 5
1 + 0 + 5 = 6
0 + 2 + 5 = 7
1 + 2 + 5 = 8
Вот так как-то надо вложенным циклом или еще чем пройтись и получить массив, портом по этому массиву циклом до первой дыры и выдать ответ 4.
Для монет в 1,3 это
1 + 0 = 1
0 + 3 = 3
1 + 3 = 4
Ответ соотстввенно 2
для 1, 2, 2
1 + 0 + 0 = 1
0 + 2 + 0 = 2
0 + 2 + 2 = 2
1 + 2 + 0 = 3
1 + 0 + 2 = 3
0 + 2 + 2 = 4
1 + 2 + 2 = 5
Ответ - 6.
обосравшийся на собесе
Ща напишу еще вторую зщадачку отдельным постом. На обе давался 1 час, для написания "на бумажке"
Ну и что еще могу сказать, так на самом деле это лотерея, потому что я ходил в эту контору уже второй раз, и в первый раз мне выпали на рандоме другие задачи, которые в тот раз я обе решил минут за 50, но завалил уже устное собеседование после этого :(
На вход дается натуральное число, на выход нужно вернуть первый простой палиндром, который будет больше этого числа
Простой - делится только на себя и 1
Палиндром - числа как 101, 30403, 4004 и так далее.
а я в шоколадницу или аэрофлот пытаюсь трудоустроиться. назначили пару собесов на пхп кодеров, но там шараги в каких-то ебенях, я даже не доехал.
просто классы туда выносишь. всю работу приложения. чтобы из контроллеров чисто классы вызывались, а вся работа и обработка проходили в моделях. контроллеры должны быть максимально короткими, т.к. весь код в моделях
Это и так все понятно. Вопрос был про немного другое - про архитектуру самих моделей и всей бизнес-логики приложения.
>просто классы туда выносишь. всю работу приложения.
кек
>чтобы из контроллеров чисто классы вызывались, а вся работа и обработка проходили в моделях.
кек^2
>контроллеры должны быть максимально короткими, т.к. весь код в моделях
кек^3
А в моем фреймворке например приветствуются тонкие модели и толстые контроллеры, но раз васян с двача так сказал, то буду ща хуярить толстые модели и всю логику в них))))
я просто намекнул тебе, что бывает два подхода, погугли что ли, чем бугуртить тут __)_)_)
>Вот так как-то надо вложенным циклом или еще чем пройтись и получить массив, портом по этому массиву циклом до первой дыры и выдать ответ 4
Получается, нужен цикл в цикле.
Один идёт по количеству монет, а второй внутри каждый раз складывает все монеты.
Ну вот я так и хотел сделать, но где-то обкакунькался.
Я хотел так сделать, а потом просто unset из массива со сдачей от 1 до 9.
Сейчас посижу, подумаю.
Блин, ну как сделать этот вызов не статическим:
protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from = null)
{
if (!empty($this->action_function) && is_callable($this->action_function)) {
$params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
call_user_func_array($this->action_function, $params);
}
}
Так ты решил эту задачу на собесе или сейчас такой умный? Вот этот вот алгоритм, который ты изложил, за решение не прокатил?
Алсо, я нашел два алгоритма решения, с помощью генерации массива биткарты (побитовая маска), и с помощью циклов, вложенных в друг-друга, количество которых равно количеству элементов исходного массива. Твой вариант - это почти что вариант биткарты, без бит карты, лол.
Без специальной подготовки, такую задачу я бы решить не смог. Но читая статьи из цикла "как я устроился в гугол и получаю 1000$ в секунду" часто встречал описания штудирования всевозможных хитрых олимпиадных задачек перед очередным собеседованием. Поэтому мне кажется, хватит ныть, садись и учи.
>>889778
Это проблема в сторонней библиотеке. В таком случае первым делом надо погуглить:
http://www.yiiframework.ru/forum/viewtopic.php?t=32889
Затем мы идем в гитхаб разработчика, и ищем в issues - не писал ли кто-то об этом? Действительно, есть такой баг: https://github.com/SDKiller/zyx-phpmailer/issues/2
Там написано, что все исправлено аж в 2014.
Открыв код https://github.com/SDKiller/zyx-phpmailer/blob/master/Mailer.php видим - действительно, исправлено.
Теперь вопрос к тебе:
Почему у тебя такая старая версия? как ты устанавливал это расширение? через композер? если да, то какая версия стоит в composer.lock и в composer.json? если нет, то почему?
>>889797
Есть раздел математики комбинаторика ( https://ru.wikipedia.org/wiki/Комбинаторика ), которая как раз изучает всякие комбинации и перестановки, и есть стандартные алгоритмы их генерации.
В твоем случае, если брать наивный неоптимизированный подход - надо перебрать все возможные выборки из монет, посчитать их суммы, отсортировать по возрастанию и найти нужное число.
Этот алгоритм не оптимизирован, потому прикинем, сколько вариантов нам придется перебрать в худшем случае. Реально ли перебрать такое число вариантов?
У нас в данном случае задача не подходит ни под одно определение из комбинаторики, но это потому что она очень простая.
Монет максимум 10, каждая из них может быть взята или нет. Это дает нам 2^10 = 1024 варианта. Немного, так что можно решать задачу тупо перебором без особых оптимизаций (оптимизацией будет выбор такого порядка перебора, чтобы сумма шла по возрастанию).
Как сгенерировать комбинации монет? Да очень просто, можно циклом, можно рекурсией. Например, комбинации можно представить двоичным 10-значным числом от 0000...0 до 1111...1, по сути надо сделать перебор этих чисел.
Самому кажется, что кривоватое решение, стоит по другому попробовать?
Есть ли статьи, аргументирующие профит от толстых контроллеров? Для начала, ты вообще понимаешь, в чем их недостатки? Я перечитал твой пост, там нет ни аргументов, ни ссылки на статью, так что пока буду считать что у тебя их и нету, как и нет твоего воображаемого фреймворка.
>>889735
> Сколько видов моделей бывают?
Модель предметной области (domain model) - так иногда называют класс, объект которого соответствует какой-то сущности (Новость), а иногда - все классы, относящиеся к логике приложения, вместе. Из-за этого наверно и путаница.
> domain models
> repositories
Лучше всего почитать у Фаулера, который эти паттерны в книге описал:
http://design-pattern.ru/patterns/domain-model.html
http://design-pattern.ru/patterns/repository.html
В Доктрине репозиториями называются классы, отвечающие за выборку сущностей из таблицы в БД. У Фаулера вроде бы Репозиторий представляет собой абстракцию над базой данных, этакое хранилище, из которого данные можно получать.
Общая архитектура обычно представляется в виде слоев: http://design-pattern.ru/patterns/service-layer.html
В приложениях обычно 1-2 слоя. Если 2 слоя - то это например нижний уровень из классов для работы с БД и лежащий над ним уровень сервисов, которые делают более сложные операции (ну например сервис регистрации, который кроме проверки и вставки данных в БД еще например отправляет письма и обновляет статистику). Больше 2 слоев тебе вряд ли понадобится.
Я бы не советовал специально как-то усложнять код и стремиться реализовать все возможные паттерны. Реши, что тебе нужно делать. Разбей это на отдельные задачи. Для каждой задачи напиши класс. А потом посмотри, логичная получается схема или нет. Можешь здесь например выложить как пример (даже не сам код, а описание классов и методов).
Ну например, тебе надо делать валидацию данных перед вставкой в БД. Если она простая, можно засунуть ее прямо в сервис, когда она станет более сложной, вынесешь в отдельный класс.
То есть начать можешь с одного слоя сервисов, каждый для своей задачи, а потом по мере усложнения выносить части в отдельные классы.
Хочу еще дать такую статью про хлеб: https://habrahabr.ru/post/153225/
Ты не дал никаких примеров, потому придется пример придумать мне. Ну вот возьмем например, файлообменник. Так как сущность там только одна - файл, то и сервис пока у нас будет один - СервисФайлов. Подумаем, какие нужны ему методы:
- проверитьФайл (можно ли такой файл загрузить к нам, правильно ли указан комментарий и тд)
- сохранитьФайл (и на диск, и в БД)
- получитьФайлПоId
- получитьСсылкуНаСкачивание
- получитьСсылкуНаСтраницуФайла
- получитьПутьКФайлуНаДиске
- удалитьФайл
Ну а дальше, может быть, эта схема будет как-то усложняться. Ну например, мы захотим для более аккуратного кода убрать из сервиса работу с БД в отдельный класс, реализующий Table Data Gateway. Затем, захотим сделать объект, представляющий Файл. Затем вынесем работу с URL в отдельный класс.
Затем вспомним, что нам надо для медиафайлов показывать информацию о них, и сделаем классы МедиаИнформация и ПолучательМедиаИнформации.
Вот я бы рассуждал примерно так. Ну и еще, можно посмотреть, как это делается в той же Симфони 2, там довольно неплохая архитектура.
Есть ли статьи, аргументирующие профит от толстых контроллеров? Для начала, ты вообще понимаешь, в чем их недостатки? Я перечитал твой пост, там нет ни аргументов, ни ссылки на статью, так что пока буду считать что у тебя их и нету, как и нет твоего воображаемого фреймворка.
>>889735
> Сколько видов моделей бывают?
Модель предметной области (domain model) - так иногда называют класс, объект которого соответствует какой-то сущности (Новость), а иногда - все классы, относящиеся к логике приложения, вместе. Из-за этого наверно и путаница.
> domain models
> repositories
Лучше всего почитать у Фаулера, который эти паттерны в книге описал:
http://design-pattern.ru/patterns/domain-model.html
http://design-pattern.ru/patterns/repository.html
В Доктрине репозиториями называются классы, отвечающие за выборку сущностей из таблицы в БД. У Фаулера вроде бы Репозиторий представляет собой абстракцию над базой данных, этакое хранилище, из которого данные можно получать.
Общая архитектура обычно представляется в виде слоев: http://design-pattern.ru/patterns/service-layer.html
В приложениях обычно 1-2 слоя. Если 2 слоя - то это например нижний уровень из классов для работы с БД и лежащий над ним уровень сервисов, которые делают более сложные операции (ну например сервис регистрации, который кроме проверки и вставки данных в БД еще например отправляет письма и обновляет статистику). Больше 2 слоев тебе вряд ли понадобится.
Я бы не советовал специально как-то усложнять код и стремиться реализовать все возможные паттерны. Реши, что тебе нужно делать. Разбей это на отдельные задачи. Для каждой задачи напиши класс. А потом посмотри, логичная получается схема или нет. Можешь здесь например выложить как пример (даже не сам код, а описание классов и методов).
Ну например, тебе надо делать валидацию данных перед вставкой в БД. Если она простая, можно засунуть ее прямо в сервис, когда она станет более сложной, вынесешь в отдельный класс.
То есть начать можешь с одного слоя сервисов, каждый для своей задачи, а потом по мере усложнения выносить части в отдельные классы.
Хочу еще дать такую статью про хлеб: https://habrahabr.ru/post/153225/
Ты не дал никаких примеров, потому придется пример придумать мне. Ну вот возьмем например, файлообменник. Так как сущность там только одна - файл, то и сервис пока у нас будет один - СервисФайлов. Подумаем, какие нужны ему методы:
- проверитьФайл (можно ли такой файл загрузить к нам, правильно ли указан комментарий и тд)
- сохранитьФайл (и на диск, и в БД)
- получитьФайлПоId
- получитьСсылкуНаСкачивание
- получитьСсылкуНаСтраницуФайла
- получитьПутьКФайлуНаДиске
- удалитьФайл
Ну а дальше, может быть, эта схема будет как-то усложняться. Ну например, мы захотим для более аккуратного кода убрать из сервиса работу с БД в отдельный класс, реализующий Table Data Gateway. Затем, захотим сделать объект, представляющий Файл. Затем вынесем работу с URL в отдельный класс.
Затем вспомним, что нам надо для медиафайлов показывать информацию о них, и сделаем классы МедиаИнформация и ПолучательМедиаИнформации.
Вот я бы рассуждал примерно так. Ну и еще, можно посмотреть, как это делается в той же Симфони 2, там довольно неплохая архитектура.
Up
я на собесе дошел мыслями до этого, но не смог на бумажке написать алгоритм этот.
ну и там электронный тест, плюс на самом деле ideone, ты просто выбираешь язык и пишешь код в форму, там и явисты и сишники какие-нибудь эти же задачи решают, просто на своём языке.
Я так-то посмотрел, это всё прочитал, но ничего не понял всё-таки.
>Почему у тебя такая старая версия? как ты устанавливал это расширение? через композер? если да, то какая версия стоит в composer.lock и в composer.json? если нет, то почему?
Через Композер устанавливал в середине этого лета.
4-я версия, как я понял.
У меня нет файла composer.loc - не нахожу его.
Что мне можно сделать в этой ситуации, обновить PHPMailer через Composer?
Вроде как не советуют просто сами файлы обновлять в папке vendor, только через Композер.
Вполне хорошо, только ещё можно было бы сократить на echo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n";
Для этого надо прямо в цикле поставить условие: если осталось с процентами и 1000 меньше 5000, то $lastPayment = $creditBalance;
$creditBalance = $creditBalance - $lastPayment;
$paymentTotal = $paymentTotal + $lastPayment;
Анончики, хочу вкотится в это ваше веб-погромирование в 25
До этого 3 года работал версталой/фронтендом
Так вот, для работодателей опыт верстки хоть как-то будет учитываться или как нулевого долбоеба будут оценивать?
Спасибо за развернутый ответ.
У меня, в принципе, нет примерной темы для конкретного сайта, т.к. я планирую просто изменить архитектуру проектов в общем.
Пока что я в голове набросал следующую архитектуру моделей, которая в целом устраивает мои привычки работы с MVC:
1 - Storage Models - модели самого низкого уровня, работают непосредственно с данными (БД, XML, json). Есть некий общий класс StorageCore, который включает в себя экземпляры всех storage models и через этот общий класс происходит работа с этими экземлярами. Сам по себе Storage Core является реализацией интерфейса IStorage, что позволяет подставлять нужную реализацию в любой момент времени. Например, для unit-тестов не вижу особого смысла работать напрямую с рабочей БД и подставить для этого реализацию Storage Core для работы с предустановленными json-файлами.
2 - Domain Models - модели-объекты записей данных. Т.е. каждый экземпляр этого класса представляет собой конкретную запись в БД.
3 - Service Models - модели-сервисы, по сути тупо хелперы, в которых непосредственно и реализована вся бизнес-логика, все связи между сущностями, все сортировки и прочие выборки. Является надстройкой над Storage Core.
4 - Bind Models - модели, которые получают данные от пользователя (формы, get-запросы) и затем обращаются к service models, получая необходимые данные (в виде набора domain models) и совершая действия. Контроллеры работают именно с bind models, не затрагивая все остальные вышеперечисленные модели. По сути вся работа контроллера это инициализировать нужный в этот момент bind model и далее смотреть, что этот BM вытворяет.
5 - View Models - модели, которые являются тем же набором разного рода domain models. Эти модели далее передаются во View (т.е. внутри себя содержат еще какие-то вспомогательные методы, к которым мы обращаемся из View.
Примерно такая структура, к которой я стремлюсь. Но в силу недостатка опыта не могу оценить адекватность этой архитектуры. Есть мнение?
Зависит от конкретной задачи. Но в целом, да. Опыт верстки для веб-разработчика большой плюс, при условии, что твой уровень пхп их устроит. Если же нет, то будут смотреть как на переводчика, который пришел на должность бизнес-аналитика.
Отлично, спасибо за ответ. Значит вкатываюсь.
>If you:
>Use Modern Versions of MySQL (late 5.1, all 5.5, 5.6, etc) AND PDO's DSN charset parameter (in PHP ≥ 5.3.6)
OR
>Don't use a vulnerable character set for connection encoding (you only use utf8 / latin1 / ascii / etc)
OR
>Enable NO_BACKSLASH_ESCAPES SQL mode
>You're 100% safe from SQL injections.
>Otherwise, you're vulnerable even though you're using PDO Prepared Statements...
Я чутка попутал. Storage Models будут реализациями своих интерфейсов. А StorageCore будет подгружать нужную реализацию этих моделей, чтобы в одном случае работать с БД, а в другом работать, например, с файлами, не меняя при этом всю остальную логику.
пиздец от джуна требуют, как будто он там будет архитектуру пилить. Хотя кого я обманываю просто я тупой и долго такое говно думаю.
cmd.exe, composer require phpmailer/phpmailer - это ведь нужно в директории vendor делать?
Подскажите, пожалуйста!
Боюсь сломать проект, там уже многое готово.
Что у тебя в composer.json написано? Ты обновляешь не то. Ты хочешь обнвоить phpmailer, а надо обновить расширение xyz-phpmailer от Юи.
Вот: http://ideone.com/GttUX6
Сейчас уже 4.7 версия его, а у меня ещё 4.0.
Да, Mailer.php ведь в xyz-phpmailer находится.
И как же его обновить теперь?
php composer.phar require --prefer-dist zyx/zyx-phpmailer "@stable" в папке vendor?
Я уже забыл, как устанавливал что через Composer.
Тебе надо почитать сначала вообще про композер и как он работает. Потому что ты постоянно все путаешь. Как можно пользоваться программой, не прочитав про нее?
composer.json ты дал не тот. Ты зачем-то мне дал composer.json от библиотеки phpmailer которая вообще отношения к проблеме не имеет.
И composer.json от xyz-phpmailer тоже не нужен.
Нужен основной composer.json, с помощью которого ты устанавливал Юи и плагины.
И что-то у меня ощущение, что ты фреймворк откуда-то скачал, а не композером ставил.
https://someapprentice.github.io/maintaskforlayout/
Проблемы со шрифтами в IE
Представляете, я заново сгенерировал .eot шрифты, и они заработали даже без прописывания своего имени в отдельном файле для IE Сначала они у меня не работали и в нём. Зато я приобрел бесценный опыт верстки под IE - для меня теперь это проще простого.
>>874513
>Также,мне кажется, не надо было определять шрифты для всех значений веса и стиля. Достаточно определить только для тех, что нужны на странице: напимер, обычный, тяжелый, сверхтяжелый.
>>875380
>> Firefox, кстати, всё равно выдает ошибки парсинга font-weight на значения bolder и lighter (если их убрать то ничего не изменится). Как такое может быть?
>Это относительный вес ("чуть потяжелее") и его не стоит указывать внутри font-face в любом случае, так как непонятно относительно чего его отсчитывать.
Я бы тоже хотел чтобы можно определить вес не численным значениями, но, как мы выяснили, для значений bolder и lighter нужно значение от которого эти значения будут отсчитываться.
>>875380
>Вот скриншот из ИЕ11: https://www.browserstack.com/screenshots/b5bec7763e6986c4898f75ece20e9d312e81834b/win10_ie_11.0.jpg
>Видно, что между шапкой и бледно-серым блоком есть белая полоска. Скорее всего у тебя там margin collapsing - маргин вывалился из шапки или из серого блока.
А можно уточнить где эта белая полоска? У меня на скриншоте ничего не видно. Я такую белую полосу вижу когда сжимаю окно меньше 320px - это оно?
>Когда задаешь font-size, стоит задавать и line-height. В абзаце текста под заголовком "Consectetur" например строки стоят очень тесно, правильный ли там line-height?
Я просто не заметил это, в фш интерлиньяж где-то явно не соответствует реальному. Приходиться на глаз определять или я что-то не знаю.
>Для иконок соцсетей надо сделать реакцию на наведение.
А что за реакцию? Когда мы наводим на них и так меняется указатель. Я думаю этого достаточно.
>>srcset="img\home_0003s_0001s_0022_Layer-1-Large.jpg"
>Я вижу, ты используешь srcset, но почему тут не указано разрешение картинки? Так и должно быть? Вот я статью нашел по теме, если что: http://frontender.info/webkit-implements-srcset-and-why-its-a-good-thing/
Не смог разобраться с этим, нужно писать srcset="img\home_0003s_0001s_0022_Layer-1-Large.jpg 270w 1x"?
https://someapprentice.github.io/maintaskforlayout/
Проблемы со шрифтами в IE
Представляете, я заново сгенерировал .eot шрифты, и они заработали даже без прописывания своего имени в отдельном файле для IE Сначала они у меня не работали и в нём. Зато я приобрел бесценный опыт верстки под IE - для меня теперь это проще простого.
>>874513
>Также,мне кажется, не надо было определять шрифты для всех значений веса и стиля. Достаточно определить только для тех, что нужны на странице: напимер, обычный, тяжелый, сверхтяжелый.
>>875380
>> Firefox, кстати, всё равно выдает ошибки парсинга font-weight на значения bolder и lighter (если их убрать то ничего не изменится). Как такое может быть?
>Это относительный вес ("чуть потяжелее") и его не стоит указывать внутри font-face в любом случае, так как непонятно относительно чего его отсчитывать.
Я бы тоже хотел чтобы можно определить вес не численным значениями, но, как мы выяснили, для значений bolder и lighter нужно значение от которого эти значения будут отсчитываться.
>>875380
>Вот скриншот из ИЕ11: https://www.browserstack.com/screenshots/b5bec7763e6986c4898f75ece20e9d312e81834b/win10_ie_11.0.jpg
>Видно, что между шапкой и бледно-серым блоком есть белая полоска. Скорее всего у тебя там margin collapsing - маргин вывалился из шапки или из серого блока.
А можно уточнить где эта белая полоска? У меня на скриншоте ничего не видно. Я такую белую полосу вижу когда сжимаю окно меньше 320px - это оно?
>Когда задаешь font-size, стоит задавать и line-height. В абзаце текста под заголовком "Consectetur" например строки стоят очень тесно, правильный ли там line-height?
Я просто не заметил это, в фш интерлиньяж где-то явно не соответствует реальному. Приходиться на глаз определять или я что-то не знаю.
>Для иконок соцсетей надо сделать реакцию на наведение.
А что за реакцию? Когда мы наводим на них и так меняется указатель. Я думаю этого достаточно.
>>srcset="img\home_0003s_0001s_0022_Layer-1-Large.jpg"
>Я вижу, ты используешь srcset, но почему тут не указано разрешение картинки? Так и должно быть? Вот я статью нашел по теме, если что: http://frontender.info/webkit-implements-srcset-and-why-its-a-good-thing/
Не смог разобраться с этим, нужно писать srcset="img\home_0003s_0001s_0022_Layer-1-Large.jpg 270w 1x"?
{
"name": "yiisoft/yii2-app-advanced",
"description": "Yii 2 Advanced Project Template",
"keywords": ["yii2", "framework", "advanced", "project template"],
"homepage": "http://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "http://www.yiiframework.com/forum/",
"wiki": "http://www.yiiframework.com/wiki/",
"irc": "//irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
},
"minimum-stability": "stable",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": ">=2.0.4",
"yiisoft/yii2-bootstrap": "",
"yiisoft/yii2-swiftmailer": "",
"zyx/zyx-phpmailer": "@stable"
},
"require-dev": {
"yiisoft/yii2-codeception": "",
"yiisoft/yii2-debug": "",
"yiisoft/yii2-gii": "",
"yiisoft/yii2-faker": ""
},
"config": {
"process-timeout": 1800
},
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
}
Вот основной composer.json.
Я ставил через Composer в режиме Development - иду по курсу от GeekBrains, расписываю подробно всё то, что говорит преподаватель, потом покажу анонам текст.
Я устанавливал ещё Bower и NPM, сам PHPMailer у меня в режиме stable.
Может, в этом причина? Там он мог давно не обновляться, конечно, но не с 2014-го же года...
Про Composer я почитаю, но мне бы ответ на этот вопрос помог, да.
Там вряд ли что найду - как обновить, там везде как установить просто.
Ну, попробую просто заново установить, да.
{
"name": "yiisoft/yii2-app-advanced",
"description": "Yii 2 Advanced Project Template",
"keywords": ["yii2", "framework", "advanced", "project template"],
"homepage": "http://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "http://www.yiiframework.com/forum/",
"wiki": "http://www.yiiframework.com/wiki/",
"irc": "//irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
},
"minimum-stability": "stable",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": ">=2.0.4",
"yiisoft/yii2-bootstrap": "",
"yiisoft/yii2-swiftmailer": "",
"zyx/zyx-phpmailer": "@stable"
},
"require-dev": {
"yiisoft/yii2-codeception": "",
"yiisoft/yii2-debug": "",
"yiisoft/yii2-gii": "",
"yiisoft/yii2-faker": ""
},
"config": {
"process-timeout": 1800
},
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
}
Вот основной composer.json.
Я ставил через Composer в режиме Development - иду по курсу от GeekBrains, расписываю подробно всё то, что говорит преподаватель, потом покажу анонам текст.
Я устанавливал ещё Bower и NPM, сам PHPMailer у меня в режиме stable.
Может, в этом причина? Там он мог давно не обновляться, конечно, но не с 2014-го же года...
Про Composer я почитаю, но мне бы ответ на этот вопрос помог, да.
Там вряд ли что найду - как обновить, там везде как установить просто.
Ну, попробую просто заново установить, да.
Б и В.
Потому что в Б цикл цикл выполнится хотя бы 1 раз, а потом проверится. В первом варианте вообще не выполнится.
Белая полоска на скриншоте https://www.browserstack.com/screenshots/b5bec7763e6986c4898f75ece20e9d312e81834b/win10_ie_11.0.jpg расположена между темным блоком в шапке (ниже кнопки See Portfolio) и светло-серым блоком с заголовком Consectetur. Полоска горизонтальная, высотой пикселей 20-30.
Если ее не видно, значит монитор плохо отображает оттенки серого, можно попробовать загрузить скриншот в графический редактор и повысить контраст/понизить яркость и я думаю тогда полоска станет видна. Ну или можно временно сделать фон на блоке Consectetur темнее.
У тебя там указана версия @stable. Я к сожалению, не знаю, как именно определяется "стабильность", скорее всего берется максимальная версия, в которой нет слов вроде dev.
Зайдем на packagist (официальный репозиторий композера), чтобы посмотреть, какая версия считается сейчас стабильной:
https://packagist.org/packages/zyx/zyx-phpmailer
Это 0.9.2
Зайдем в проект на гитхабе, в releases и найдем там 0.9.2, которой уже как 2 года с лишним: https://github.com/SDKiller/zyx-phpmailer/commits/0.9.2
Видно что в коммитах исправления бага нету. Оно вышло позже. Значит, надо брать не stable, а версию из dev-master.
Еще конечно есть вариант с помощью error_reporting игнорировать сообщения уровня E_DEPRECATED, но это по моему плохая идея.
Ну и если исправления не было бы, ты всегда имеешь возможность исправить ситуацию, форкнув репозиторий на свой аккаунт, внеся в него любые изменения и подключив библиотеку из своего гитхаба (надо поколдовать с repositories в composer.json).
надо исправить composer.json и сделать update.
Также, если есть желание, можно написать авторам этого composer.json (я не знаю, где ты го взял, это ведь не от разработчиков Юи наверно, а какая-то левая сборка?) и предложить им исправить версию пакета.
> Про Composer я почитаю, но мне бы ответ на этот вопрос помог, да.
Ты бы понял, как определить версию установленного пакета (по composer.json), ты бы нашел гитхаб проекта и issue с проблемой в нем. Просто у меня сложилось ощущение, что для тебя композер это черный ящик, и ты просто следуешь инструкциям в курсе, а как только что-то идет не так, теряешься. Потому стоит понимать, что в композере ничего такого необычного нет, он просто подбирает пакеты исходя их требований в разных composer.json и устанавливает их.
можно, но зачем?
Огромное человеческое спасибо, ОП!
неправильно йоба, хули ты всех в заблуждения вводишь
А почему ты считаешь комбинацию, при которой все монеты не выбраны? Я просто хочу понять, нужно ли ее считать, или нет?
Если все возможные суммы исходных чисел находить как сумму всех возможных сочетаний, то получается другой ответ С1монетыИз10+С2монетИз10+...С10монетИз10 = 1023. Но можно прибавить С0из10, тогда получится 1024. На эту сумму нельзя что-либо купить, и соответственно дать сдачу. Т.е. ряд двоичных чисел можно начать с 0000000001 а не с 0000000000.
монеты считаете,что все так плохо в пидорахии?
https://github.com/never3ver/fileshare
Попытался разобраться с тестированием, что-то там сделал, но наверно отложу эту тему, думаю лучше сначала с большими фреймворками познакомиться а потом уже в это лезть.
>>890378
Вот ссылки на архивач: https://www.google.ru/search?q=клуб+php+site:arhivach.org&btnG=Поиск&newwindow=1
Алсо в предыдущем треде (который я в архиваче не нахожу) есть ссылка https://docs.google.com/document/d/1H2H9h-UtaBGjrfmHh1ClbdJl1nH1Vx9wA6rAfcVbyEo/edit
Блин, опять засиделся за задачками, на работу опаздываю уже.
Тебе надо конкатинировать переменную $randomText в $name внутри цикла.
А потом $name вывести, как ты и выводишь.
Всё.
*конкатенировать
Очень сильно спасибо
Курсы пройди какие-нибудь, есть же. В принципе, что там может быть сложного? Скажешь, что работал с несколькими фреймворками, с тем же Бутстрапом, да и хватит, я думаю.
'^(?P<controller>[a-z-]+)/?(?P<action>[a-z-]+)?$'
Точнее меня интересует для чего здесь <controller> и <action>, какую роль они выполняют в этом случае? Всё остальное вроде бы понятно. Под этот паттерн подходят выражения вроде post/create и т.д. Сама регулярка используется при создании роутинга, как правила для названий контроллера и экшена
По сути, должно апдейтить цены, но нихуя не происходит, оптные макаки, подскажите.
даже вникать лень, нахуй сразу послан мешать верстку с пыхо кодом, перейди для начала на фреймворки, и делай rest контроллеры, а на клиенте angular\react\хоть небо, хоть аллаха
фреймворкобляди не нужны, что я захочу то сам сделаю на чистом ПХП и хуй соси Я УЖЕ ВСЕ ПОФИКСИЛ
>>890740
Я думал, что я видел дохуя хуевого когда на пыхе, но смотря на это у меня мигрень началась.
Если хочешь вкатиться нормально и чтобы люди не плевались от твоего кода - в шапке треда есть всё для новичков и для не новичков тоже есть много интересных вещей.
Я прочитал основы, у меня был опыт [h]говно[/h]кода на C#, дальше разбираюсь сам
Он к тому, что ты - быдлокодер.
>фреймворкобляди не нужны
>>890773
>фреймворкобляди не нужны
>Слушай, я всего 3 месяца на пыхе кодю, хуй знает что к чему вообще
Не надо переделывать собаку в человека, а человека — в собаку. Ничего хорошего из этого не получится.(с) профессор Преображенский
не понял прикол с собакой.
Суть в том что если хочешь помочь, можешь мыльцо оставить своё. Все совершали ошибки по началу, в чем твоя проблема?
>>890777
Каким образом проебался?
>>856303
https://arhivach.org/thread/193343/#819083
https://arhivach.org/thread/204328/#849196
https://arhivach.org/thread/204328/#856303
>>>>Также, у тебя в контроллере стоит 4 вызова render. Ты выносишь знание о структуре страницы в контроллер, но удобнее просто подключить один шаблон, а он уже пусть подключает что ему нужно.
>>Перенес рендеры из контроллера в шаблоны:
>>https://github.com/someApprentice/Students/commit/6b1fb52461786f9fe0966562c73b9f6f99968d5c
>Нет. ты пока не все перенес...
https://github.com/someApprentice/Students/commit/679a05c33e5ea62efb6e11c82c90c72e65cf33c1
Остальные исправления были здесь https://arhivach.org/thread/197740/#836646
В этих ссылках можно запутаться, но можете не сомневаться - ~99.9% ваших замечаний исправлены 0.1% это те которые я мог не заметить\забыть\потерять
Со Студентами мы разобрались?
>не понял прикол с собакой.
Лол, блджад.
И не надо, я не тебе писал.
>Суть в том что если хочешь помочь, можешь мыльцо оставить своё. Все совершали ошибки по началу, в чем твоя проблема?
>Каким образом проебался?
Просто ты хапанул лишнюю пару хромосом.
>Просто ты хапанул лишнюю пару хромосом.
А я вижу ты с рождения умеешь и на пыхе писать, и на чем угодно
Дело даже не в твоем говнокоде, а в том, что ты "с тугой резьбой"тупорылый.
>А я вижу ты с рождения умеешь и на пыхе писать, и на чем угодно
А тебе, с таким подходом к делу, и жизни не хватит, чтобы научиться нормально программировать хоть на чем-то.
Ожидаю вопроса: "скаким таким подходом?"
Отвечаю сразу: "иди нахуй тупица, даже это не можешь понять"
>Ожидаю вопроса: "скаким таким подходом?"
Даже не думал этот вопрос задавать, хули ты сразу.
>ты "с тугой резьбой"
Очень огромный смысл, говорить это человеку, который пытается хоть что-то сделать с минимальным опытом.
Я же хочу чтоб мне на ошибки показали, а не хуйню писали такие как ты, строя из себя Аллаха
>Я же хочу чтоб мне на ошибки показали, а не хуйню писали такие как ты, строя из себя Аллаха
Ясно.
Просто сейчас - это не реально.
А я про ошибки непосредственно в моём говнокоде. Я учел совет про фреймворки.
>мешать верстку с пыхо кодом
Ну тут уж извини, пока-что не умею по-другому.
>Ну тут уж извини, пока-что не умею по-другому.
Тогда спросил-бы как это делать, а не писать плохо про фрэймворки, которые очень хорошо решают эту проблему с помощью шаблонизаторов.
Поясняю на пальцах.
В одном файле .php ты описываешь логику.
А в другом ты пишешь весь html+все эти вызовы "echo".
Понимаешь?
>>890806
Я думал демчиками уже никто не пользуется.
А в этот дургой уже где-то в начале пишешь include_once("Ссылка на файл с логикой") ?
Что-то не получается у меня найти её
В графическом редакторе при увеличении должно хоть что-то показаться
Может это исправилось уже само?
Да.
Можно использовать еще require, он в случае ошибки остановит скрипт и плюнет ошибкой.
И скобки не обязательны.
И давай всему, что есть ИНФОРМАТИВНЫЕ имена (файлам, переменным, функциям и тд). Загугли как называть переменные или как оформлять код на php ну ты понел.
Хорошие люди даже сделали хорошую штуку - PSR
Просто знакомые попросили им сайт сделать, а я на отъебись начал клепать ибо правок у них дохуя, платить не хотят. Да и не спал день, туплю сильно.
Может быть. Если взять скриншот https://www.browserstack.com/screenshots/b5bec7763e6986c4898f75ece20e9d312e81834b/win10_ie_11.0.jpg - полоса есть. Видно ее?
Проверим, исправилась ли проблема. Я зашел на modern.ie и сделал там новый скриншот: https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/win10_ie_11.0.jpg
Полосы больше нет. Но я вижу такие вещи:
- меню упирается в правый край без паддинга, надо хотя бы 5px паддинга, ведь в книгах и журналах буквы не налезают на самый край странице (хотя может это из-за несовершенства технологий печати конечно). То же касается логотипа.
- список consecuter, tristlquet на такой ширине было бы выгоднее выводить в 2-3 колонки, а не вертикально. Если там сделать верстку теми же инлайн-блоками, то они будут подстраиваться сами под ширину страницы.
В версии для ИЕ8 ( https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/win7_ie_8.0.jpg ) отвалились картинки в блоке consecuter (там используется что-то из CSS3? В принипе, можно и без них конечно) и в блоке социальных кнопок внизу появились надписи.
В мобильной версии ( https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/ios_iPhone-6-Plus_8.3_portrait.jpg ) шрифт в шапке слишком большой. Наверно надо для мобильных устройств его уменьшить.
http://ekbkrasota.ru/
Да пожалуйста, блять, я уже недели 3-4 делаю эту хуйню. Заебался. Не дай аллах кому попадется такой чел.
Знаешь что самое интересное, ведь по началу был хороший код.
>>890794
Не надо тут писать такие вещи. Ты вряд ли врач, и вряд ли можешь сделать выводы дистанционно.
Да и многим программистам какой-то гениальности и не требуется, решают типовые задачи для которых давно известно решение. Усидчивость и любовь читать статьи и документацию, однако, нужна.
>>890763
Проповедовать невежество в другие треды плиз. У нас можно проповедовать только пользу от серьезного и глубокого изучения технологий.
>>890761
Если вникать лень, может и комментарий писать не стоит?
Чтобы использовать реакт или ангулар, нужно понимать всякие концепции, MVC для начала. Хотя многие конечно это пропускают, ну не знаю, какой у них в итоге код получается.
>>890740
- разнеси отдельно логику и шаблоны в соответствие с MVC ( http://www.phpinfo.su/articles/practice/shablony_v_php.html https://github.com/codedokode/pasta/blob/master/arch/mvc.md )
- не пиши HTML код внутри echo, это неудобно
- вынеси код работы с БД отдельно от работы с формой
В общем, в нынешнем коде разбираться не особо хочется. Пожалуй, я на это тратить время не буду.
Тебе надо поучиться для начала даже не ООП, а просто процедурному программированию с функциями.Разбей свою простыню кода на отдельные задачи и разнеси их по функциям. Нужно учиться мыслить более высокуровнево, не "скопировать значение из переменной в массив", а "проверить данные функцией валидации".
>>890804
Тебе рано брать фреймворки. Для начала стоит поизучать функции, ООП, MVC.
>>890794
Не надо тут писать такие вещи. Ты вряд ли врач, и вряд ли можешь сделать выводы дистанционно.
Да и многим программистам какой-то гениальности и не требуется, решают типовые задачи для которых давно известно решение. Усидчивость и любовь читать статьи и документацию, однако, нужна.
>>890763
Проповедовать невежество в другие треды плиз. У нас можно проповедовать только пользу от серьезного и глубокого изучения технологий.
>>890761
Если вникать лень, может и комментарий писать не стоит?
Чтобы использовать реакт или ангулар, нужно понимать всякие концепции, MVC для начала. Хотя многие конечно это пропускают, ну не знаю, какой у них в итоге код получается.
>>890740
- разнеси отдельно логику и шаблоны в соответствие с MVC ( http://www.phpinfo.su/articles/practice/shablony_v_php.html https://github.com/codedokode/pasta/blob/master/arch/mvc.md )
- не пиши HTML код внутри echo, это неудобно
- вынеси код работы с БД отдельно от работы с формой
В общем, в нынешнем коде разбираться не особо хочется. Пожалуй, я на это тратить время не буду.
Тебе надо поучиться для начала даже не ООП, а просто процедурному программированию с функциями.Разбей свою простыню кода на отдельные задачи и разнеси их по функциям. Нужно учиться мыслить более высокуровнево, не "скопировать значение из переменной в массив", а "проверить данные функцией валидации".
>>890804
Тебе рано брать фреймворки. Для начала стоит поизучать функции, ООП, MVC.
Работает.
Форма ПОЛУЧИТЬ КОНСУЛЬТАЦИЮ не работает.
Такое кстать и без php можно сделать за часик. Это если еще такие просьбы будут.
Сомневаюсь. Человек обычно всегда пишет в одинаковой манере и специально писать хуже, чем обычно, неудобно.
>>890761
Не надо в такой манере писать комментарии, лучше вообще ничего не писать тогда.
>>890763
И в такой тоже.
>>890712
Это именованные подмаски: http://php.net/manual/ru/regexp.reference.subpatterns.php
В результате при вызове preg_match они кладут подстроку в массив не под числовым, а под строковым индексом.
http://php.net/manual/ru/function.preg-match.php - тут смотри примеры кода.
>>890637
Вот ты говоришь, что знаешь обычную верстку, но не знаешь адаптированную, это как? Это ведь скорее всего значит что ты и обычную не знаешь.
HTML задуман, чтобы страницы могли отображаться на разных устройствах с разными размерами экранов. Если ты привык все прибивать гвоздями и жестко указывать размеры, это значит, что CSS ты толком не изучил (и кстати у нас есть в ОП посте задачки на него и там вся верстка нужна резиновая).
Если же тебя интересуют общие принципы, то в адаптивной верстке делают дополнительные CSS правила, которые применяются например на экранах меньше определенной ширины, или отдельные правила для печати (ну например на печати можно после ссылки печатать ее адрес, так как иначе непонятно куда она ведет).
Обычно на экранах маленькой ширины содержимое сайта выстраивается в одну колонку, вертикально. То есть страница выводится так, чтобы ее удобно было читать на узком экране смартфона, прокручивая только вертикально, и без зума.
Технически это делается с помощью @media-правил (медиазапросов) и метатега meta viewport. Погугли и изучи их.
ну например:
- https://habrahabr.ru/company/google/blog/173861/
- https://html5book.ru/css3-mediazaprosy/
- http://frontender.com.ua/mobile-web/wtf-viewport/
Также погугли статьи вроде "лучшие отзывчивые сайты" и посмотри примеры там. Ты можешь имитировать узкий экран, сделав окно браузера узким или исплоьзуя "режим тестирования адаптивной верстки" (иконка смартфона) в отладчике браузера (Ctrl + SHift + I). А если у тебя есть смартфон, ты можешь открывать сайты на нем и сравнивать с обычной версией.
> если у всего остального что я учил вроде ООП на ПХП был чёткий алгоритм работы и обучения, то в адаптивной вёрстке всё как-то меняется в зависимости от случая, поэтому я никак не могу понять само ядро этой технологии.
А ты сам CSS изучил хорошо? Например, знаешь отличия вестки горизонтально идущих блоков инлайн-блоками от верстки флоатами? Если нет, то тебе надо изучить позиционирование, то есть способы, с помощью которых мы задаем относительное расположение блоков.Также, надо изучать, как верстать резиново, то есть с укзанием размеров в процентах либо с автоматическим определением размеров. То есть прежде чем браться за адаптивность, стоит полностью разобраться с позиционированием и резиновой (подстраивающейся под ширину) версткой. У нас в Оп посте есть задачки по теме.
Сомневаюсь. Человек обычно всегда пишет в одинаковой манере и специально писать хуже, чем обычно, неудобно.
>>890761
Не надо в такой манере писать комментарии, лучше вообще ничего не писать тогда.
>>890763
И в такой тоже.
>>890712
Это именованные подмаски: http://php.net/manual/ru/regexp.reference.subpatterns.php
В результате при вызове preg_match они кладут подстроку в массив не под числовым, а под строковым индексом.
http://php.net/manual/ru/function.preg-match.php - тут смотри примеры кода.
>>890637
Вот ты говоришь, что знаешь обычную верстку, но не знаешь адаптированную, это как? Это ведь скорее всего значит что ты и обычную не знаешь.
HTML задуман, чтобы страницы могли отображаться на разных устройствах с разными размерами экранов. Если ты привык все прибивать гвоздями и жестко указывать размеры, это значит, что CSS ты толком не изучил (и кстати у нас есть в ОП посте задачки на него и там вся верстка нужна резиновая).
Если же тебя интересуют общие принципы, то в адаптивной верстке делают дополнительные CSS правила, которые применяются например на экранах меньше определенной ширины, или отдельные правила для печати (ну например на печати можно после ссылки печатать ее адрес, так как иначе непонятно куда она ведет).
Обычно на экранах маленькой ширины содержимое сайта выстраивается в одну колонку, вертикально. То есть страница выводится так, чтобы ее удобно было читать на узком экране смартфона, прокручивая только вертикально, и без зума.
Технически это делается с помощью @media-правил (медиазапросов) и метатега meta viewport. Погугли и изучи их.
ну например:
- https://habrahabr.ru/company/google/blog/173861/
- https://html5book.ru/css3-mediazaprosy/
- http://frontender.com.ua/mobile-web/wtf-viewport/
Также погугли статьи вроде "лучшие отзывчивые сайты" и посмотри примеры там. Ты можешь имитировать узкий экран, сделав окно браузера узким или исплоьзуя "режим тестирования адаптивной верстки" (иконка смартфона) в отладчике браузера (Ctrl + SHift + I). А если у тебя есть смартфон, ты можешь открывать сайты на нем и сравнивать с обычной версией.
> если у всего остального что я учил вроде ООП на ПХП был чёткий алгоритм работы и обучения, то в адаптивной вёрстке всё как-то меняется в зависимости от случая, поэтому я никак не могу понять само ядро этой технологии.
А ты сам CSS изучил хорошо? Например, знаешь отличия вестки горизонтально идущих блоков инлайн-блоками от верстки флоатами? Если нет, то тебе надо изучить позиционирование, то есть способы, с помощью которых мы задаем относительное расположение блоков.Также, надо изучать, как верстать резиново, то есть с укзанием размеров в процентах либо с автоматическим определением размеров. То есть прежде чем браться за адаптивность, стоит полностью разобраться с позиционированием и резиновой (подстраивающейся под ширину) версткой. У нас в Оп посте есть задачки по теме.
Не согласен с твоим подходом. Внедрение толстого клиента на JS сильно усложняет приложение, и должны быть обоснования расходам на это усложнение. Такое обычно советуют те, кто не осилил серверные языки, и потому хочет писать больше на яваскрипте.
В твоем случае у нам фактически получается 2 приложения (клиент + сервер), которые надо поддержвать, плюс АПИ между ними. Код получается сложнее, сайт грузится и работает медленнее.
Не так давно какие-то иностранные чуваки решили похвастаться сделанным сайтом на HN: https://whosfiring.com/ (всего 3 недели прошло и уже не работает)
дискуссия на HN: https://news.ycombinator.com/item?id=12956243
Эти чуваки сделали мегабайтное яваскрипт-приложение на Ember, чтобы отправить запрос через REST API и вывести на странице 10 ссылок с абзацем текста. Любому понятно, что сразу отдать с сервера страницу с 10 ссылками было бы быстрее и с точки зрения времени загрузки сайта, и с точки зрения разработки. (Ну ОП конечно зашел в тред и пояснил им, в чем они не правы).
Не надо тащить клиенсткие приложения там, где они не нужны и не дают преимуществ. Так же как не надо арендовать строительный кран для постройки собачьей будки.
Ты можешь сделать так:
- завести переменную, положить в нее пустую строку, и на каждом шаге цикла прибавлять к ней слог с помощью оператора-точки
- завести массив, на каждом шаге цикла класть в него слог, в конце склеить элементы с помощью implode
>>889959
А ты читал статью про выпечку хлеба на хабре? Вот у меня первое ощущение такое: ты зачем-то решил использовать все паттерны, которые видел в книгах. Идти надо от простого к сложному, а не планировать сложную архитектуру изначально.
Ну и еще, я бы советовал ознакомиться с Симфони 2. Это фреймворк для сложных приложений, и ты сможешь сравнить свой подход с другим, и может что-то полезное перенять (или понять, что свой фреймворк писать уже не нужно).
> Есть некий общий класс StorageCore, который включает в себя экземпляры всех storage models и через этот общий класс происходит работа с этими экземлярами
Вот это уже усложнение, не очень понятно ради чего. для разных сущностей там будут разные методы и обощить их не получится.
> А StorageCore будет подгружать нужную реализацию этих моделей, чтобы в одном случае работать с БД, а в другом работать, например, с файлами, не меняя при этом всю остальную логику.
Это сложная штука. Подменить код для работы с БД кодом для работы с файлами сложно. Ну приведу пример: если у тебя есть SQL запрос на несколько таблиц, тебе придется писать его аналог обычным кодом. И при любых изменениях придется делать двойной объем работы. На мой взгляд, оно того не стоит. Проще поменять способ тестирования.
Майкрософт пытался решить эту проблему в C#. Они сделали LINQ, это напоминающий SQL синтаксис, который позволяет одинаково работать с коллекицями (массивами) как с базой данных. Также есть библиотеки, которые транслируют LINQ в SQL запросы и таким образом, один и тот же код может выбирать данные как из таблицы, так и из массива. Вот пример:
... result = from u in users
where u.CreditLimit.Value > 20000
select new
{
u.FirstName,
u.LastName,
u.Address1_City
};
Это очень продвинутая штука. Ну например, ты можешь в условие WHERE передать анонимную функцию вида x => x > 10 и она сама разберет код этой функции и сделает из нее аналогичное SQL условие. Ты замучаешься делать аналог этой технологии.
Но зато LINQ позволяет одним кодом делать выборку как из БД, так и из других источников данных.
В PHP что-то отдаленно похожее есть в ORM Доктрине. Там есть свой язык DQL, и она разбирает запросы на нем, генерируя SQL. Теоретически можно написать интерпретатор таких запросов, который позволит их выполнять не на базе данных, а на массиве. Это долго и сложно. Я предложил использовать DQL вместо SQL, так как для него уже есть парсер. Хотя если погуглить, можно и для SQL найти парсер: https://github.com/greenlion/PHP-SQL-Parser
Это, как я сказал, долго. Кроме того, тебе придется учиться оптимизировать запросы, использовать индексы, чтобы они выполнялись быстрее. Хотя получился бы интересный проект, и было бы интересно выложить его в опен сурс. Он бы многим пригодился, но не уверен что ты один его потянешь.
Другой подход - отказаться от чистого SQL и составлять запросы с помощью Query Builder, так:
$b = $em->createQueryBuilder();
$b->from('users', 'u');
$b->andWhere('u.karma > 10');
$b->orderBy('u.name');
И опять же, написать свой код, который сможет такие запросы выполнять на массивах. Но писать запросы таким образом очень неудобно.
В общем, поддерживать 2 набора репозиториев - очень неудобно. А чтобы иметь возможность один запрос выполнять и с базой, и с массивом, надо писать сложные библиотеки. Проще поменять методику тестирования и тестировать на отдельной тестовой базе данных.
Есть разные варианты, например, можно перед тестом очищать базу и загружать в нее заранее опрделенные данные (fixtures). Можно тест заворачивать в транзакцию, и делать rollback (откат) в конце.
Ты можешь сделать так:
- завести переменную, положить в нее пустую строку, и на каждом шаге цикла прибавлять к ней слог с помощью оператора-точки
- завести массив, на каждом шаге цикла класть в него слог, в конце склеить элементы с помощью implode
>>889959
А ты читал статью про выпечку хлеба на хабре? Вот у меня первое ощущение такое: ты зачем-то решил использовать все паттерны, которые видел в книгах. Идти надо от простого к сложному, а не планировать сложную архитектуру изначально.
Ну и еще, я бы советовал ознакомиться с Симфони 2. Это фреймворк для сложных приложений, и ты сможешь сравнить свой подход с другим, и может что-то полезное перенять (или понять, что свой фреймворк писать уже не нужно).
> Есть некий общий класс StorageCore, который включает в себя экземпляры всех storage models и через этот общий класс происходит работа с этими экземлярами
Вот это уже усложнение, не очень понятно ради чего. для разных сущностей там будут разные методы и обощить их не получится.
> А StorageCore будет подгружать нужную реализацию этих моделей, чтобы в одном случае работать с БД, а в другом работать, например, с файлами, не меняя при этом всю остальную логику.
Это сложная штука. Подменить код для работы с БД кодом для работы с файлами сложно. Ну приведу пример: если у тебя есть SQL запрос на несколько таблиц, тебе придется писать его аналог обычным кодом. И при любых изменениях придется делать двойной объем работы. На мой взгляд, оно того не стоит. Проще поменять способ тестирования.
Майкрософт пытался решить эту проблему в C#. Они сделали LINQ, это напоминающий SQL синтаксис, который позволяет одинаково работать с коллекицями (массивами) как с базой данных. Также есть библиотеки, которые транслируют LINQ в SQL запросы и таким образом, один и тот же код может выбирать данные как из таблицы, так и из массива. Вот пример:
... result = from u in users
where u.CreditLimit.Value > 20000
select new
{
u.FirstName,
u.LastName,
u.Address1_City
};
Это очень продвинутая штука. Ну например, ты можешь в условие WHERE передать анонимную функцию вида x => x > 10 и она сама разберет код этой функции и сделает из нее аналогичное SQL условие. Ты замучаешься делать аналог этой технологии.
Но зато LINQ позволяет одним кодом делать выборку как из БД, так и из других источников данных.
В PHP что-то отдаленно похожее есть в ORM Доктрине. Там есть свой язык DQL, и она разбирает запросы на нем, генерируя SQL. Теоретически можно написать интерпретатор таких запросов, который позволит их выполнять не на базе данных, а на массиве. Это долго и сложно. Я предложил использовать DQL вместо SQL, так как для него уже есть парсер. Хотя если погуглить, можно и для SQL найти парсер: https://github.com/greenlion/PHP-SQL-Parser
Это, как я сказал, долго. Кроме того, тебе придется учиться оптимизировать запросы, использовать индексы, чтобы они выполнялись быстрее. Хотя получился бы интересный проект, и было бы интересно выложить его в опен сурс. Он бы многим пригодился, но не уверен что ты один его потянешь.
Другой подход - отказаться от чистого SQL и составлять запросы с помощью Query Builder, так:
$b = $em->createQueryBuilder();
$b->from('users', 'u');
$b->andWhere('u.karma > 10');
$b->orderBy('u.name');
И опять же, написать свой код, который сможет такие запросы выполнять на массивах. Но писать запросы таким образом очень неудобно.
В общем, поддерживать 2 набора репозиториев - очень неудобно. А чтобы иметь возможность один запрос выполнять и с базой, и с массивом, надо писать сложные библиотеки. Проще поменять методику тестирования и тестировать на отдельной тестовой базе данных.
Есть разные варианты, например, можно перед тестом очищать базу и загружать в нее заранее опрделенные данные (fixtures). Можно тест заворачивать в транзакцию, и делать rollback (откат) в конце.
Ну и вместо написания своих Storage Models, советую рассмотреть вариант использовать готовый ORM вроде Doctrine или другой. Хотя у них и недостатки тоже есть.
> 2 - Domain Models - модели-объекты записей данных. Т.е. каждый экземпляр этого класса представляет собой конкретную запись в БД.
Так делают, но лучше писать не "модель представляет запись в БД", а "модель отображается на БД", то есть подчеркнуть что модель у нас первична, а база лишь служит для ее хранения.
> Service Models - модели-сервисы,
Правильнее просто сервисы. Сервисы это часть модели в MVC, но их так, как ты, никто не называет.
> Bind Models - модели, которые получают данные от пользователя (формы, get-запросы)
Это называется формы. В Симфони есть компонент Symfony Forms (его можно использовать отдельно) для работы с формами и валидации. Он умеет автоматически переносить данные из моделей в форму и обратно.
> и затем обращаются к service models, получая необходимые данные
Вот уже пошло усложнение. А почему форма должна сама куда-то обращаться и передавать данные? Почему форма должна знать про сервисы? лучше разделять задачи и сделать чтобы форма отвечала только за работу с POST-данными. А куда их дальше передать, пусть решает контроллер.
> View Models - модели, которые являются тем же набором разного рода domain models. Эти модели далее передаются во View (т.е. внутри себя содержат еще какие-то вспомогательные методы, к которым мы обращаемся из View.
Опять выглядит как усложнение, что мешает передавать во вью сразу Domain Models? view model как правило не используется в серверном коде, только в клиентском варианте MVC с паттернами вроде data binding.
Я советую тебе не усложнять без надобности и почитать туториалы по Симфони. Многие компоненты Симфони можно использовать отдельно, и ты можешь даже собрать из них свой фреймворк.
Код вроде работает. Но выражение в строке лучше заключать в фигурные скобки ( http://php.net/manual/ru/language.types.string.php#language.types.string.parsing ) и избавиться от повтора кода, например, циклом.
Также, можно сделать цикл, описывающий структуру стиха:
[$word1, ' ', $word2, ' ', ...]
И генерировать стих по нему.
Она принимает на вход SQL запрос, анализирует, а на выходе выдает что-то вроде дерева AST, который содержит структуру запроса. По этому дереву можно понять, какой у нас вид запроса, с какими таблицами он работает, по каким условиям делает сортировку и тд.
Посмотрите на код библиотеки, оцените используемые алгоритмы, подумайте, удобно ли:
- поддерживать код
- искать в нем баги и исправлять их
- расширять код, ну например, добавить какой-то новый синтаксис
- использовать код, ну допустим у вас есть задача найти все упоминаемые в SQL запросе названия таблиц или например оценить число строк, которое выберет запрос
Что бы вы предложили поменять? Как бы вы решали такую задачу?
Заметьте, что в библиотеке есть тесты. В них можно посмотреть примеры ее использования.
>>890895
>искать в нем баги и исправлять их
Система ошибок так себе
>>890895
Нужен парсер грамматики
>>использовать код, ну допустим у вас есть задача найти все упоминаемые в SQL запросе названия таблиц или например оценить число строк, которое выберет запрос
PVS Studio только для SQL
>- поддерживать код
Ну вы понели))
Да у вас архитектуры как таковой я и не заметил.
Просмотрел вакансии на back-end разработчика, и практически нигде не написано в требованиях "алгоритмы".
Это маст хэв вещь?
ты ето прислал? Просто я сейчас ввел все и у меня заработало.
Есть абстрактный класс Model, у него наследники Employee и Department.
Есть абстрактный класс TableDataGateway, у него наследники EmployeeTDGW и DepartmentTDGW
Я в классе TableDataGateway пишу: abstract public function add(Model $object); - подразумевая, что можно передавать только Model и её наследников
В дочерних классах я хочу видеть что-то типа public function add(Department $department) - уточняю, что не любой Model, а только Department
Но выскакивает warning кричащий о несоответствии типов. Пришлось в наследниках так-же прописывать Model в качестве переданных параметров.
Как можно сделать такое уточнение и что-бы валидатору понравилось моё решение?
Наследование это вид отношения "А является подмножеством B", то есть мы в любой момент можем подставить вместо родительского класса дочерний и всё должно быть ок, так как наследник именно расширяет родительский класс, а не уточняет, в противном случае нарушается контракт. Это один из принципов SOLID.
Я бы взял готовую ОРМ в твоём случае.
Либо делай отдельный
public function addDepartment (Department $department)
Либо в методе проверяй тип с помощью instanceof
Есть правило, что объект класса-наследника можно использовать вместо объекта-предка. Соответственно, при наследовании можно расширять базовый класс, но нельзя отбирать какие-то возможности.
Уточняя тайп-хинт, ты делаешь функцию несовместимой с функцией в базовом классе, так как она принимает меньший набор объектов.
Можно считать это особенностью наследования. Есть еще другие известные проблемы, например проблема квадрата и прямоугольника: http://sergeyteplyakov.blogspot.ru/2014/09/liskov-substitution-principle.html
В твоем случае можно конечно в классе-наследнике поставить проверку через if .. instanceof, но это будет лишь попытка костылем обойти принцип Лисков.
Давай подумаем: а почему вообще мы решили сделать много методов add, свой в каждом классе? Если у них одинаковый принцип работы, мы ведь можем сделать один такой универсальный метод в базовом классе. А раз мы хотим в каждом классе делать свой add, то может быть это разные методы, не имеющие ничего общего? К тому же может оказаться, например, что в каких-то классах там будут еще дополнительные аргументы.
Так что я думаю, надо либо делать универсальный метод add, либо признать что это разные, никак не связанные друг с другом методы.
Возможно ты хотел сделать абстрактный метод, чтобы требовать от наследников возможность делать вставку. В этом случае надо сделать один метод add в базовом классе, а абстрактным сделать метод вроде getTableName().
Если программировать умеешь (независимо от языка), то можешь и не трогать.
Лучше брось эту идею и иди изучать Node.JS. Там синтаксис почти повторяет Питон и Руби, это более модная технология, и наверняка ты уже яваскрипт знаешь на достаточном уровне.
Пробовал примерно год назад - слишком много жс-лапшы получается(ну это я еще пхп не пробовал, лол). Модная технология, то модная. Но с таким же успехом можно и в сторону го какого-нибудь посмотреть
Не делай так, это говнокод. Методы дочерних классов должны полностью соответствовать методам родительских. Если нужно что-то новое, пиши новый метод или используй композицию.
Рисует всякие интересные графики: https://gosmonitor.ru/mob/229
И отчеты: https://gosmonitor.ru/expertresult/82982
В общем, сделано неплохо, хотя конечно страница с графиками у меня в браузере тормозит при прокрутке. Идея грамотная, чтобы сделать единый мониторинг для сотен государственных сайтов. Я даже удивился, не ожидал такого прогресса от государства.
Если вспомнить провал с дорогущим американским сайтом по здравоохранению, то у нас все не так и плохо. Потихоньку все это развивается, что радует.
Хотя конечно методику оценки открытых данных, на мой взгляд, переусложнили: https://gosmonitor.ru/expertresult/235712
> 20
> Информация о приложениях, разработанных на основе размещенных наборов открытых данных
Не думаю, что это нужно.
ого гусьмонитор есть ахуеть прогресс, заживем, завтра же доктора перестанут всем зеленкой мазать анус, прописывать глицын, свежий воздух сон и утреннюю зарядку вместо блять реальных лекарств, ВСД и астения станут страшной байкой для молодых врачей.
>- меню упирается в правый край без паддинга, надо хотя бы 5px паддинга, ведь в книгах и журналах буквы не налезают на самый край странице (хотя может это из-за несовершенства технологий печати конечно). То же касается логотипа.
Добавил отступы: https://github.com/someApprentice/maintaskforlayout/commit/d3fc44bc664b9ea61a7aefef33a072e2fec35a64
>- список consecuter, tristlquet на такой ширине было бы выгоднее выводить в 2-3 колонки, а не вертикально. Если там сделать верстку теми же инлайн-блоками, то они будут подстраиваться сами под ширину страницы.
Изначально так и было, но когда места хватало только на 3 блока, то один лишний блок вставал где-то отдельно. Мне показалось это не красиво, и я решил что будет лучше вывести их все в одну колонку.
>В версии для ИЕ8 ( https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/win7_ie_8.0.jpg ) отвалились картинки в блоке consecuter (там используется что-то из CSS3? В принипе, можно и без них конечно) и в блоке социальных кнопок внизу появились надписи.
А ведь это всего лишь проблема в том что в старых браузерах, поддерживающие css2, используется одинарное двоеточие, а новые, с css3, поддерживают двойные. При этом новые браузеры не отказываются поддерживать и одинарные, но почему-то я выбрал именно двойные одинарные двоеточия в соц.сетях это должно быть ошибкой и не могу вспомнить почему... Значит, если можно решить что можно и без них, то я предпочту так и сделать, потому что не хочу определять появление надписей отдельно от IE8.
>В мобильной версии ( https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/ios_iPhone-6-Plus_8.3_portrait.jpg ) шрифт в шапке слишком большой. Наверно надо для мобильных устройств его уменьшить.
Уменьшил шрифт (и нечаянно вместе с этим закоммитил исправление с двойными двоеточиями): https://github.com/someApprentice/maintaskforlayout/commit/97590807dc8da1d88e4e738b7f0c8a336ecf585b
>Если вспомнить провал с дорогущим американским сайтом по здравоохранению, то у нас все не так и плохо. Потихоньку все это развивается, что радует.
А я никогда не сомневался в отечественных ИТ'шниках. Уверен что в службе безопасности всё на высшем мировом уровне с этим. Если по вашему мнению это только начало развития, то меня это только радует, потому что это даёт большой простор для меня где можно заработать.
>^\\s(8|([+]\\s7))...
Дальше нужно чекать 10цифр, пока придумал просто написать кусок, а потом его 10раз скопировать, но есть ли способ лучше? Уже 3-тий или 4-ый день пытаюсь придумать, чёто нихуя.
Можно ещё вот так как-нибудь сократить, но всё равно, может целиком выражение можно записать?
https://github.com/anotherCodeMunkey/fileshare
Что-то нихуя не работает. Если точнее, то надо вытащить из БД цифру последнюю самую.
Все, отбой, заработало.
>Вот ты говоришь, что знаешь обычную верстку, но не знаешь адаптированную, это как? Это ведь скорее всего значит что ты и обычную не знаешь.
Возможно ты прав, я знаю принципы адаптивной вёрстки, и вроде бы их применяю, но когда дело доходит до реального проекта вылезают всякие недочёты, что-то не получается выравнять так как нужно потому что что-то другое мешает. Ну а вообще мне не принципиально считать сейчас знаю я обычную вёрстку или нет, мне надо изучить адаптивную вёрстку, чтобы иметь все необходимые скилы для получения работы. Для меня адаптивная вёрстка сложнее даже чем ООП в ПХП, не знаю почему
Новички часто верстают абсолютами и/или жестким позиционированием, с виду получается похоже на макет, но такой метод верстки чреват бессонными ночами в будущем, потому что тебе придется практически заново всё верстать под каждый медиа.
То-есть не зацикливайся над каким-то конкретным элементом конкретной страницы, сперва сделай каркас без жестких рамок и он будет уже по своему адаптивным, пользуйся REM, EM для font-size. Пользуйся процентами и готовыми grid'ами, но если тебе нужна только сетка в проекте - не тащи весь пак того же бутстрапа, возьми только сетку. Я не верстальщик, могу в чем-то быть не прав, но версткой занимался когда только взяли на работу.
Две половинки твоего мозга ненавидят друг друга, из-за этого должны ненавидеть друг друга животные?
Ты настолько даун, что свою обертку для curla написать не можешь? Даже я их пишу, уж на что юниор.
>>866133
Ну что, проверим-ка файлообменник. Сразу же скажу по поводу скриншотов - нужно было перед каждым поставить хотя бы строчку текста, а то для увидевшего их первый раз довольно трудно понять, где заканчивается одна страница и начинается следующая. Но хорошо, что они у тебя есть, можно сразу оценить верстку, не заглядывая в код.
Также, я вижу, что верстка кривоватая. Ну например, высота кнопки не совпадает с высотой поля ввода слева, форма комментирования тоже кривая. Ты уже дошел до файлообменника, это довольно серьезный уровень, и если знания HTML/CSS у тебя не соответствуют знанию серверных технологий, то у нас есть задачки по CSS в ОП посте.
В реальном проекте вряд ли тебе выделят персонального верстальщика, и делать какие-то простые вещи ты должен уметь сам. Вообще, верстальщики - это часто недоучившиеся программисты, и ты в общем-то должен знать не меньше них.
Там, где выводятся подробности о файле, не хватает единиц измерения. "Частота дискретизации: 44100". 44100 чего?
Кнопки "скачать" и "удалить" стоило расположить горизонтально, и кнопку удаления сделать менее заметной, например, в виде ссылки или в виде обычной белой кнопки. Дело в том, что большая синяя кнопка называется "primary", "основная", и 2 основных кнопки - это как-то нелогично. То есть это скорее замечание по интерфейсу, не надо визуально выделять слишком много элементов (ну и кстати, заголовок комментария, который такого же яркого цвета, как и кнопка, тоже как-то отвлекает на себя внимание от кнопки "ответить").
"Подтвердите... Подумай..." - лучше тогда было написать "Подтверди". Да, это не замечания по коду, но в реальном проекте у тебя вряд ли будет персональный корректор, который будет за тобой исправлять сообщения и лучше учиться обращать внимание на такие вещи. И сразу же на будущее скажу, не смешивай английские и русские сообщения в одном интерфейсе ("размер: 11.3 Mb" -> "размер: 11,3 Мб").
> Время загрузки: 2016-10-31
Ой-ой, какой роботизированный формат. В русском языке даты обычно пишут либо как "31.10.2016", либо "31 октября 2016".
> composer.phar
Это не твой код, ему в репозитории делать нечего. Стоит добавить его в gitignore и убрать из репозитория.
https://github.com/TheSidSpears/FileHosting/blob/master/httpd.conf
Тут в примере конфига блок с localhost явно лишний и не относится к файлообменнику.
https://github.com/TheSidSpears/FileHosting/blob/master/filehosting.sql#L31
> `path` mediumtext NOT NULL,
MEDIUMTEXT - это текст размером до 16 мегабайт по моему, и это многовато для пути. Также, по полям типа TEXT по моему нельзя делать индексы, так что тут однозначно лучше исплоьзовать varchar. Индексы обязательно нужны, иначе после нескольких тысяч комментариев в таблице все начнет работать небыстро (советую статью http://ruhighload.com/post/Работа+с+индексами+в+MySQL для ознакомления).
К parentId в таблице comments должен быть добавлен внешний ключ. Вообще, любые поля, которые ссылаются на другие поля, надо оформить как внешние ключи.
В таблице файлов не очень понятно зачем разделять путь к файлу на path и name.
> `size` int(11)
int принимает значения от -2 до +2 млрд. То есть у тебя нельзя хранить файлы больше 2 Гб.
> `mime` text,
TEXT содержит до 65535 байт. Многовато для маленькой строки.
> `numberOfDownloads` int(255)
255 тут рекомендуемая ширина колонки для вывода числа (на хранение оно никак не влияет). Не многовато ли?
https://github.com/TheSidSpears/FileHosting/blob/master/public/index.php#L3
> if (PHP_SAPI == 'cli-server') {
Хотя так можно, я бы вынес код роутинга для встроенного в php сервера в отдельный файл, например cli-server.php. Хотя с другой стороны, он небольшой и особо не мешает. И это, как я понимаю, разработчики Слима такое придумали.
https://github.com/TheSidSpears/FileHosting/blob/master/src/settings.php#L9
> 'addContentLengthHeader' => false, // Allow the web server to send the content-length header
А в чем смысл этой настройки? Зачем отключать этот заголовок?
Мне, конечно, кажется, что файл настроек получился какой-то громоздкий. Хорошо бы хранить там только те настройки, которые пользователь может поменять, а те, что не может, хранить где-то в коде. Как я понимаю, это опять же придумали разработчики Слима, что-то мне это не очень нравится. Какой смысл смешивать пользовательские и внутренние настройки? Вообще, мне это разделение на seetings.php/dependencies и так далее, не нравится. Во втором слиме все просто писалось в одном файле, и предполагалось, что кода будет немного, и потому можно его хранить в одном файле. Ну и читать было легко и удобно. А сейчас они раскидали все по 4 файлам, и я не вижу, какие это преимущества дает.
И разбиение на файлы ведь нельзя сравнить с разбиением на функции или классы. Функцию можно вызвать, а вот файлы эти из любого места кода приинклюдить нельзя - они заточены на подключение только из index.php. Спрошу-ка у авторов шаблона приложения на гитхабе.
Ну к примеру, представим, что мы хотим сделать программу для командной строки и в ней использовать контейнер. Как ее инициализировать? В студентах мы делали файл bootstrap.php, который инициализирует приложение, а тут - придется видимо копипастить код из index.php.
Насчет папки classes, она, мне кажется, не нужна, так как в современных приложениях 95% кода - это классы и незачем лишний раз об этом напоминать.
https://github.com/TheSidSpears/FileHosting/blob/master/src/middleware.php
тут остался бесполезный код
> //Определяем переменные, которые используются в >1 роутере
> function init_vars($container){
Там по моему просто можно как-то добавить переменную во вью. В Слим 2 это было что-то вроде $app->view->set('x', 1); Посмотри-ка, нельзя ли тут так же сделать. А то какие-то костыли идут. И плюс, из-за объявления функции файл routes.php стало нельзя подключать дважды (в тестах там на каждый тест приложение инициализируется заново).
> $app->get('/[message/{code}]'
Я думаю, неправильно использовать путь в URL для уведомления. Ведь новый путь в УРЛ обычно соответствует новой странице. Но страница-то одна, значит и путь у нее должен быть один. А для передачи уведомления лучше использовать параметр в query string: /?notify=deleted.
> $messager=new CodeMessager();
> $isValidCode=$messager->setCode($args['code']);
Мне не оченть нравится такой способ использования класса. Вот у тебя сделано так:
$m->setCode(..);
echo $m->getText();
Но ведь есть минимум 2 других способа:
1) объект представляет собой 1 сообщение: $m = new Message($code); echo $m->getText();
2) объект является сервисом для работы с разными кодами сообщений $m = new Message(); echo $m->getText($code);
Твой способ выглядит как без надобности усложненный вариант 2. При твоем подходе сложнее понять, как использовать класс, так как не очевидно, что надо вызвать setCode перед getText.
>>866133
Ну что, проверим-ка файлообменник. Сразу же скажу по поводу скриншотов - нужно было перед каждым поставить хотя бы строчку текста, а то для увидевшего их первый раз довольно трудно понять, где заканчивается одна страница и начинается следующая. Но хорошо, что они у тебя есть, можно сразу оценить верстку, не заглядывая в код.
Также, я вижу, что верстка кривоватая. Ну например, высота кнопки не совпадает с высотой поля ввода слева, форма комментирования тоже кривая. Ты уже дошел до файлообменника, это довольно серьезный уровень, и если знания HTML/CSS у тебя не соответствуют знанию серверных технологий, то у нас есть задачки по CSS в ОП посте.
В реальном проекте вряд ли тебе выделят персонального верстальщика, и делать какие-то простые вещи ты должен уметь сам. Вообще, верстальщики - это часто недоучившиеся программисты, и ты в общем-то должен знать не меньше них.
Там, где выводятся подробности о файле, не хватает единиц измерения. "Частота дискретизации: 44100". 44100 чего?
Кнопки "скачать" и "удалить" стоило расположить горизонтально, и кнопку удаления сделать менее заметной, например, в виде ссылки или в виде обычной белой кнопки. Дело в том, что большая синяя кнопка называется "primary", "основная", и 2 основных кнопки - это как-то нелогично. То есть это скорее замечание по интерфейсу, не надо визуально выделять слишком много элементов (ну и кстати, заголовок комментария, который такого же яркого цвета, как и кнопка, тоже как-то отвлекает на себя внимание от кнопки "ответить").
"Подтвердите... Подумай..." - лучше тогда было написать "Подтверди". Да, это не замечания по коду, но в реальном проекте у тебя вряд ли будет персональный корректор, который будет за тобой исправлять сообщения и лучше учиться обращать внимание на такие вещи. И сразу же на будущее скажу, не смешивай английские и русские сообщения в одном интерфейсе ("размер: 11.3 Mb" -> "размер: 11,3 Мб").
> Время загрузки: 2016-10-31
Ой-ой, какой роботизированный формат. В русском языке даты обычно пишут либо как "31.10.2016", либо "31 октября 2016".
> composer.phar
Это не твой код, ему в репозитории делать нечего. Стоит добавить его в gitignore и убрать из репозитория.
https://github.com/TheSidSpears/FileHosting/blob/master/httpd.conf
Тут в примере конфига блок с localhost явно лишний и не относится к файлообменнику.
https://github.com/TheSidSpears/FileHosting/blob/master/filehosting.sql#L31
> `path` mediumtext NOT NULL,
MEDIUMTEXT - это текст размером до 16 мегабайт по моему, и это многовато для пути. Также, по полям типа TEXT по моему нельзя делать индексы, так что тут однозначно лучше исплоьзовать varchar. Индексы обязательно нужны, иначе после нескольких тысяч комментариев в таблице все начнет работать небыстро (советую статью http://ruhighload.com/post/Работа+с+индексами+в+MySQL для ознакомления).
К parentId в таблице comments должен быть добавлен внешний ключ. Вообще, любые поля, которые ссылаются на другие поля, надо оформить как внешние ключи.
В таблице файлов не очень понятно зачем разделять путь к файлу на path и name.
> `size` int(11)
int принимает значения от -2 до +2 млрд. То есть у тебя нельзя хранить файлы больше 2 Гб.
> `mime` text,
TEXT содержит до 65535 байт. Многовато для маленькой строки.
> `numberOfDownloads` int(255)
255 тут рекомендуемая ширина колонки для вывода числа (на хранение оно никак не влияет). Не многовато ли?
https://github.com/TheSidSpears/FileHosting/blob/master/public/index.php#L3
> if (PHP_SAPI == 'cli-server') {
Хотя так можно, я бы вынес код роутинга для встроенного в php сервера в отдельный файл, например cli-server.php. Хотя с другой стороны, он небольшой и особо не мешает. И это, как я понимаю, разработчики Слима такое придумали.
https://github.com/TheSidSpears/FileHosting/blob/master/src/settings.php#L9
> 'addContentLengthHeader' => false, // Allow the web server to send the content-length header
А в чем смысл этой настройки? Зачем отключать этот заголовок?
Мне, конечно, кажется, что файл настроек получился какой-то громоздкий. Хорошо бы хранить там только те настройки, которые пользователь может поменять, а те, что не может, хранить где-то в коде. Как я понимаю, это опять же придумали разработчики Слима, что-то мне это не очень нравится. Какой смысл смешивать пользовательские и внутренние настройки? Вообще, мне это разделение на seetings.php/dependencies и так далее, не нравится. Во втором слиме все просто писалось в одном файле, и предполагалось, что кода будет немного, и потому можно его хранить в одном файле. Ну и читать было легко и удобно. А сейчас они раскидали все по 4 файлам, и я не вижу, какие это преимущества дает.
И разбиение на файлы ведь нельзя сравнить с разбиением на функции или классы. Функцию можно вызвать, а вот файлы эти из любого места кода приинклюдить нельзя - они заточены на подключение только из index.php. Спрошу-ка у авторов шаблона приложения на гитхабе.
Ну к примеру, представим, что мы хотим сделать программу для командной строки и в ней использовать контейнер. Как ее инициализировать? В студентах мы делали файл bootstrap.php, который инициализирует приложение, а тут - придется видимо копипастить код из index.php.
Насчет папки classes, она, мне кажется, не нужна, так как в современных приложениях 95% кода - это классы и незачем лишний раз об этом напоминать.
https://github.com/TheSidSpears/FileHosting/blob/master/src/middleware.php
тут остался бесполезный код
> //Определяем переменные, которые используются в >1 роутере
> function init_vars($container){
Там по моему просто можно как-то добавить переменную во вью. В Слим 2 это было что-то вроде $app->view->set('x', 1); Посмотри-ка, нельзя ли тут так же сделать. А то какие-то костыли идут. И плюс, из-за объявления функции файл routes.php стало нельзя подключать дважды (в тестах там на каждый тест приложение инициализируется заново).
> $app->get('/[message/{code}]'
Я думаю, неправильно использовать путь в URL для уведомления. Ведь новый путь в УРЛ обычно соответствует новой странице. Но страница-то одна, значит и путь у нее должен быть один. А для передачи уведомления лучше использовать параметр в query string: /?notify=deleted.
> $messager=new CodeMessager();
> $isValidCode=$messager->setCode($args['code']);
Мне не оченть нравится такой способ использования класса. Вот у тебя сделано так:
$m->setCode(..);
echo $m->getText();
Но ведь есть минимум 2 других способа:
1) объект представляет собой 1 сообщение: $m = new Message($code); echo $m->getText();
2) объект является сервисом для работы с разными кодами сообщений $m = new Message(); echo $m->getText($code);
Твой способ выглядит как без надобности усложненный вариант 2. При твоем подходе сложнее понять, как использовать класс, так как не очевидно, что надо вызвать setCode перед getText.
>>866133
> https://github.com/TheSidSpears/FileHosting/blob/master/src/routes.php#L39
Вот тут многовато что-то кода получается. Я бы стремился к такому:
$fileModel = $fileService->prepareFile(...);
$errors = $fileService->storeFile($fileModel);
Ну вообще, вот представь, что например, тебе понадобится загружать файл скриптом из команндой строки. Много ли кода тебе придется копипастить? Напиши-ка скрипт cli/upload.php, которому дается путь к файлу на диске и который должен вывести ссылку на страницу просмотра файла либо сообщение об ошибке.
То же самое касается работы с токенами. Почему ты там вручную собираешь модель пользователя, а не запрашиваешь ее у usersGW?
Надо учиться выделять в задаче отдельные функции, а не писать все простыней.
И надо бы сохранять причину ошибки. Например, одно дело - файл не загрузился, другое дело - файл больше разрешенного размера.
Вместо COOKIE/setcookie лучше использовать объекты запроса/ответа Слима. Тогда например можно будет как-то тестировать этот роут.
> $userId['files']=$this->filesGW->getFile($_COOKIE['fileId'])->userId;
Не очень понимаю, зачем нужна кука fileId. id файла, для которого делается описание, надо передавать в запросе. А с кукой все как-то переусложнено получается.
> ($_POST['description']
надо использовать объект запроса
> $messager=new OutMessager();
> $messager->setType(OutMessager::TYPE_ERROR);
Тип лучше передавать в конструктор. Тогда функция валидации может сразу возвращать такие объекты.
Вместо возврата массива или true из функции валидации лучше возвращать массив или пустой массив. Плохо делать у функции нескоько типов возвращаемых значений.
> $userId['files']=$this->filesGW->getFile($_COOKIE['fileId'])->userId;
Не очень понятно, зачем тут массив, а не обычная переменная. А также, если вдруг такого файла нет, тут будет ошибка при попытке обратиться к свойству несуществующего объекта.
> if (isset($url)) {
Это плохая идея, что у тебя переменная может существовать, а может и нет. Как в таких условиях писать надежный код? Если ты определяешь переменную внутри блока иф, только там ты ее и должен использовать.
> if ($validErrors===true) {
> //Записываем в БД
> $this->commentsGW->addComment($comment);
После успешной обработки POST запроса надо делать редирект. Это по моему было написано в моем уроке про формы. Иначе обновление страницы отправит второй запрос.
Когда ты пишешь if/else, где одна ветка маленькая, а другая большая, и маленькая содержит что-нибудь вроде показа 404 страницы, она должна идти первой ради читабельности.
> $fileUri=Helper::getPathForFile($this->settings['uploadUri'],$fileModel);
Неудобно каждый раз передавать URL папки с файлами. Лучше передать ее в конструктор класса-хелпера.
Плохо, что ты используешь один и тот же массив $args, и для хранения пришедших из роута аргументов, и для передачи во view.
> if ($_POST['nick']==NULL) {
POST содержит либо строки, либо массивы, и не может содержать NULL. Ай-я-яй, такая ошибка.
> //Средствами PHP
> $file=readfile($path);
Надо бы нормально отдавать содержимое через response (там есть возможность передать поток, соответствующий открытому файлу), а не выводить напрямую. Вот какой смысл дальше возвращать объект response, если при попытке вывести заголовки из него будт ошибка?
Вообще, отдачу файла я бы вынес в отдельный метод, а не писал в контроллере. Вдруг еще где пригодится.
Тебе также надо разобраться, что такое и зачем нужны объекты request/response в Слиме.
> $app->get('/delete/{id}'
Кто удаляет файлы GET-запросом? GET используется только для операций чтения, не меняющих данные на сервере, это даже из названия понятно.
Проверку прав тоже можно бы вынести в функцию вида:
...->canModify($user, $file)
Это позволит легко, например, добавить модератора, который может править и удалять любые файлы.
Удаление у тебя опять же, сделано простыней в контроллере. Лучше сделать нормальную функцию где-то в сервисе, которая позволит за 1 вызов удалить файл отовсюду. Также, порядок удаления неправильный. Что будет, если скрипт упадет после удаления файла из ФС, но до удаления из БД?
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/FilesFileManager.php
Этот класс назван неправильно. По определению, "менеджер файлов" - это класс, который позволяет обработать несколько файлов, но у тебя там есть поля вроде $path, и класс видимо рассчитан на работу с единственным файлом.
Я вообще плохо понимаю логику этого класса. Вот у тебя есть поле $path, но в методе deleteFile почему-то оно не используется, а $path передается снаружи. Определись, что у тебя за класс -менеджер для работы с файлами, или класс для работы с единственным файлом.
> execDisable($fileName)
Имя функции должно начинаться с глагола.
> if (!preg_match("/^((\w)|(\d)|[ -_])(.)(".implode('|', $this->validTypes).")$/iu", $fileName)){
Вместо этой сложной регулярки лучше получить расширение файла и сравнить со списком.
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/FilesFileManager.php#L45
> if (copy($_FILES['file']['tmp_name'],
Почему у тебя в модели идет работа с параметрами из HTTP-запроса? Это не соответствует идее MVC.
> public function addComment(Comment $comment){
> @return bool status of adding to DB
У тебя же стоит режим ERRMODE_EXCEPTION? Тогда exec не должен вернуть false.
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/DataBase/CommentsTDGW.php#L60
Тут в generatePath нет проверки на случай, если указан несуществующий parentId.
> //Выбираем путь самого последнего дочернего коммента (001.003.007)
Я не вижу, как это запрос выбирает именно последний коммент, и как он гарантирует, что мы берем дочерний коммент, а не более глубокого потомка.
Вообще, мне кажется там можно было бы получить самый последний коммент одним запросом c MAX()/ORDER BY DESC, а не двумя, как у тебя.
> AND `path` LIKE '$path.%'
данные надо передавать через плейсхолдеры.
> AND `path` LIKE '___' /три символа*/
Этот запрос не оптимизировать индексами. Надо выбирать по parentId IS NULL + MAX или ORDER BY.
Нет проверок при добавлении комментария на максимальное число комментариев в ветке или макисмальную глубину.
> $nulls = ($len==1) ? '00' : '0';
Есть str_pad и sprintf для этого.
> return $this->db->lastInsertId();
Можно этот id сразу проставлять в объект File.
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Models/Comment.php#L48
Вот здесь записано число символов в пути. Но еще оно записано в классе CommentGW. Нехорошо. Я думаю, лучше сделать у commentsGW статический метод для вычисления глубины (или для разбиения пути на части) и тут его вызывать.
> public function addInfo
Вот название не очень. Info ничего не значит, потому получается просто add(). Лучше бы назвать setAttributes или setProperties.
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Helpers/CodeMessager.php#L23
> foreach ($this->messages as $key => &$code) {
Я думаю, вместо этого перетасовывания свойств в конструкторе проще работать с таким массивом, который есть.
> abstract class Messager{
Правильнее передавать код в конструктор и назвать класс Message. OutMessager тоже переименовать нормально.
>>866133
> https://github.com/TheSidSpears/FileHosting/blob/master/src/routes.php#L39
Вот тут многовато что-то кода получается. Я бы стремился к такому:
$fileModel = $fileService->prepareFile(...);
$errors = $fileService->storeFile($fileModel);
Ну вообще, вот представь, что например, тебе понадобится загружать файл скриптом из команндой строки. Много ли кода тебе придется копипастить? Напиши-ка скрипт cli/upload.php, которому дается путь к файлу на диске и который должен вывести ссылку на страницу просмотра файла либо сообщение об ошибке.
То же самое касается работы с токенами. Почему ты там вручную собираешь модель пользователя, а не запрашиваешь ее у usersGW?
Надо учиться выделять в задаче отдельные функции, а не писать все простыней.
И надо бы сохранять причину ошибки. Например, одно дело - файл не загрузился, другое дело - файл больше разрешенного размера.
Вместо COOKIE/setcookie лучше использовать объекты запроса/ответа Слима. Тогда например можно будет как-то тестировать этот роут.
> $userId['files']=$this->filesGW->getFile($_COOKIE['fileId'])->userId;
Не очень понимаю, зачем нужна кука fileId. id файла, для которого делается описание, надо передавать в запросе. А с кукой все как-то переусложнено получается.
> ($_POST['description']
надо использовать объект запроса
> $messager=new OutMessager();
> $messager->setType(OutMessager::TYPE_ERROR);
Тип лучше передавать в конструктор. Тогда функция валидации может сразу возвращать такие объекты.
Вместо возврата массива или true из функции валидации лучше возвращать массив или пустой массив. Плохо делать у функции нескоько типов возвращаемых значений.
> $userId['files']=$this->filesGW->getFile($_COOKIE['fileId'])->userId;
Не очень понятно, зачем тут массив, а не обычная переменная. А также, если вдруг такого файла нет, тут будет ошибка при попытке обратиться к свойству несуществующего объекта.
> if (isset($url)) {
Это плохая идея, что у тебя переменная может существовать, а может и нет. Как в таких условиях писать надежный код? Если ты определяешь переменную внутри блока иф, только там ты ее и должен использовать.
> if ($validErrors===true) {
> //Записываем в БД
> $this->commentsGW->addComment($comment);
После успешной обработки POST запроса надо делать редирект. Это по моему было написано в моем уроке про формы. Иначе обновление страницы отправит второй запрос.
Когда ты пишешь if/else, где одна ветка маленькая, а другая большая, и маленькая содержит что-нибудь вроде показа 404 страницы, она должна идти первой ради читабельности.
> $fileUri=Helper::getPathForFile($this->settings['uploadUri'],$fileModel);
Неудобно каждый раз передавать URL папки с файлами. Лучше передать ее в конструктор класса-хелпера.
Плохо, что ты используешь один и тот же массив $args, и для хранения пришедших из роута аргументов, и для передачи во view.
> if ($_POST['nick']==NULL) {
POST содержит либо строки, либо массивы, и не может содержать NULL. Ай-я-яй, такая ошибка.
> //Средствами PHP
> $file=readfile($path);
Надо бы нормально отдавать содержимое через response (там есть возможность передать поток, соответствующий открытому файлу), а не выводить напрямую. Вот какой смысл дальше возвращать объект response, если при попытке вывести заголовки из него будт ошибка?
Вообще, отдачу файла я бы вынес в отдельный метод, а не писал в контроллере. Вдруг еще где пригодится.
Тебе также надо разобраться, что такое и зачем нужны объекты request/response в Слиме.
> $app->get('/delete/{id}'
Кто удаляет файлы GET-запросом? GET используется только для операций чтения, не меняющих данные на сервере, это даже из названия понятно.
Проверку прав тоже можно бы вынести в функцию вида:
...->canModify($user, $file)
Это позволит легко, например, добавить модератора, который может править и удалять любые файлы.
Удаление у тебя опять же, сделано простыней в контроллере. Лучше сделать нормальную функцию где-то в сервисе, которая позволит за 1 вызов удалить файл отовсюду. Также, порядок удаления неправильный. Что будет, если скрипт упадет после удаления файла из ФС, но до удаления из БД?
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/FilesFileManager.php
Этот класс назван неправильно. По определению, "менеджер файлов" - это класс, который позволяет обработать несколько файлов, но у тебя там есть поля вроде $path, и класс видимо рассчитан на работу с единственным файлом.
Я вообще плохо понимаю логику этого класса. Вот у тебя есть поле $path, но в методе deleteFile почему-то оно не используется, а $path передается снаружи. Определись, что у тебя за класс -менеджер для работы с файлами, или класс для работы с единственным файлом.
> execDisable($fileName)
Имя функции должно начинаться с глагола.
> if (!preg_match("/^((\w)|(\d)|[ -_])(.)(".implode('|', $this->validTypes).")$/iu", $fileName)){
Вместо этой сложной регулярки лучше получить расширение файла и сравнить со списком.
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/FilesFileManager.php#L45
> if (copy($_FILES['file']['tmp_name'],
Почему у тебя в модели идет работа с параметрами из HTTP-запроса? Это не соответствует идее MVC.
> public function addComment(Comment $comment){
> @return bool status of adding to DB
У тебя же стоит режим ERRMODE_EXCEPTION? Тогда exec не должен вернуть false.
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/DataBase/CommentsTDGW.php#L60
Тут в generatePath нет проверки на случай, если указан несуществующий parentId.
> //Выбираем путь самого последнего дочернего коммента (001.003.007)
Я не вижу, как это запрос выбирает именно последний коммент, и как он гарантирует, что мы берем дочерний коммент, а не более глубокого потомка.
Вообще, мне кажется там можно было бы получить самый последний коммент одним запросом c MAX()/ORDER BY DESC, а не двумя, как у тебя.
> AND `path` LIKE '$path.%'
данные надо передавать через плейсхолдеры.
> AND `path` LIKE '___' /три символа*/
Этот запрос не оптимизировать индексами. Надо выбирать по parentId IS NULL + MAX или ORDER BY.
Нет проверок при добавлении комментария на максимальное число комментариев в ветке или макисмальную глубину.
> $nulls = ($len==1) ? '00' : '0';
Есть str_pad и sprintf для этого.
> return $this->db->lastInsertId();
Можно этот id сразу проставлять в объект File.
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Models/Comment.php#L48
Вот здесь записано число символов в пути. Но еще оно записано в классе CommentGW. Нехорошо. Я думаю, лучше сделать у commentsGW статический метод для вычисления глубины (или для разбиения пути на части) и тут его вызывать.
> public function addInfo
Вот название не очень. Info ничего не значит, потому получается просто add(). Лучше бы назвать setAttributes или setProperties.
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Helpers/CodeMessager.php#L23
> foreach ($this->messages as $key => &$code) {
Я думаю, вместо этого перетасовывания свойств в конструкторе проще работать с таким массивом, который есть.
> abstract class Messager{
Правильнее передавать код в конструктор и назвать класс Message. OutMessager тоже переименовать нормально.
>>866133
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Helpers/ID3Choser.php#L55
Вместо этих плясок с заменой ключей, возможно, лучше сделать объект, представляющий информацию о файле, и имеющий методы для ее получения в нужном виде. Хотя, может, можно и так оставить.
> Добавляет хеш к имени файла, игнорируя разрешение (любой вложенности вроде: archive.tar.gz)
> static function addHashToFileName(string $filename)
А ты тестировал эту функцию на файлах без расширения и файлах, начинающихся с точки?
> https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Validators/Comments.php#L10
> 'message' => 'может состоять из любых символов' //по-идее, это никогда не выводится
Может тогда такое правило вадидации и не требуется?
> {% if messagers is defined %}
Лучше сделать, чтобы эта переменная была всегда.
> alert-{{ messager.getType() }}
Метод надо назвать getCssClass и возвращать название класса целиком, чтобы по нему можно было искать.
https://github.com/TheSidSpears/FileHosting/blob/master/templates/comment_form.html#L5
> aria-describedby="sizing-addon3"
Что-то я сомневаюсь, что символ "@" может служить описанием поля.
> <img src="{{ uploadUri }}{{ file.path }}{{ file.name }}">
Надо сделать метод полученя URL картинки, а не размазывать этот алгоритм по коду.
> {% elseif file.getType() == 'audio' or file.getType() == 'video' %}
> <div class="player" id="uppod_player"></div>
Ты делаешь воспроизведение видео в браузера, а ты знаешь, какие форматы какие бразеры поддерживают? И что надо делать, чтобы, как на ютубе или википедии, работало (почти) везде?
> https://github.com/TheSidSpears/FileHosting/blob/master/public/css/uploader-master.css#L59
> .uploader div.browser label
div в этом правиле явно лишний.
https://github.com/TheSidSpears/FileHosting/blob/master/public/css/uploader-master.css#L91
Здесь странно, что есть -o-transform и -moz-transform, но нет правила без префикса.
Советую не использовать id в верстке, так как преимуществ у них никаких, а недостаток, что два id не могут встречаться на одной странице.
> glyphicon-preview
Плохо, что ты используешь имя класса, похожее на название из бутстрапа. Неочевидно, что это твой класс. Вообще, мне не нравится, что бутстрап не использует префиксы. Я погуглил тут https://github.com/twbs/bootstrap/issues/1235 и как я понимаю, их мнение такое, что они не библиотека, а фреймворк и им незачем ставить префиксы.
https://github.com/TheSidSpears/FileHosting/blob/master/public/js/helper.js#L4
> создаем в форме переменную, содержащую id отвечаемого коммента
Проще было сразу создать это поле в шаблоне.
> Добавляем кнопку "Написать коммент без ответа"
Проще вставить ее в шаблон, но скрыть. Так при изменениях в верстке нам не придется лезть в JS. Вообще, старайся избегать вынесения верстки из HTML в JS.
--------------
В общем, по поводу архитектуры у тебя пока все не очень хорошо. Я вижу, что ты пока толком не разобрался ни в самом Слиме (и объектах request/response), ни в разбиении кода на классы и функции (так как у тебя действия вроде удаления файла не вынесены в отдельную функцию). Надо это исправлять. Если что-то непонятно, есть вопросы или возражения - пиши.
И кстати, а ты автоматизированные тесты написать к файлообменнику не хочешь? У меня есть обзорный урок по тестированию, если что: https://gist.github.com/codedokode/a455bde7d0748c0a351a
>>866133
https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Helpers/ID3Choser.php#L55
Вместо этих плясок с заменой ключей, возможно, лучше сделать объект, представляющий информацию о файле, и имеющий методы для ее получения в нужном виде. Хотя, может, можно и так оставить.
> Добавляет хеш к имени файла, игнорируя разрешение (любой вложенности вроде: archive.tar.gz)
> static function addHashToFileName(string $filename)
А ты тестировал эту функцию на файлах без расширения и файлах, начинающихся с точки?
> https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Validators/Comments.php#L10
> 'message' => 'может состоять из любых символов' //по-идее, это никогда не выводится
Может тогда такое правило вадидации и не требуется?
> {% if messagers is defined %}
Лучше сделать, чтобы эта переменная была всегда.
> alert-{{ messager.getType() }}
Метод надо назвать getCssClass и возвращать название класса целиком, чтобы по нему можно было искать.
https://github.com/TheSidSpears/FileHosting/blob/master/templates/comment_form.html#L5
> aria-describedby="sizing-addon3"
Что-то я сомневаюсь, что символ "@" может служить описанием поля.
> <img src="{{ uploadUri }}{{ file.path }}{{ file.name }}">
Надо сделать метод полученя URL картинки, а не размазывать этот алгоритм по коду.
> {% elseif file.getType() == 'audio' or file.getType() == 'video' %}
> <div class="player" id="uppod_player"></div>
Ты делаешь воспроизведение видео в браузера, а ты знаешь, какие форматы какие бразеры поддерживают? И что надо делать, чтобы, как на ютубе или википедии, работало (почти) везде?
> https://github.com/TheSidSpears/FileHosting/blob/master/public/css/uploader-master.css#L59
> .uploader div.browser label
div в этом правиле явно лишний.
https://github.com/TheSidSpears/FileHosting/blob/master/public/css/uploader-master.css#L91
Здесь странно, что есть -o-transform и -moz-transform, но нет правила без префикса.
Советую не использовать id в верстке, так как преимуществ у них никаких, а недостаток, что два id не могут встречаться на одной странице.
> glyphicon-preview
Плохо, что ты используешь имя класса, похожее на название из бутстрапа. Неочевидно, что это твой класс. Вообще, мне не нравится, что бутстрап не использует префиксы. Я погуглил тут https://github.com/twbs/bootstrap/issues/1235 и как я понимаю, их мнение такое, что они не библиотека, а фреймворк и им незачем ставить префиксы.
https://github.com/TheSidSpears/FileHosting/blob/master/public/js/helper.js#L4
> создаем в форме переменную, содержащую id отвечаемого коммента
Проще было сразу создать это поле в шаблоне.
> Добавляем кнопку "Написать коммент без ответа"
Проще вставить ее в шаблон, но скрыть. Так при изменениях в верстке нам не придется лезть в JS. Вообще, старайся избегать вынесения верстки из HTML в JS.
--------------
В общем, по поводу архитектуры у тебя пока все не очень хорошо. Я вижу, что ты пока толком не разобрался ни в самом Слиме (и объектах request/response), ни в разбиении кода на классы и функции (так как у тебя действия вроде удаления файла не вынесены в отдельную функцию). Надо это исправлять. Если что-то непонятно, есть вопросы или возражения - пиши.
И кстати, а ты автоматизированные тесты написать к файлообменнику не хочешь? У меня есть обзорный урок по тестированию, если что: https://gist.github.com/codedokode/a455bde7d0748c0a351a
>>873486
>>873545
Ну вот, а я надеялся закрыть уже эту задачу. Нет, рано.
Во-первых, отвалилась регистрация. То есть запись добавляется в БД, но с cookie IS NULL. И соответственно после регистрации я снова вижу предложение зарегистрироваться.
Во-вторых, кто-то подменяет емайлы вроде ?\2saaANUSпримеGn}рPUNCTUM9uYрф на punycode (*VNsaaANUSxn--e1afmkf9 UdPUNCTUMc>Lxn--p1ai). Оказалось, виноват Хром (и спецификации, которым он следует). Введенный в поле формы адрес на русском перекодируется и отправляется на сервер в punycode. Кошмар какой-то. Получается, инпуты с типом email не всегда желательно использовать. Век живи - век учись.
Также, в бутстрапе какой-то бледный цвет у mark. Он настолько бледный, что на моей (плохой) матрице почти не заметен. Опять же, ты тут не при чем, исправлять не надо.
Не проверяется уникальность email. При попытке второй раз зарегистрироваться с тем же email вместо ошибки вылетает исключение. Поскажу: дело в том, что значение нельзя сравнивать с NULL через = или <>. NULL в базах данных значит "неизвестно", и сравнение с неизвестным дает такой же результат. Сделай запрос SELECT NULL = NULL, NULL != NULL, NULL = 1, NULL != 1 и посмотри сам (какой результат ты ожидаешь?).
Поскольку NULL значит "неизвестно", то результат сравнения NULL с NULL тоже неизвестен.
Аналогично попытка использовать NULL в математических выражениях даст такой же результат.
https://github.com/never3ver/students_list/blob/master/app/Pager.php#L54
Тут ссылка подставляется в HTML без htmspecialchars, нехорошо. Вообще, вынести HTML код сюда, как мне кажется, плохая идея. Код в public function getNumbersLinks() и похожих функциях вполне можно перенести в шаблон.
https://github.com/never3ver/students_list/blob/master/app/Helper.php#L37
> public static function getPlaceholder() {
> return htmlspecialchars(trim(strval($_GET['search'])));
htmlspecialchars надо ставить в шаблоне. Также, плохо что ты здесь лезешь в глобальную переменную GET. Это абсолютно неочевидно, если смотреть на код в шаблоне. Непонятно, почему прямо из вью идет обращение к GET-переменным.
Также, значение из search надо подставлять не как плейсхолдер, а как значение поля ввода, чтобы оно редактировалось.
https://github.com/never3ver/students_list/blob/master/templates/index.html#L10
То же самое. view не должен лезть в GET-переменные. Ты пытаешься к ним пробраться в обход контроллера.
Если открыть пустой сайт, без студентов, то надпись "Ничего не найдено" оказывается частично перекрыта шапкой.
>>873486
>>873545
Ну вот, а я надеялся закрыть уже эту задачу. Нет, рано.
Во-первых, отвалилась регистрация. То есть запись добавляется в БД, но с cookie IS NULL. И соответственно после регистрации я снова вижу предложение зарегистрироваться.
Во-вторых, кто-то подменяет емайлы вроде ?\2saaANUSпримеGn}рPUNCTUM9uYрф на punycode (*VNsaaANUSxn--e1afmkf9 UdPUNCTUMc>Lxn--p1ai). Оказалось, виноват Хром (и спецификации, которым он следует). Введенный в поле формы адрес на русском перекодируется и отправляется на сервер в punycode. Кошмар какой-то. Получается, инпуты с типом email не всегда желательно использовать. Век живи - век учись.
Также, в бутстрапе какой-то бледный цвет у mark. Он настолько бледный, что на моей (плохой) матрице почти не заметен. Опять же, ты тут не при чем, исправлять не надо.
Не проверяется уникальность email. При попытке второй раз зарегистрироваться с тем же email вместо ошибки вылетает исключение. Поскажу: дело в том, что значение нельзя сравнивать с NULL через = или <>. NULL в базах данных значит "неизвестно", и сравнение с неизвестным дает такой же результат. Сделай запрос SELECT NULL = NULL, NULL != NULL, NULL = 1, NULL != 1 и посмотри сам (какой результат ты ожидаешь?).
Поскольку NULL значит "неизвестно", то результат сравнения NULL с NULL тоже неизвестен.
Аналогично попытка использовать NULL в математических выражениях даст такой же результат.
https://github.com/never3ver/students_list/blob/master/app/Pager.php#L54
Тут ссылка подставляется в HTML без htmspecialchars, нехорошо. Вообще, вынести HTML код сюда, как мне кажется, плохая идея. Код в public function getNumbersLinks() и похожих функциях вполне можно перенести в шаблон.
https://github.com/never3ver/students_list/blob/master/app/Helper.php#L37
> public static function getPlaceholder() {
> return htmlspecialchars(trim(strval($_GET['search'])));
htmlspecialchars надо ставить в шаблоне. Также, плохо что ты здесь лезешь в глобальную переменную GET. Это абсолютно неочевидно, если смотреть на код в шаблоне. Непонятно, почему прямо из вью идет обращение к GET-переменным.
Также, значение из search надо подставлять не как плейсхолдер, а как значение поля ввода, чтобы оно редактировалось.
https://github.com/never3ver/students_list/blob/master/templates/index.html#L10
То же самое. view не должен лезть в GET-переменные. Ты пытаешься к ним пробраться в обход контроллера.
Если открыть пустой сайт, без студентов, то надпись "Ничего не найдено" оказывается частично перекрыта шапкой.
Делать из этого екзешник не надо. Ты ведь не хочешь перекомпилировать все при каждой правке.
Команды командной строки можно записать в .bat-скрипт. При двойном клике (или при вызове из командной строки) этот скрипт выполнит все записанные в нем команды.
Погугли про bat-скрипты.
В линуксе есть bash-скрипты, то же самое, но во много раз мощнее. В новой винде есть Powershell.
Если окно консоли закрывается после выполнения скрипта, либо поставь галочку в его настройках, либо допиши команду pause в конец.
Совсем забыл про них, спасибо!
При чем тут обертку написать, видимо даун ты так изобретаешь велосипеды когда есть удобные AngryCurl/RollingCurl и тд.
Вопрос был именно по той библиотеке, и к тем кто пользовался ею. Не люблю таких джуниоров как ты, они нихуя не знаю но везде носятся со своим компетентным мнением.
>Вообще, вынести HTML код сюда, как мне кажется, плохая идея. Код в public function getNumbersLinks() и похожих функциях вполне можно перенести в шаблон.
Оно раньше и было в шаблоне, но ты (или не ты?) сказал что так нельзя. В остальном все понял, спасибо, переделаю.
Можно делать это и параллельно. Если ты хочешь программировать на php, то html знать обязательно. Выясни лучше сначала что тебе нужно просто html (статичная страница) или php (работа с формами\запросами\функциями короче полное погружение в программирование)
Не пользовался, только слышал, он поддерживает смену проксей и юзерагента на лету?
Спасибо!
За это время учебник пройден (кроме маршрутизатора - той задачи на поиск кратчайших путей), к Студентам и Файлообменнику не приступал.
Работаю над своим проектом на Yii2 с хорошим знакомым программистом.
Получилось конечно как-то сложнее и больше текста, чем я задумывал. Аноны, почитайте, напишите, что непонятно.
Работаю над контентной частью проекта, расписал ТЗ по максимуму - всё описано, что нужно.
Просто перестал бояться программирования, многие процессы стал осознавать.
Надеюсь, в будущем году проект будет запущен для целевой аудитории.
> Нужно ли разделять код на файлы, как это делали в задаче про студентов?
Не обязательно, но было бы неплохо, потренируешься, так как в больших приложениях требуется это делать.
> Как подключить все файлы, не в head же прописывать link для десятка файлов?
Если файлов меньше 10, то можно и вручную подключать. Если их больше - придется настраивать и подключать сборщик. Ты разбиваешь свой код на модули, указываешь зависимости, а сборщик на них ориентируется.
В режиме разработки удобно сделать так, чтобы загрузчки просто подгружал исходные модули (не требуя никаких сборок или компиляций), а в режиме сборки версии для продакшена обычно модули склеивают в один файл, иногда еще минифицируют или оптмизируют код. Один файл нужен, так как много мелких файлов будут медленно загружаться.
Казалось бы, то, что я написал выше, очевидно и даже не вызывает вопросов. Но почему-то многие разработчики делают какие-то сложные системы на gulp/grunt и подобных системах, которые отслеживают изменение файлов, перекомпилируют код, в общем всячески замедляют себе разработку, вместо того чтобы просто использовать исходные файлы. Странные люди.
Бывает, что загрузчики сделаны криво и вместо подгрузки файлов дописыванием тега script в head используют другие примемы, вроде загрузки файла аяксом и выполнения через eval. Не советую их использовать, так как в отладчике браузера эти файлы не будут отображаться под своими именами.
Есть несколько систем модулей:
- common.js, основанная на модулях Node.JS, в браузере она работать сама по себе не будет (так как там используется синхронная функция require), надо либо подгружать файлы аяксом, либо обрабатывать, то есть работать с ними будет неудобно
- AMD, где модули определяются внутри функции и их можно подгружать асинхронно. Но минус в том, что синтаксис довольно грромоздкий
- стандартные модули из ES6: http://frontender.info/es6-modules/ - будущий стандарт, который имеет удобный синтаксис и не требует предварительной обработки, но поддерживается только в новых браузерах. Эту проблему можно решить использованием сборщика, который понимает этот формат, но генерирует на выходе совместимый со старыми браузерами код.
Из популярных сборщиков я слышал про RequireJS (ориентирован по моему на AMD) и более новый WebPack.
В общем, изучи все эти системы.
> Разделяются ли классы на различные файлы?
Логично класть каждый класс в свой файл, как и в PHP. И делать конструктор класса экспортом по умолчанию. Только вот стандартов в JS никаких нет, и каждый называет файлы как ему нравится.
> Как обернуть весь код в модуль, если файлов несколько?
Идея модулей как раз в том, чтобы разбить код на много модулей, а не один.
Вообще, ты можешь еще посмотреть, как устроена Google Closure Library. Это не очень новый проект (потому они изобрели свою систему модулей), и не модный (как какой-нибудь React) и его структура во многом скопирована с Явы, но его полезно посмотреть в плане того, как там все организовано. В том числе, как код разбит на файлы.
Вот пример класса: https://github.com/google/closure-library/blob/master/closure/goog/events/eventhandler.js (они используют свой формат модулей)
Вот пример модной библиотеки React, опять же посмотри, как у них сделано разделение на модули: https://github.com/facebook/react (они используют CommonJS)
Ну и пример Angular 2, который использует модули ES6 и TypeScript: https://github.com/angular/angular/
> Нужно ли разделять код на файлы, как это делали в задаче про студентов?
Не обязательно, но было бы неплохо, потренируешься, так как в больших приложениях требуется это делать.
> Как подключить все файлы, не в head же прописывать link для десятка файлов?
Если файлов меньше 10, то можно и вручную подключать. Если их больше - придется настраивать и подключать сборщик. Ты разбиваешь свой код на модули, указываешь зависимости, а сборщик на них ориентируется.
В режиме разработки удобно сделать так, чтобы загрузчки просто подгружал исходные модули (не требуя никаких сборок или компиляций), а в режиме сборки версии для продакшена обычно модули склеивают в один файл, иногда еще минифицируют или оптмизируют код. Один файл нужен, так как много мелких файлов будут медленно загружаться.
Казалось бы, то, что я написал выше, очевидно и даже не вызывает вопросов. Но почему-то многие разработчики делают какие-то сложные системы на gulp/grunt и подобных системах, которые отслеживают изменение файлов, перекомпилируют код, в общем всячески замедляют себе разработку, вместо того чтобы просто использовать исходные файлы. Странные люди.
Бывает, что загрузчики сделаны криво и вместо подгрузки файлов дописыванием тега script в head используют другие примемы, вроде загрузки файла аяксом и выполнения через eval. Не советую их использовать, так как в отладчике браузера эти файлы не будут отображаться под своими именами.
Есть несколько систем модулей:
- common.js, основанная на модулях Node.JS, в браузере она работать сама по себе не будет (так как там используется синхронная функция require), надо либо подгружать файлы аяксом, либо обрабатывать, то есть работать с ними будет неудобно
- AMD, где модули определяются внутри функции и их можно подгружать асинхронно. Но минус в том, что синтаксис довольно грромоздкий
- стандартные модули из ES6: http://frontender.info/es6-modules/ - будущий стандарт, который имеет удобный синтаксис и не требует предварительной обработки, но поддерживается только в новых браузерах. Эту проблему можно решить использованием сборщика, который понимает этот формат, но генерирует на выходе совместимый со старыми браузерами код.
Из популярных сборщиков я слышал про RequireJS (ориентирован по моему на AMD) и более новый WebPack.
В общем, изучи все эти системы.
> Разделяются ли классы на различные файлы?
Логично класть каждый класс в свой файл, как и в PHP. И делать конструктор класса экспортом по умолчанию. Только вот стандартов в JS никаких нет, и каждый называет файлы как ему нравится.
> Как обернуть весь код в модуль, если файлов несколько?
Идея модулей как раз в том, чтобы разбить код на много модулей, а не один.
Вообще, ты можешь еще посмотреть, как устроена Google Closure Library. Это не очень новый проект (потому они изобрели свою систему модулей), и не модный (как какой-нибудь React) и его структура во многом скопирована с Явы, но его полезно посмотреть в плане того, как там все организовано. В том числе, как код разбит на файлы.
Вот пример класса: https://github.com/google/closure-library/blob/master/closure/goog/events/eventhandler.js (они используют свой формат модулей)
Вот пример модной библиотеки React, опять же посмотри, как у них сделано разделение на модули: https://github.com/facebook/react (они используют CommonJS)
Ну и пример Angular 2, который использует модули ES6 и TypeScript: https://github.com/angular/angular/
> if ($creditBalance < 0 && $creditBalance < $monthlyPayment) {
Тут одно из условий лишнее, если первое выполняется, то второе можно уже не проверять.
Считает верно.
>>892325
Как сказать.. с одной стороны, знание HTML даст тебе возможность верстать веб-странички, с другой - PHP тебя приучает к "компьютерному" мышлению и после него HTML легче учится. Если есть возможность, учи и то и то сразу.
>>892423
С "даунами" иди в какой-нибудь другой тред.
>>892272
Это хорошо. А то много всяких сомнительных учебников с устаревшим или небезопасным кодом или без ООП.
>>892109
С "даунами" в другой тред.
>>891622
Адаптивная верстка это часть обычной верстки и надо сначала разобраться с последней. Если тебе не принципиально, можешь ничего не учить, а на собеседовании сказать, что знаешь.
>>891707
Изучи исходный код.
>>891621
Какое это отношение имеет к изучению PHP? Создай сам свой форум и пости туда что хочешь.
> if ($creditBalance < 0 && $creditBalance < $monthlyPayment) {
Тут одно из условий лишнее, если первое выполняется, то второе можно уже не проверять.
Считает верно.
>>892325
Как сказать.. с одной стороны, знание HTML даст тебе возможность верстать веб-странички, с другой - PHP тебя приучает к "компьютерному" мышлению и после него HTML легче учится. Если есть возможность, учи и то и то сразу.
>>892423
С "даунами" иди в какой-нибудь другой тред.
>>892272
Это хорошо. А то много всяких сомнительных учебников с устаревшим или небезопасным кодом или без ООП.
>>892109
С "даунами" в другой тред.
>>891622
Адаптивная верстка это часть обычной верстки и надо сначала разобраться с последней. Если тебе не принципиально, можешь ничего не учить, а на собеседовании сказать, что знаешь.
>>891707
Изучи исходный код.
>>891621
Какое это отношение имеет к изучению PHP? Создай сам свой форум и пости туда что хочешь.
Для начала надо определить, что такое "последняя" строка. В базе строки не хранятся в каком-то определенном порядке. Порядок определяется при выборке с помощью ORDER.
>>891502
Это неправильный подход. Во-первых, ты генерируешь регулярку, что усложняет чтение кода. Тут этого не требуется. Во-вторых, \W это любой символ, кроме буквы, цифры ли подчеркивания, и твоя регулярка будет пропускать любой мусор. Стоит ограничиться только скобками, минусами, пробелами.
>>891497
Попробуй написать такие регулярки:
- один из символов "минус", "скобка", "пробел"
- любое число таких символов
- цифра, за ней любое число таких символов
- (цифра, за ней любое число таких символов) повторяется 10 раз
Для повторения N раз есть квантификатор {N}, он есть у меня в учебнике и в мануале: http://php.net/manual/ru/regexp.reference.repetition.php
Большое спасибо за очень подробный ответ!
Первый класс в первом файле :
class User {
public $name;
public $lastname;
//и остальные свойства которые есть у юзера
}
Второй класс во втором файле:
class User_mapper {
public $db;
function __construct(PDO $db) {
$this->db = $db;
}
public function add_user($user) {
//Описание метода
}
public function out_user() {
//Описание метода
}
}
Теперь чтобы использовать в главном файле прописываем:
$db = new PDO("Здесь разные настройки и т.д.");
$user_mapper = User_maper($db);
$user = new User();
$user->name = "Админ";
$user->lastname = "Тожеадмин";
//Если нужно передать в метод маппера какие-то свойства метода Юзер, тогда делаем так
$user_mapper->add_user($user);
Я правильно понял смысл дата маппера или нет?
Первый класс в первом файле :
class User {
public $name;
public $lastname;
//и остальные свойства которые есть у юзера
}
Второй класс во втором файле:
class User_mapper {
public $db;
function __construct(PDO $db) {
$this->db = $db;
}
public function add_user($user) {
//Описание метода
}
public function out_user() {
//Описание метода
}
}
Теперь чтобы использовать в главном файле прописываем:
$db = new PDO("Здесь разные настройки и т.д.");
$user_mapper = User_maper($db);
$user = new User();
$user->name = "Админ";
$user->lastname = "Тожеадмин";
//Если нужно передать в метод маппера какие-то свойства метода Юзер, тогда делаем так
$user_mapper->add_user($user);
Я правильно понял смысл дата маппера или нет?
Класс User представляет информацию о пользователе (надо же как-то ее хранить в программе?).
Класс UserMapper позволяет загружать и сохранять объекты User в базу данных.
В общем, примерно согласуется с твоим кодом, только непонятно, что за метод out_user(), который ничего не принимает на вход.
Ну и код конечно довольно странный. Например, с какой целью поле db сделано публичным? Почему используются подчеркивания. а не кемелКейс?
> //Если нужно передать в метод маппера какие-то свойства метода Юзер, тогда делаем так
Мы передаем не какие-то свойства, а все. Объект User должен быть заполнен полностью, иначе как с ним работать, если непонятно, заполнено поле или нет?
Анон, вопрос по урокам, которые были в шапке. Задача на регулярные выражения.
Задачка на проверку телефонов
Дан текст, который по идее должен быть номером телефона в виде 8-(911)-506 56 56 (т.е. человек может ввести не только цифры, но и скобки, минусы, может что-то еще). Но в реальности, пользователь может вместо номера написать что угодно. Напиши скрипт для проверки правильности введенного номера («8(911)-506 56 56» — правильный номер, «8-911-50-656-56» — правильный, «89115065656» — правильный, «02» — неправильный, «89115065656 позвать Люду» — неправильный).
Вот список номеров:
// Правильные:
$correctNumbers = [
'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'
];
// Неправильные:
$incorrectNumbers = [
'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' / нет + /
];
Анон, вопрос по урокам, которые были в шапке. Задача на регулярные выражения.
Задачка на проверку телефонов
Дан текст, который по идее должен быть номером телефона в виде 8-(911)-506 56 56 (т.е. человек может ввести не только цифры, но и скобки, минусы, может что-то еще). Но в реальности, пользователь может вместо номера написать что угодно. Напиши скрипт для проверки правильности введенного номера («8(911)-506 56 56» — правильный номер, «8-911-50-656-56» — правильный, «89115065656» — правильный, «02» — неправильный, «89115065656 позвать Люду» — неправильный).
Вот список номеров:
// Правильные:
$correctNumbers = [
'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'
];
// Неправильные:
$incorrectNumbers = [
'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' / нет + /
];
Помоги регулярное выражение составить. Как я понимаю, должно получится нечто подобное: $regexp = '/^([+7]|[+ 7]|[8])(???)$/m';
>>874960
>>876772
Ты зря взял структуру файлов с Юи, так как она довольно неудачная. Чем например, components отличается от models? Также, имена неймспейсов с маленькой буквы не соответствуют рекомендациям PSR-4.
https://github.com/InitF/StudentList/blob/master/components/DbConnector.php
Этот класс довольно бесполезен. Зачем он нужен, если можно и без него создать объект PDO?
> } catch (\PDOException $e){
> echo $e->getMessage();
Это неправильно, читай урок по исключениям и в следующий раз не копируй бездумно код: https://github.com/codedokode/pasta/blob/master/php/exceptions.md
Твой код выводит подробности ошибки пользователю (зачем они ему?), а в лог ничего не пишет.
https://github.com/InitF/StudentList/blob/master/components/Route.php
Неудачное название. Route значит "маршрут", а "маршрутизатор" будет Router. Более того, твой роутер вызывает контроллеры и правильнее его называть FrontController.
> if (($pos = strpos($path, '?')) !== false) {
> $path = substr($path, 0, $pos);
Лучше использовать parse_url.
> }elseif ($path == '/reg' || $path == '/reg/'){
Желательно, чтобы у страницы был один URL, а не два.
> IndexController::action();
Статические методы это не ООП. В уроке про DI кратко описано, чем они плохи: https://github.com/codedokode/pasta/blob/master/arch/di.md
https://github.com/InitF/StudentList/blob/master/components/StudentValidation.php#L11
> private $_student;
Не надо ставить подчеркивание в начале.
> 'Максимальная длина имени 50 символов, а вы ввели' . mb_strlen($this->_student->name);
Нету пробела между сообщением и числом.
> [a-яёА-ЯЁ]{1,}
{1,} это тоже самое, что знак плюс.
> if (mb_strlen($this->_student->last_name) > 50){
> $this->errors['last_name'][] = 'Максимальная длина фамилии 70 символов
Числа не совпадают.
https://github.com/InitF/StudentList/blob/master/components/StudentValidation.php#L120
Лучше передавать StudentTableGateway через DI как описано в уроке про DI по ссылке выше.
> public function runValidate()
Функция не очищает массив ошибок и при повторном вызове там будут старые ошибки перемешаны с новыми.
Вместо public $errors стоило сделать методы для получения ошибок, например, проверить, есть ли ошибки, получить список ошибок для поля и тд.
https://github.com/InitF/StudentList/blob/master/composer.json
тут поля вроде name, descrption, authors можно было не указывать. Они нужны для оформления библиотек, а если тебе нужна только автозагрузка, то достаточно ключа autoload.
https://github.com/InitF/StudentList/blob/master/controllers/ErrorController.php
При ошибке 404 надо выдавать соответствующий HTTP код. Ты же выдаешь страницу с кодом 200, как будто бы все в порядке. Прочитай про коды состояния в HTTP: https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP (если не знаешь HTTP, то почитай сначала про сам HTTP, например в моем уроке https://github.com/codedokode/pasta/blob/master/network/http.md)
https://github.com/InitF/StudentList/blob/master/view/main.html#L27
View не должен обращаться к кукам, это задача контроллера.
> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
Не советую подключать скрипты со сторонних серверов, лучше сохранить файл к себе. А то добавляется лишняя точка отказа, ну и данные о посетителях сливаются гуглу.
Не вижу пагинации. Надо бы ее сделать.
При поиске стоит показывать введенное слово в поле поиска.
> https://github.com/InitF/StudentList/blob/master/view/index.html#L12
<?php foreach ($students as $student) {
В шаблонах используют версии с двоеточием: http://www.phpinfo.su/articles/practice/shablony_v_php.html
При выводе надо экранировать данные, чтобы не получить XSS: https://github.com/codedokode/pasta/blob/master/security/xss.md
Вообще, я советую перечитать замечания к задаче, там вроде это упоминается.
> if (isset($_POST)
Это бессмысленная проверка, так как POST существует всегда.
> $student->nonresident = $post['nonresident'] == 1 ? 'Да' : 'Нет';
Тут стоит использовать латинские идентификаторы и в коде указывать их как константы в классе Student: https://github.com/codedokode/pasta/blob/master/good-code.md#Используй-константы-когда-есть-выбор-из-нескольких-вариантов
> $student->reg_date = date("Y-m-d H:i:s");
При редактировании дату обновлять не надо.
> echo json_encode($response);
Надо выдавать правильный Content-Type, указывающий, что ответ в формате JSON.
>$response['state'] = 'not_done';
Что обозначает это состояние? По моему, результат валидации - либо да, либо нет. Я бы использовал true/false вместо строковых констант, в которых легко опечататься.
https://github.com/InitF/StudentList/blob/master/controllers/RegController.php#L67
> public static function generateString($length = 40){
Почему эта функция публичная? Ее предполагается где-то еще исползовать? Контроллер это не сервис, чтобы предоставлять полезные функции для других классов.
Способ использования класса валидации нелогичный:
> $validation = new StudentValidation($student);
> $validation->runValidate();
> if (empty($validation->errors)) {
Почему функция runValidate не вернет результат сразу, а вместо этого его надо получать каким-то обходным путем? Плюс неочевидно, что надо вызвать runValidate(), ведь поле errors доступно с момента создания объекта.
> $studentTable = new StudentTableGateway();
Это разбросано много раз по коду. По моему, сервис удобнее создать 1 раз в 1 месте и использовать далее один и тот же экземпляр.
Я вижу, ты используешь яваскрипт для обработки данных формы. Но почему бы не предусмотреть, как запасной вариант, обычную отправку формы, например, если яваскрипт отключен? Это не потребует много доработок, я думаю.
Нет защиты от CSRF.
https://github.com/InitF/StudentList/blob/master/model/StudentTableGateway.php#L21
> $result = $stmt->execute((array)$student);
Это неудачная идея. Кто-то добавит новые поля в модель, и тут будет ошибка о лишних значениях плейсхолдеров. То есть расширение класса модели ломает код работы с БД. Это неправильно. Лучше заложить где-то список полей явно.
Создание нового StudentTableGateway у тебя создает новое соединение с базой. Надо тут использовать принцип DI.
> public function checkEmail($email)
Неудачное название, из названия не понятно, как интерпретировать результат. Если вернется true, то что это значит? Надо называть вроде isEmailUsed/isEmailAvailable/isEmailUnique
При редактировании не будет ошибки об использованном email?
Я бы советовал бутстрап хранить в отдельной папке, чтобы не смешивать твой код и сторонний и проще было обновлять.
> $(document).ready(function () {
> $(document).on('click', '.js-submit-student', Form.submit)
зачем дожидаться document.ready? А если в конце страницы какой-нибудь рекламный баннер долго инициализируется, и в это время отправить форму? Не лучше ли вписать вызов в onsubmit на теге form?
> Form.response = JSON.parse(data);
Не лучше ли использовать $.ajax с dataType = 'json', он будет работать во всех браузерах, а не только в новых, где есть объект JSON? Вот ты исплоьзуешь объект JSON, а ты проверил, какие браузеры его поддерживают?
Также, у тебя нет индикатора того, что идет обработка запроса (разве что кнопка блокируется). Стоило бы добавить.
Код работы с формой написан так, что он не поддерживает более 1 формы на странице. Ну например, эта строка $('.form-group').removeClass('has-error'); очищает ошибки на всех формах на странице. Лучше делать все в передлах одной формы. Также лучше на мой взгляд, было бы использовать тут нормальный ООП, а не класс на статических методах.
> if (Form.errors[key][+i+1] !== undefined){
> message += '<br>'
Использование <br> для верстки говорит о том, что ты плоховато знаешь HTML. У нас в ОП посте есть задачи, если что.
>>874960
>>876772
Ты зря взял структуру файлов с Юи, так как она довольно неудачная. Чем например, components отличается от models? Также, имена неймспейсов с маленькой буквы не соответствуют рекомендациям PSR-4.
https://github.com/InitF/StudentList/blob/master/components/DbConnector.php
Этот класс довольно бесполезен. Зачем он нужен, если можно и без него создать объект PDO?
> } catch (\PDOException $e){
> echo $e->getMessage();
Это неправильно, читай урок по исключениям и в следующий раз не копируй бездумно код: https://github.com/codedokode/pasta/blob/master/php/exceptions.md
Твой код выводит подробности ошибки пользователю (зачем они ему?), а в лог ничего не пишет.
https://github.com/InitF/StudentList/blob/master/components/Route.php
Неудачное название. Route значит "маршрут", а "маршрутизатор" будет Router. Более того, твой роутер вызывает контроллеры и правильнее его называть FrontController.
> if (($pos = strpos($path, '?')) !== false) {
> $path = substr($path, 0, $pos);
Лучше использовать parse_url.
> }elseif ($path == '/reg' || $path == '/reg/'){
Желательно, чтобы у страницы был один URL, а не два.
> IndexController::action();
Статические методы это не ООП. В уроке про DI кратко описано, чем они плохи: https://github.com/codedokode/pasta/blob/master/arch/di.md
https://github.com/InitF/StudentList/blob/master/components/StudentValidation.php#L11
> private $_student;
Не надо ставить подчеркивание в начале.
> 'Максимальная длина имени 50 символов, а вы ввели' . mb_strlen($this->_student->name);
Нету пробела между сообщением и числом.
> [a-яёА-ЯЁ]{1,}
{1,} это тоже самое, что знак плюс.
> if (mb_strlen($this->_student->last_name) > 50){
> $this->errors['last_name'][] = 'Максимальная длина фамилии 70 символов
Числа не совпадают.
https://github.com/InitF/StudentList/blob/master/components/StudentValidation.php#L120
Лучше передавать StudentTableGateway через DI как описано в уроке про DI по ссылке выше.
> public function runValidate()
Функция не очищает массив ошибок и при повторном вызове там будут старые ошибки перемешаны с новыми.
Вместо public $errors стоило сделать методы для получения ошибок, например, проверить, есть ли ошибки, получить список ошибок для поля и тд.
https://github.com/InitF/StudentList/blob/master/composer.json
тут поля вроде name, descrption, authors можно было не указывать. Они нужны для оформления библиотек, а если тебе нужна только автозагрузка, то достаточно ключа autoload.
https://github.com/InitF/StudentList/blob/master/controllers/ErrorController.php
При ошибке 404 надо выдавать соответствующий HTTP код. Ты же выдаешь страницу с кодом 200, как будто бы все в порядке. Прочитай про коды состояния в HTTP: https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP (если не знаешь HTTP, то почитай сначала про сам HTTP, например в моем уроке https://github.com/codedokode/pasta/blob/master/network/http.md)
https://github.com/InitF/StudentList/blob/master/view/main.html#L27
View не должен обращаться к кукам, это задача контроллера.
> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
Не советую подключать скрипты со сторонних серверов, лучше сохранить файл к себе. А то добавляется лишняя точка отказа, ну и данные о посетителях сливаются гуглу.
Не вижу пагинации. Надо бы ее сделать.
При поиске стоит показывать введенное слово в поле поиска.
> https://github.com/InitF/StudentList/blob/master/view/index.html#L12
<?php foreach ($students as $student) {
В шаблонах используют версии с двоеточием: http://www.phpinfo.su/articles/practice/shablony_v_php.html
При выводе надо экранировать данные, чтобы не получить XSS: https://github.com/codedokode/pasta/blob/master/security/xss.md
Вообще, я советую перечитать замечания к задаче, там вроде это упоминается.
> if (isset($_POST)
Это бессмысленная проверка, так как POST существует всегда.
> $student->nonresident = $post['nonresident'] == 1 ? 'Да' : 'Нет';
Тут стоит использовать латинские идентификаторы и в коде указывать их как константы в классе Student: https://github.com/codedokode/pasta/blob/master/good-code.md#Используй-константы-когда-есть-выбор-из-нескольких-вариантов
> $student->reg_date = date("Y-m-d H:i:s");
При редактировании дату обновлять не надо.
> echo json_encode($response);
Надо выдавать правильный Content-Type, указывающий, что ответ в формате JSON.
>$response['state'] = 'not_done';
Что обозначает это состояние? По моему, результат валидации - либо да, либо нет. Я бы использовал true/false вместо строковых констант, в которых легко опечататься.
https://github.com/InitF/StudentList/blob/master/controllers/RegController.php#L67
> public static function generateString($length = 40){
Почему эта функция публичная? Ее предполагается где-то еще исползовать? Контроллер это не сервис, чтобы предоставлять полезные функции для других классов.
Способ использования класса валидации нелогичный:
> $validation = new StudentValidation($student);
> $validation->runValidate();
> if (empty($validation->errors)) {
Почему функция runValidate не вернет результат сразу, а вместо этого его надо получать каким-то обходным путем? Плюс неочевидно, что надо вызвать runValidate(), ведь поле errors доступно с момента создания объекта.
> $studentTable = new StudentTableGateway();
Это разбросано много раз по коду. По моему, сервис удобнее создать 1 раз в 1 месте и использовать далее один и тот же экземпляр.
Я вижу, ты используешь яваскрипт для обработки данных формы. Но почему бы не предусмотреть, как запасной вариант, обычную отправку формы, например, если яваскрипт отключен? Это не потребует много доработок, я думаю.
Нет защиты от CSRF.
https://github.com/InitF/StudentList/blob/master/model/StudentTableGateway.php#L21
> $result = $stmt->execute((array)$student);
Это неудачная идея. Кто-то добавит новые поля в модель, и тут будет ошибка о лишних значениях плейсхолдеров. То есть расширение класса модели ломает код работы с БД. Это неправильно. Лучше заложить где-то список полей явно.
Создание нового StudentTableGateway у тебя создает новое соединение с базой. Надо тут использовать принцип DI.
> public function checkEmail($email)
Неудачное название, из названия не понятно, как интерпретировать результат. Если вернется true, то что это значит? Надо называть вроде isEmailUsed/isEmailAvailable/isEmailUnique
При редактировании не будет ошибки об использованном email?
Я бы советовал бутстрап хранить в отдельной папке, чтобы не смешивать твой код и сторонний и проще было обновлять.
> $(document).ready(function () {
> $(document).on('click', '.js-submit-student', Form.submit)
зачем дожидаться document.ready? А если в конце страницы какой-нибудь рекламный баннер долго инициализируется, и в это время отправить форму? Не лучше ли вписать вызов в onsubmit на теге form?
> Form.response = JSON.parse(data);
Не лучше ли использовать $.ajax с dataType = 'json', он будет работать во всех браузерах, а не только в новых, где есть объект JSON? Вот ты исплоьзуешь объект JSON, а ты проверил, какие браузеры его поддерживают?
Также, у тебя нет индикатора того, что идет обработка запроса (разве что кнопка блокируется). Стоило бы добавить.
Код работы с формой написан так, что он не поддерживает более 1 формы на странице. Ну например, эта строка $('.form-group').removeClass('has-error'); очищает ошибки на всех формах на странице. Лучше делать все в передлах одной формы. Также лучше на мой взгляд, было бы использовать тут нормальный ООП, а не класс на статических методах.
> if (Form.errors[key][+i+1] !== undefined){
> message += '<br>'
Использование <br> для верстки говорит о том, что ты плоховато знаешь HTML. У нас в ОП посте есть задачи, если что.
Составляй по шагам:
- напиши выражение для "ровно одна скобка, минус или пробел"
- любое число минусов, скобок, пробелов
- ровно 1 цифра, за ней любое число минусов, скобок, пробелов
- то же самое, повторяется 10 раз
Укажите на проблемы, если они есть (конечно есть):
https://jsfiddle.net/9ypeL84s/
а) общая концепция (сам думаю, что говнокод)
, если не пиздец, то
б) неучтенные ошибки
в) краткость
г) понятность приведенного кода с точки зрения стилистики
д) отвечает ли требованиям ООП?
Если есть возможность, направить что гуглить, чтобы исправить сие.
P.S.: как и любой говнокод, работает как задумано, как аллах.
Спасибо. Попробовал решить первую задачу http://ideone.com/5l3ws7
В процессе возникло пару вопросов:
$str = iconv("utf-8","utf-16", $str);
Кодирует в utf-16le и ставит впереди BOM FFFE. Если указать utf-16be (или le), то BOM не ставится (потому что считается мы ты точно знаем кодировку и BOM не понадобится?). Бывают ли ситуации когда BOM придется добавлять в ручную, если например, мы отдаем данные куда-нибудь?
Я не уверен, что хорошо понимаю, как анализировать эффективность алгоритма. Возьму эту задачку, мыслю так: раз элементы в массиве в произвольном порядке, то алгоритм будет линейным и невозможно написать ничего эффективней O(n). Дальше подразумеваю, что n - количество элементов в массиве и n > 2
Первое решение: http://ideone.com/LSTgO2
Лучшее время будет у массива одинаковых элементов, в алгоритме произойдёт n-1 итераций цикла, n-1 сравнений, 0 присвоений
У массива, отсортированного по убыванию: n-1 итераций цикла, (n-1)5 сравнений, n-1 присвоений.
У массива, отсортированного по возрастанию: n-1 итераций цикла, (n-1)3 сравнений, (n-1)2 присвоений.
Я так понимаю, что сложность алгоритма O(n)? Константы, то есть значения, которые не зависят от количества элементов в массиве, можно опустить.
Второе решение: http://ideone.com/8ascih
Решение использует array_unique, rsort и array_slice. Я нагуглил, что array_unique использует сортировку (уже nlogn), у быстрой сортировки сложность nlogn, array_slice не учитываем, так как в моём случае эта функция для всех входных данных вырезает первые 2 элемента. Итого выходит nlogn+n*logn?
Угол между стрелками: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Угол-между-стрелками
http://ideone.com/kbwyYu
Дерево: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Дерево
https://jsfiddle.net/5L14too1/3/
Сделал на JS, так как в браузере легко отладить программу, а за отладчик PHP я пока не садился. Это, видимо, сигнал к тому, что мой подход к решению задачи слишком запутанный, раз без отладчика я не могу его реализовать.
Задачи по датам: https://gist.github.com/codedokode/10539805#Задачи
Чувствую, что очень переусложнил обе.
1. http://ideone.com/Kqcxgc
2. http://ideone.com/E1Ig43
Здесь не понимаю, как лучше указывать формат праздника. Например, здесь http://php.net/manual/en/function.date.php пишут, что можно использовать d и j для дней 1-30 и 01-30 соответственно.
Качалка файлов: https://arhivach.org/thread/213097/#884783
> Небольшая мелочь. Функция curl_init может вернуть false, у тебя это не проверяется.
Не считаю перечисленные тобой недочёты мелочью, если в программе произошла ошибка, то программист должен узнать об этом как можно раньше. Спасибо, что сообщаешь об этом.
> Для курла нет ограничения на скорость скачивания.
Я нашёл такой пакет: https://github.com/bandwidth-throttle/bandwidth-throttle
Но я не осилил исходник, там используются stream/resource с которыми я не знаком. Исходный код Guzzle так же не могу осилить по той же причине. В общем, пока забил на загрузчик.
Я не уверен, что хорошо понимаю, как анализировать эффективность алгоритма. Возьму эту задачку, мыслю так: раз элементы в массиве в произвольном порядке, то алгоритм будет линейным и невозможно написать ничего эффективней O(n). Дальше подразумеваю, что n - количество элементов в массиве и n > 2
Первое решение: http://ideone.com/LSTgO2
Лучшее время будет у массива одинаковых элементов, в алгоритме произойдёт n-1 итераций цикла, n-1 сравнений, 0 присвоений
У массива, отсортированного по убыванию: n-1 итераций цикла, (n-1)5 сравнений, n-1 присвоений.
У массива, отсортированного по возрастанию: n-1 итераций цикла, (n-1)3 сравнений, (n-1)2 присвоений.
Я так понимаю, что сложность алгоритма O(n)? Константы, то есть значения, которые не зависят от количества элементов в массиве, можно опустить.
Второе решение: http://ideone.com/8ascih
Решение использует array_unique, rsort и array_slice. Я нагуглил, что array_unique использует сортировку (уже nlogn), у быстрой сортировки сложность nlogn, array_slice не учитываем, так как в моём случае эта функция для всех входных данных вырезает первые 2 элемента. Итого выходит nlogn+n*logn?
Угол между стрелками: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Угол-между-стрелками
http://ideone.com/kbwyYu
Дерево: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Дерево
https://jsfiddle.net/5L14too1/3/
Сделал на JS, так как в браузере легко отладить программу, а за отладчик PHP я пока не садился. Это, видимо, сигнал к тому, что мой подход к решению задачи слишком запутанный, раз без отладчика я не могу его реализовать.
Задачи по датам: https://gist.github.com/codedokode/10539805#Задачи
Чувствую, что очень переусложнил обе.
1. http://ideone.com/Kqcxgc
2. http://ideone.com/E1Ig43
Здесь не понимаю, как лучше указывать формат праздника. Например, здесь http://php.net/manual/en/function.date.php пишут, что можно использовать d и j для дней 1-30 и 01-30 соответственно.
Качалка файлов: https://arhivach.org/thread/213097/#884783
> Небольшая мелочь. Функция curl_init может вернуть false, у тебя это не проверяется.
Не считаю перечисленные тобой недочёты мелочью, если в программе произошла ошибка, то программист должен узнать об этом как можно раньше. Спасибо, что сообщаешь об этом.
> Для курла нет ограничения на скорость скачивания.
Я нашёл такой пакет: https://github.com/bandwidth-throttle/bandwidth-throttle
Но я не осилил исходник, там используются stream/resource с которыми я не знаком. Исходный код Guzzle так же не могу осилить по той же причине. В общем, пока забил на загрузчик.
Интересно, я про такое не знал. Давай я тогда тогда научу тебя, как определить, кто отвечает за работу этой функции.
iconv - это не функция самого PHP. PHP лишь предоставляет доступ к сишной функции (это понятно отсюда: http://php.net/manual/ru/iconv.requirements.php ), которая в linux системе может либо входить в состав стандартной библиотеки (glibc), либо поставляться отдельно в библиотеке libiconv. Я думаю, отдельная версия используется на Windows, где нет glibc.
Если функция берется из библиотеки glibc (GNU libc), которая поставляется отдельно от PHP (от нее зависят почти все программы, так что я думаю она идет как часть базовой системы), можно посмотреть ее официальный сайт: https://www.gnu.org/software/libc/ . На нем есть документация, и описание сишной функции iconv: https://www.gnu.org/software/libc/manual/html_mono/libc.html#Generic-Charset-Conversion которое довольно длинное, запутанное и не дает нам ответа.
Однако мы можем кое-что сделать для проверки. Мы можем использовать программу командной строки iconv, которая использует ту же сишную функцию, что и PHP, и посмотреть, как она ведет себя.
echo Hello | iconv -f utf-8 -t utf-16 | od -t x1
Результат: 0000000 ff fe 48 00 65 00 6c 00 6c 00 6f 00 0a 00
То есть BOM вставляет не PHP, а сишная функция iconv.
На всякий случай заглянем еще в исходники PHP. Зайдем сюда: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c , заметим что PHP-функции iconv соответствует функция с немного другим именем php_if_iconv, и найдем ее код: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c#L2442
Видно, что она почти ничего не делает, кроме вызова другой функции php_iconv_string: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c#L553 Почитаем код, и видим что в общем-то тут тоже специально BOM не добавляется.
Дальше можно поковырять исходники glibc, тут https://sourceware.org/git/?p=glibc.git;a=tree;f=iconv;hb=refs/heads/master , но что-то там все запутанно.
По коду:
Я думаю, что незачем создавать промежуточный массив 2-байтных строк. Выгоднее создавать сразу массив кодов. Или выводить их. У тебя есть массив отдельных символов - можно сделать функцию, которая получает 1 utf-8 символ на вход и выдает его codepoint.
Также, предлагаю доработать код для поддержки utf-32, чтобы для символов, не входящих в UCS-2, код отображался бы тоже правильно, а не как 2 суррогатных символа.
Интересно, я про такое не знал. Давай я тогда тогда научу тебя, как определить, кто отвечает за работу этой функции.
iconv - это не функция самого PHP. PHP лишь предоставляет доступ к сишной функции (это понятно отсюда: http://php.net/manual/ru/iconv.requirements.php ), которая в linux системе может либо входить в состав стандартной библиотеки (glibc), либо поставляться отдельно в библиотеке libiconv. Я думаю, отдельная версия используется на Windows, где нет glibc.
Если функция берется из библиотеки glibc (GNU libc), которая поставляется отдельно от PHP (от нее зависят почти все программы, так что я думаю она идет как часть базовой системы), можно посмотреть ее официальный сайт: https://www.gnu.org/software/libc/ . На нем есть документация, и описание сишной функции iconv: https://www.gnu.org/software/libc/manual/html_mono/libc.html#Generic-Charset-Conversion которое довольно длинное, запутанное и не дает нам ответа.
Однако мы можем кое-что сделать для проверки. Мы можем использовать программу командной строки iconv, которая использует ту же сишную функцию, что и PHP, и посмотреть, как она ведет себя.
echo Hello | iconv -f utf-8 -t utf-16 | od -t x1
Результат: 0000000 ff fe 48 00 65 00 6c 00 6c 00 6f 00 0a 00
То есть BOM вставляет не PHP, а сишная функция iconv.
На всякий случай заглянем еще в исходники PHP. Зайдем сюда: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c , заметим что PHP-функции iconv соответствует функция с немного другим именем php_if_iconv, и найдем ее код: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c#L2442
Видно, что она почти ничего не делает, кроме вызова другой функции php_iconv_string: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c#L553 Почитаем код, и видим что в общем-то тут тоже специально BOM не добавляется.
Дальше можно поковырять исходники glibc, тут https://sourceware.org/git/?p=glibc.git;a=tree;f=iconv;hb=refs/heads/master , но что-то там все запутанно.
По коду:
Я думаю, что незачем создавать промежуточный массив 2-байтных строк. Выгоднее создавать сразу массив кодов. Или выводить их. У тебя есть массив отдельных символов - можно сделать функцию, которая получает 1 utf-8 символ на вход и выдает его codepoint.
Также, предлагаю доработать код для поддержки utf-32, чтобы для символов, не входящих в UCS-2, код отображался бы тоже правильно, а не как 2 суррогатных символа.
Насчет ООП: прототипы используются неправильно. Рекомендую почитать например тут https://learn.javascript.ru/prototypes (вообще, learn.javascript.ru стоит прочесть целиком, много полезного).
Замечания по коду:
Переменные надо называть нормально. Непонятно, что такое o или t, и это замедляет чтение кода. Надо дать им нормальные имена.
Функцию надо разбить на несколько отдельных. Тут смешано несколько задач в одной функции, и из-за этого код получился запутанным и ограниченным. Ну например, здесь нельзя никак указать дополнительные опции для $.ajax (например, cache), кроме тех, что разрешены. Не вижу смысла делать такое ограничение.
Ну например, что касается функции повтора запросов. Это можно сделать отдельной функцией вида:
sendRequestWithRetry(options, maxRetries)
где options - опции для $.ajax.
> if (t-- > 0
тут совмещено 2 действия (уменьшение переменной и проверка), и такой код тяжело читать. И вообще, не очень нормально, что if что-то модифицирует. Не надо стремиться записать код в одну длинную строку.
> && XMLHttpRequest.status != 404
Это явно неправильное условие. Ну например, сервер может вернуть 400 или 403, которые явно не требуют повтора. Логично делать повтор при TCp ошибках (обычно это код 0), или ошибках 5xx. Советую почитать про коды состояния HTTP.
> MyClass.prototype.myErrorHandler(
Это неправильно. При прототипном ООП мы вызываем метод как obj.method(), а prototype используем только при описании метода. Советую решить задачу про гамбургеры из JS-задач из ОП поста.
> function(XMLHttpRequest) {
Непраильно называть переменную с большой буквы, да еще и перекрывая глобальный объект с таким же именем.
> success: function(jsonapi) {
неудачное название переменной jsonapi. В ней же не API хранится, а результат вызова.
> switch (jsonapi.data.meta) {
> case 'imeta':
> this[jsonapi.data.meta] = jsonapi.data.values;
Это какой-то странный код. Во-первых, он добавляет неочевидные побочные эффекты к функции, по-вторых, this тут будет указывать на другой объект (скорее всего на window). А, хотя там есть context. Но все равно неправильно так исплоьзовать свойств prototype так как он не для этого предназначен, не для хранения свойств объекта, а для описания методов, которые есть у всех объектов одного класса.
> switch (jsonapi.data.meta) {
> case 'imeta':
Непонятно, зачем тут switch, а не if.
Комментарий к функции написан с исплоьзованием какого синтаксиса? В jsDoc имена переменных вроде не берутся в квадратные скобки.
Насчет ООП: прототипы используются неправильно. Рекомендую почитать например тут https://learn.javascript.ru/prototypes (вообще, learn.javascript.ru стоит прочесть целиком, много полезного).
Замечания по коду:
Переменные надо называть нормально. Непонятно, что такое o или t, и это замедляет чтение кода. Надо дать им нормальные имена.
Функцию надо разбить на несколько отдельных. Тут смешано несколько задач в одной функции, и из-за этого код получился запутанным и ограниченным. Ну например, здесь нельзя никак указать дополнительные опции для $.ajax (например, cache), кроме тех, что разрешены. Не вижу смысла делать такое ограничение.
Ну например, что касается функции повтора запросов. Это можно сделать отдельной функцией вида:
sendRequestWithRetry(options, maxRetries)
где options - опции для $.ajax.
> if (t-- > 0
тут совмещено 2 действия (уменьшение переменной и проверка), и такой код тяжело читать. И вообще, не очень нормально, что if что-то модифицирует. Не надо стремиться записать код в одну длинную строку.
> && XMLHttpRequest.status != 404
Это явно неправильное условие. Ну например, сервер может вернуть 400 или 403, которые явно не требуют повтора. Логично делать повтор при TCp ошибках (обычно это код 0), или ошибках 5xx. Советую почитать про коды состояния HTTP.
> MyClass.prototype.myErrorHandler(
Это неправильно. При прототипном ООП мы вызываем метод как obj.method(), а prototype используем только при описании метода. Советую решить задачу про гамбургеры из JS-задач из ОП поста.
> function(XMLHttpRequest) {
Непраильно называть переменную с большой буквы, да еще и перекрывая глобальный объект с таким же именем.
> success: function(jsonapi) {
неудачное название переменной jsonapi. В ней же не API хранится, а результат вызова.
> switch (jsonapi.data.meta) {
> case 'imeta':
> this[jsonapi.data.meta] = jsonapi.data.values;
Это какой-то странный код. Во-первых, он добавляет неочевидные побочные эффекты к функции, по-вторых, this тут будет указывать на другой объект (скорее всего на window). А, хотя там есть context. Но все равно неправильно так исплоьзовать свойств prototype так как он не для этого предназначен, не для хранения свойств объекта, а для описания методов, которые есть у всех объектов одного класса.
> switch (jsonapi.data.meta) {
> case 'imeta':
Непонятно, зачем тут switch, а не if.
Комментарий к функции написан с исплоьзованием какого синтаксиса? В jsDoc имена переменных вроде не берутся в квадратные скобки.
Вообще, насчет повтора запросов, тут надо думать, а нужно ли оно и не лучше ли дать пользователю решать, когда повторить попытку.
Ну представим, что у пользователя периодически пропадает связь и запросы отваливаются после долгого таймаута. Может пользователь бы хотел что-то другое сделать, но ему придется ждать пока все попытки отработают.
Шта?..
В чем боль-то? Добавляют в PHP7.2 функции для получения кода многобайтового символа и генерации символа по коду.
Весь похапе боль не ври мне тут говно
Отрицательная сумма получается из-за того, что когда там остается 1200 долга, ты все равно платишь банку 5000. А надо эти оставшиеся 1200 и платить.
Я бы написал так:
если (долг больше чем плата в месяц) {
платим = плата в месяц;
} иначе {
платим = сумма долга;
}
Ну и далее этот if можно заменить на min() или max().
>>880900
Не знаю, не писал ничего под magento. Попробуй посмотреть код и почитать документацию.
>>882320
Не знаю, я бы начал с изучения документации самого фейсбука.
>>882619
Хотя я толком не понял в чем проблема из твоего описания, но возможно, тебе еще стоит подучить PHP, чтобы лучше знать его возможности? Ну или напиши подробнее, пока не понятно.
> Вопрос, нужно создавать каждую страницу заново? Или можно как-то с помощью хитроумного кода менять содержимое основной страницы.
Не понял вопрос. зачем "создавать каждую страницу заново"?
>>882645
Смешивать PHP c HTML можно, не надо просто смешивать логику получения данных и логику их отображения. Таблица генерируется циклом вроде foreach.
>>882669
Не надо изобретать свой шаблонизатор. Надо брать готовый.
>>882731
Что значит "у нас"? За отправку файлов отвечает браузер, его разработчики и HTML стандарты.
>>883499
Не знаю. Я бы нашел сайт или статью с обзорами разных CMS и фреймворков для начала. Ну и далее сам бы уже смотрел проекты, которые там упоминаются.
Отрицательная сумма получается из-за того, что когда там остается 1200 долга, ты все равно платишь банку 5000. А надо эти оставшиеся 1200 и платить.
Я бы написал так:
если (долг больше чем плата в месяц) {
платим = плата в месяц;
} иначе {
платим = сумма долга;
}
Ну и далее этот if можно заменить на min() или max().
>>880900
Не знаю, не писал ничего под magento. Попробуй посмотреть код и почитать документацию.
>>882320
Не знаю, я бы начал с изучения документации самого фейсбука.
>>882619
Хотя я толком не понял в чем проблема из твоего описания, но возможно, тебе еще стоит подучить PHP, чтобы лучше знать его возможности? Ну или напиши подробнее, пока не понятно.
> Вопрос, нужно создавать каждую страницу заново? Или можно как-то с помощью хитроумного кода менять содержимое основной страницы.
Не понял вопрос. зачем "создавать каждую страницу заново"?
>>882645
Смешивать PHP c HTML можно, не надо просто смешивать логику получения данных и логику их отображения. Таблица генерируется циклом вроде foreach.
>>882669
Не надо изобретать свой шаблонизатор. Надо брать готовый.
>>882731
Что значит "у нас"? За отправку файлов отвечает браузер, его разработчики и HTML стандарты.
>>883499
Не знаю. Я бы нашел сайт или статью с обзорами разных CMS и фреймворков для начала. Ну и далее сам бы уже смотрел проекты, которые там упоминаются.
http://ideone.com/82ziTH
Переделал задачу. Тема мне понравилась. Было интересно посмотреть, как по разному можно упаковывать данные в бинарные формы в зависимости от поставленных требований.
Вынужденные жертвы.
Потому что загаживают тред оффтопиком в стиле пэхапэ против бэтмана, сделайте мой фриланс и т.д. Посмотри в архиваче на начало тредов и на конец. Почувствуй разницу. Когда то было два php треда: учебный и для бурных дискуссий, тогда было полегче.
Интересно, а как они оценивают эту "информационную открытость"? Лазают вручную смотрят? Или ботов заставляют по определенным алгоритмам? И конечно же вопрос: я тупой, зачем вся эта хрень вообще нужна?
>>895872
>>895925
Еще бы конеш не удаляли треды, как например на доброчане.
Кстати, еще строку превратить в коды байт можно функцией bin2hex, но она генерирует 16-чные цифры без пробелов между ними.
> utf-32 string starts with 4 bytes BOM and 2 "empty" bytes (FFFE + 0000)
Неточно, в utf-32 символ занимает 4 байта и последовательность ff fe 00 00 - это и есть 1 символ BOM, а далее 4 байта - это код символа. Я думаю, надо было использовать utf-32 le или be с явным указанием вида кодировки (чтобы байты там шли в нужном порядке) и не мучаться с определением, где что.
Я вижу, ты там получаешь 16-чный код склеиванием побайтово, если бы тебе нужен был 10-чный код то пришлось бы умножать на степени числа 256:
b3 * 256 ^ 3 + b2 *256 ^ 2 + b1 * 256 ^ 1 + b0 * 256 ^ 0.
Я может еще потом сделаю урок про представление чисел в памяти, там тоже много интересного. Вот например, как представляются числа с плавающей запятой: https://habrahabr.ru/post/112953/
Но в общем, я думаю, эта задача решена.
Если хочешь помучать utf-8, можешь попробовать решит задачу удаления из строки неправильных utf-8 последовательностей, но она сложная. Проверить, что в строке есть неправильные последовательности можно например так
preg_match("//u", $string) вернет false, а не 0 или 1.
И что именно из этого ты не можешь сделать? Если ничего,то стоит начать с теории и изучения учебника в ОП посте.
Мониторинг нужен, так как без него что-то на одном из сайтов может отвалиться и никто не заметит. А так руководство в Москве может это увидеть. Может там еще уведомления какие раcсылаются. Плюс, у них там есть рейтинги, опять же, руководство может посмотреть как дела.
Мониторинг используют и коммерческие компании.
Проверка ручная, там есть список пунктов и человек проверяет их выполнение.
"Открытость" нужна, чтобы госорганы предоставляли машинночитамые данные, которые потом другие люди могут использовать в своем приложении. Ну условно говоря, госорган может предоставлять расписание автобусов, а кто-то сделает приложение, показывающее какой автобус куда едет. Или госорган может предоставить базу названий улиц и домов, а ты в своем приложении сделаешь автодополнение при ввода адреса.
В любом случае, наличие данных лучше их отсутствия.
Госорганы конечно не хотят лишний раз заморачиваться, потому там и сделали всякие рейтинги и проверки, чтобы мотивировать их.
Вот например московские открытые данные: https://data.mos.ru/
Там можно узнать к примеру, что в Москве 48 снегоплавильных пунктов: https://data.mos.ru/opendata/7701236617-statsionarnye-snegoplavilnye-punkty
https://ideone.com/LO13Fo
Вот тут написано про подмаски: http://php.net/manual/ru/function.preg-replace.php
Переменные $n содержат то, что захватила регулярка скобочками. Попробуй добавить их в регулярку.
Я уже разобрался в preg_replace заменил $1 на $0 и все сработало
Я думаю, потому что классы только относительно недавно в ES5 или ES6 появились, а не в ES3. Хуже совместимость будет.
Object.assign это просто неглубокое копирование свойств. Код там равносилен коду вроде
X.prototype.method =function () { ... };
>классы только относительно недавно в ES5 или ES6 появились, а не в ES3
Проверил, и классы и Object.assign описаны в ECMAScript 2015 (6th Edition, ECMA-262)
В соседней ветке мне объяснили так:
>assign копирует.
>extends наследует.
>js динамический язык. все может быть переопределено в рантайме. если переопределить метод в прототипе, у всех унаследовавшихся он тоже переопределится.
>ассигн используют тут вместо clone.
Но в примере свойства копируются в прототип:
Object.assign( Car.prototype, EventDispatcher.prototype );
или
Object.assign( EventDispatcher.prototype, {...} )
Следовательно все экземпляры класса Car и EventDispatcher унаследуют свойства, скопированные в прототипы этих классов? Т.е. тут .assign не копирует а наследует, как ты и написал: равносильно X.prototype.method =function () { ... }; ??? Вопрос все еще открыт, зачем автор в примере так извращается, или что я упускаю?
А, я сначала не так понял и не так ответил. Я думал вопрос был про использование assign в этом файле https://github.com/mrdoob/eventdispatcher.js/blob/master/src/EventDispatcher.js
Насчет es5 ты прав, я что-то не подумал. Можно было использовать синтаксис с class.
В примере с Car (на мой взгляд, кстати, неудачно выбрана машина в качестве примера, ну в какой программе у нас будет машина с событиями?), там автор кода не хочет наследовать Car от EventDispatcher, например, может он хочет его от чего-то другого унаследовать, может потому что там наследование логически не очень подходит (машина это ведь не улучшенный вариант EventDispatcher, хотя я видел и примеры наследования от EventDispatcher).
В чистом ООП, если мы не хотим применять наследование (так как наследование это отношение вида "A является B", а нам нужно "A содержит B"), мы используем аггрегирование: https://ru.wikipedia.org/wiki/Агрегирование_(программирование)
То есть мы создаем объект Event Dispatcher внутри car:
function Car() {
this._eventDispatcher = new EventDispatcher();
}
Но если свойство приватное, тогда мы должны выдать наружу методы, например для подписки на события (и делать это придется в каждом классе, который использует события):
Car.prototype.addEventListener = function ( ... ) {
this._eventDispatcher.addEventListener(...);
};
Или же мы должны сделать свойство _eventDispatcher публичным, такое тоже бывает. Хотя конечно это не очень красиво с точки зрения инкапсуляции, так как по идее внешний код должен иметь возможность только подписываться на события, а не генерировать их.
Автор решил упростить код и просто скопировать методы из прототипа EventDispatcher в прототип Car. Это еще называется "mixin", примешивание. Оно имеет свои недостатки, ну например:
- в данном примере не вызывается конструктор EventDipatcher. В моем примере с аггрегированием он вызывается.
- нет никакой защиты от конфликтов. Что будет, если мы в класс Car и в примесь добавим свойство или метод с одинаковым именем? Код просто будет работать неправильно, причем исключение может быть и не будет выброшено. Впрочем, код, который копирует прототипы, мог бы это проверять.
- такие же конфликты возможны если мы примешиваем в класс несколько примесей и в них добавим свойства/методы с одинаковым именем
Тем не менее такой подход иногда используют.
В общем, в данном случае автор решил использовать mixin.
Насчет событий, я видел разные подходы:
- иногда класс наследуют от EventDispatcher
- иногда используют аггрегирование
- иногда миксины, в PHP можно использовать трейты
- иногда делают на каждое событие отдельный объект, на который можно подписаться. Их можно выставить как публичные свойства:
this.onDataLoaded = new EventSource;
this.onError = new EventSource;
...
this.onError.trigger('Some error text');
А подписка делается так:
x.onDataLoaded.subscribe(function (event) { ... });
В языке C# даже сделали специальный тип поля "событие", хотя я не уверен что для событий нужно что-то специально делать на уровне языка. Там в класс добавляется специальное поле-источник событий, а при обращении к нему как к функции происходит вызов подписчиков: https://msdn.microsoft.com/ru-ru/library/edzehd2t(v=vs.110).aspx
А, я сначала не так понял и не так ответил. Я думал вопрос был про использование assign в этом файле https://github.com/mrdoob/eventdispatcher.js/blob/master/src/EventDispatcher.js
Насчет es5 ты прав, я что-то не подумал. Можно было использовать синтаксис с class.
В примере с Car (на мой взгляд, кстати, неудачно выбрана машина в качестве примера, ну в какой программе у нас будет машина с событиями?), там автор кода не хочет наследовать Car от EventDispatcher, например, может он хочет его от чего-то другого унаследовать, может потому что там наследование логически не очень подходит (машина это ведь не улучшенный вариант EventDispatcher, хотя я видел и примеры наследования от EventDispatcher).
В чистом ООП, если мы не хотим применять наследование (так как наследование это отношение вида "A является B", а нам нужно "A содержит B"), мы используем аггрегирование: https://ru.wikipedia.org/wiki/Агрегирование_(программирование)
То есть мы создаем объект Event Dispatcher внутри car:
function Car() {
this._eventDispatcher = new EventDispatcher();
}
Но если свойство приватное, тогда мы должны выдать наружу методы, например для подписки на события (и делать это придется в каждом классе, который использует события):
Car.prototype.addEventListener = function ( ... ) {
this._eventDispatcher.addEventListener(...);
};
Или же мы должны сделать свойство _eventDispatcher публичным, такое тоже бывает. Хотя конечно это не очень красиво с точки зрения инкапсуляции, так как по идее внешний код должен иметь возможность только подписываться на события, а не генерировать их.
Автор решил упростить код и просто скопировать методы из прототипа EventDispatcher в прототип Car. Это еще называется "mixin", примешивание. Оно имеет свои недостатки, ну например:
- в данном примере не вызывается конструктор EventDipatcher. В моем примере с аггрегированием он вызывается.
- нет никакой защиты от конфликтов. Что будет, если мы в класс Car и в примесь добавим свойство или метод с одинаковым именем? Код просто будет работать неправильно, причем исключение может быть и не будет выброшено. Впрочем, код, который копирует прототипы, мог бы это проверять.
- такие же конфликты возможны если мы примешиваем в класс несколько примесей и в них добавим свойства/методы с одинаковым именем
Тем не менее такой подход иногда используют.
В общем, в данном случае автор решил использовать mixin.
Насчет событий, я видел разные подходы:
- иногда класс наследуют от EventDispatcher
- иногда используют аггрегирование
- иногда миксины, в PHP можно использовать трейты
- иногда делают на каждое событие отдельный объект, на который можно подписаться. Их можно выставить как публичные свойства:
this.onDataLoaded = new EventSource;
this.onError = new EventSource;
...
this.onError.trigger('Some error text');
А подписка делается так:
x.onDataLoaded.subscribe(function (event) { ... });
В языке C# даже сделали специальный тип поля "событие", хотя я не уверен что для событий нужно что-то специально делать на уровне языка. Там в класс добавляется специальное поле-источник событий, а при обращении к нему как к функции происходит вызов подписчиков: https://msdn.microsoft.com/ru-ru/library/edzehd2t(v=vs.110).aspx
Кстати, в коде там можно заметить, что ради использования класса как миксина они создают поля при первом обращении, а не в конструкторе:
https://github.com/mrdoob/eventdispatcher.js/blob/master/src/EventDispatcher.js#L11
if ( this._listeners === undefined ) this._listeners = {};
>автор кода не хочет наследовать Car от EventDispatcher, например, может он хочет его от чего-то другого унаследовать
>машина это ведь не улучшенный вариант EventDispatcher
Вот теперь дошло, спасибо большое.
Спасибо, замечания учту.
Буквально сегодня я отчаялся и решил спросить ещё одну подсказку здесь, но пока я пытался сформулировать вопросы, я решил её сам:
https://dkab.github.io/jasmine-tests/?spec=6
https://jsfiddle.net/92nc4fj2/
Только один вопрос
http://pastebin.ru/yLh80hF8
>> var args = [].slice.call(arguments);
>> args.shift();
>можно без shift, указать аргумент для slice
А как указать его? Через .slice(1).call(...) или .slice.call(1)(...) не получилось...
Скоро будут исправлены остальные замечания
Большое спасибо!!!
> Через .slice(1).call(...) или .slice.call(1)(...) не получилось
И не должно, ты пытаешься вызвать call у результата функции, а нужно вызывать у самой функции. Вот тут написано как использовать call: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
И да, эта тема хорошо разжёвано у Кантора.
А насчёт сложности заданий, то у меня от четвёртой были такие же ощущения как и у тебя, так что всё норм, проходят дни и мозг сам по-немногу раскладывает непонятное по полочкам.
Если честно, то я действительно взялся за эту задачу только пару дней назад. Остальное время я ужасался сложностью этой задачи и впадал в прострацию.
Лучше не ужасаться, а написать, что именно непонятно, и попросить совет. В нашем треде обычно всегда что-нибудь посоветуют.
>>897432
>>> var args = [].slice.call(arguments);
>>> args.shift();
>>можно без shift, указать аргумент для slice
> А как указать его? Через .slice(1).call(...) или .slice.call(1)(...) не получилось...
А ты пробовал читать справку по методу call и разобраться, как работает [].slice.call? Например тут:
- https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/call
- https://learn.javascript.ru/call-apply
Тут надо понимать такие вещи:
- "методом" в других языках принято называть функцию, которая объявлена в классе и вызывается не сама по себе, а на каком-то объекте: someObject.someMethod(); Но в JS как таковых до ES5, методов не было и не было специального синтаксиса их создания - есть просто обычные функции, записанные в свойства объекта. Мы добавлям функцию объект или прототип объекта - и получается что-то похожее на метод. Для сравнения, в PHP есть специальный синтаксис для методов: class X { public function () { ... }; }
Вообще, JS более динамический язык. В PHP мы объявляем класс, и после этого его нельзя поменять.В JS мы можем в любой момент добавить в объект новые поля. Это имеет как плюсы, так и минусы - когда класс неизменен, легче разбираться в коде, и объекты такого класса можно хранить в памяти более эффективно.
- в JS функции являются еще и объектами с конструктором Function. Потому у них самих могут быть и свойства, и "методы". И можно даже делать так (но не нужно, чтобы не путать людей):
function x() {};
x.something = 1;
x.someMethod = function () {};
или так:
var x = new Function(...);
x();
- в JS методы - это просто поля объекта, в которых записаны функции. Можно (но не нужно) добавить метод в любой объект:
var x = [1, 2, 3];
x.test = function () { return 5; };
console.log(x.test());
- у массивов есть метод slice (который тоже является объектом), а когда мы пишем [].slice без скобок, то мы не вызвыаем его, а просто получаем этот объект. Сравни:
var x = [].slice; - копируем в переменную x ссылку на метод slice у массива.
[].slice() - вызваем метод slice()
- у функций есть метод call, который позволяет вызвать функцию с заданным значением this и аргументами
- есть особые правила, как именно определяется значение this при вызове функции. Описано например тут: https://learn.javascript.ru/objects-more
Изучив теорию, советую ответить на вопрос: чему будет равен (или на какой объект будет указывать) this внутри функции в следующих случаях:
1)
function x() { }; x();
2)
var z = {};
z.test = function () {};
z.test();
3)
var z = {};
z.test = function() {};
var fn = z.test;
fn();
Лучше не ужасаться, а написать, что именно непонятно, и попросить совет. В нашем треде обычно всегда что-нибудь посоветуют.
>>897432
>>> var args = [].slice.call(arguments);
>>> args.shift();
>>можно без shift, указать аргумент для slice
> А как указать его? Через .slice(1).call(...) или .slice.call(1)(...) не получилось...
А ты пробовал читать справку по методу call и разобраться, как работает [].slice.call? Например тут:
- https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/call
- https://learn.javascript.ru/call-apply
Тут надо понимать такие вещи:
- "методом" в других языках принято называть функцию, которая объявлена в классе и вызывается не сама по себе, а на каком-то объекте: someObject.someMethod(); Но в JS как таковых до ES5, методов не было и не было специального синтаксиса их создания - есть просто обычные функции, записанные в свойства объекта. Мы добавлям функцию объект или прототип объекта - и получается что-то похожее на метод. Для сравнения, в PHP есть специальный синтаксис для методов: class X { public function () { ... }; }
Вообще, JS более динамический язык. В PHP мы объявляем класс, и после этого его нельзя поменять.В JS мы можем в любой момент добавить в объект новые поля. Это имеет как плюсы, так и минусы - когда класс неизменен, легче разбираться в коде, и объекты такого класса можно хранить в памяти более эффективно.
- в JS функции являются еще и объектами с конструктором Function. Потому у них самих могут быть и свойства, и "методы". И можно даже делать так (но не нужно, чтобы не путать людей):
function x() {};
x.something = 1;
x.someMethod = function () {};
или так:
var x = new Function(...);
x();
- в JS методы - это просто поля объекта, в которых записаны функции. Можно (но не нужно) добавить метод в любой объект:
var x = [1, 2, 3];
x.test = function () { return 5; };
console.log(x.test());
- у массивов есть метод slice (который тоже является объектом), а когда мы пишем [].slice без скобок, то мы не вызвыаем его, а просто получаем этот объект. Сравни:
var x = [].slice; - копируем в переменную x ссылку на метод slice у массива.
[].slice() - вызваем метод slice()
- у функций есть метод call, который позволяет вызвать функцию с заданным значением this и аргументами
- есть особые правила, как именно определяется значение this при вызове функции. Описано например тут: https://learn.javascript.ru/objects-more
Изучив теорию, советую ответить на вопрос: чему будет равен (или на какой объект будет указывать) this внутри функции в следующих случаях:
1)
function x() { }; x();
2)
var z = {};
z.test = function () {};
z.test();
3)
var z = {};
z.test = function() {};
var fn = z.test;
fn();
https://github.com/lordelph/pastebin
>в JS функции являются еще и объектами с конструктором Function. Потому у них самих могут быть и свойства, и "методы". И можно даже делать так (но не нужно, чтобы не путать людей):
>function x() {};
>x.something = 1;
>x.someMethod = function () {};
или так:
>var x = new Function(...);
>x();
>в JS методы - это просто поля объекта, в которых записаны функции. Можно (но не нужно) добавить метод в любой объект:
>var x = [1, 2, 3];
>x.test = function () { return 5; };
>console.log(x.test());
Объясни пожалуйста понятно, почему не нужно? Как лучше? Просто я вот знаю только эти способы как раз, и считал что это и есть магия ООП в js! Теперь твой пост вогнал меня в фрустрацию.
Проблема такая: допустим, есть большое приложение, состоящее из тысч файлов, и в нем мы в одном месте определяем класс и его методы:
class SomeClass {
someMethod: function () { ... }
}
где-то в другом используем объект этого класса:
/**
*@param obj {SomeClass}
*/
function doSomething(obj) {
obj.someMethod(...);
...
}
Если мы хотим понять, что делает тот или иной метод, как его использовать, какие методы вообще доступны у объекта obj, мы можем посмотреть определение класса SomeClass.
Но если мы начинаем добавлять (или, что еще хуже, заменять) методы динамически, где-то в третьем месте программы, то все становится запутанным. Как понять, где именно в этот объект добавлен какой-то метод? Как понять, какие именно методы добавлены, а какие нет? Можем ли мы их тут вызвать? Нам придется разбирать код, анализировать, где и при каких условиях методы добавляются. Если код большой, то это сложно и занимает много времени.
Потому магию надо использовать очень ограниченно. Если над проектом работает несколько человек, то другие могут не знать об этой магии, например.
Обычно магию применяют в библиотеках, но у них обычно есть документация, где это описано.
Конечно, если у тебя программа из 100 строк, то о таких вещах можно не беспокоиться и писать как угодно. Но реальные проекты - большие, в них сотни тысяч строк, над ними может работать десяток людей, и терять время на выяснение, как работает какой-то нестандартный код, недопустимо. Код должен быть простым и понятным.
Проблема такая: допустим, есть большое приложение, состоящее из тысч файлов, и в нем мы в одном месте определяем класс и его методы:
class SomeClass {
someMethod: function () { ... }
}
где-то в другом используем объект этого класса:
/**
*@param obj {SomeClass}
*/
function doSomething(obj) {
obj.someMethod(...);
...
}
Если мы хотим понять, что делает тот или иной метод, как его использовать, какие методы вообще доступны у объекта obj, мы можем посмотреть определение класса SomeClass.
Но если мы начинаем добавлять (или, что еще хуже, заменять) методы динамически, где-то в третьем месте программы, то все становится запутанным. Как понять, где именно в этот объект добавлен какой-то метод? Как понять, какие именно методы добавлены, а какие нет? Можем ли мы их тут вызвать? Нам придется разбирать код, анализировать, где и при каких условиях методы добавляются. Если код большой, то это сложно и занимает много времени.
Потому магию надо использовать очень ограниченно. Если над проектом работает несколько человек, то другие могут не знать об этой магии, например.
Обычно магию применяют в библиотеках, но у них обычно есть документация, где это описано.
Конечно, если у тебя программа из 100 строк, то о таких вещах можно не беспокоиться и писать как угодно. Но реальные проекты - большие, в них сотни тысяч строк, над ними может работать десяток людей, и терять время на выяснение, как работает какой-то нестандартный код, недопустимо. Код должен быть простым и понятным.
У кого впска под рукой? Поставьте это говно, а то на моем хостинге не встает нихуя
https://github.com/lordelph/pastebin
Теперь конкретнее:
>function x() {};
>x.something = 1;
>x.someMethod = function () {};
Непонятно, зачем добавлять свойства в функцию, если можно просто сделать отдельные переменные или отдельный объект. Выгоды тут никакой нет, только код запутаннее стал.
>var x = [1, 2, 3];
>x.test = function () { return 5; };
То же самое, если тебе хочется что-то сделать с массивом, лучше сделать отдельную функцию и передать в нее массив как аргумент. Массив - это стандартный объект в JS и разработчик не ожидает, что у него есть какие-то дополнительные методы, не описанные в документации.
По поводу скуки. Эти задачи - это основы, которые надо пройти, чтобы перейти к более интересным вещам вроде добавления интерактивных элементов на страницу. Если не понимать, как работают замыкания, как определяется this, то сложно будет разбраться в коде, где это используется.
Если тебе не очень нравятся абстрактные задачи, ты ведь знаешь HTML, ты можешь попробовать начинать параллельно делать что-нибудь посложнее, можно игру в сапера, можно игру "арканоид" ( https://gist.github.com/codedokode/9933897 ) или, например, какое-нибудь простое приложение, если тебе не нравятся игры (например, написать простую электронную таблицу вроде экселя). Главное, чтобы это было на какую-то интересную тебе тему.
Что касается задачи:
> var args = [].slice.call(arguments);
> args.shift();
Было бы хорошо, если бы ты понял, как сделать это без shift(). call тут по сути вызывает функцию [].slice, подсовывая в this ей вместо массива переменную arguments. Надо подумать, как тут передать в эту функцию еще и аргумент, чтобы она сделала копию, начиная с 1-го, а не с 0-го элемента.
> for(var i = 0; i < args.length; i++) {
> oldArgs = args;
Скопировать массив можно методом slice: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
Решено верно.
На локалхосте ставь, ленивое говно.
Ну, второе конечно пушка.
Но вот первый пример:
>function x() {};
конструктор
>x.something = 1;
>x.someMethod = function () {};
методы и свойства.
(правда, если быть честным, использую вот так:
> function x((obj)arg) {
> this.something = arg.something;
> };
>x.prototype.someMethod = function() {};
>...
);
var example = new x(arg);
и понеслась... Получается, это тоже неправильно так делать.
>>897643
Мне например программирование не нужно как профессия, и просто люблю понемножку разбираться (ооочень медленно), как работают те или иные подходы; но считаю если ты хочешь зарабатывать этим, сделать это своим главным занятием в жизни - НУЖНО МНОГО РАБОТАТЬ. Прям просто ДОФИГА, в идеале каждый возможный вариант разобрать, разложить для себя по полочкам возможности и баги, потом приступать к следующему шагу, а не просто блин
>Можем быть это потому что я полностью не читал учебник по js а лишь бегло пробежался по нему
это хуйня подход. Умные люди уже обожглись не раз и пытаются преподнести материал чтобы он легче усвоился (ОП например или автор того сайта по javascript). Это не мануалы и не справочники, тут живые люди с тобой работают, которые тоже с чего-то начинали и подсказывают тебе как тебе, да ТЕБЕ, будет проще начать самому. Такое вот мнение. >>897432
Например, ты на CodeCademy базовый курс хотя бы прошел?
Ну, второе конечно пушка.
Но вот первый пример:
>function x() {};
конструктор
>x.something = 1;
>x.someMethod = function () {};
методы и свойства.
(правда, если быть честным, использую вот так:
> function x((obj)arg) {
> this.something = arg.something;
> };
>x.prototype.someMethod = function() {};
>...
);
var example = new x(arg);
и понеслась... Получается, это тоже неправильно так делать.
>>897643
Мне например программирование не нужно как профессия, и просто люблю понемножку разбираться (ооочень медленно), как работают те или иные подходы; но считаю если ты хочешь зарабатывать этим, сделать это своим главным занятием в жизни - НУЖНО МНОГО РАБОТАТЬ. Прям просто ДОФИГА, в идеале каждый возможный вариант разобрать, разложить для себя по полочкам возможности и баги, потом приступать к следующему шагу, а не просто блин
>Можем быть это потому что я полностью не читал учебник по js а лишь бегло пробежался по нему
это хуйня подход. Умные люди уже обожглись не раз и пытаются преподнести материал чтобы он легче усвоился (ОП например или автор того сайта по javascript). Это не мануалы и не справочники, тут живые люди с тобой работают, которые тоже с чего-то начинали и подсказывают тебе как тебе, да ТЕБЕ, будет проще начать самому. Такое вот мнение. >>897432
Например, ты на CodeCademy базовый курс хотя бы прошел?
Упростил вывод дерева и переписал на PHP: http://ideone.com/2fkGTp
Дом 1. https://jsfiddle.net/z49dssxz/
> Сделай функции dom.hasClass(node, klass)
А в тестах написано так: l(hasClass(createNode('div'..., то есть без объекта dom. Я просто не совсем понял зачем он здесь нужен, для группировки методовкак в случае с Math.pow/Math.sin?
Дом 2: https://jsfiddle.net/je858mz4/1/
> Ты можешь заметить, что, если быстро кликать по клеткам, браузер пытается выделять ячейки таблицы, и выглядит это некрасиво.
Я лихорадочно кликал по таблице из-под Хрома 50, Мозиллы 41,49, IE11, но так и смог добиться этого эффекта.
Полагаю, для решения должно хватить таких CSS-правил: http://stackoverflow.com/a/6382492
Было бы удобно, если бы эти задания были в репозитории pasta
> var example = new x(arg);
> и понеслась... Получается, это тоже неправильно так делать.
В твоем примере происходит добавление методов в прототип, чтобы они были доступны во всех объектах. Это как раз нормальный паттерн, при условии, что добавление делается в одном месте кода, а не раскидано по разным файлам.
В моем примере метод добавляется в один экземпляр объекта - функцию или массив, и смысла как раз это не имеет. Вместо x.something можно просто написать var something = 1.
Насчет разбраться - это хорошая идея, я когда был начинающим, тоже мог зарыться в мануалы или спецификации, чтобы выяснить что как работает. Или мерять размеры инпутов в разных браузерах. Это полезный подход, и я думаю, на собеседовании это произведет хорошее впечатление.
Вы видите копию треда, сохраненную 21 декабря 2016 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.