Вы видите копию треда, сохраненную 2 апреля 2016 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это не чат! Пожалуйста не флудите, а старайтесь постить только вопросы, решения и ответы. Сколько лет вы не можете найти работу никому не интересно. Высказывайтесь одним большим постом а не цепочкой мелких
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут: >>678185 (OP) (1000 постов!)
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост).
Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП отвечает даже на самые нубские вопросы. ОП заходит где-то раз в 2-3 дня, не жди его, решай задачки дальше.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Учебник дает основы языка PHP, но чтобы делать сайты, этого недостаточно. Если ты его прошел, то надо переходить в более серьезным задачкам, которые научат тебя как выдавать страницы в браузер, работе с таблицами в БД, работе с формами, MVC.
- Для начала установи Апач + PHP (советы ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Yii2: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование
- Если ты все решил, переходи к Symfony 2/Doctrine 2
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP на сервере для отдачи странички в браузер: https://php.net/manual/ru/tutorial.php Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что, задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://gist.github.com/codedokode/10539213
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1
Нужен ли ООП, фреймворки, MVC? — Да, однозначно. Посмотри любую вакансию.
Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.net/45000175 и получи личную немного устаревшую копию сайта
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
Подскажи сайты для поиска работы, я не умею гуглить? — 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/php-fig/fig-standards/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-2-coding-style-guide.md
------------------
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию 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/php-fig/fig-standards/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-2-coding-style-guide.md
------------------
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
Стоит начинать учить php с Yii1?
На работе дали задачу сделать модуль на yii. А я верстальщик и знаю только js и php на уровне учебника в шапке.
Не получится ли так же, как если начинать учить js через jquery?
Попробуй сделать какую-нибудь задачку из бонусных у ОП на сайте в шапке. Если пойдёт легко и хорошо - берись за ООП, БД и фреймворки.
Извини анончик, но если мы не будем такое пресекать, то опять начнется флуд и тред уйдет в бамплимит за 4 дня. Каждый работает в своем темпе, если ты не уверен или запутался ты можешь показать код и спросить мнение ОПа или других анонов. Никто не запрещает пользоваться подсказками и обсуждать как лучше реализовать ту или иную вещь.
Также может быть что-то полезное есть в комментариях к самой задаче.
Давайте стараться больше уделять внимания техническим вопросам, коду, а не общим обсуждениям.
В макете красиво нарисовано так что цифра 05 прижимается верхними пикселями к верхней же границе картинки
В реальности несмотря на все сбросы маржинов и паддингов у заголовка (желтый блок) все равно остаются пробелы сверху и снизу. Мне на тостере прояснили что это высота строки, такая характеристика шрифта и что никаким другим путем кроме подбирания вручную line-height не добиться требуемого результата.
пик 1: line-height: 1em, не круто
пик 2: line-height: .61em, вроде норм, но 1. кумарит подбирать вручную 2. при смене семейства шрифта надо опять подбирать 3. текст как бы выезжает за границы блока(желтого), вроде ничего страшного но мало ли 4. от этого блока в свою очередь зависит другой, там где месяц тоже надо поджимать и изменение одного влечет бардак с остальными 5. если заголовок будет содержать две строки с отличающимся line-height ничего не выйдет
Есть еще конечно вариант подвигать маржином но это вообще мрачно.
Собственно вопрос, почему верстка это такая боль и что тут делать, сидеть подбирать или делать первый вариант где поджимается блок, а не шрифт.
Что бы можно было по людски выделять строчку, и нажимать жучка и видеть в консоли что хрониться в переменной, делать пошаговую отладку?
line height - это единственный выход, да верстка - боль и мрак, где все берется с потолка и лепится из говна и палок.
Ну вот, дадут мне макет на собеседовании, скажут сверстай.
Поджимать блок и не париться за эти пробелы, если что валить на то что дизайнер сильно много хочет?
Лепить из говна и палок где у каждого второго блока будут логарифмы уровня font: 2.654em/.812em ?
http://ideone.com/dNpjm1
Можешь картинке паддинг сверху поставить. хз, я не работаю версталой.
мне нужно что-то сделать чтобы не писать echo по 2 раза
1) поиграть с line-height - начни с изчения теории: http://css-live.ru/articles/vvedenie-v-inlajnovyj-kontekst-formatirovaniya-ikf-osnovnye-ponyatiya-1-ya-publikaciya-cikla-tajny-css2-1.html
2) если не получится, подбить вверх маргин-топом
Вообще, конечно, по идее такое выравнивание надо делать за счет vertical-align: top или text-top, но это требует чтобы блок с картинкой были инлайн-блокам и и шли рядом, это не всегда приемлемо.
(кстати ты знаешь что на jsfiddle работает emmet сокращалка css, можно писать div.class или fl:l или w200)
Мне кажется line-height помог бы: https://jsfiddle.net/3Lsrnp50/1/
Мне больше нравится первый вариант из двух.
> 2. при смене семейства шрифта надо опять подбирать
Что поделать
> сидеть подбирать или делать первый вариант где поджимается блок,
подбирать line-height
>>689678
Придется курить мануалы по xdebug и phpstorm
>>689701
Это не так и часто встречается.
1) поиграть с line-height - начни с изчения теории: http://css-live.ru/articles/vvedenie-v-inlajnovyj-kontekst-formatirovaniya-ikf-osnovnye-ponyatiya-1-ya-publikaciya-cikla-tajny-css2-1.html
2) если не получится, подбить вверх маргин-топом
Вообще, конечно, по идее такое выравнивание надо делать за счет vertical-align: top или text-top, но это требует чтобы блок с картинкой были инлайн-блокам и и шли рядом, это не всегда приемлемо.
(кстати ты знаешь что на jsfiddle работает emmet сокращалка css, можно писать div.class или fl:l или w200)
Мне кажется line-height помог бы: https://jsfiddle.net/3Lsrnp50/1/
Мне больше нравится первый вариант из двух.
> 2. при смене семейства шрифта надо опять подбирать
Что поделать
> сидеть подбирать или делать первый вариант где поджимается блок,
подбирать line-height
>>689678
Придется курить мануалы по xdebug и phpstorm
>>689701
Это не так и часто встречается.
http://lorempixel.com/
итальяшка пока отмораживается и не хочет фиксить
https://github.com/fzaninotto/Faker/issues/851
Придется самому расширять под другой сервис?
https://unsplash.it/
О, уже работает, но долго грузится.
Полчаса назад сервис лежал, пруф на скриншоте. Ну и индус в issues свидетель, что работать сервис стал нестабильно.
Подковырял код фейкера под другой сервис (как будто он не может полечь).
https://gist.github.com/anonymous/5c53e40ac7c519313a96
Фактически там только заменен адрес lorempixel.com на unsplash.it, еще удалены теги категорий из урла, потому что у unsplash категорий не наблюдаю.
Встает вопрос по наследованию. Можно как-то дропнуть метод или свойство, унаследованное от предка?
Вот у меня есть класс Faker\Provider\Image, у него статическое защищенное свойство $categories, в котором хранится массив категорий сервиса lorempixel. От него я наследую свой класс, в котором переопределяю методы imageUrl и image.
А с унаследованным свойством categories что делать? Мне эта байда в новом классе ни к чему. Что делать? Пусть валяется?
Как-то нехорошо, лишний мусор.
Думаю, fzaninotto неудачно спроектировал в этом месте. Нужно было учесть, что сервисов для генерации картинок больше одного, и сделать один абстрактный класс Image, а от него уже унаследовать LoremImage, тогда у меня была бы возможность унаследоваться не от LoremImage как сейчас, а от абстрактного класса.
Метод image можно оставить в абстрактном классе, а imageUrl и все связанные с ним свойства и может быть приватные методы уже раскидать по конкретным классам.
http://placekitten.com/
> Встает вопрос по наследованию. Можно как-то дропнуть метод или свойство, унаследованное от предка?
Нет так как оно может быть нужно классам-предкам. Также, это нарушит принцип подстановки Лисков так как класс-наследник должен подставляться на место предка (то есть быть совместимым с ним).
> Думаю, fzaninotto неудачно спроектировал в этом месте.
Возможно. Но конфигурирование не позволило бы получать картинку одной строчкой.
> Нужно было учесть, что сервисов для генерации картинок больше одного, и сделать один абстрактный класс Image, а от него уже унаследовать LoremImage, тогда у меня была бы возможность унаследоваться не от LoremImage как сейчас, а от абстрактного класса.
Тут не нужно наследование, хватит строки с URL с плейсхолдерами мне кажется (хотя конечно может и нет).
Ну с выравниванием по верхнему краю ручной подбор line-height помогает, да. Но озвученные проблемы никуда не пропадают.
С выравниванием по нижнему краю еще хуже, отрицательные значения в line-height не допускаются, выходит, там только маржином выталкивать
>(кстати ты знаешь что на jsfiddle работает emmet сокращалка css, можно писать div.class или fl:l или w200)
Я на jade пишу, сокращает здорово.
Чтобы в итоге вывелось, сколько потрачено месяцев и т.п.?
Ну ты как будто не сам решал задачу - просто после цикла поставь echo с нужными параметрами.
>Надо проверить номер на правильность
Сделано в предыдущей части задания в 2 вариантах.
Короткий
>>689422
Усложненный (строгий формат, хотя как видим это было не нужно, в след.части задачи чистим все лишние символы preg_replace)
>>689487
>и привести любой номер к единому формату 89114044411 (то есть, заменить +7 на 8 и выкинуть весь мусор вроде пробелов, скобок и минусов, кроме цифр)
Может быть можно было одним выражением, но прогнал дважды через preg_replace, вернее скормил ему массивы.
Первый раз заменяем пробелы, скобки и проч.символы на пустую строку; второй раз заменяем +\s?7 на 8.
http://ideone.com/yxipgN
>Автозамена. Напиши скрипт, заменяющий определенное слово на другое (например, слово «дурак» на «хороший человек» в фразе «ты дурак»).
http://ideone.com/28HkY8
> Напиши скрипт, выводящий все email, встречающиеся в тексте
Мы кажется в итоге пришли к выводу, что сейчас в имени почты может содержаться что угодно, где-то там была статья на хабре, которая убеждает вместо одной крайности (писать длиннющую регулярку с перечислением всех доменных имен, встречающихся в природе) броситься в другую (регулярка вида /[^@]+@[^@]+/ или что-то в этом роде).
Но я пока использую регулярное выражение из урока http://archive-ipq-co.narod.ru/l1/regexp.html
Кстати, вместо[что-то]+ может все-таки ограничить около {1,255}, чтобы нам не кидали текст по 500 кб
http://www.w3schools.com/jsref/prop_email_maxlength.asp
>The default value is 524288
http://ideone.com/K8g3QR
Уже умею верстать говносайтики и могу пойти работать в говноконторке, но в вакансиях на фронтендера\версталу нужен пхп. Так вот что именно мне нужно?
Вопрос здесь.
http://ru.stackoverflow.com/questions/503591/fatal-error-call-to-a-member-function-fetch-on-boolean
потратить два-три года на изучение пхп, жаваскрипт и еще какого-нибудь типизированного языка, не забудь прочитать и переписать паттерны, а также алгоритмы.
Конкретизирую - что именно мне нужно знать из пхп чтоб работать в говноконторке в своей мухосрани за 25к?
Алсо, есть аналог htmlacademy?
я тебе уже написал.
>static function getStudentList(){
>$db = Database::connect();
>$sql = "SELECT id, name, surname, class, points FROM student"
Разве тебе ОП не говорил что так делать не стоит? Ты можешь класс StudentDataGateway сделать зависимым от PDO, это называется Dependency Injection, почитай урок https://gist.github.com/codedokode/e1d31a31b37d5f635057
Это поможет тебе избавится от вызова статистического метода connect() и каждый раз при вызове функции ты сможешь использовать уже готовый PDO.
>while($row = $result->fetch()){
Вот этот цикл я вообще не понял зачем тут, еще и переменная $i какая-то. Если ты используешь PDO, в нем есть метод fetchAll(), который сможет вывести все результаты в массив или объект. Почитать про него можешь тут
http://php.net/manual/en/pdostatement.fetchall.php
http://php.net/manual/ru/pdostatement.fetchall.php - на русском
По поводу твоей ошибки
>Fatal error: Call to a member function fetch() on boolean
Очевидно что твоя переменная $result равняется false, а это как известно из-за ошибки при работе с базой данных. Чтобы получить больше информации, включи выбрасывание исключений при ошибках в PDO, это лучше всего делать при подключении вот так:
>$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
Тогда PDO при любой ошибке работы с базой данных выбросит исключение и завершит выполнение скрипта, что позволит тебе узнать в чем именно проблема. И пытайся избавляться от статистических методов.
Вордпресс. Опционально джумла, друпал или битрикс.
Из php синтаксис хотя бы.
Не знаю, w3schools например http://www.w3schools.com/php/default.asp
Или всякие видеокурсы посмотри на трекерах, этого будет достаточно чтобы натянуть верстку или пофиксить плагин.
>>689917
Ни тебе, ни ему это не нужно.
Спасибо за адекватный ответ. Ответ про два-три года другого анона показался толстотой.
1)Берётся WordPress, вставляются туда свои данные, картиночки, ???????, PROFIT!
2)Берётся WordPress, делается основной каркас, затем открывается код, плюётся на индусопись, стирается, пишется руками на пхп.
3)Сразу берётся и пишется руками на пхп?
4)Берётся уже написанный ранее сайт, редактируются css-стили, вставляются новые картиночки, новый сайт готов?
Вроде почти всё получилось, но не могу сделать так, чтобы выводило последний месяц, посмотри пожалуйста :3
И еще, код очень криво написан, да ?
http://ideone.com/MYuqmO
Неправильно решено, там должно быть 61270р с копейками.
То на серьезном уровне нужно долго учиться, чтобы устроиться на большую зп в москве. Но тебе же нужно верстальщиком в мухосрани.
>>689935
В документации вордпресса все написано https://codex.wordpress.org/Заглавная_страница
Вордпресс и другие cms это готовые шаблонные приложения. От тебя требуется натянуть верстку по предложенному макету, пофиксить ошибки в чужих плагинах, написать собственный плагин (надстройку, которая добавляет функционал).
В оп-посте учебник для начинающих по php http://archive-ipq-co.narod.ru/
Там хорошая теория, есть задачи (сложноватые наверное).
Я же сразу написал про говносайты и говноконторы, разумеется для высокой зп придется дохуя учить.
>У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/
>- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
>- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
>- Еще более сложная и долгая задача на Yii/Yii2: https://gist.github.com/codedokode/8733007
>Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
Когда я решу всё эти задачи, я смогу начинать фрилансить, в общем? Или начать работать удалённо? Или пойти в говноконторку?
Да.
нет, не будет ослом, то замануха.
Ты точно в говноконторы ходил?Ибо в ниих берут без опыта, главное тестовое задание нормально сделать, на портфолио похуй.
Двачую. Я пришел, и меня взяли без тестового. Просто сказал, что знаю html и css без пруфов.
Если ты toppestkek (даже гитхаб назвал по-дегенератски), то мы в курсе уровня твоих знаний.
Еще у тебя психические проблемы.
Или соглашайся на низкоквалифицированную работу (ничего в этом позорного, вон миллионы людей работают на заводах или кассирами), или да, смирись и годами прилежно учись.
> «Grammar Nazi». Напиши скрипт, проверяющий текст на наличие злостных ошибок
http://ideone.com/B8LyiA
Дегенерат на сосаче детектирует у других псих проблемы, спешите видеть. Когда в последний раз на говно/поней/фурри/трапов дрочил?
Что касается гитхаба, я его вообще just for lulz завел, там вон одни парсеры борд. За красивыми гитами тебе к пидорасам типа айдихи, у которого на две строчки кода многотомный дискрипшн с картинками))
>Если ты направо и налево обзываешь всех больными, может проблемы у тебя?
А по моему он прав, зачем сидеть в треде, который ты ненавидишь и считаешь всех червями-школьниками, но при малейшей проблеме идти и плакаться в него-же?
Там чужой код нужно было расширить.
>>690092
https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
И не ругайся, ты пугаешь опа.
>>690060
Не отрицаю.
бампусиики
Спасибо
И да, по JavaScript и JQuery тоже нашёл его курс, он хоть сгодится?
Вообще, такое ощущение создаётся, что веб-разработчик и верстальщик это разные профессии.
Несложно угадать, если ты мод, у которого трэк аайпи, дебилушка.
Пограммисты-пограммистушки, поясните за код
http://ideone.com/OWQsMA
Сначала нужно проверять имя, это чек
Затем номер - чек
Затем в номере только цифры - не чек.
Если ввести буквы - выводит что номер превысил 13 символов.
Как бы вы сделали и в чем упущения?
До этого вообще проверки с регулярками не юзал, только на ограничение символов.
лол, конечно разные. На крупных проектах программист делает логику и основной функционал, верстальщик все это дело оборачивает в приятный глазу вид под уже нарисованный дизайнером шаблон.
<pizdos/> одним словом. Но для начала и фриланса нужно все эти 3 функции совмещать (программиста, верстальщика и десигнера)?
>Надо варнинги перехватыват и очищать, там есть функция.
Но зачем мне знать об этих неминуемых варнингах? Проще собаку поставить.
> Ну и как я вижу, там много случае где твой парсер не вырезает яваскрипт-ссылки. А ведь есть еще data-ссылки. Плоховато у тебя с теорией. Надо использовать белый список, то есть разрешить толкьо определенные протоколы в ссылках.
Но ведь DOM тоже не имеет автомата для выреза такого шлака. Через DOM я могу только перебрать аттрибуты.
Добавь <!doctype html>
>там описывается 7 уровней сетевого взаимодействия. Но для меня это теория, абстракция
А это и есть абстракция.
5 и 6 уровни существуют только в стандартах фактически - вот написали такие уебанские стандарты, deal with it.
1 уровень - витуха, воткнутая в твой комп. В ней бегают электрические сигналы.
2 уровень - твоя сетевая карта и свитч провайдера. Они знают друг друга по MAC-адресам.
3 уровень - маршрутизация, IP-адреса. IP-адреса в сети существуют поверх MAC-адресов. Устройство может иметь мак, но не иметь IP, но не может иметь IP и не иметь MAC.
4 уровень - тот самый TCP/IP, отвечает за установку соединения между двумя точками. Различие между 3 и 4 уровнем в том, что 3 уровень - это карта с маршрутами, а 4 уровень - налаженные грузоперевозки по этой карте с маршрутами.
Ну и 7 уровень это все, что ходит поверх TCP/IP. То есть весь Интернет. HTTP и так далее.
>Имя слишком длинное (до 13 символов
Интересный ты.
А если кто-то введет ФИО? Вот ты и потерял заказ.
Не нужно делать жесткую валидацию вещей, которые потом все равно будет читать человек.
>htmlspecialchars
Эта функция нужна для вывода данных в html-код. Убери это.
Кроме того, e-mail сообщение по умолчанию plain/text.
>Если ввести буквы - выводит что номер превысил 13 символов.
strlen возвращает длину строку в байтах. 7 русских букв - 14 байтов.
Используй mb_strlen, а в начале кода пропиши mb_internal_encoding('utf-8');
Если ты будешь проверять номера телефонов сугубо на цифры - будешь терять заказы.
Твоя регулярка верна, только убери модификатор i. Заглавных цифр не существует.
>2007 года
Не смотреть ни в коем случае.
>Евгению Попову вы здесь относитесь хуёво
Его код был ужасен даже в 2007. Если ты сейчас обучишься по его шедеврам, ты будешь писать хуже, чем писал бы самостоятельно.
>>690068
>Пропущена запятая перед предлогом "а" или "но".
А если предложение начинается с предлога?
>>689946
Жизненно.
Если предложение начинается с предлога, то перед ним не будет пробела и... а, ну да. Будет точка и пробел. Добавил точку во фрагмент
[^.,]\s\b(но|а)
http://ideone.com/DBrEeG
Задание на поиск "опечаток" на коррумпированных сайтах.
http://ideone.com/wtKLsF
Скобки, скобки, тысячи их.
Признаюсь честно, под конец уже как дебил наугад расставлял номера подмасок.
Там как-то явно можно лучше решить.
В условии предлагается
>Подсказки для глупеньких: слова с опечатками найти легко: это слово, которое начинается с одной или нескольких русских букв, за которыми идет латинская
Не согласен, зайчик. А вдруг слово начинается с большой латинской буквы, например [K]алининградская область, или [M]агнитогорск.
Так что пришлось исходить из того, что либо слева от латинской буквы кириллица (тогда справа ее нет), либо справа (тогда слева ее нет). Потому что две подряд латинские буквы это уже слишком. Хотя... можно подобрать и такие слова наверное. Или я усложняю?
Кстати, а эту дырочку на сайте госзаказов хоть прикрыли за эти годы? Если нет, может настучим на них (куда? задорнов.джопег. Нет, ну мелкую сошку то никто крышевать не будет).
Прикрепляю песню "ансамбля Христа Спасителя", призывающую граждан бороться с произволом бандитов во власти.
https://www.youtube.com/watch?v=VyxcHbdLhac
Одна латинская буква тоже заматчится.
>(?(4):[а-яё])
Что это, пупсик? Кстати, это условие никогда не выполнится.
Это условная подмаска, поросеночек http://php.net/manual/ru/regexp.reference.conditional.php
Лол, помнишь ту серию сауспарка?
"Как ты его назвал?
- Поросенком...
- Нет, ты должен был назвать его говнюком, как настоящий мужЫк!
- Пап, но я...
- А ну быстро назови своего друга говнюком!"
>>690410
Я устал, не добивай.
Точку с запятой, тире сам смог вспонмить. У тире там еще кажется много видов. Кстати, нельзя ли в регулярках писать код типа U+2014.
Ну в общем идея понятна, список знаков препинания можно дополнять если что.
http://ideone.com/DBrEeG
А в каком порядке все-таки нумеруются подмаски, особенно когда они вложены друг в друга?
((a(с))(b))((d)(e)) Тут какой порядок будет?
>>690034
https://github.com/toppestkek/Blog/blob/master/app/ctrlIndex.php
Я бы тебя за хлебушек не взял на работу.
http://ideone.com/64LcDn
Я тут подумал - функция же будет удобней, если скрипту скармливать данные из формы, так как сразу будет пересчитывать все?
Или обернуть возвращенные значения в переменные, чтоб помещать туда итог? Ну и так тоже сделал
Как лучше то?
Так php-скрипты могут выполняться не только в веб-среде, данные не обязательно приходят из формы, из консоли его могут запустить например. Нужна именно универсальная функция.
Переменным давай внятные имена, не calkR, а exchangeDollarsToRoubles, чтобы можно было из названия понять, что делает эта функция.
Большое приложение полностью будет состоять из таких вызовов, и ни желания ни времени не будет лезть в их код и смотреть что они там внутри делают.
Английский желательно подтянуть, это понадобится не только для того чтобы давать имена переменным, вся литература к сожалению только на английском.
Набирать на клавиатуре нужно быстро и вслепую, а не как клуша двумя пальцами.
>обернуть возвращенные значения в переменные, чтоб помещать туда итог
Да, так лучше. Логика (всякие вычисления) должны быть отделены от представления (как ты результат собираешься выводить).
Полученный результат можно вывести в браузере при помощи html-разметки. А может быть это консольное приложение, тогда вывод будет другим, может программа вообще ничего не выводит, может она пишет в файл, тоже неизвестно в каком формате.
мимопроходил
Этот анон >>690615 правильно написал в общем, а я еще дополню. Важно уметь разделять код на независимые части, а не смешивать все в кучу. Потому получение данных из формы и расчет должны быть в разных местах. Один код который работает с формой, и отдельно универсальная функция перевода валют.
Код важно разделять даже если мы никогда эту функцию не будем как-то еще использовать - разделять надо ради упрощения и читабельности.
Ну и почитай еще тогда про побочные эффекты: https://github.com/codedokode/pasta/blob/master/good-code.md#Избегай-побочных-эффектов
спасибо за развернутый ответ, но так как скрипт небольшой я не стал писать длинные имена функциям
Там короче файлы нужно помещать не в www, а в www/html.
Да, в apache2.conf написано <Directory /var/www/>.
Только вот зайди в sites-available, там файл 000-default.conf, а в нем
DocumentRoot /var/www/html
Но я в общем тоже краб, помню некоторые настройки, но не понимаю за что они отвечают.
В таких случах надо смотреть лог сервера (в линуксе /car/log/httpd/...) и там будет полный путь где он пытался искать файл.
>>690626
Лучше приучаться сразу писать нормально а не заставлять людей расшифровывать сокращения. Раз скрипт небольшой, то и функций в нем немного, значит и много усилий правильные имена не потребуют.
>>690632
А ты читал в мануале за что отвечает блок <Dicrectory> ? Прочитай. И про DocumentRoot тоже.
Также, тебе надо научится настраивать виртуальные хосты так что читай
https://httpd.apache.org/docs/2.2/ru/vhosts/
https://www.google.ru/search?q=debian+apache&btnG=Поиск&newwindow=1&gbv=1
Почему у меня не выполняется этот код? И где искать логи httpd? Пути как ты указал у меня нет. Заранее извиняюсь за тупость.
>$REQUEST_METHOD
Что за переменная request_method? Она вообще есть? Может ты хотел написать $_SERVER['REQUEST_METHOD']?
Логи попробуй поискать в /var/log/apache2/
httpd это и есть сервер.
Спасибо. Всё так и есть. Но всё равно не выводятся данные.
Твои данные в массиве $_POST. Имя html элемента соответствует индексу в массиве $_POST.
Например
<input type="text" name="username">
При отправке $_POST запроса значение этого поля ты сможешь получить через $_POST['username'].
У тебя какой-то странный код обработки формы, почитай урок ОПа https://github.com/codedokode/pasta/blob/master/forms.md
Есть ли разделение труда, типа отдел верстальщиков-фронтендеров, бекенд-программисты, системные администраторы, или везде фулстаки (которые на словах умеют "все", но делают это все плохо)?
Проводят ли старшие программисты код-ревью, то есть проверку кода джунов?
Есть ли семинары или что-то подобное для повышения квалификации?
Как проходит именно рабочий процесс? Тимлид бегает и раздает всем мелкие задания, следит за выполнением и подсказывает (инбифо: размечтался), или все более бюрократично, типа вон список задач, бери шо хочешь, делай как хочешь, сдавай как хочешь. Только если будет жалоба, тебя выпизднут.
Про скрам слышал, в теории красиво, но из того что читал в интернете складывается впечатление что это манагерская хуита, лишь бы больше времени апщаца и меньше заниматься делом.
Какие виды деятельности преобладают? Я имею ввиду, что есть мелкие студии, которые исключительно специализируются по натягиванию верстки на cms; есть большие конторы со своими проектами, которые ведутся годами, а есть всеядные конторы, где ничем не брезгуют, есть и свои проекты, и легаси, и пофиксить вон тот говносайт.
Я бы предпочел именно третий вариант, такую контору средней руки. Там наверное и коллектив небольшой с четко налаженной работой, тогда как в больших компаниях бюрократия, а в вебстудиях дно и бесперспективность.
tldr: как организован рабочий процесс? Вот завтра я приду на работу, усажу свой зад на стул или что у них там из мебели, дальше что? Контроль работы, коллективная работа, оценка проделанной работы, список задач?
То есть мне нужно ко всему проекту подключить классы, каждый класс - отдельный файл. Если не через require, то... как? Не понятно
Работаю вот в такой всеядной конторке, менеджеры раскидывают задания, иногда местные страшие что-то скипают если сидишь без работы. Старшые при вопросах отправляют в гугл, только если уж совсем пизда, то помогут.
не надейся, что в 2016 году еще осталась такая работа, как "натягивание верстки на цмс", ты либо программист либо нет.
нет
Куда еще подробнее?
Если в коде упоминается класс, то должен быть и доступ к этому классу.
Поэтому сначала объявляли все классы прямо в том же файле:
<?php
class Example
{
100500 строк;
}
class AnotherExample
{
еще 100500 строк
}
// а теперь эти классы используются, в данном случае создаем экземпляры объектов
$example = new Example;
$anotherExample = new AnotherExample;
Так как в больших проектах программа требует сотни и тысячи классов, неудобно их описывать в одном файле.
Тогда каждый класс стали писать в отдельном файле, и подключать их к главному скрипту при помощи выражения require.
require грубо говоря копирует содержимое файла и вставляет его в то место, где прописана эта инструкция.
Теперь код выглядит
require '/classes/Example.php';
require '/classes/AnotherExample.php';
$example = new Example;
$anotherExample = new AnotherExample;
Уже лучше, но если нужны сотни классов, придется писать сотни строк require classname.
Тогда разработчики сделали возможность объявить функцию, которая будет вызываться при обращении к классу, которого не видит php.
spl_autoload_register(function ($className) {
$path = 'classes/' . $className . '.php';
if (file_exists($path)) {
require_once $path;
}
});
$example = new Example;
$anotherExample = new AnotherExample;
Что произойдет в такой программе?
Php зарегистрирует функцию автозагрузки, т.е. положит ее куда-то себе в память и забудет о ней, пока не нужна.
Дальше он видит строку $example = new Example; и спрашивает себя: а есть ли в коде выше объявление этого класса? Нету. Значит нужно запустить ту функцию, которую зарегистрировали через spl_autoload_register, передав ей в качестве аргумента название класса Example.
Выполняется функция, к имени класса добавляется путь к папке 'classes/', получается 'classes/Example.php'.
Вот теперь произойдет require_once 'classes/Example.php'; и программа создаст экземпляр этого класса. (Если такой файл существует по указанному пути)
Дальше скрипт наткнется на выражение $anotherExample = new AnotherExample, повторить вышеописанный порядок действий.
Короче, когда php не может найти класс, он перед тем как орать об ошибке выполнит функцию, которую ты зарегистрировал, передавая ей в качестве параметра название класса.
А внутри этой свой функции автозагрузки ты и делаешь require путь/к/классу/НазваниеКласса.php
Куда еще подробнее?
Если в коде упоминается класс, то должен быть и доступ к этому классу.
Поэтому сначала объявляли все классы прямо в том же файле:
<?php
class Example
{
100500 строк;
}
class AnotherExample
{
еще 100500 строк
}
// а теперь эти классы используются, в данном случае создаем экземпляры объектов
$example = new Example;
$anotherExample = new AnotherExample;
Так как в больших проектах программа требует сотни и тысячи классов, неудобно их описывать в одном файле.
Тогда каждый класс стали писать в отдельном файле, и подключать их к главному скрипту при помощи выражения require.
require грубо говоря копирует содержимое файла и вставляет его в то место, где прописана эта инструкция.
Теперь код выглядит
require '/classes/Example.php';
require '/classes/AnotherExample.php';
$example = new Example;
$anotherExample = new AnotherExample;
Уже лучше, но если нужны сотни классов, придется писать сотни строк require classname.
Тогда разработчики сделали возможность объявить функцию, которая будет вызываться при обращении к классу, которого не видит php.
spl_autoload_register(function ($className) {
$path = 'classes/' . $className . '.php';
if (file_exists($path)) {
require_once $path;
}
});
$example = new Example;
$anotherExample = new AnotherExample;
Что произойдет в такой программе?
Php зарегистрирует функцию автозагрузки, т.е. положит ее куда-то себе в память и забудет о ней, пока не нужна.
Дальше он видит строку $example = new Example; и спрашивает себя: а есть ли в коде выше объявление этого класса? Нету. Значит нужно запустить ту функцию, которую зарегистрировали через spl_autoload_register, передав ей в качестве аргумента название класса Example.
Выполняется функция, к имени класса добавляется путь к папке 'classes/', получается 'classes/Example.php'.
Вот теперь произойдет require_once 'classes/Example.php'; и программа создаст экземпляр этого класса. (Если такой файл существует по указанному пути)
Дальше скрипт наткнется на выражение $anotherExample = new AnotherExample, повторить вышеописанный порядок действий.
Короче, когда php не может найти класс, он перед тем как орать об ошибке выполнит функцию, которую ты зарегистрировал, передавая ей в качестве параметра название класса.
А внутри этой свой функции автозагрузки ты и делаешь require путь/к/классу/НазваниеКласса.php
Т.е. одной функцией spl_autoload_register(function ($className) я автоматически буду подгружать все классы из указанного $path (папки) в свой проект при необходимости(при запросе)?
И ещё такой момент: в конце статьи ОП-чик говорит что-то про composer.json, чем полностью выбил меня из колеи (впервые слышу об этом), в студентах это пока не потрубется и можно использовать только spl_autoload_register,
>require грубо говоря копирует содержимое файла и вставляет его в то место, где прописана эта инструкция.
Нет, не так. Это не Си. require просто выполняет код из указанного файла. Соответственно если в том файле описан класс, то при выполнении require этот класс будет создан в памяти PHP и станет доступен для использования.
Я думаю, все эти аналогии вроде "реквайр подключает файл" непарвильные. Он просто загружает файл и выполняет код из него.
>>690806
МОжно только spl_autoload_register, но надо хорошо ее изучить и прочитать весь мануал по ней и связанным темам.
После студентов я делал хуевые фиксы на сайтах и пару плагинов под вордпрессс, а потом устроился.
Помоги, пожалуйста, у меня этот код даёт ошибку, что я делаю не так?
первое - пхп-скрипт, который создаёт объект класса Student
второе - класс Student.php, к которому должен обращаться автозагруз
Неймспейс не используешь потому что.
Нужно писать new \Classes\Student;
И "classes" это для примера, если бы в примере было написано ваш/путь/к/папке/c/классами, ты создал бы тоже создал такую структуру директорий? Пути должны быть более осмысленными, по стандарту psr0
Назови неймспейс по имени своего приложения. Например Students, или College, или как-нибудь осмысленно. Как бы ты назвал свой сайт? Какое бы хотел видеть доменное имя, вместо http://localhost? (только не example.com или site.ru, пожалуйста)
Дочитай до конца статью
https://github.com/codedokode/pasta/blob/master/php/autoload.md#Неймспейсы-пространства-имен
https://github.com/codedokode/pasta/blob/master/php/autoload.md#psr-4
Ты как-то бегло и невнимательно.
Привыкай что нужно будет постоянно часами сидеть и изучать очередной мануал/документацию, написанную непонятно кем (или вообще сгенерированную роботом, ага).
спасибо. Пока лучше вообще отключу неймспес тогда. Пошёл читать
Как выводить эти формы или вывести одну форму для трех сущностей
Я в тупике
EntityType - не подходит, как я понял, но может я не правильно понял
ArrayCollection - тоже как то не то, хотя опять же
Поясните как использовать EntityType или ArrayCollection если они решат проблему, или посоветуйте что-нибудь друзья
Хотя я знаком с Симфони, но несколько раз приходится перечитать пост чтобы понять в чем проблема. Ты бы написал какую часть приложения (модели, формы) ты делаешь. Видимо обе.
Первое что надо вспомнить - что в Симфони формы обычно работают с моделями. То есть они используют объекты моделей для хранения данных. При обработке запроса данные из POST переносятся в модель, при выводе формы данные из модели выводятся с помощью шаблона.
Потому начни с проектирования моделей Doctrine, которые бы описывали тест с вопросами и ответами. Обрати внимание, что есть разные типы вопросов - это классический пример наследования таблиц - и надо определиться с выборо паттерна наследоваия таблиц (с оглядкой на то, поддерживается ли он доктриной или нет).
Если не уверен, можешь мне показать промежуточный вариант.
Насколько я помню, в тесте вопросы добавляются динамически. Значит каждый вопрос - это форма, а все вместе - коллекция форм. В Симфони форма и поле формы наследуют один общий класс и потому поля и формы могут произвольно вкладываться друг в друга. Хороший повод перечитать документацию, посмотреть исходный код форм симфони.
Я не уверен что стандартными средствами Симфони можно сделать все, что требуется, так что будь готов дописывать какой-то кастомный яваскрипт, который будет генерировать эти формы, например из шаблона.
Я нагуглил такой урок: http://symfony.com/doc/current/cookbook/form/form_collections.html - но там мне реально не нравится как они засовывают шаблон формы в атрибут. Некрасиво как-то, лучше в тег скрипт с нестандартным типом.
Ты наверно заметил что прямого ответа на вопрос нет. Придется подумать самому.
Вот рекомендуемый порядок действий:
- определиться с схемой БД
- сделать соответствующие модели доктрины представляющие части теста
- сделать формы для редактирования этих моделей
Можешь показывать промежуточные результаты
> Поясните как использовать EntityType или ArrayCollection если они решат проблему
Ты по моему все смешал - ArrayCollection это класс представляющий коллекцию моделей доктрины, а EntityType это что-то из форм.
Хотя я знаком с Симфони, но несколько раз приходится перечитать пост чтобы понять в чем проблема. Ты бы написал какую часть приложения (модели, формы) ты делаешь. Видимо обе.
Первое что надо вспомнить - что в Симфони формы обычно работают с моделями. То есть они используют объекты моделей для хранения данных. При обработке запроса данные из POST переносятся в модель, при выводе формы данные из модели выводятся с помощью шаблона.
Потому начни с проектирования моделей Doctrine, которые бы описывали тест с вопросами и ответами. Обрати внимание, что есть разные типы вопросов - это классический пример наследования таблиц - и надо определиться с выборо паттерна наследоваия таблиц (с оглядкой на то, поддерживается ли он доктриной или нет).
Если не уверен, можешь мне показать промежуточный вариант.
Насколько я помню, в тесте вопросы добавляются динамически. Значит каждый вопрос - это форма, а все вместе - коллекция форм. В Симфони форма и поле формы наследуют один общий класс и потому поля и формы могут произвольно вкладываться друг в друга. Хороший повод перечитать документацию, посмотреть исходный код форм симфони.
Я не уверен что стандартными средствами Симфони можно сделать все, что требуется, так что будь готов дописывать какой-то кастомный яваскрипт, который будет генерировать эти формы, например из шаблона.
Я нагуглил такой урок: http://symfony.com/doc/current/cookbook/form/form_collections.html - но там мне реально не нравится как они засовывают шаблон формы в атрибут. Некрасиво как-то, лучше в тег скрипт с нестандартным типом.
Ты наверно заметил что прямого ответа на вопрос нет. Придется подумать самому.
Вот рекомендуемый порядок действий:
- определиться с схемой БД
- сделать соответствующие модели доктрины представляющие части теста
- сделать формы для редактирования этих моделей
Можешь показывать промежуточные результаты
> Поясните как использовать EntityType или ArrayCollection если они решат проблему
Ты по моему все смешал - ArrayCollection это класс представляющий коллекцию моделей доктрины, а EntityType это что-то из форм.
Это ведь не ОП ответил? А то я сижу жду, а ответ может уже есть. ОП, почему ты не подписываешься, мне например иногда непросто различить.
Дымящаяся куча вводных слов под спойлером. Давно не был в треде. Я тот анон, который захламлял тред яваскриптом и версткой пока делал макет. ОП, скорее всего вспомнишь меня по куче километровых паст, которыми мы обменялись месяцев 5 назад.
Так вот ближе к делу. Как-то недавно мне посоветовали не сидеть за учебниками а написать что-то свое. До этого недели 2 потратил на учебник с DOMом но после долгого перерыва как-то сложно было вкатиться, да и сам DOM каким-то сложным мне показался. Но вдруг я подумал о совете про свой проект и за неделю я написал целую игру с экономикой, кучей счетчиков, циклами, магазином, улучшениями и сложными скриптами. Даже чертовыми фреймворками воспользовался и сохранение игры через куки сделал. И все без какой-либо помощи в написании кода. Только одних скриптов больше тысячи(!1!) строк. На некоторые копипасты мне конечно указали, но в целом очень даже похвалили за такие успехи. Заодно еще и вспомнил штмл с ксс. Ссылку не дам :3 Так как помню, что у тебя пунктик на проверку всего что сюда скидывают, а там много кода и время у анонов я отнимать не хочу, ведь это не задача из твоего учебника. Так вот вот взглянув на всю эту продуктивность я подумал, а почему бы не продолжать в том же духе и взяться за что-то еще более серьезное. И вот я придумал еще одну игру, но там уже даже познаний моего знакомого, который не один год работает программистом уже не хватает, вот я и вернулся в тред за помощью.
Напомню, что с твоей помощью уже выучил HTML, CSS, Javascript и самостоятельно DOM. Не весь конечно, но если что догуглю пробелы.
Планирую написать игру. Саму идею рассказывать не буду. Скажу лишь, что мне нужно будет рандомно соединять двух желающих поиграть людей. Примерно как это сделано в хартстоуне. Нет, у меня не карточная игра, не клон этого хартстоуна, и вообще оригинальная, что я аж сам офигел от того что ее придумал. Серьезно :3
Как я понял мне нужно знать базы данных и приступить наконец к учебнику по PHP для написания серверной части. И вот как раз перед учебником по PHP я бы хотел получить знания по базам данных. Написать что-нибудь с помощью их. Я предполагаю в качестве тренировки я смогу запилить что-то типа чата чтобы написанные пользователями сообщения отправлялись в базу данных а оттуда в окно чата и могли бы быть видны всем. Ну это все теория в которой я даже не разбираюсь. А надо бы разобраться. Что мне нужно учить для создания баз данных? SQL? Это ведь отдельный язык баз данных? А потом уже искать учебник по определенной базе данных типа MySQL? Или может мне не MySQL понадобится а что-то другое, а он уже давно устарел и все тру пользуются чем-то другим?
Дымящаяся куча вводных слов под спойлером. Давно не был в треде. Я тот анон, который захламлял тред яваскриптом и версткой пока делал макет. ОП, скорее всего вспомнишь меня по куче километровых паст, которыми мы обменялись месяцев 5 назад.
Так вот ближе к делу. Как-то недавно мне посоветовали не сидеть за учебниками а написать что-то свое. До этого недели 2 потратил на учебник с DOMом но после долгого перерыва как-то сложно было вкатиться, да и сам DOM каким-то сложным мне показался. Но вдруг я подумал о совете про свой проект и за неделю я написал целую игру с экономикой, кучей счетчиков, циклами, магазином, улучшениями и сложными скриптами. Даже чертовыми фреймворками воспользовался и сохранение игры через куки сделал. И все без какой-либо помощи в написании кода. Только одних скриптов больше тысячи(!1!) строк. На некоторые копипасты мне конечно указали, но в целом очень даже похвалили за такие успехи. Заодно еще и вспомнил штмл с ксс. Ссылку не дам :3 Так как помню, что у тебя пунктик на проверку всего что сюда скидывают, а там много кода и время у анонов я отнимать не хочу, ведь это не задача из твоего учебника. Так вот вот взглянув на всю эту продуктивность я подумал, а почему бы не продолжать в том же духе и взяться за что-то еще более серьезное. И вот я придумал еще одну игру, но там уже даже познаний моего знакомого, который не один год работает программистом уже не хватает, вот я и вернулся в тред за помощью.
Напомню, что с твоей помощью уже выучил HTML, CSS, Javascript и самостоятельно DOM. Не весь конечно, но если что догуглю пробелы.
Планирую написать игру. Саму идею рассказывать не буду. Скажу лишь, что мне нужно будет рандомно соединять двух желающих поиграть людей. Примерно как это сделано в хартстоуне. Нет, у меня не карточная игра, не клон этого хартстоуна, и вообще оригинальная, что я аж сам офигел от того что ее придумал. Серьезно :3
Как я понял мне нужно знать базы данных и приступить наконец к учебнику по PHP для написания серверной части. И вот как раз перед учебником по PHP я бы хотел получить знания по базам данных. Написать что-нибудь с помощью их. Я предполагаю в качестве тренировки я смогу запилить что-то типа чата чтобы написанные пользователями сообщения отправлялись в базу данных а оттуда в окно чата и могли бы быть видны всем. Ну это все теория в которой я даже не разбираюсь. А надо бы разобраться. Что мне нужно учить для создания баз данных? SQL? Это ведь отдельный язык баз данных? А потом уже искать учебник по определенной базе данных типа MySQL? Или может мне не MySQL понадобится а что-то другое, а он уже давно устарел и все тру пользуются чем-то другим?
Что за игра, дай ссылку?
Мы-то ту не ОПы, просто хочется посмотреть, чего можно достичь при желании.
Да я помню как ОП проверял даже сайт где анон падающие цифры как в матрице делал и пастой ему отвечал. Не хочу чтобы он сидел и гору левого кода смотрел. Не то что бы мне стыдно за него, я наоборот очень даже им горд. Потому как все полгода пока я изучал здесь программирование я ныл что не умею ничего активного делать. Даже не мог сделать чтобы по кнопке что-нибудь в стиле "скрыть\показать картинку" происходило. А тут сел и через неделю игра целая.
Дай посмотреть-то, интересно же.
Советы ОПа всегда уместны, он тоже дополнительно прокачивает скилл, когда смотрит на говнокод, инфа соточка. Иначе не отвечал бы всем нам тут.
Какого уровня игра, вот как здесь, например: http://codecanyon.net/category/html5/games
Там игры на HTML5, простые браузерки, можно в страничку встроить, canvas, все дела.
Хотелось бы научиться такие делать тоже.
Объясните где я обосрался?
Много кто. Посмотри в wordstat.yandex запрос "играть онлайн на сайте" или подобные. Там сотни тысяч в месяц запросов, а то и миллионы.
>flappy bird
>полмиллиарда установок
>кто в это играет
Ахуеть я придурок. Спасибо, Анон.
Никто не играет, там же написано кол-во продаж (1-2 в среднем).
>>690977
Прямо умиление берет от этого восторженного наивного ребенка)))
Но молодец, практика это главное. Не будешь писать код, не будет прогресса.
Ошибок там конечно наверняка море, но это не главное, главное усердие.
Непонятно правда, в чем вопрос был.
под онлайном я понимаю что нибудь уровнем повыше
Мне 39 лет, какой еще ребенок? Шучу, конечно :3 Ясное дело как со стороны выглядит, ну да и ладно, может так и есть, кто знает.
Вопрос в базах данных. Пока я даже понятия не имею как их делать, подключать, писать, использовать и все такое. Просил годной литературы и какого-нибудь краткого общего объяснения.
http://codecanyon.net/category/html5/games?page=31
>Никто не играет, там же написано кол-во продаж (1-2 в среднем).
>до тысячи покупок всего за пару месяцев
Там просто каждый день новые появляются.
Да я бы даже скинул, но там счетчик онлайна со встроенным диваноном по айпишникам. Пришлось бы всем прокси надевать. Да и чат в виде виджета вк запилен в котором можно меня легко задиванонить, так что лучше не буду.
Чтобы было хоть какое-то представление - смесь куки кликера и какой-нибудь стратегии со всякими улучшениями.
те даже на простой,но интересной игрушке можно немножко срубить бабла?
Вполне. Только лучше бесплатные приложения для Андроид и iOS, это я как диванный эксперт тебе говорю.
Вот не об игре, просто читал сегодня как раз: https://vc.ru/p/currency
>>691070
Не, флаппи бесплатная, там только реклама была от Гугла, пока создатель не удалил её.
В оп-посте ссылки на задания по файлообменнику и сайту для студентов. К ним подробные комментарии как писать веб-приложения.
Это для учебы, в реальности конечно все пишут на фреймворках (или cms, кому что ближе).
>>691058
Все шапке, что ты не как олдфак треда.
Ссылки на оповские мануалы на гитхабе в шапке.
https://gist.github.com/codedokode/10539213
Но там в основном собрана туча ссылок на разные скучные справочники и документации.
Php вряд ли годится для онлайн-игры, хотя в учебных целях почему бы и нет.
Если ты знаешь javascript, есть смысл смотреть в сторону nodjs. Хотя там свои сложности.
И mysql для браузерной игры особо не нужен, есть же локальное хранилище. Ну или хранить на сервере в редисе.
Не знаю, подожди опа.
и как ему удалось заработать 50к бачей на рекламе?большинство пользователей пропускает ее
На Андроид установи какую-нибудь игру - там хер пропустишь.
Вот живой пример: чашка Петри, чел сделал аналог игры Агарио. Там счет заработанного идет уже на миллионы.
так вроде должна быть функция пропустить или не?и как считается-тупо клик или еще определ время на просмотр?
Платят и за показы, и за клики, только по-разному.
Ещё могут быть оплаты за игровую валюту: посмотри видео от партнеров - получи 30 плюшек на счёт. Но это для топовых игр, конечно.
Так-то тупо блок Адсенса обычно, во время игры меняется реклама врем от времени.
Я даже знаю кто сделал аналог. Он тут с нами сидит. Именуют его гоблин.
MySQL не нужен в том смысле что вообще базы данных не нужны? А как же регистрации, аккаунты, личная статистика и все такое. Да и играть будут два человека друг против друга. "Локальное хранилище" в моем понимании что-то в стиле кук и хранится в браузере, а мне то надо чтобы нельзя было читерить и цифры хранились в базе.
Насчет шапки. Ее-то я посмотрел уже. Учебник по SQL там ну уж слишком большой. Знакомый сказал мне особо много не понадобится, всего-лишь небольшой набор элементарных вещей. И из целого учебника выцеживать то, что я даже не знаю что мне нужно, как-то не хочется.
Судя по твоему посту, ты совсем не понимаешь откуда начать, так что для тебя сложно. А так серверная часть для крестиков-ноликов даже на PHP реализуется за один вечер.
>>686858
>>686858
Вот мои посты выше. Пост с обьяснением проблемы и пост с моим гитхабом. В чем дело. Я таки полазил и понял, что не работает конкретно добавление в базу данных. Ставил условие чтобы делать header только если mysqli_query возвращает true и не перенаправляло. Скажите, что из моего кода может быть устаревшим для 7php, mysql 5.7, apache2.4? Проблема так и не пофикшена, не работает оно. Если у кого-то установлены именно 7php, mysql 5.7, apache2.4 убедительная просьба - запустите проект с гита(ссылка на пост с ним выше) и напишите в тред результат. Если я не найду решения то прийдется таки работать с денвером, чего я очень не хочу, а сроки поджимают.
дай алгоритм действий
И тут же еще один вопрос, мне нужно в функцию контроллера передавать маппер, что бы не нарушать DI, если я его правильно понимаю, как это реализовать?
public function index(Request $request, Application $app) вот же как выглядит контроллер
Я вижу серьезные ошибки в твоем коде. Несмотря на то, что я аж в 2 уроках предупреждаю об этом, ты видимо их не читал, зря.
Вот возьми свой код:
https://github.com/EvgheniiSytnyk/Clio-Caliope/blob/master/register.php#L38
> mysqli_query($link,"INSERT INTO users SET user_login='".$login."', user_password='".$password."'");
> header("Location: login.php"); exit();
И сравни с кодом из мануала:
http://php.net/manual/ru/mysqli.quickstart.statements.php
http://php.net/manual/ru/mysqli.query.php
там есть разница в том как ты используешь query и как ее надо использовать.
Я не могу гарантировать что это напрямую связано с ошибкой но вполне может быть причиной мешающей найти ее.
При DI обычно зависимости передаются в конструктор а не функцию. Ну и для контроллеров обычно DI не делают (но есть люди которые наоборот считают что надо делать, по их мнению контроллер это такой же сервис), так как это управляющий всем процессом скрипт и он может сам получать нужные ему объекты как хочет.
То есть можешь просто передать DI контейнер в конструктор контроллера и далее его исопльзовать.
>>691226
Почему бы и нет? Для меню все равно 1-2 переменных достаточно.
>>691089
Браузерное хранилище никак не поможет в случае игры нескольких игроков по сети через сервер.
>>691120
> Знакомый сказал мне особо много не понадобится, всего-лишь небольшой набор элементарных вещей.
У нас есть в шапке задания по SQL и там перечислено что надо знать чтобы использовать и проектировать базы данных. Не представляю как можно что-то нормально сделать не зная этого.
Ну и если ты про учебник Пирамидина, то он по моему простой, а объем там из-за того что элементарные вещи по несколько страниц объясняют.
>>691103
Пожалуйста, давайте не будем скатывать тред про программирование в оффтопик. Вы бы еще тут про ЕОТ своих писать начали.
>>691068
Заработать можно на любой популярной вещи.
>>691029
Студентов сделай для начала из ОП поста.
>>691006
Да, но так как у меня не очень много времени, в первую очередь буду смотреть код тех кто решает наши задачи или у кого есть какой-то конкретный вопрос.
При DI обычно зависимости передаются в конструктор а не функцию. Ну и для контроллеров обычно DI не делают (но есть люди которые наоборот считают что надо делать, по их мнению контроллер это такой же сервис), так как это управляющий всем процессом скрипт и он может сам получать нужные ему объекты как хочет.
То есть можешь просто передать DI контейнер в конструктор контроллера и далее его исопльзовать.
>>691226
Почему бы и нет? Для меню все равно 1-2 переменных достаточно.
>>691089
Браузерное хранилище никак не поможет в случае игры нескольких игроков по сети через сервер.
>>691120
> Знакомый сказал мне особо много не понадобится, всего-лишь небольшой набор элементарных вещей.
У нас есть в шапке задания по SQL и там перечислено что надо знать чтобы использовать и проектировать базы данных. Не представляю как можно что-то нормально сделать не зная этого.
Ну и если ты про учебник Пирамидина, то он по моему простой, а объем там из-за того что элементарные вещи по несколько страниц объясняют.
>>691103
Пожалуйста, давайте не будем скатывать тред про программирование в оффтопик. Вы бы еще тут про ЕОТ своих писать начали.
>>691068
Заработать можно на любой популярной вещи.
>>691029
Студентов сделай для начала из ОП поста.
>>691006
Да, но так как у меня не очень много времени, в первую очередь буду смотреть код тех кто решает наши задачи или у кого есть какой-то конкретный вопрос.
Промахнулся
Вопрос остается, как в Silex передать маппер в конструктор, лол.
Хотелось бы, как в magento, шоль, отдельный блок который ее генерит
Не уверен насчет кода, но аватарка знакомая.
Писать свое - хорошая идея, но надо все равно продолжать учиться. Я замечаю такую вещь, что когда начинающий анон например доходит до задачи про студентов, или например до задачи про минера на JS, у него появляется завышенная оценка своих сопсобностей. Сделав простое приложение, люди думают что теперь-то они могут сделать что угодно, и дальше учиться незачем.
Но это именно ложное ощущение. Ведь мало знать синтаксис и популярные стандартные функции. Реальные задачи отличаются от наших тем, что в них приходится работать с огромными по объему приложениями. Десятки тысяч файлов с кодом - не редкость. И чтобы работать с таким кодом, мало знания синтаксиса. Нужно уметь писать простой и поддерживаемый код, контролировать его сложность, уметь правильно проектировать классы и взаимодействие между ними.
Потому вам все равно надо продолжать учиться.
> я бы хотел получить знания по базам данных. Написать что-нибудь с помощью их.
Ты не можешь написать что-то "на базах данных" так как это система хранения данных, а не среда программирования. База данных не будет тебе выдавать веб-странички и не позволит отправлять данные в нее с них.
У нас есть в ОП посте урок и задачи по MySQL, там написано что надо выучить и какие задачи стоит решить для проверки знаний. даже решив их все, ты все равно не сможешь написать чат без знаний серверного языка программирования.
То есть тебе нужен как минимум PHP. Причем если делать чат серьезно, с сокетами и асинхронщиной, то придется еще изучать эти сокеты и сетевое программирование. Путь не короткий.
SQL это язык для написания запросов к БД. MySQL это СУБД поддерживающая SQL. Язык MySQL на 90% соответствует стандарту SQL и на 10% состоит из своих особенностей и дополнений.
В таких ситуациях надо ставить эхо в загрузчик, чтобы выводилось имя класса и предполагаемый путь к файлу. И по ним смотреть что не так.
Как минимум надо учесть что неймспейсы в имени класса содержат бекслеши в то время как в именах файлах надо использовать прямые слеши - в линуксе только они работают.
>>690725
Тебе в логе PHP пишет: ты обращаешься к несуществующей переменной. Из-за этого видимо и не срабатывает иф. Не игнорируй сообщения которые пишет пхп.
Ты пробовал гуглить эту переменную? Погугли.
Также почитай мануал: http://php.net/manual/ru/tutorial.forms.php
Похоже что учебник по которому ты учишься настолько устарел что код не работает в современном PHP.
Если хочешь учиться современной версии PHP - читай php the right way и решай нашу задачу про студентов. Мы старью не учим.
Порядок отсчитывается по открывающим (левым) скобкам:
((a(с))(b))((d)(e))
1 ((a(с))(b))((d)(e))
2 (a(с))
3 (с)
4 (b)
5 ((d)(e))
6 (d)
7 (e)
Если под ОПом ты имеешь в виду ОПа этого треда (меня) то я ничего подобного не говорил. Если тебя не брали куда-то на работу значит ты не соответствуешь их требованиям и надо учиться дальше. Давай на этом закроем эту тему и не будем возвращаться к ней.
Это тред про программирование. Обсуждать как ты не прошел собеседование можно в нытик-треде который всегда висит на первой странице раздела.
>>690093
Он не для этого. Он запрещает переопределение метода или наследование класса.
Чтобы поле не было видно в потомках его надо делать private.
>>690092
Исключения используй.
>>690074
Покинь тред.
>>690055
С этим в другой раздел. Этот для программирования.
>>689908
> Но я пока использую регулярное выражение из урока http://archive-ipq-co.narod.ru/l1/regexp.html
> [\w+.-]+@[a-z.-]+/
Ни в коем случае это не используй - тут куча ошибок:
- имя может содержать другие символы вроде знака процента.
- домен может содержать как минимум цифры
- рано или поздно начнут появляться кириллические адреса - стандарты не запрещают вроде
>>689822
Ксс не идеален и приходится искать компромиссы. Отрицательный маргин подобранный под размер шрифта не такой и старшный компромисс при условии что этот шрифт распространен.
> отрицательные значения в line-height не допускаются
Логично, как высота строки может быть отрицательной.
>>689811
Спасибо за вклад. Но так как задача большая и на английском, не уверен что смогу добавить ее в список. Хотя, можно конечно перевести ее.
Так как это тестовое задание, мы не будем давать посказки - ведь тебе самому важно оценить свои способности, а подсказки этому помешают.
>>691253
Под контроллером ты имеешь в виду controller provider?
Судя по http://silex.sensiolabs.org/doc/providers.html#controller-providers ты сам создаешь его экземпляр и соответственно можешь передать у конструктор что хочешь. Уточни вопрос и дополни кратким примером кода если надо.
Если под ОПом ты имеешь в виду ОПа этого треда (меня) то я ничего подобного не говорил. Если тебя не брали куда-то на работу значит ты не соответствуешь их требованиям и надо учиться дальше. Давай на этом закроем эту тему и не будем возвращаться к ней.
Это тред про программирование. Обсуждать как ты не прошел собеседование можно в нытик-треде который всегда висит на первой странице раздела.
>>690093
Он не для этого. Он запрещает переопределение метода или наследование класса.
Чтобы поле не было видно в потомках его надо делать private.
>>690092
Исключения используй.
>>690074
Покинь тред.
>>690055
С этим в другой раздел. Этот для программирования.
>>689908
> Но я пока использую регулярное выражение из урока http://archive-ipq-co.narod.ru/l1/regexp.html
> [\w+.-]+@[a-z.-]+/
Ни в коем случае это не используй - тут куча ошибок:
- имя может содержать другие символы вроде знака процента.
- домен может содержать как минимум цифры
- рано или поздно начнут появляться кириллические адреса - стандарты не запрещают вроде
>>689822
Ксс не идеален и приходится искать компромиссы. Отрицательный маргин подобранный под размер шрифта не такой и старшный компромисс при условии что этот шрифт распространен.
> отрицательные значения в line-height не допускаются
Логично, как высота строки может быть отрицательной.
>>689811
Спасибо за вклад. Но так как задача большая и на английском, не уверен что смогу добавить ее в список. Хотя, можно конечно перевести ее.
Так как это тестовое задание, мы не будем давать посказки - ведь тебе самому важно оценить свои способности, а подсказки этому помешают.
>>691253
Под контроллером ты имеешь в виду controller provider?
Судя по http://silex.sensiolabs.org/doc/providers.html#controller-providers ты сам создаешь его экземпляр и соответственно можешь передать у конструктор что хочешь. Уточни вопрос и дополни кратким примером кода если надо.
for ($deposit = 10000; $deposit <= 1000000; $deposit = $deposit + ($deposit * 0.1)){
echo "Шел $year год... в этом году на счету " . $deposit ."<br>";
$year++;
}
задачка на миллион, верно?
>>691290
Слишком много кода в шапке цикла, тяжеловато читать. Я бы перенес увеличение года в скобки, а депозит вынес. Хотя праивла позволяют даже указать обе переменных через запятую.
Ну и посмотри внимательно: если наберется ровно миллион, твой цикл будет выполняться дальше.
Короче завел твое добро на php-7.0+mysql-5.7.8+apache-2.4.
С дефолтной установкой вылезли две проблемы:
1. Можно войти в mysql только с рута в системе. Толи криво встал у меня, толи теперь такая политика безопасности я х.з. Ну создал пользователя, подключение пошло. Воткни хотя бы после подключения к бд для вывода ошибок:
if (!$link) {
echo "Error: Unable to connect to MySQL." . PHP_EOL;
echo "Debugging errno: " . mysqli_connect_errno() . PHP_EOL;
echo "Debugging error: " . mysqli_connect_error() . PHP_EOL;
exit;
}
2. При вставке в register.php вылетает ошибка, user_hash не передается и не задано дефолтное значение. Решение: добавить default '0' для этого столбца, как у тебя сделано для user_ip.
После этого все заработало.
А где ты этот ад взял вообще и зачем он тебе?
Про то что в mysqli надо всегда проверять результат, я пишу везде где могу. Люди все равно продолжают его не проверять. Не знаю кто виноват. плохие учебники, невнимательные люди или разработчики, заложившие по умолчанию вариант "игнорирвоать все ошибки". Переходите на PDO лучше.
>>691321 - mysqli, woocommerce, картинка с енотом, регистронезависимый поиск в postgresql https://github.com/foobar1643/student-list/
>>691322 - задача про стихи и еще что то
>>691323 https://github.com/foobar1643/student-list/
>>691324 много задач от енота, yoda speak, клавиша shift и другие
>>691325 граммар наци, вопрос про мемкеш
>>691326 сложная задача про банкомат, палиндром, айпад
>>691327 енот граммар наци, двоичный поиск
>>691328 лиличка,
>>691329 ООО вектор, автомобильные номера, номера телефонов
>>691331
> array_push($topsOut, $amount);
> array_push($topsIncluded, $amount-$nomination);
> array_push($weights, $nomination);
> мне кажется не очень удачная идея вести 3 стека
Это способ хранение графа с помощью списка рёбер
$topsOut - массив вершин, из которых выходят рёбра.
$topsIncluded - массив вершин, в которые входят рёбра.
$weights - массив весов рёбер.
Я так до конца и не смог додуматься, как организовать перебор всех комбинаций и при этом учитывать количество заданных банкнот. Короче так я и не осили эту задачу в полном объеме.
А как вообще в жизни выглядит приготовление жратвы?
1) Берется доширак, заливается кипятком, вставляются туда опциональные фигни типа лавровых листов, ????? PROFIT!
2) Берется лапша, варится соус, добавляются овощи, затем смешивается все.
3) Сразу берется мясо, разделывается, раскатывается тесто, варятся овощи, добавляются специи и делается блюдо?
4) Берется уже готовое блюдо, в него добавляются новые ингридиенты, новое блюдо готово?
Думай.
Вполне обычное решение вроде?
В заменах мало значений, но это не проблема, конечно: http://ideone.com/c9obR9
Тебе надо подписать что хранят эти массивы. Если это граф - то что является узлами и связями. Сами названия переменных мне ничего не говорят, а сидеть реверс-инжинирить твой код мне было некогда. Если ты не делаешь свой код понятным, тебе не смогут ничего посоветовать.
Аналогично стоит подписать что делает функция, что у нее на входе и что на выходе.
Тем более, если у тебя граф, для них есть много стандартных алгоритмов.
> Я так до конца и не смог додуматься, как организовать перебор всех комбинаций и при этом учитывать количество заданных банкнот. Короче так я и не осили эту задачу в полном объеме.
Можно начать с наивного варианта: перебирать все допустимые комбинации купюр пока не выпадет нужная.
>>691411
Замена сделана неправильно.
http://ideone.com/A6jXzi
Теперь все верно
>$stavka
>$komissiya
>. " месяц кредита, " . "В этом месяце кредит составил " . round($credit) . ", " . "Всего было выплачено уже: " . $totalPayment . "<br>"
Ты так и не стал на путь исправления...
Считает неверно: там должно получиться 61270 рублей со многими копейками.
Конкретно у тебя не считается последняя выплата в 262 рубля, к которой прибавлена комиссия в 1000р и три процента на 8 с небольшим рублей.
$app->get('/', 'Controllers\IndexController::index')->bind('homepage');
Вот мапится контроллер к роутеру.
Мне нужно передать в IndexControoller конструктор хотя бы $app['db'], как это сделать?
С силексом я не работал, но в слиме можно поместить контроллер в контейнер и передать ему все что хочешь.
>$container['ExampleController'] = function ($container) {
>return new ExampleController($container);
>};
Потом в роутере ты просто пользуешься контроллером который у тебя в контейнере вот так
>$app->get('/path/to/controller', 'ExampleController');
Так же можно указать функцию которая будет вызвана, например
>$app->get('/path/to/controller', 'ExampleController:someFunction');
Если её не указывать, будет вызвана функция __invoke()
Попробуй погуглить, может в силексе тоже можно как-нибудь подобным образом сделать, разработчик у слима и силекса один, насколько я понимаю.
В требованиях на вакансиях верстальщика часто встречается "базовое знание php", "хотя бы понимать что такое PHP".
Что они хотят видеть и к чему я должен быть готов?
>ЧТо жуткого в БЭМ?
Ээээ.... Как бы общее впечатление от легаси моей конторы. Ладно там проекты масштаба яндекса. А для микродрисни мне такой слон не нужен.
Я имею в виду не весь их стек инструментов а только систему именования классов. Ну и кстати идея разбивать CSS код на файлы тоже неплохая.
Так считает же неправильно всё равно, ты о чём?
Поставь в сумму кредита 1000 - должно получиться 2030, а у тебя вот что: http://ideone.com/NNceu6
Уходит в минус всё, выплачивается два месяца.
Можно попробывать не указывать, но как мне тогда после передачи выбрасывать нужную функцию для обработки запросан на роутер?
Частные случаи жи, надо что бы во всех работало, ах да и смени названия переменных, за кирилические название уебать хочется
Надо чтобы работало на любых суммах кредииа, любых разумных значениях процентов, комиссий и лимитов. То есть если кредит выплачиваемый - программа должна его правильно считать.
Я бы советовал радикально упростить код. Сейчас в нем очень много действий и легко допустить ошибку.
Незачем повторять код 2 раза для обычных платедей и последнего. Надо написать универсальный код. В примечаниях к задаче есть подсказки вроде бы.
по поводу перевода строк - добавляй \n после br чтобы оно и на идеоне переносилось
Или сделай так
### переносы строк и br
Чтобы переносы строк нормально работали и в браузере и в ideone (и в консоли), можно использовать для этого \n, а в начале программы поставить
header("Content-Type: text/plain; charset=utf-8");
Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать переносы строк в нем (так как в языке HTML перенос строки равносилен пробелу).
Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
http://ideone.com/N1elKn // Числа прописью
конструкция из IF в в функции переименования маленьких чисел похожа на фрактал. Но совершенно не редактируема, как литой кусок говна. Каждый раз, после ошибки, приходится переписывать ее занаво, т.к. не получается разобраться. Даже с комментами. Просто количество скобочек сбивает с толку. Мне кажется есть более лучшее решение.
Аа, соррян, это ОП поменял описание недавно, наверное, а я не разобрался в твоём коде.
Да, сейчас всё правильно работает с 40000: http://ideone.com/9LfriQ
Но с 1000 работает неправильно, я выше ссылку давал. Надо это исправлять.
Вот я хз че тут делать и куда вешать проверку если кредит изначально мелкий очень
Так посмотри сам, никто тебе не будет тыкать ошибки в таких простых алгоритмах
Не хочется ковыряться вилкой в твоём коде: всё эти кавычки, конкатенация на пустом месте.
Но алгоритм должен быть таким:
1. Прибавляем к $creditBalance проценты и $servicePayment.
2. Если получившаяся переменная меньше $monthlyPayment, то выплачиваем именно её и прибавляем её к $paymentTotal. После этого завершаем цикл.
3. Если получившаяся переменная больше или равна $monthlyPayment, то отнимаем от неё $monthlyPayment, продолжаем цикл.
Это работает на любых суммах правильно. Самый естественный алгоритм.
Ты как моя математичка - написала ебовую дробь и "ОЙ НУ ТУТ ТАК ПРОСТА И ПАНЯТНА ЧТО НИПАЙМЕТ ТОЛЬКО КАМАР". В итоге из 25 человек математику сдали нормально лишь трое, которые репетиторов нанимали.
Я хер знает как на такой мелкий кредит сделать проверку. Он сразу соответствует двум критериям и действие выполнится дважды.
>Я хер знает как на такой мелкий кредит сделать проверку. Он сразу соответствует двум критериям и действие выполнится дважды.
Это значит, что ты перемудрил с решением.
>if ($credit - $payment/2 < 0)
Что? Что это вообще за чушь? Для чего нужно узнавать, когда разница суммы кредита и разделённой надвое суммы выплат будет меньше нуля? Чё-то ты загнался куда-то, попробуй сделать по алгоритму выше.
Другой анон
Потому что я работаю, и если ты собираешься работать, будь готов что тебя пошлют нахер, при тупых вопросах и попросят показать, что ты уже пробывал.
Подсказка:
На самом начале надо чекнуть, не больше ли сума месячного платежа, чем собственно говоря сам кредит.
Тогда на 4000 тысячах он выплачивает 4200 не считая % и комиссию, и гасит на месяц раньше..
Я уже 5 раз с утра переписываю, чет я не осиливаю это
Тут все либо проще чем мне думается,
либо я думаю очень хуево
На сумме 40000 кредита, предпоследний платеж 4200+-, мы платим 5000 + комиссия 1000.
Получается, что кредит не гасится, но условие
$кредит > $платежа срабатывает.
Для этого в старой версии у меня стоял костыль
>if ($credit - $payment/2 < 0)
Который не срабатывал на 1000 кредита, но зато на других суммах работал как надо (я полагаю что до 2500, пока платеж == 5000)
Первое, что тебе надо сделать, это связать всё с "сумма кредита равняется к сумме кредита прибавить проценты и комиссию за пользование", без отнимания месячной выплаты. Это надо проверять: если больше месячной выплаты - всё продолжается, если меньше - выплачиваем и заканчиваем.
Я пойду займусь пока математикой и наверстаю 6-7 классы, с 10 утра решаю этот алгоритм, я уже готов.
Попробуй проще подходить к сути.
Попробуй для себя расписать шаги, которые должна выполнять программа, мне очень помогает такое.
Вот тут что надо сделать?
1. Прибавляем к сумме кредита 3 процента и 1000 рублей комиссии.
2. Если это больше месячной выплаты в 5000, то отнимаем от суммы кредита эти 5000, прибавляем к общим выплатам эти пять тысяч. Цикл продолжается.
3. Если это ("Прибавляем к сумме кредита 3 процента и 1000 рублей комиссии") меньше 5000, то выплачиваем только "это" - и всё прекращаем.
Что тут такого непонятного?
Мне слегка припекло от того, что я почему-то не могу объяснить тебе это, обычно получалось.
Как было бы в реальности: ты прибавляешь к сумме кредита три процента и тысячу комиссии, а потом отнимаешь пять тысяч - месячную плату. Когда у тебя сумма кредита стала рублей 200-300, то ты снова прибавляешь к ней 3 процента и 1000 комиссии, а потом выплачиваешь только получившееся.
Что тут непонятного-то?..
http://ideone.com/F0XefS
Тут нет ответа? https://www.google.ru/search?q=doctrine+dbal+last+insert+id&newwindow=1&gbv=1&sei=th3sVoDmC4Ga6ATg142wCg
Алсо если ты уж взял доктрину, бери doctrine ORM. Чуть-чуть похимичив с аннотациями ты получишь готовый маппер, способный сохранять и загружать твои модели в базу.
У меня в маппере собственно говоря две функции, зачем мне лишний раз грузить ORM, лол? И getLastId мне не нравится, ибо с двумя одновремнными загрузками могут возникнуть траблы.
Или не возникнут?
По дефолту добро лежит в /var/www/html.
http://w99953g4.bget.ru/
Кнопки и ссылки не работают, все статичное, только нескучные обои и анимацию добавил.
Там есть сомнительные моменты, но они и в макете такие. Под мобильные макета нет, на свое усмотрение там чуть столбцы подвигал при 320 и 640, шрифт и картинки уже лень подгонять.
В последнем хроме и лисе вроде ничего не ломается.
Джипег макета пикрил
Проверил, нету.
адаптивность хуевая, по центру выравняй паддинги поставь, смотри чтобы все умещалось .
Продаван, плиз. Когда там на собеседование очередное пойдешь?
Почему в десктопном масштабе меню собрано в кнопку? Понятно, что там меню нет и это просто значок, но всё же.
Также при уменьшении масштаба страница не становится похожей на твой макет - картинки-превью по ширине экрана располагаются, а всё остальное просто уменьшается. Нет жёлтого фона по сторонам, общий темный фон так и остаётся.
Не могу загрузить картинку, тут скрин: https://gyazo.com/d0bc673a0579d1d20b0f3cccd441514c
Плагины для жквери своровал, а так сам.
>>691876
Фулстекобоярам верстка не нужна?
>>691883
Меню в макете нет, а сам я не знаю как сделать красивые кнопочки.
>Нет жёлтого фона по сторонам
Это не часть макета, в psd его нет
>картинки-превью по ширине экрана располагаются, а всё остальное просто уменьшается
Честно говоря из макета я не понял как этот блок себя должен вести при масштабировании.
Поправил только что на альтернативную версию, так лучше?
Ну, я подумал, что надо, чтобы так же в точности выглядело, как на твоей картинке.
А то ведь верхний слайдер растягивается по ширине: https://gyazo.com/dad91187317faa20d6d97240b959d20a
https://gyazo.com/8945dc3484878909ffb078e9deb7dc33 - тоже смотрится не вполне органично. И внизу тоже футер растягивается.
Так-то всё нормально, конечно, и с самого начала было, это всё уже мелочи.
Почему повезло? За такую нищенскую ЗП работы полно. Но не легче ли грузчиком столько же зарабатывать и не ебать себе мозг говнокодингом?
Грузчиком не посидишь на кресле. Я тоже работаю и получаю 40-50к. Но это тоже нищенство.
Многие аноны были бы рады любой работе кодером, лишь бы опыта набраться.
Раз никто не пишут, то буду городить костыль:
[code]function console_log( $data ){[/code]
[code] echo '<script>';[/code]
[code] echo 'console.log('. json_encode( $data ) .')';[/code]
[code] echo '</script>';[/code]
[code]}[/code]
Чё-т в голосяку с тебя.
Вы тут задачку из гайда Опа разбираете, с кредитом на айфон, я правильно понял? Я короче вот так решил:
http://ideone.com/M5gkaB
Добавил переменную последний_платеж которая юзается если остаток меньше или равен ежемесячному_платежу. Вышло в ноль, процент посчитан, комиссия за обслуживание тоже. Правильно сделал?
Мимо только два часа назад начал читать гайд Опа, до этого код в глаза не видел.
xdebug
И правда ведь, ответ что то мимо глаз прошел. Фиксанул.
http://ideone.com/M5gkaB
>>692038-ньюфаг
Можно сократить всё, чтобы два раза echo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n"; не повторялось.
>( $creditBalance * $percent ) + $servicePayment
Вот это повторяется несколько раз, надо избавиться от повторов.
это я знаю; просто не так сформулировал вопрос.
Как рассчитать размер шрифта так, чтоб слово вместилось по ширине в пикчу (без переносов)? Например, ширина пикчи 100рх.
Ну для ( $creditBalance $percent ) + $servicePayment* вроде как можно отдельную переменную ввести, или надо как то все реорганизовать? Не в курсе просто стандартов написания кода видимо не дошел еще. Вывод информации после срабатывания условия тоже вообще не представляю как не повторяя строку сделать видимо опять же еще не дошел. В целом то решение хотя бы близко к верному?
Подскажите, как организовать поиск в базе со связью "многие ко многим"?
Вот у меня есть три таблицы, как этой пикче. Я хочу сделать следующее: выбрать все записи из таблицы items, которым в таблице items_filters соответствуют значения фильтров, которые передаёт пользователь. Хуёво сформулировал, поэтому вот небольшое пояснение.
Например, если пользователь передал два фильтра с каким-либо filter_id (допустим, filter_id = 1 и filter_id = 2), то выбраться должны такие записи из таблицы items, которым соответствуют записи в таблице items_filters, у которых `items`.`item_id`=`items_filters`.`item_id` И `items_filters`.`filter_id`равняются '1' И '2'
Опять нихуя не понятно, ну да ладно.
В общем, я составляю запросы вот такого вида, но они, понятное дело, выводят объявления, где filter_id=1 ИЛИ filter_id=2
SELECT * FROM `items_filters` INNER JOIN `items` ON `items`.`item_id`=`items_filters`.`item_id` WHERE `items_filters`.`filter_id`=4 OR `items_filters`.`filter_id`=6
Если заменить OR на AND, то выводиться ничего не будет по вполне понятным причинам.
Считает всё верно.
Но надо стремиться к оптимуму, чтобы не копипастить и не делать лишних телодвижений в программе.
>Вывод информации после срабатывания условия тоже вообще не представляю как не повторяя строку сделать
Просто echo должно быть за пределами всех условий.
Ай, не та пикча
Добротно, про мобильность уже сказали, я бы просто забил на нее и сделал без нее, если уж полноценно ее не поддерживать. лучше никакой чем хуевая
>аватарка знакомая
maketi.esy.es Может вспомнишь так :3 Ну да ладно, не важно.
>Писать свое - хорошая идея, но надо все равно продолжать учиться.
А я и не забрасываю. Просто буду учить параллельно и по мере необходимости что-ли.
>То есть тебе нужен как минимум PHP. Причем если делать чат серьезно, с сокетами и асинхронщиной, то придется еще изучать эти сокеты и сетевое программирование. Путь не короткий.
Ну значит приступаю к твоему учебнику по PHP, наконец.
Ну вот опять какое-то слово мудреное принес ахах, для меня "сокеты" это алмазики из WoW, которые в доспехи вставлять надо. Тред не зашкварен, лет 5 назад играл.
Сложновато чутка перестраиваться в PHP после JS и вот вопросы которые у меня возникли по твоему учебнику.
Вот задача на игру в кубики. https://ideone.com/uufpgm
1)В строке где показываем выпавшие номера переменные заключены в фигурные скобки. Для чего? Только для читаемости?
2)Так же в if при перечислении нескольких условий, они заключены в скобки. Это обязательно?
3)Так странно эти переносы строки выглядят посреди текста. Не легче ли там сделать два эха на выпавшие у анона и компа номера, а то общая строка меня смущает и длиной и этими переносами. Или типа лишние действия не нужны, зачем усложнять, все будет медленнее работать и все такое?
Айфон в кредит https://ideone.com/XBhKRi
>В строке где показываем выпавшие номера переменные заключены в фигурные скобки. Для чего? Только для читаемости?
Фигурные скобки нужны чтобы разделять переменные и текст, когда идет подставление. Представь ситуацию когда нужно вывести переменную и рядом с ней поставить какой-нибудь символ не ставя при этом пробел. Тут есть несколько способов, но если нет желания использовать конкатенацию строк (во втором посте про неё написано, кстати) то можно сделать вот так
>echo("Example {$variable}string");
>2)Так же в if при перечислении нескольких условий, они заключены в скобки. Это обязательно?
Это не совсем понял. Если подразумеваешь вот такое
>if($foo == true && $bar == false)
То там не нужны скобки.
Вообще насколько я знаю, там скобки не обязательны, может быть это для читабельности сделано. Тут лучше ОПа подождать, он лучше объяснит.
Про фигурные скобки:
http://php.net/manual/ru/language.types.string.php#language.types.string.parsing
http://php.net/manual/ru/language.types.string.php#language.types.string.syntax.double
> 2)Так же в if при перечислении нескольких условий, они заключены в скобки. Это обязательно?
Чтобы не надо было гадать, какой порядок выполнения операций и лезть в мануал, мы ставим скобки и задаем его явно.
> Не легче ли там сделать два эха на выпавшие у анона и компа номера, а то общая строка меня смущает и длиной и этими переносами
как хочешь, так и делай.
Бамп вопросу. Помогите, пожалуйста, я очень не хочу писать кучу быдлокода, если существует относительно простое решение.
>>692068
Хороший вопрос у тебя, прямо хоть в задачи добавляй. Аноны, кто изучает mysql, почитайте вопрос, предложите свои варианты.
Твоя задача, так же как и многие другие решается аналогично - джойним, отбираем строки с помощью WHERE, группируем, фильтруем группы через HAVING
Соответственно ответ направшивается сам собой:
- либо в WHERE поставить OR а потом через HAVING выбрать группы содержащие ровно 2 строки
- либо в HAVING написать условие что группа должна содержать И первый id, и второй
И есть еще третий вариант. Ты можешь приджойнить таблицу item_files 2 раза и записать 2 условия в WHERE. Это может быть выгоднее в плане производительности за счет использования индексов. А может и нет - надо тестировать
Если тебе не понятны эти варианты, тебе стоит подучить теорию, например решить нашу заадчку на лайки в уроке по mysql из ОП поста.
Ссылки: http://stackoverflow.com/questions/33647944/mysql-group-by-having-different-values-same-field
Я не понял его вопрос.
Нужно выбрать все items, которым соответствуют filter_id 1 и 2?
Почему не написать тогда WHERE IN?
SELECT i.* FROM items i
JOIN items_filters fi ON i.item_id = it.item_id
WHERE filter_id IN (1, 2)
Дальше стал изучать самостоятельно. Немного про сети почитал. От компа по кабелю бегут импульсы, коммутатор их считывает, читает мак адрес. Если такого хоста нет в коммутаторе, то он рассылает на все порты полученный фрейм и ищет нужный. Дальше 3 уровня я не вижу, где IP. По сути ведь коммутатор передаст на хост фреймы и все. Где 3й уровень? Знаю, что далее фрейм инкапсулируется в IP-пакеты, при этом стирается предыдущий заголовок с мак адресом и записывается новый с IP-адресом. Читаю теорию сетей, об устройстве интернета, и в голове каша. Немного про вланы почитал, интересно все это. Я хотя бы немного стал понимать как оно все работает на физическом уровне. Вообщем, ОП, такие дела, помоги мне разобраться.
Кевин Янк "ПХП и МУСКЛ от новичка к профессионалу"
Страница 134. Связь многие к многим
...
Таблица jokecategory связывает идентификаторы шуток jokeid и категорий
categoryid.
Таблица joke содержит шутки.
Таблица category содержит категории.
...
Теперь, когда промежуточная таблица готова (jokecategory) и содержит назначенные категории,
вы можете использовать оператор JOIN, чтобы сформулировать несколько
интересных и практичных запросов, например вывести список всех шуток в категории
«О д'Артаньяне».
SELECT joketext
FROM joke INNER JOIN jokecategory
ON joke.id = jokeid
INNER JOIN category
ON categoryid = category.id
WHERE name = "о д'Артаньяне"
Как видите, в этом запросе используются два оператора JOIN. Первый объединяет
таблицы jоке и jokecategory , а второй берет готовые данные и объединяет
их с таблицей category .
Следующий запрос выводит список категорий, в которых содержатся шутки,
начинающиеся словами «сколько адвокатов».
SELECT name
FROM joke INNER JOIN jokecategory
ON joke.id = jokeid
INNER JOIN category
ON categoryid = category.id
WHERE joketext LIKE «Сколько адвокатов^»
Кевин Янк "ПХП и МУСКЛ от новичка к профессионалу"
Страница 134. Связь многие к многим
...
Таблица jokecategory связывает идентификаторы шуток jokeid и категорий
categoryid.
Таблица joke содержит шутки.
Таблица category содержит категории.
...
Теперь, когда промежуточная таблица готова (jokecategory) и содержит назначенные категории,
вы можете использовать оператор JOIN, чтобы сформулировать несколько
интересных и практичных запросов, например вывести список всех шуток в категории
«О д'Артаньяне».
SELECT joketext
FROM joke INNER JOIN jokecategory
ON joke.id = jokeid
INNER JOIN category
ON categoryid = category.id
WHERE name = "о д'Артаньяне"
Как видите, в этом запросе используются два оператора JOIN. Первый объединяет
таблицы jоке и jokecategory , а второй берет готовые данные и объединяет
их с таблицей category .
Следующий запрос выводит список категорий, в которых содержатся шутки,
начинающиеся словами «сколько адвокатов».
SELECT name
FROM joke INNER JOIN jokecategory
ON joke.id = jokeid
INNER JOIN category
ON categoryid = category.id
WHERE joketext LIKE «Сколько адвокатов^»
http://ideone.com/NeVOHe
я перехожу к следующей теме
Не сдавайся, анон, у тебя все получится.
>if ($credit + $komissiya < $payment)
А где же проценты?
Почему ты не пытаешься сделать так, как я предлагал выше? Самый же простой и естественный алгоритм? Какого, спрашивается, хера?
Также без этой задачи ты не сможешь правильно решить следующую - кредит на Айпад.
Я сам сидел с ней целую неделю. Это стоит того.
я так и делаю, просто я уже реально не понимаю в какую сторону копать надо..
>$credit = $credit + ($credit * $stavka);
>$credit = $credit - $payment + $komissiya;
Это вообще что за бред?
Вот твоя тенденция всё усложнять идёт от кучи кавычек и конкатенации через идиотские названия у переменных и усложнение вычислений.
Будь проще, и всё получится.
Да, я увидел потом.
Это как-то всё странно, не нужны такие усложнения.
Просто попробуй в if и else расписать тот алгоритм, который я выше тебе расписал.
если элемент не передается в форму никакую (да и если даже передается)
$('selector).click(function(){
$('anotherSelector').val()
или
$('anotherSelector').html()
});
в одну переменную сразу идут проценты, затем из нее вычитается платеж и комиссия
Это как в универе, когда учился, дали задачу школьную, где все решение было в 1 строчку, а мы давай матрицы строить, графики, системами уравнений решать
В val() передавать то что мне надо? Например есть такое <div class="data">100</div>
При нажатии на чекбокс мн нужно чтобы к тому что в диве прибавилось 10. Что тогда в val() писать?
Не нужно вычитать платёж сразу! Я же писал тебе два раза!
>>692347
То да. Но я сам через такое же прошёл с этой задачей в конце прошлого года, могу понять братишек. Я помню почти все значения $creditBalance наизусть, кроме копеек, конечно, я не настолько поехал.
ты не написал что надо передавать. в val идет если у тебя инпут, если хтмл то и пиши хтмл. загугли просто эти две функции.
Вот попробуй прочитать свой код:
> $credit = $credit + ($credit * $stavka);
> $credit = $credit - $payment + $komissiya;
Прибавляем к кредиту проценты, вычитаем платеж (5000) и прибавляем комиссию.
Вот уже тут видна ошибка. Если ты взял кредит на 1000 то не должен платить 5000.
То есть не спеши платить по кредиту. Посмотри чему равен долг и посчитай сколько ты платишь в этом месяце.
Ну и дальше ты еще неправильно прогнозируешь сумму долга на следующий месяц:
> if ($credit + $komissiya < $payment){
Если кредит + комиссия (а где проценты?) меньше ежемесячного платежа....
Надо стереть код и написать заново.
Тебе надо изучить яваскрипт, например learn.javascript.ru и не забивать тред вопросами "сделайте мою работу за меня".
Надо это делать внутри условия.
Если это больше месячной платы - вычитаем месячную плату.
Если это меньше месячной платы - вычитаем только это.
Всё, больше ничего тут не нужно.
Исправления по студентам из прошлого треда.
>>691323
> $auth = $regHelper->getUpdatedFields($auth, $student);
>Это на мой взгляд можно было сделать лучше. Не создавать отдельный объект студента для передачи в update, а передавать туда $student. Алсо, название переменной auth плохое.
Там идея была в том, чтобы загрузить студента из БД, и заполнять его из POST, только если в форме присутствует поле, ты мне об этом писал пару тредов назад. Проблема была из-за того что объект студента все равно заполнялся из формы, независимо от того авторизирован он или нет. И для этого я сделал отдельный объект студента который никак не менялся (кроме как перед заполнением). Сейчас я сделал по другому - чтобы не менять весь алгоритм заполнения формы, я немного поменял функцию заполнения модели студента из POST. Наверное так нужно было сделать с самого начала, просто я об этом тогда не подумал.
>Давай поскорее добьем задачу и пойдем дальше.
У меня почти готов файлообменник на слиме, я делал его паралельно с студентами, там осталось только мелкие баги пофиксить и комментарии к файлам доделать. Пользуясь случаем, задам пару вопросов про оформление на гитхабе и поиск.
1. Я сделал поиск через сфинкс, нужно ли в репозиторий включать мой sphinx.conf с настроенными индексами, или лучше оставить все заполнение для людей которые будут устанавливать приложение?
2. Так же, переиндексацию я сделал через cron, для этого пришлось написать CLI скрипт на PHP который очищает реалтайм индекс при переиндексации (как очистить rt индексы из командной строки я не нашел). Нужно ли включать его в репозиторий (с bash скриптом для крона) или опять же, это оставить для тех кто устанавливает?
3. Если приложению не удалось подключится к поисковому демону (сфинкс просто не устанавливали, например), в этом случае достаточно будет вывести ошибку 503 и написать что подключения к демону нет, или лучше будет на странице с поиском вывести заглушку "Поиск временно недоступен" с кодом 200 и основной навигацией приложения?
Алсо, спасибо тебе за то что ты делаешь.
Исправления по студентам из прошлого треда.
>>691323
> $auth = $regHelper->getUpdatedFields($auth, $student);
>Это на мой взгляд можно было сделать лучше. Не создавать отдельный объект студента для передачи в update, а передавать туда $student. Алсо, название переменной auth плохое.
Там идея была в том, чтобы загрузить студента из БД, и заполнять его из POST, только если в форме присутствует поле, ты мне об этом писал пару тредов назад. Проблема была из-за того что объект студента все равно заполнялся из формы, независимо от того авторизирован он или нет. И для этого я сделал отдельный объект студента который никак не менялся (кроме как перед заполнением). Сейчас я сделал по другому - чтобы не менять весь алгоритм заполнения формы, я немного поменял функцию заполнения модели студента из POST. Наверное так нужно было сделать с самого начала, просто я об этом тогда не подумал.
>Давай поскорее добьем задачу и пойдем дальше.
У меня почти готов файлообменник на слиме, я делал его паралельно с студентами, там осталось только мелкие баги пофиксить и комментарии к файлам доделать. Пользуясь случаем, задам пару вопросов про оформление на гитхабе и поиск.
1. Я сделал поиск через сфинкс, нужно ли в репозиторий включать мой sphinx.conf с настроенными индексами, или лучше оставить все заполнение для людей которые будут устанавливать приложение?
2. Так же, переиндексацию я сделал через cron, для этого пришлось написать CLI скрипт на PHP который очищает реалтайм индекс при переиндексации (как очистить rt индексы из командной строки я не нашел). Нужно ли включать его в репозиторий (с bash скриптом для крона) или опять же, это оставить для тех кто устанавливает?
3. Если приложению не удалось подключится к поисковому демону (сфинкс просто не устанавливали, например), в этом случае достаточно будет вывести ошибку 503 и написать что подключения к демону нет, или лучше будет на странице с поиском вывести заглушку "Поиск временно недоступен" с кодом 200 и основной навигацией приложения?
Алсо, спасибо тебе за то что ты делаешь.
Аноны, как из массива взять не ключ, а значение?
Почитай мануал по функции array_rand()
http://php.net/manual/en/function.array-rand.php
http://php.net/manual/ru/function.array-rand.php -на русском
Она возвращает рандомный ключ, не значение.
В твоем случае будет
> $random = $answers[array_rand ($answers)];
Нет. Тут же написано
http://php.net/manual/ru/function.array-rand.php#refsect1-function.array-rand-returnvalues
>При выборе только одного элемента, array_rand() возвращает ключ для случайного элемента.
В твоем случае переменная $random будет случайным ключом из массива $answers.
Потом ты конечно можешь написать так
>echo($answers[$random]);
Но это уже усложнение, там в мануале еще и примеры использования функции есть.
>>Это одномерный массив, двухмерный это когда массив в массив вложен.
>>Плохо что исправления - в отдельном массиве, легче ощибиться...
>>Выражения для зделал/зделаю можно собрать в одно.
http://ideone.com/mQRO16 // «Grammar Nazi»
Собрал поиск, описание и исправления в один многомерный массив )
Мне кажется там на месте тупо эйчарша смотрит список требований, видит, что нет технического во и рубит с плеча.
Не могу уже, что делать-то?
>>Это не чат! Пожалуйста не флудите, а старайтесь постить только вопросы, решения и ответы. Сколько лет вы не можете найти работу никому не интересно. Высказывайтесь одним большим постом а не цепочкой мелких
ничего, переживешь, ничего с тобой не случится
Если использовать твой пример, то должно получиться следующее: я хочу отобрать шутки, которые относятся сразу к нескольким категориям.
>>692171
Ну, я тоже подумал про подобный метод. Считать количество фильтров, передаваемых пользователем, затем выбирать группы, содержащие столько строк, сколько передано фильтров.
Джойнить два раза - зачем? А если будет передано десять фильтров?
>>692208
Получается то же самое, что и при использовании OR в условии в моём запросе.
И почему он выводит информацию не один раз, а каждый раз когда выполняет тело цикла?
>И почему он выводит информацию не один раз, а каждый раз когда выполняет тело цикла?
Потому-что у echo внутри цикла, гений.
for ($i=0; $i <= $halfLength; $i++) {
if(mb_substr($text, 1) == mb_substr($text, -1))}
echo "Ура, это {$result}\n";
Почему тогда он ругается?
Скрыл твой пост из-за ожидания собственного бугурта.
Советов ты не слушаешь, делаешь всё так, что ни черта не понятно. Пусть аноны с более крепкими сраками тебе помогают.
>>692559
Очевидно он не поставил точку с запятой после скобки. И интерпретатор об этом написал, кстати. Очень плохо что ты не умеешь или не хочешь понимать сообщения об ошибках.
>>692561
http://ideone.com/IgCOr6
Там проглядел точку с запятой. Но что тут не так? Почему else не связан с if?
Туплю. Но теперь хоть слово и удовлетворяет условию, оно почему-то не работает. И как убрать повторение того, что выводиться в echo?
Пробелы-то надо убирать из того текста, который получился у нас после перевода в нижний регистр.
Где логика в твоём решении?
>>692576
break поставь. Только от этого не исправится неправильное решение.
Чому? Если буквы сразу не одинаковые, то всё, ломать цикл, выводить "Не палиндром". Разве нет?
Там нужен Break, но совсем не для того, чтобы
>убрать повторение того, что выводиться в echo
Сейчас он поставит его бездумно и у него echo будет выводиться один раз, как он и хочет, но не потому что так правильно, а потому у цикла будет всего одна итерация.
Ну ты же посоветовал ему поставить break как решение именно этой проблемы, хотя break тут не причем.
http://ideone.com/IgCOr6
Может ли быть из-за того, что сравниваются только первый и последний символ? При сравнение не увеличевается число?
Хм, что-то не пойму тебя.
Там именно нужен break и в правильном решении. Потому что как только символы не совпали - всё, выходим из цикла и выдаём "Не палиндром".
Именно в этом условии - когда символы не равны друг другу, а не в другом условии, когда они равны.
Вот тебе задача попроще:
выведи с помощью цикла по одной букве из строки с начала и по одной с конца.
>mb_substr($noSpace, 1)
Какой это символ с начала строки, по-твоему?
Ожидаю, что будет дальше.
Ведь там нигде нет $i, ох лол.
> Если это граф - то что является узлами и связями.
Как то так.
Я понял, что это херовый вариант.
Енот шлёт котиков опу
Анончик, ты конечно красивую картинку добавил, но так и не написал что значат в твоем графе цифры на вершинах и связах. Вот вершина с цифрой 8 - это что? Сумма?
Нужно было всего-то создать переменную с последним значением кредита с % и комиссией и вычесть ее из суммы остатка кредита.
> Вот вершина с цифрой 8
Эта заданная сумма. Следующая вершина, это заданная сумма минус номинал банкноты (вес связи) и т.д. до нуля, причем подсчитывая сколько раз взяли банкноту. Вообще это херовый вариант.
Ссылку на код в студию.
Мало добиться правильного значения, там ещё и оптимально всё должно быть, без копипаста и лишних телодвижений.
Вы вообще уже края потеряли. Гугль вашу мать.
https://www.digitalocean.com/community/tutorials/how-to-install-linux-apache-mysql-php-lamp-stack-on-ubuntu-14-04
Cейчас установлено php5 на убунту, пишу:
sudo apt-get update && apt-get purge php5-fpm && apt-get --purge autoremove && apt-get install php7.0-fpm php7.0-mysql php7.0 libapache2-mod-php7.0
sudo service apache2 restart
и пишет невозможно заблокировать невозможно заблокировать var/lib/dpkg
>невозможно заблокировать var/lib/dpkg
Очевидно что то пользуется dpkg. Нужно это закрыть. Можно попробовать полечить перезагрузкой.
phpinfo();
?>
Когда в браузере запускаю localhost/info.php то выводит чисто код пхп-документа. В чем дело?
Сервер неправильно настроен, и\или на нем не работает пхп.
Читал ли ты урок ОПа? Там как раз описывается твоя ошибка и способ её решения.
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Там виндоус же,а у меня убунту
Спасибо, няша
http://www.emoji.esy.es/
[кто не понял, выбираем смайлики и пишем текст — получаем код, который можно вставить в личные сообщения вк или в комментарии к записям, например]
>>692834
Это значит нет права рута. sudo применяется только к первой команде.
>>692820
Держи, только форматирование побилось немного:
http://www.mediafire.com/download/s12ktalf8r8rl48/pr-threads-69-70.zip
http://rghost.ru/88vjBYS7y
>>692866
В Апаче должен быть модуль-посредник, который будет передавать запросы интерпретатору PHP на выполнение. И он должен быть включен и настроен в конфиге: http://php.net/manual/ru/install.php
Насколько я помню, в убуте/дебиане это все делается автоматически при установке пакета php5-apache2 - поищи пакеты, содержащие в названии оба этих слова.
Скачал с рутрекера книжку про ООП в PHP. Намереваюсь осилить.
http://rutracker.org/forum/viewtopic.php?t=5109503
Годнота?
Стремно грузится - пропиши смайликам ширину/высоту.
Не очень ясный интерфейс.
Алсо, ничто не мешает тебе сделать предпросмотр. И показывать не код смайлика в полях, к тому же испорченный, а сам смайлик.
Ну и буквы жуткие получаются.
Буквы ага, потому что сам забивал. Нашел где-то нормальный пиксельный шрифт, сделаю лучше.
Насчет предпросмотра не очень понял — это как?
fastfix
<script>
var checked = document.querySelectorAll("input[type='checkbox']:checked");
for (var i = 0; i < checked.length; i++) {
str+=checked.value;
}
alert(str);
</script>
Хоть всё и работает, я уверен, что это единичный случай, который развалится, если добавить к нему хотя бы одно слово.
Поясните чем можно сократить код так, чтобы не пришлось прописывать рандом для каждой переменной.
Потому что твоя переменая str доступна только внутри цикла, и вывод аlert ничего не знает о ней.
Почему идеон ругается? Ставит предупреждение, но работает. В чем я неправ?
https://ideone.com/EZ8v2o
А ты проверял свое решение на списке номеров из учебника? Я как минимум вижу что наличие знака + в номерах вроде +71234567890 никак не проверяется.
Не надо там строить сложнейшие выражения. просто проверь что идет +7 или 8, а за ними ровно 10 цифр вперемешку с любым числом скобок/минусов/пробелов
И проверь на большом списке номеров из учебника.
>>689627
Может и получится. Но это работа - тут твоя обязанность выполнить поставленную цель максимально эффективно.
>>689704
Совет по коду: Эти строки повтряются:
> $paymentTotal = $paymentTotal + $creditBalance;
> $creditBalance = $creditBalance -$monthlyPayment;
> echo "{$month} месяц спустя: долг
Попробуй убрать повторы. Также, if можно заменить на вызов функций min или max.
>>689822
Я слышал в языках с отступами инлайновые теги вроде span неудобно писать.
Ну и мимопроходя, замечу что в верстке странно расставлены теги (h1-h2-h3-h4 - заголовков больше чем обычного текста), подозрительно много дивов и бессимтемно составлены названия классов
Алсо логичнее вкладывать a внутрь h1.
А ты проверял свое решение на списке номеров из учебника? Я как минимум вижу что наличие знака + в номерах вроде +71234567890 никак не проверяется.
Не надо там строить сложнейшие выражения. просто проверь что идет +7 или 8, а за ними ровно 10 цифр вперемешку с любым числом скобок/минусов/пробелов
И проверь на большом списке номеров из учебника.
>>689627
Может и получится. Но это работа - тут твоя обязанность выполнить поставленную цель максимально эффективно.
>>689704
Совет по коду: Эти строки повтряются:
> $paymentTotal = $paymentTotal + $creditBalance;
> $creditBalance = $creditBalance -$monthlyPayment;
> echo "{$month} месяц спустя: долг
Попробуй убрать повторы. Также, if можно заменить на вызов функций min или max.
>>689822
Я слышал в языках с отступами инлайновые теги вроде span неудобно писать.
Ну и мимопроходя, замечу что в верстке странно расставлены теги (h1-h2-h3-h4 - заголовков больше чем обычного текста), подозрительно много дивов и бессимтемно составлены названия классов
Алсо логичнее вкладывать a внутрь h1.
> Сделано в предыдущей части задания в 2 вариантах.
Старые версии задачи я проверил в старом же треде.
>Может быть можно было одним выражением, но прогнал дважды через preg_replace, вернее скормил ему массивы.
> Первый раз заменяем пробелы, скобки и проч.символы на пустую строку; второй раз заменяем +\s?7 на 8.
Можно и так, почему нет. Нормализация номеров сделана верно.
Почитай замечания к предыдущим решениям.
>>689895
Ок, верно, хотя для букв можно было вместо (|||) применить квадратные скобки
>>689908
> Мы кажется в итоге пришли к выводу, что сейчас в имени почты может содержаться что угодно
В общем да, так же как и в телефоне. Тут такие аргументы:
- если это поле ввода которое будет читать человек то надо минимально его ограничивать - тот же номер телефона можно написать в разном формате
- с другой стороны, валидация может помочь в случаях когда человек опечатался и например ввел вместо 10 цифр номера только 9.
Здесь мы ищем емайл в тексте - нужно определиться с правилами.
>>690012
Ты плохо знаешь PDO и это мешает тебе полноценно использовать его возможности. Полистай мануал по нему, может что интересное найдешь: http://php.net/manual/ru/book.pdo.php
Как минимум цикл с fetch бессмысленный - это можно сделать лучше.
Насчет статических методов и бессмысленных классов вроде Db::connect - избавляйся от них. Я знаю, такой код можно увидеть в других учебниках, но это лишь говорит о том что их авторы не осилившие ООП.
> Сделано в предыдущей части задания в 2 вариантах.
Старые версии задачи я проверил в старом же треде.
>Может быть можно было одним выражением, но прогнал дважды через preg_replace, вернее скормил ему массивы.
> Первый раз заменяем пробелы, скобки и проч.символы на пустую строку; второй раз заменяем +\s?7 на 8.
Можно и так, почему нет. Нормализация номеров сделана верно.
Почитай замечания к предыдущим решениям.
>>689895
Ок, верно, хотя для букв можно было вместо (|||) применить квадратные скобки
>>689908
> Мы кажется в итоге пришли к выводу, что сейчас в имени почты может содержаться что угодно
В общем да, так же как и в телефоне. Тут такие аргументы:
- если это поле ввода которое будет читать человек то надо минимально его ограничивать - тот же номер телефона можно написать в разном формате
- с другой стороны, валидация может помочь в случаях когда человек опечатался и например ввел вместо 10 цифр номера только 9.
Здесь мы ищем емайл в тексте - нужно определиться с правилами.
>>690012
Ты плохо знаешь PDO и это мешает тебе полноценно использовать его возможности. Полистай мануал по нему, может что интересное найдешь: http://php.net/manual/ru/book.pdo.php
Как минимум цикл с fetch бессмысленный - это можно сделать лучше.
Насчет статических методов и бессмысленных классов вроде Db::connect - избавляйся от них. Я знаю, такой код можно увидеть в других учебниках, но это лишь говорит о том что их авторы не осилившие ООП.
Вот я вижу у тебя эту строчку, написанную аж 2 раза:
> $creditBalance = ( $creditBalance $percent ) + $servicePayment - $monthlyPayment;
Ты ее взял очевидно из кода в учебнике. Но там специально дан неправильный код, и именно эта строчка неправильная, так что не надо было ее копировать. И все почему-то ее копируют, только потому что она там была в исходном коде, хотя я специально написал ее неправильно и копировать ее как раз не надо.
Лучше всего написать код самому.
Твой код потому неправильно работает и дает неправильный ответ, должно быть 61270.
Вот правильный алгоритм:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
>>690068
> // не могу придумать внятное имя
В линуксовой программе grep это называется context - думаю, хорошее название, даже по русски говорят "в каком контексте (=окружении) встречается это слово"
Вообще, контекст конечно можно еще реализовать по другому. У функции preg_match_all есть опция, которая при нахождении совпадения возвращает отступ от начала строки в байтах. Можно преобразовать этот отступ в число символов и взять N символов справа и слева. Но это сложно.
> .{0,{$offset}}\b\w[жш]ы\w*\b.
Вот сложновато, я бы просто написал .{0,$offset}[жш]ы.{0,$offset}
Так, в общем, хорошо сделано.
Вот я вижу у тебя эту строчку, написанную аж 2 раза:
> $creditBalance = ( $creditBalance $percent ) + $servicePayment - $monthlyPayment;
Ты ее взял очевидно из кода в учебнике. Но там специально дан неправильный код, и именно эта строчка неправильная, так что не надо было ее копировать. И все почему-то ее копируют, только потому что она там была в исходном коде, хотя я специально написал ее неправильно и копировать ее как раз не надо.
Лучше всего написать код самому.
Твой код потому неправильно работает и дает неправильный ответ, должно быть 61270.
Вот правильный алгоритм:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
>>690068
> // не могу придумать внятное имя
В линуксовой программе grep это называется context - думаю, хорошее название, даже по русски говорят "в каком контексте (=окружении) встречается это слово"
Вообще, контекст конечно можно еще реализовать по другому. У функции preg_match_all есть опция, которая при нахождении совпадения возвращает отступ от начала строки в байтах. Можно преобразовать этот отступ в число символов и взять N символов справа и слева. Но это сложно.
> .{0,{$offset}}\b\w[жш]ы\w*\b.
Вот сложновато, я бы просто написал .{0,$offset}[жш]ы.{0,$offset}
Так, в общем, хорошо сделано.
OSI это именно что теория, 7 уровней это не значит что в любом протоколе из ровно семь, то есть часть уровней может отсутствовать. Но польза в том что эта теория определяет названия для этих уровней, ну и вообще, позволяет разобрать почти любой протокол на уровни.
Вот в википедии написано:
> Назначение модели OSI состоит в обобщенном представлении средств сетевого взаимодействия. Она разрабатывалась в качестве своего рода универсального языка сетевых специалистов, именно поэтому её называют справочной моделью
> Так вот строение интернета и сетевые протоколы я как раз и не понимаю. Надеюсь на подробный ответ.
Есть пасты (возможно ты уже видел их):
http://pastebin.ru/dnO7PZfq
http://pastebin.ru/KO4E1mB4
Есть такие задания:
1) изучи команду tracert/traceroute. Возьми какой-нибудь сервер, например reddit.com, и определи через какие города и страны идут пакеты от тебя к нему. С помощью traceroute ты определяешь путь, а далее с помощью whois (например whois7.ru) определяешь местоположение узлов.
Попробуй сделать traceroute для узла bad.horse
Понимаешь ли ты алгоритм работы программе traceroute? Как она определяет путь?
2) посмотри что выведет команда ipconfig, route print, arp -a (если ты под windows) или ifconfig, route -n, ip route list, arp -a под линукс. Понимаешь ли ты что такое маска сети? Зачем она нужна? Шлюз по умолчанию? Зачем нужен ARP? Как компьютер получает сетевые настройки когда подсоединяется например к вайфай сети?
Как работает DHCP? Есть ли риски безопасности при использовании DHCP в публичной сети? Может ли сетевая карта иметь несколько IP адресов? Может ли компьютер иметь несколько IP адресов? Видит ли гугл твой MAC адрес когда ты заходишь на его сайт? Видит ли гугл IP адрес твоей сетевой карты? Зачем нужен NAT? Что такое "серые" IP? Легально ли их использование?
Как NAT понимает, кому в локальной сети передавать приходящие из интернета пакеты если они все адресованы одному и тому же IP? Какой у него алгоритм работы?
Зачем нужен маршрутизатор/роутер? Можно ли подсоединить к интернету больше 4 млрд устройств (то есть больше числа возможных Ipv4 адресов)? Чем Ipv6 оличается от IPv4? Работает ли у твоего провайдера IPv6? Правда ли что UDP лучше чем TCP и скоро заменит его?
Что такое автономная сеть (AS)?
Можешь ли ты кратко (кратко!) написать что происходит когда ты пытаешься соединиться с удаленным хостом, например через telnet google.com 80? Какие пакеты отправляются и что с ними происходит? Какие протоколы используются? Кратко.
3) соединись с каким-нибудь сайтом через telnet/netcat и отправь вручную GET запрос, если конечно ты раньше этого не делал. Команда выглядит примерно как cat request.txt | nc -vv google.com 80 или telnet google.com 80 < request.txt
4) далее, освой утилиту netcat, в линуксе она есть, для windows можно попробовать версию отсюда https://github.com/diegocr/netcat или отсюда https://eternallybored.org/misc/netcat/ или отсюда https://nmap.org/ncat/
В одной консоли открой любой порт на прослушивание, в другой консоли подсоединись к нему и перешли какую-нибудь строку.
5) освой программу wireshark (c ГУИ, кроссплатформенный) либо tcpdump (линукс, консольный). Изучи, какие пакеты принимает и отправляет твой компьютер. Позапускай разные программы и посмотри, что они шлют в интернет. Попробуй через telnet/netcat куда-нибудь соединиться и что-нибудь отправить, попробуй сделать ping или traceroute. Также, возможно ты увидишь широковещательный мусор который шлют твои соседи по сети провайдера (если только ты не за роутером).
В Wireshark ты видишь заголовки разных уровней: и заголовки протокола TCP, и IP, и Ethernet заголовки, в которые пакет завернут как луковица.
Если есть какие-то вопросы, уточняй.
OSI это именно что теория, 7 уровней это не значит что в любом протоколе из ровно семь, то есть часть уровней может отсутствовать. Но польза в том что эта теория определяет названия для этих уровней, ну и вообще, позволяет разобрать почти любой протокол на уровни.
Вот в википедии написано:
> Назначение модели OSI состоит в обобщенном представлении средств сетевого взаимодействия. Она разрабатывалась в качестве своего рода универсального языка сетевых специалистов, именно поэтому её называют справочной моделью
> Так вот строение интернета и сетевые протоколы я как раз и не понимаю. Надеюсь на подробный ответ.
Есть пасты (возможно ты уже видел их):
http://pastebin.ru/dnO7PZfq
http://pastebin.ru/KO4E1mB4
Есть такие задания:
1) изучи команду tracert/traceroute. Возьми какой-нибудь сервер, например reddit.com, и определи через какие города и страны идут пакеты от тебя к нему. С помощью traceroute ты определяешь путь, а далее с помощью whois (например whois7.ru) определяешь местоположение узлов.
Попробуй сделать traceroute для узла bad.horse
Понимаешь ли ты алгоритм работы программе traceroute? Как она определяет путь?
2) посмотри что выведет команда ipconfig, route print, arp -a (если ты под windows) или ifconfig, route -n, ip route list, arp -a под линукс. Понимаешь ли ты что такое маска сети? Зачем она нужна? Шлюз по умолчанию? Зачем нужен ARP? Как компьютер получает сетевые настройки когда подсоединяется например к вайфай сети?
Как работает DHCP? Есть ли риски безопасности при использовании DHCP в публичной сети? Может ли сетевая карта иметь несколько IP адресов? Может ли компьютер иметь несколько IP адресов? Видит ли гугл твой MAC адрес когда ты заходишь на его сайт? Видит ли гугл IP адрес твоей сетевой карты? Зачем нужен NAT? Что такое "серые" IP? Легально ли их использование?
Как NAT понимает, кому в локальной сети передавать приходящие из интернета пакеты если они все адресованы одному и тому же IP? Какой у него алгоритм работы?
Зачем нужен маршрутизатор/роутер? Можно ли подсоединить к интернету больше 4 млрд устройств (то есть больше числа возможных Ipv4 адресов)? Чем Ipv6 оличается от IPv4? Работает ли у твоего провайдера IPv6? Правда ли что UDP лучше чем TCP и скоро заменит его?
Что такое автономная сеть (AS)?
Можешь ли ты кратко (кратко!) написать что происходит когда ты пытаешься соединиться с удаленным хостом, например через telnet google.com 80? Какие пакеты отправляются и что с ними происходит? Какие протоколы используются? Кратко.
3) соединись с каким-нибудь сайтом через telnet/netcat и отправь вручную GET запрос, если конечно ты раньше этого не делал. Команда выглядит примерно как cat request.txt | nc -vv google.com 80 или telnet google.com 80 < request.txt
4) далее, освой утилиту netcat, в линуксе она есть, для windows можно попробовать версию отсюда https://github.com/diegocr/netcat или отсюда https://eternallybored.org/misc/netcat/ или отсюда https://nmap.org/ncat/
В одной консоли открой любой порт на прослушивание, в другой консоли подсоединись к нему и перешли какую-нибудь строку.
5) освой программу wireshark (c ГУИ, кроссплатформенный) либо tcpdump (линукс, консольный). Изучи, какие пакеты принимает и отправляет твой компьютер. Позапускай разные программы и посмотри, что они шлют в интернет. Попробуй через telnet/netcat куда-нибудь соединиться и что-нибудь отправить, попробуй сделать ping или traceroute. Также, возможно ты увидишь широковещательный мусор который шлют твои соседи по сети провайдера (если только ты не за роутером).
В Wireshark ты видишь заголовки разных уровней: и заголовки протокола TCP, и IP, и Ethernet заголовки, в которые пакет завернут как луковица.
Если есть какие-то вопросы, уточняй.
Собака уберет не только варнинги но и настоящие ошибки. Это не то что нам надо.
> Но ведь DOM тоже не имеет автомата для выреза такого шлака. Через DOM я могу только перебрать аттрибуты.
DOM дает удобное представление кода в виде дерева. Можно написать легкий и понятный алгоритм обхода этого дерева и его трансформации. Например, если я хочу добавить удаление атрибута, я могу написать просто
$node->removeAttribute('x');
Твой код не дает удобного представления. Малейшие изменения требуют анализа твоего конечного автомата, проектирования нового, тестирования. То есть из-за того что твой код не понятен и не нагляден, работа с ним требует больше времени. Это может и оправдано если ты перерабатываешь гигабайты кода, но мне кажется это не так.
Ну представь простое правило. Например, если после тега h1 идет div с классом .some-div, то надо добавить их общему родителю класс .has-h1-and-some-div. Или например запрет на размещение картинок внутри тега h1. В DOM это решается довольно простым и читаемым кодом, а что насчет твоего подхода? Рискнешь такое напсиать?
То есть DOM дает нам удобный способ работы с деревом. Ты пишешь, что что-то там неудобно - но скорее всего ты просто невнимательно изучил эту библиотеку. В сравнении с уровнем на котором работает твоя программа (уровень лексического анализа) - это небо и земля, это позволяет быстрее и проще писать код.
И код очистки тегов/атрибутов по списку, написанный на DOM, будет простым и лаконичным. Алгоритм там такой:
Загружаем HTML код в дерево
Обходим дерево, для каждого узла:
- если это запрещенный узел, удаляем его, оставляя содержимое
- если это разрешенный узел, обходим атрибуты, для каждого
-- есди это запрещенный атрибут, удаляем
-- если разрешенный, и содержит ссылку, проверяем ее формат
Выгружаем дерево в HTML
Вот посмотри на этот алгоритм. Это 2 цикла + 2 ифа. Там конечно будут вспомогательныей функции, но сам алгоритм элементарен. Я его написал не думая за полминуты. Твой алгоритм можно описать за полминуты? В этом сила ДОМа. Плюс, там есть XPath (а поверх него можно реализовать поиск по CSS селектору).
>>690373
На эту модель можно натягивать более высокоуровневые протоколы - например REST API, поверх HTTPS, который передает данные поверх SSL, работающем поверх TCP/IP. Для REST API транспорт это HTTPS.
Собака уберет не только варнинги но и настоящие ошибки. Это не то что нам надо.
> Но ведь DOM тоже не имеет автомата для выреза такого шлака. Через DOM я могу только перебрать аттрибуты.
DOM дает удобное представление кода в виде дерева. Можно написать легкий и понятный алгоритм обхода этого дерева и его трансформации. Например, если я хочу добавить удаление атрибута, я могу написать просто
$node->removeAttribute('x');
Твой код не дает удобного представления. Малейшие изменения требуют анализа твоего конечного автомата, проектирования нового, тестирования. То есть из-за того что твой код не понятен и не нагляден, работа с ним требует больше времени. Это может и оправдано если ты перерабатываешь гигабайты кода, но мне кажется это не так.
Ну представь простое правило. Например, если после тега h1 идет div с классом .some-div, то надо добавить их общему родителю класс .has-h1-and-some-div. Или например запрет на размещение картинок внутри тега h1. В DOM это решается довольно простым и читаемым кодом, а что насчет твоего подхода? Рискнешь такое напсиать?
То есть DOM дает нам удобный способ работы с деревом. Ты пишешь, что что-то там неудобно - но скорее всего ты просто невнимательно изучил эту библиотеку. В сравнении с уровнем на котором работает твоя программа (уровень лексического анализа) - это небо и земля, это позволяет быстрее и проще писать код.
И код очистки тегов/атрибутов по списку, написанный на DOM, будет простым и лаконичным. Алгоритм там такой:
Загружаем HTML код в дерево
Обходим дерево, для каждого узла:
- если это запрещенный узел, удаляем его, оставляя содержимое
- если это разрешенный узел, обходим атрибуты, для каждого
-- есди это запрещенный атрибут, удаляем
-- если разрешенный, и содержит ссылку, проверяем ее формат
Выгружаем дерево в HTML
Вот посмотри на этот алгоритм. Это 2 цикла + 2 ифа. Там конечно будут вспомогательныей функции, но сам алгоритм элементарен. Я его написал не думая за полминуты. Твой алгоритм можно описать за полминуты? В этом сила ДОМа. Плюс, там есть XPath (а поверх него можно реализовать поиск по CSS селектору).
>>690373
На эту модель можно натягивать более высокоуровневые протоколы - например REST API, поверх HTTPS, который передает данные поверх SSL, работающем поверх TCP/IP. Для REST API транспорт это HTTPS.
> От компа по кабелю бегут импульсы, коммутатор их считывает, читает мак адрес. Если такого хоста нет в коммутаторе, то он рассылает на все порты полученный фрейм и ищет нужный.
Тут есть 2 уровня: Ethernet и IP.
Ethernet - это технология связи небольшого числа близко расположенных компьютеров в локальную сеть. Мы ставим коммутатор, и кабелями втыкаем в него компьютеры (в древние времена коммутаторов не было, был просто один общий кабель, к которому подключались компьютеры). Теперь они могут пересылать друг другу пакеты по MAC адресу (это серийный номер сетевой карты, гарантированно разный у разных устройств). Принцип работы примерно такой:
- узел хочет отправить пакет. Он берет полезные данные, приписывает спереди к ним заголовки (формат пакета посмотри в википедии сам) и отправляет пакет в сеть. Этот пакет получают все сетевые карты, подсоединенные к ней, и они сравнивают адрес назначения со своим мак-адресом. Если совпадает - пакет принимается, и сетевая карта уведомляет процессор о его прибытии. Если нет- пакет отбрасывается
- также, есть специальный широковещательный адрес - пакет с таким адресом принимают все компьютеры
- также, сетевую карту можно перевести в отладочный (promiscious mode) режим и она будет ловить все пакеты
Теперь твоя очередь подумать и ответить на вопрос:
- чем ограничено число компьютеров в сегменте Ethernet и макс. расстояние между ними?
- что поменялось после замены общего кабеля на коммутатор? Я понимаю, что ты можешь не знать как он устроен, но подумай, каким преимущества у него могут быть?
Давным-давно были чистые Ethernet-сети (например сеть внутри компании), без других протоколов вроде IP, но сейчас конечно их никто в чистом виде не использует.
> вланы
Влан это просто имитация рздельных ethernet сетей программно. То есть пакеты идут по одному кабелю, но коммутатор фильтрует их, и не позволяет узлам из одного влана общаться с узлами из другого, создавая видимость что у нас 2 несвязанных отдельных сети. Все это делается прозрачно для узлов, они не могут никак проверить реально ли они изолированы или просто в отдельном влане.
Идем далее, на уровень IP. Протокол IP позволяет нам связать несколько сегментов Enternet в одну общую IP-сеть. В отличие от технологии Ethernet, число компьютеров в этой сети и расстояние между ними может быть большим -
например на нашей планете есть глобальная IP-сеть с миллиардом подключенных к ней устройств. Каждое напрямую подсоединенное устройство имеет уникальный IP адрес и любые 2 устройства могут обмениваться пакетами, указав адрес назначения. Адреса распределяет IANA и это гарантирует их уникальность.
Поскольку ethernet пакет не содержит полей для указания IP адреса, придуман Ip пакет, который вкладывается внутрь ethernet пакета. Почитай в википедии подробнее.
Формально Интернет - это объединение автономных сетей. Автономная сеть - это сеть, которая принадлежит одной организации. Например, сеть провайдера или сеть крупной компании. Организации договариваются об обмене трафиком и таким образом автономные сети объединяются в интернет. Интернет - это не телефонная сеть у которой есть центр и один владелец. Это объединение независимых сетей.
Сети связываются таким образом: между 2 или более соседними ethernet сегментами ставится маршрутизатор (роутер), имеющий 2 или более сетевых карты. Он позволяет пересылать пакеты между сетями. Маршрутизатор знает о соседних маршрутизаторах и знает куда надо переслать пакет в зависимости от его IP адреса. Более того, схема связей может перестраиваться - например при аварии в одном ethernet сегменте роутер может посылать пакеты через другие сегменты. За это отвечают протоколы вроде BGP.
Я выше написал что интернет - это огромная IP-сеть из множества узлов. Но вообще, кроме основной глобальной сети есть еще множество локальных IP-сетей - например внутренняя сеть провайдера. Это что-то вроде отдельного "интернета" в пределах города. В ней могут быть свои "серые" IP адреса, которые не имеют прямой связи с узлами в интернете. Локальная сеть может соединяться с глобальным интернетом через NAT, который позволяет внутренним узлам отправлять пакеты наружу.
Вопросы:
- опиши кратко алгоритм работы роутера сязывающего 2 сети
- есть ли у коммутатора IP адрес? У роутера?
- каким образом компьютер в IP сети узнает свой IP адрес?
- опиши что делает ОС когда программа просит ее отправить IP пакет с такими-то данными на такой-то IP адрес
- если в сегменте ethernet упадет маршрутизатор, связывающий его с другими сегментами, смогут ли узлы в этом сегменте пересылать пакеты друг другу?
- что если компьютер получает пакет в котором указан его мак-адрес, но не его IP? Или наоборот, его IP, но не его мак?
- что такое маска сети?
- что такое широковещательный IP адрес? В чем отличие от широковещательного мак адреса?
Ну и вопросы которые я написал выше.
> От компа по кабелю бегут импульсы, коммутатор их считывает, читает мак адрес. Если такого хоста нет в коммутаторе, то он рассылает на все порты полученный фрейм и ищет нужный.
Тут есть 2 уровня: Ethernet и IP.
Ethernet - это технология связи небольшого числа близко расположенных компьютеров в локальную сеть. Мы ставим коммутатор, и кабелями втыкаем в него компьютеры (в древние времена коммутаторов не было, был просто один общий кабель, к которому подключались компьютеры). Теперь они могут пересылать друг другу пакеты по MAC адресу (это серийный номер сетевой карты, гарантированно разный у разных устройств). Принцип работы примерно такой:
- узел хочет отправить пакет. Он берет полезные данные, приписывает спереди к ним заголовки (формат пакета посмотри в википедии сам) и отправляет пакет в сеть. Этот пакет получают все сетевые карты, подсоединенные к ней, и они сравнивают адрес назначения со своим мак-адресом. Если совпадает - пакет принимается, и сетевая карта уведомляет процессор о его прибытии. Если нет- пакет отбрасывается
- также, есть специальный широковещательный адрес - пакет с таким адресом принимают все компьютеры
- также, сетевую карту можно перевести в отладочный (promiscious mode) режим и она будет ловить все пакеты
Теперь твоя очередь подумать и ответить на вопрос:
- чем ограничено число компьютеров в сегменте Ethernet и макс. расстояние между ними?
- что поменялось после замены общего кабеля на коммутатор? Я понимаю, что ты можешь не знать как он устроен, но подумай, каким преимущества у него могут быть?
Давным-давно были чистые Ethernet-сети (например сеть внутри компании), без других протоколов вроде IP, но сейчас конечно их никто в чистом виде не использует.
> вланы
Влан это просто имитация рздельных ethernet сетей программно. То есть пакеты идут по одному кабелю, но коммутатор фильтрует их, и не позволяет узлам из одного влана общаться с узлами из другого, создавая видимость что у нас 2 несвязанных отдельных сети. Все это делается прозрачно для узлов, они не могут никак проверить реально ли они изолированы или просто в отдельном влане.
Идем далее, на уровень IP. Протокол IP позволяет нам связать несколько сегментов Enternet в одну общую IP-сеть. В отличие от технологии Ethernet, число компьютеров в этой сети и расстояние между ними может быть большим -
например на нашей планете есть глобальная IP-сеть с миллиардом подключенных к ней устройств. Каждое напрямую подсоединенное устройство имеет уникальный IP адрес и любые 2 устройства могут обмениваться пакетами, указав адрес назначения. Адреса распределяет IANA и это гарантирует их уникальность.
Поскольку ethernet пакет не содержит полей для указания IP адреса, придуман Ip пакет, который вкладывается внутрь ethernet пакета. Почитай в википедии подробнее.
Формально Интернет - это объединение автономных сетей. Автономная сеть - это сеть, которая принадлежит одной организации. Например, сеть провайдера или сеть крупной компании. Организации договариваются об обмене трафиком и таким образом автономные сети объединяются в интернет. Интернет - это не телефонная сеть у которой есть центр и один владелец. Это объединение независимых сетей.
Сети связываются таким образом: между 2 или более соседними ethernet сегментами ставится маршрутизатор (роутер), имеющий 2 или более сетевых карты. Он позволяет пересылать пакеты между сетями. Маршрутизатор знает о соседних маршрутизаторах и знает куда надо переслать пакет в зависимости от его IP адреса. Более того, схема связей может перестраиваться - например при аварии в одном ethernet сегменте роутер может посылать пакеты через другие сегменты. За это отвечают протоколы вроде BGP.
Я выше написал что интернет - это огромная IP-сеть из множества узлов. Но вообще, кроме основной глобальной сети есть еще множество локальных IP-сетей - например внутренняя сеть провайдера. Это что-то вроде отдельного "интернета" в пределах города. В ней могут быть свои "серые" IP адреса, которые не имеют прямой связи с узлами в интернете. Локальная сеть может соединяться с глобальным интернетом через NAT, который позволяет внутренним узлам отправлять пакеты наружу.
Вопросы:
- опиши кратко алгоритм работы роутера сязывающего 2 сети
- есть ли у коммутатора IP адрес? У роутера?
- каким образом компьютер в IP сети узнает свой IP адрес?
- опиши что делает ОС когда программа просит ее отправить IP пакет с такими-то данными на такой-то IP адрес
- если в сегменте ethernet упадет маршрутизатор, связывающий его с другими сегментами, смогут ли узлы в этом сегменте пересылать пакеты друг другу?
- что если компьютер получает пакет в котором указан его мак-адрес, но не его IP? Или наоборот, его IP, но не его мак?
- что такое маска сети?
- что такое широковещательный IP адрес? В чем отличие от широковещательного мак адреса?
Ну и вопросы которые я написал выше.
4.1 https://ideone.com/qUpQUI
5.1 http://ideone.com/sMgDgr
5.2 http://ideone.com/OEDO0b
5.3 http://ideone.com/LKM2eh
5.4 http://ideone.com/sw6DJA
5.5 http://ideone.com/SUvW2G
5.6 https://ideone.com/nYMiVc
http://ideone.com/O8hBUP - шифровка\дешифровка
http://ideone.com/kG9U2m - полиндром ( но он не правильно сделан, не могу понять где ошибка)
Довольно сложно с нуля вкатываться, но очень интересно :3
Все думал, почему же не работает. Только перечитав дошло, что в отличие от JS функции в PHP не видят внешних переменных.
Как раз только что осилятор казалось бы элементарной задачи нерешаемой без уродского костыля
Покажите лайтовый примерчик , что бы я понимал , что да как.
Есть у меня допустим таблица новостей , а в ней поле category,
и как мне сделать что бы category зависело допустим от другой таблички , и я сюда бы просто подставлял 1/2/3/4/ , а оно брало инфу из другой таблицы?
Ты все решишь, няш :3
Еще один ОЙ ПОГЛАДЬТЕ ПО ГОЛОВКЕ, СКАЖИТЕ ЧТО ВСЕ ХОРОШО И Я НИКАКОЙ НЕ ГЛУПЕНЬКИЙ(((
да я тупой блять. я не понимаю все равно. мне бы примерчик лайтовый , было бы найсово.
Забагованная же прога. Даже в этом треде 100500 раз упоминалось что некоторые вещи только из-за него и не работают. При этом есть хайп, есть рекомендации от хороших лекторов...
>Забагованная же прога.
Приведи пример.
Я вспоминаю только баги с встроенным пхп-сервером, но тебе ничего не мешает взять и поставить отдельный LAMP-стэк и деплоить свои приложения туда.
Пхпшторм очень мощная ИДЕ в которой есть интеграция практически со всеми фреймворками разного назначения, начиная от PHPUnit, заканчивая устаревшими версиями какого-нибудь Codeigniter. Ну и так как это ИДЕ, там присутствуют многие другие функции которых ты не найдешь в обычном текстовом редакторе.
А вообще это дело вкуса, мне например удобнее писать в редакторе, деплоить, тестировать и дебажить отдельными средствами.
Привет, оп, посмотри студентов.
https://github.com/greenTea242/Student-list
То, что я переделал и какие у меня вопросы:
Fixview у меня теперь без htmlspecialchars, я его записываю вручную на выходе, поэтому на входе эту функцию оставляю.
> Также функция подсветки должна правильно делать htmlspecialchars, чтобы символы вроде & или < в HTML коде выводились корректно.
Как сделать так чтобы htmlspecialchars не съел тег <mark>? Я пропускаю два значения через функцию paintFound заранее, а только потом его вставляю. Правильно?
Пикрелейтед 1.
Пришлось поставить public свойства вместо private, потому что в последнем случае (private свойства) при добавлении модели и превращении ее в массив в ключи влезает имя класса, что вызывает у pdo ошибки. Могут ли свойства быть public или таки неправильно?
https://github.com/greenTea242/Student-list/blob/master/public/register.php#L45
if($cookie) - оставляю, так как иниициализация произойдет, если будет удовлетворено еще одно условие $validator->isAbiturientIDExist($_COOKIE["abiturientID"]). Новый метод который проверяет наличие данного куки в бд.
Добавил удаление лишнего пробела для строки запроса из двух слов вида "Иван Иванов". Так же смог конкатировать несколько столбцов по совету анона из прошлого треда и теперь тот самый иван иванов у меня находится и обводится(появился explode в ViewHelper::paintFound. Обводится Иван Иван(конец обводки)ов.
> require_once "../autoload.php";
> require_once "../src/config.php";
> require_once "../src/ini.php";
> Мне кажется хватило бы одного реквайра.
Первые два рекваера делаются в последнем.
Переделал регулярку на имена чтобы новая возможность функции fix_view убирать лишние пробелы использовалась не только в поисковых запросах. Т.е. при регистрации имени ПробелПробелИван валидация пройдет в отличии от прошлого кода, эти два пробела сами уберутся.
> Проще сделать наверно через min/max. Или сделать функцию исправления числа страниц, которая проверит что она принимает разрешенные знаечния.
Перенес условие как метод в pager.
Остальные советы тоже постарался сделать, просто не все расписал. Боюсь неправильно исключения сделал, хотя вроде работает.
Привет, оп, посмотри студентов.
https://github.com/greenTea242/Student-list
То, что я переделал и какие у меня вопросы:
Fixview у меня теперь без htmlspecialchars, я его записываю вручную на выходе, поэтому на входе эту функцию оставляю.
> Также функция подсветки должна правильно делать htmlspecialchars, чтобы символы вроде & или < в HTML коде выводились корректно.
Как сделать так чтобы htmlspecialchars не съел тег <mark>? Я пропускаю два значения через функцию paintFound заранее, а только потом его вставляю. Правильно?
Пикрелейтед 1.
Пришлось поставить public свойства вместо private, потому что в последнем случае (private свойства) при добавлении модели и превращении ее в массив в ключи влезает имя класса, что вызывает у pdo ошибки. Могут ли свойства быть public или таки неправильно?
https://github.com/greenTea242/Student-list/blob/master/public/register.php#L45
if($cookie) - оставляю, так как иниициализация произойдет, если будет удовлетворено еще одно условие $validator->isAbiturientIDExist($_COOKIE["abiturientID"]). Новый метод который проверяет наличие данного куки в бд.
Добавил удаление лишнего пробела для строки запроса из двух слов вида "Иван Иванов". Так же смог конкатировать несколько столбцов по совету анона из прошлого треда и теперь тот самый иван иванов у меня находится и обводится(появился explode в ViewHelper::paintFound. Обводится Иван Иван(конец обводки)ов.
> require_once "../autoload.php";
> require_once "../src/config.php";
> require_once "../src/ini.php";
> Мне кажется хватило бы одного реквайра.
Первые два рекваера делаются в последнем.
Переделал регулярку на имена чтобы новая возможность функции fix_view убирать лишние пробелы использовалась не только в поисковых запросах. Т.е. при регистрации имени ПробелПробелИван валидация пройдет в отличии от прошлого кода, эти два пробела сами уберутся.
> Проще сделать наверно через min/max. Или сделать функцию исправления числа страниц, которая проверит что она принимает разрешенные знаечния.
Перенес условие как метод в pager.
Остальные советы тоже постарался сделать, просто не все расписал. Боюсь неправильно исключения сделал, хотя вроде работает.
Ты ведь не в голове решал - показывай код, поможем разобраться. Эту задачу многие не могут решить с первого раза. Неделя над ней, когда идёшь с нуля, - это норма.
А как пересчитать количество всех совпадений не по строкам, а по буквам?
input
Петушок
Порошок
out
шок (2)
п (2)
о (1)
...
<!DOCTYPE html>
<head>
<link href="style.css" rel='stylesheet' type='text/css'/>
<title>GuestBook</title>
<meta charset="UTF-8">
</head>
<body>
Открой дебаггер в хроме и посмотри куда указывает ссылка. Если браузер что-то не может загрузить, ошибка вместе с ссылкой будет в консоли. От этого уже сможешь понять что у тебя не так, и указать абсолютный путь, если нужно.
Использовать __DIR__ в HTML неправильно, наверное. В случае с слимом лучше указать абсолютный путь от корня сайта, например:
<link href="/GuestBook/views/style.css" rel='stylesheet' type='text/css'/>
Будет сформировано как
http://localhost/GuestBook/views/style.css
И еще, рекомендую почитать урок ОПа про структуру URL
https://github.com/codedokode/pasta/blob/master/network/urls.md
А вообще я понял, дело в том, что там виджет (форма логина через фб) автоматом ставит хедер со стилями и его уже не перепишешь.
Да там из-за фейсбука хедер другой просто.
>>693124
> каждая подключеннная к сети сетевая карта имеет уникальный IP адрес
Уникальный ли? Я уже встречал такое, что файлообменник ругался на то, что с моего айпишника уже качали и надо подождать.
> это серийный номер сетевой карты, гарантированно разный у разных устройств
Как раз читал, что теоретически - да, но практически бывали случаи совпадения.
> Понимаешь ли ты алгоритм работы программе traceroute? Как она определяет путь?
traceroute посылает ICMP-пакеты на близжайший маршрутизатор со значением "время жизни" равному 1. Далее маршрутизатор отправляет обратно ответ, что "время жизни" пакета истекло, и он не в состоянии отправить его дальше. Таким образом traceroute увеличивает каждый раз "время жизни" пакет на 1, и соответственно пакет достигает более дальнего маршрутизатора. Пакет достигает конечного хоста, при этом в ICMP-пакете указан заведомо несуществующий порт, поэтому хост отдает ответ, что порт не доступен. По такому сообщению traceroute и узнает об окончании трассировки. Все верно я понял?
> посмотри что выведет команда ipconfig, route print, arp -a (если ты под windows) или ifconfig, route -n, ip route list, arp -a под линукс
ifconfig выводит мои сетевые интерфейсы, один из которых так называемый loopback. Я правда не совсем понимаю, доходит ли пакет до маршрузитора, когда я отправляю пакет по адресу 127.0.0.1. В теоретической части я читал, что если пакет адресата содержит тот же мак-адрес, то маршрутизатор его отбрасывает. Считается, что данная информация (в пакете) уже известна хосту.
route -n что-то не то выдает. У меня внутренний ip адрес своей сети, который у каждого офиса в здании свой. В gateway адрес маршрутизатора, куда отправляются пакеты. А route -n выводит Destination 0.0.0.0 почему-то, но Gateway кстати верный.
А вот ip route list как раз все верно выводит, gateway и мой внутренний ip.
arp -a указывает куда я как раз шлю пакеты.
> маска сети
Маска сети помогает найти границы подсети. Не помню как вычисляется. Вроде логическим умножением.
> Шлюз по умолчанию?
А шлюз это же gateway? Куда все офисное здание шлет пакеты. Свитч?
> Зачем нужен ARP?
Сейчас в википедии прочитал. Так это как раз то, о чем я и писал. Если адресат еще неизвестен в коммутаторе, то он отправляет широковещательный запрос на все порты, и ему откликается тот новый хост, передавая мак адрес. Теперь у коммутатора получается полная таблица соответствия мак адресов, айпишников и портов, ну и вланов вроде. Больше коммутатору не нужно будет отправлять широковещательный запрос.
> Как компьютер получает сетевые настройки когда подсоединяется например к вайфай сети?
Вот этого я не знаю. Компьютер наверное отправит пару пакетов, получит ответы и готово.
> Как работает DHCP?
DHCP-сервер это провайдер? При подключении кабеля, он мне автоматически отправляет ip, dns сервер, шлюз?
> Есть ли риски безопасности при использовании DHCP в публичной сети?
Вот этого я не нашел, но логически понятно, что можно перехватить настройки, и как этим воспользоваться, наверное.
> Может ли сетевая карта иметь несколько IP адресов?
Наверное нет.
> Может ли компьютер иметь несколько IP адресов?
Компьютер да. Изначально уже есть 2 IP-адреса. Локальный и публичный.
> Видит ли гугл твой MAC адрес когда ты заходишь на его сайт?
Нет, потому что на канальном уровне заголовок с MAC-адресом перезаписывается на IP.
> Видит ли гугл IP адрес твоей сетевой карты?
Да, виден. А нет, может и нет. Прочитал следующий вопрос. Прочитал про NAT. Теперь да, смотря как компьютер подключен к сети, через NAT или нет.
> Зачем нужен NAT?
Наверное потому что публичных айпишников ограниченное количество. И теперь понятно почему на некоторых файлообменниках мне писали, что с такого айпишник уже качали и нужно подождать.
> Что такое "серые" IP? Легально ли их использование?
Ну вот как раз айпишники, которые за NAT. И да, более чем легально, я полагаю.
> Как NAT понимает, кому в локальной сети передавать приходящие из интернета пакеты если они все адресованы одному и тому же IP? Какой у него алгоритм работы?
Когда роутер принимает пакет, то он на лету меняется IP-адрес отправителя на свой, а также записывает номер порта, чтобы различать присланные пакеты от разных компьтеров. Когда принимает ответный пакет из интернета, то меняет свой IP-адрес на адрес твоего компьютера. Вся эта информация содержится в некой таблице, базе данных, запись в которой стирается после закрытия соединения.
А влияет ли это на скорость, ОП?
> Зачем нужен маршрутизатор/роутер?
Чтобы соединять сегменты сети друг с другом? Посылая запрос, например, гугл, пакеты проходят через огромное множество маршрутизаторов, пока не дойдут до пункта назначения.
> Можно ли подсоединить к интернету больше 4 млрд устройств (то есть больше числа возможных Ipv4 адресов)?
Ну да, для этого и используют NAT.
> Чем Ipv6 оличается от IPv4?
Количеством цифр в адресе?
> Работает ли у твоего провайдера IPv6?
Да.
> Правда ли что UDP лучше чем TCP и скоро заменит его?
Лучше в плане скорости, но UDP не отвечает за надежность доставки пакетов.
ОП, я что-то тогда не понимаю. У нас все офисное здание за NAT. Так вот google как то умудряется забанить только один компьютер за спам. С помощью кук получается?
> Что такое автономная сеть (AS)?
Это какие то централизованные организации, которые предоставляют доступ к интернету провайдерам? Они же вроде и айпишники выдают.
> Можешь ли ты кратко (кратко!) написать что происходит когда ты пытаешься соединиться с удаленным хостом, например через telnet google.com 80?
Отправляю пакеты на шлюз, тот меняет мой айпишник на свой. Отправляет на следующий маршрутизатор, и так до пункта назначения и обратно.
> В одной консоли открой любой порт на прослушивание, в другой консоли подсоединись к нему и перешли какую-нибудь строку.
Забавно, я в локалке чатик создал.
> Также, возможно ты увидишь широковещательный мусор который шлют твои соседи по сети провайдера (если только ты не за роутером).
Да-да, постоянно какие то пакеты идут.
Завтра остальное.
>>693124
> каждая подключеннная к сети сетевая карта имеет уникальный IP адрес
Уникальный ли? Я уже встречал такое, что файлообменник ругался на то, что с моего айпишника уже качали и надо подождать.
> это серийный номер сетевой карты, гарантированно разный у разных устройств
Как раз читал, что теоретически - да, но практически бывали случаи совпадения.
> Понимаешь ли ты алгоритм работы программе traceroute? Как она определяет путь?
traceroute посылает ICMP-пакеты на близжайший маршрутизатор со значением "время жизни" равному 1. Далее маршрутизатор отправляет обратно ответ, что "время жизни" пакета истекло, и он не в состоянии отправить его дальше. Таким образом traceroute увеличивает каждый раз "время жизни" пакет на 1, и соответственно пакет достигает более дальнего маршрутизатора. Пакет достигает конечного хоста, при этом в ICMP-пакете указан заведомо несуществующий порт, поэтому хост отдает ответ, что порт не доступен. По такому сообщению traceroute и узнает об окончании трассировки. Все верно я понял?
> посмотри что выведет команда ipconfig, route print, arp -a (если ты под windows) или ifconfig, route -n, ip route list, arp -a под линукс
ifconfig выводит мои сетевые интерфейсы, один из которых так называемый loopback. Я правда не совсем понимаю, доходит ли пакет до маршрузитора, когда я отправляю пакет по адресу 127.0.0.1. В теоретической части я читал, что если пакет адресата содержит тот же мак-адрес, то маршрутизатор его отбрасывает. Считается, что данная информация (в пакете) уже известна хосту.
route -n что-то не то выдает. У меня внутренний ip адрес своей сети, который у каждого офиса в здании свой. В gateway адрес маршрутизатора, куда отправляются пакеты. А route -n выводит Destination 0.0.0.0 почему-то, но Gateway кстати верный.
А вот ip route list как раз все верно выводит, gateway и мой внутренний ip.
arp -a указывает куда я как раз шлю пакеты.
> маска сети
Маска сети помогает найти границы подсети. Не помню как вычисляется. Вроде логическим умножением.
> Шлюз по умолчанию?
А шлюз это же gateway? Куда все офисное здание шлет пакеты. Свитч?
> Зачем нужен ARP?
Сейчас в википедии прочитал. Так это как раз то, о чем я и писал. Если адресат еще неизвестен в коммутаторе, то он отправляет широковещательный запрос на все порты, и ему откликается тот новый хост, передавая мак адрес. Теперь у коммутатора получается полная таблица соответствия мак адресов, айпишников и портов, ну и вланов вроде. Больше коммутатору не нужно будет отправлять широковещательный запрос.
> Как компьютер получает сетевые настройки когда подсоединяется например к вайфай сети?
Вот этого я не знаю. Компьютер наверное отправит пару пакетов, получит ответы и готово.
> Как работает DHCP?
DHCP-сервер это провайдер? При подключении кабеля, он мне автоматически отправляет ip, dns сервер, шлюз?
> Есть ли риски безопасности при использовании DHCP в публичной сети?
Вот этого я не нашел, но логически понятно, что можно перехватить настройки, и как этим воспользоваться, наверное.
> Может ли сетевая карта иметь несколько IP адресов?
Наверное нет.
> Может ли компьютер иметь несколько IP адресов?
Компьютер да. Изначально уже есть 2 IP-адреса. Локальный и публичный.
> Видит ли гугл твой MAC адрес когда ты заходишь на его сайт?
Нет, потому что на канальном уровне заголовок с MAC-адресом перезаписывается на IP.
> Видит ли гугл IP адрес твоей сетевой карты?
Да, виден. А нет, может и нет. Прочитал следующий вопрос. Прочитал про NAT. Теперь да, смотря как компьютер подключен к сети, через NAT или нет.
> Зачем нужен NAT?
Наверное потому что публичных айпишников ограниченное количество. И теперь понятно почему на некоторых файлообменниках мне писали, что с такого айпишник уже качали и нужно подождать.
> Что такое "серые" IP? Легально ли их использование?
Ну вот как раз айпишники, которые за NAT. И да, более чем легально, я полагаю.
> Как NAT понимает, кому в локальной сети передавать приходящие из интернета пакеты если они все адресованы одному и тому же IP? Какой у него алгоритм работы?
Когда роутер принимает пакет, то он на лету меняется IP-адрес отправителя на свой, а также записывает номер порта, чтобы различать присланные пакеты от разных компьтеров. Когда принимает ответный пакет из интернета, то меняет свой IP-адрес на адрес твоего компьютера. Вся эта информация содержится в некой таблице, базе данных, запись в которой стирается после закрытия соединения.
А влияет ли это на скорость, ОП?
> Зачем нужен маршрутизатор/роутер?
Чтобы соединять сегменты сети друг с другом? Посылая запрос, например, гугл, пакеты проходят через огромное множество маршрутизаторов, пока не дойдут до пункта назначения.
> Можно ли подсоединить к интернету больше 4 млрд устройств (то есть больше числа возможных Ipv4 адресов)?
Ну да, для этого и используют NAT.
> Чем Ipv6 оличается от IPv4?
Количеством цифр в адресе?
> Работает ли у твоего провайдера IPv6?
Да.
> Правда ли что UDP лучше чем TCP и скоро заменит его?
Лучше в плане скорости, но UDP не отвечает за надежность доставки пакетов.
ОП, я что-то тогда не понимаю. У нас все офисное здание за NAT. Так вот google как то умудряется забанить только один компьютер за спам. С помощью кук получается?
> Что такое автономная сеть (AS)?
Это какие то централизованные организации, которые предоставляют доступ к интернету провайдерам? Они же вроде и айпишники выдают.
> Можешь ли ты кратко (кратко!) написать что происходит когда ты пытаешься соединиться с удаленным хостом, например через telnet google.com 80?
Отправляю пакеты на шлюз, тот меняет мой айпишник на свой. Отправляет на следующий маршрутизатор, и так до пункта назначения и обратно.
> В одной консоли открой любой порт на прослушивание, в другой консоли подсоединись к нему и перешли какую-нибудь строку.
Забавно, я в локалке чатик создал.
> Также, возможно ты увидишь широковещательный мусор который шлют твои соседи по сети провайдера (если только ты не за роутером).
Да-да, постоянно какие то пакеты идут.
Завтра остальное.
Создаю тест с вопросами/ответами/баллами/нужное вставить, делаю это все через формы. Нужна помощь анона в таком вопросе: вот хочу чтобы каждый вопрос выводился последовательно после предыдущего или в зависимости от данного ответа, знаю что нужно использовать js/jquery и хочу ознакомиться, но функций там очень много, потому прошу твоей помощи.
> Уникальный ли? Я уже встречал такое, что файлообменник ругался на то, что с моего айпишника уже качали и надо подождать.
Это не твой айпишник, а айпишник твоего провайдера со всеми пользователями.
Это ты не изучил NAT. Если бы у нас была единая глобальная сеть - НАТ был бы не нужен и проблемы с фалообменником не было. Но большинство провайдеров подключают пользователей не напрямую в интернет, а в свою локальную сеть, которая соединена с интернетом через NAT, но не является его частью. Если смотреть снаружи - то весь ваш провайдер виден как 1 или несколько узлов, а локальная сеть и все ее пользоватеои не видны. То есть тут мы имеем 2 независимых IP-сети, связанных шлюзом с NAT.
> Как раз читал, что теоретически - да, но практически бывали случаи совпадения.
По идее не должны быть, если пользователь не переопределяет мак адрес вручную. Наверно дело в этом. Ну или производитель безответственный - китаец какой-нибудь, который не получил префикс, а использует чужие адреса. Использование компонентов от хороших производителей решает эту проблему.
> Все верно я понял?
Да, но тут есть ошибка:
> Пакет достигает конечного хоста, при этом в ICMP-пакете указан заведомо несуществующий порт
В ICMP пакетах нет номера порта. Он посылает TCP пакет.
https://ru.wikipedia.org/wiki/ICMP
> Я правда не совсем понимаю, доходит ли пакет до маршрузитора, когда я отправляю пакет по адресу 127.0.0.1
Нет, пакет отправляенный на адрес интерфейса не идет через другие интерфейсы, а передается напрямую. Аналогично ты можешь отправить пакет на IP своей сетевой карты, и он тоже не покинет компьютер.
> arp -a указывает куда я как раз шлю пакеты.
Вообще-то это кеш ARP запросов. Почитай что это такое.
> Маска сети помогает найти границы подсети.
Зачем это нужно? Выглядит как ненужное усложнение.
> А шлюз это же gateway? Куда все офисное здание шлет пакеты. Свитч?
Это узел имеющий соединение более чем с одним сегментом ethernet и умеющий передавать пакет между сегментами.
Логика тут простая:
- если цель находится на твоем же компьютере, пакет передатся ей
- если цель в той же подсети что и ты, пакет шлется ей напрямую на ее мак адрес.
- если нет, то пакет шлется на мак-адрес шлюза. Потому и важно знать кто является шлюзом.
Эти правила описаны в таблице роутинга. которую выводит ip route list. Если у узла больше 1 сетевой карты, правила чуть усложняются. Также, в этом случае можно включить в ОС настройку, делающую твой компьютер роутером, или наоборот, отключающую эту возможность.
Как узел узнает мак-адрес другого узла - узнай самостоятельно.
> Уникальный ли? Я уже встречал такое, что файлообменник ругался на то, что с моего айпишника уже качали и надо подождать.
Это не твой айпишник, а айпишник твоего провайдера со всеми пользователями.
Это ты не изучил NAT. Если бы у нас была единая глобальная сеть - НАТ был бы не нужен и проблемы с фалообменником не было. Но большинство провайдеров подключают пользователей не напрямую в интернет, а в свою локальную сеть, которая соединена с интернетом через NAT, но не является его частью. Если смотреть снаружи - то весь ваш провайдер виден как 1 или несколько узлов, а локальная сеть и все ее пользоватеои не видны. То есть тут мы имеем 2 независимых IP-сети, связанных шлюзом с NAT.
> Как раз читал, что теоретически - да, но практически бывали случаи совпадения.
По идее не должны быть, если пользователь не переопределяет мак адрес вручную. Наверно дело в этом. Ну или производитель безответственный - китаец какой-нибудь, который не получил префикс, а использует чужие адреса. Использование компонентов от хороших производителей решает эту проблему.
> Все верно я понял?
Да, но тут есть ошибка:
> Пакет достигает конечного хоста, при этом в ICMP-пакете указан заведомо несуществующий порт
В ICMP пакетах нет номера порта. Он посылает TCP пакет.
https://ru.wikipedia.org/wiki/ICMP
> Я правда не совсем понимаю, доходит ли пакет до маршрузитора, когда я отправляю пакет по адресу 127.0.0.1
Нет, пакет отправляенный на адрес интерфейса не идет через другие интерфейсы, а передается напрямую. Аналогично ты можешь отправить пакет на IP своей сетевой карты, и он тоже не покинет компьютер.
> arp -a указывает куда я как раз шлю пакеты.
Вообще-то это кеш ARP запросов. Почитай что это такое.
> Маска сети помогает найти границы подсети.
Зачем это нужно? Выглядит как ненужное усложнение.
> А шлюз это же gateway? Куда все офисное здание шлет пакеты. Свитч?
Это узел имеющий соединение более чем с одним сегментом ethernet и умеющий передавать пакет между сегментами.
Логика тут простая:
- если цель находится на твоем же компьютере, пакет передатся ей
- если цель в той же подсети что и ты, пакет шлется ей напрямую на ее мак адрес.
- если нет, то пакет шлется на мак-адрес шлюза. Потому и важно знать кто является шлюзом.
Эти правила описаны в таблице роутинга. которую выводит ip route list. Если у узла больше 1 сетевой карты, правила чуть усложняются. Также, в этом случае можно включить в ОС настройку, делающую твой компьютер роутером, или наоборот, отключающую эту возможность.
Как узел узнает мак-адрес другого узла - узнай самостоятельно.
> Если адресат еще неизвестен в коммутаторе, то он отправляет широковещательный запрос на все порты, и ему откликается тот новый хост, передавая мак адрес
Нет, все неправильно. ARP это протокол, который позволяет узлу получить по IP мак-адрес своего собрата находящегося в том же сегменте. Исплоьзуется отправка пакета на широковещательный мак-адрес (ff:ff:ff:ff:ff:ff по моему). То есть выглядит это так:
10.0.0.2 - всем: who-has IP 10.0.0.3 ?
10.0.0.3 - 10.0.0.2: это я
Из ответа первый узел узнает мак второго. Все это работает только внутри одного сегмента езернет.
То что ты написал про коммутатор не имеет отношения. Там описано другое. процесс обучения, в ходе которого коммутатор запоминает мак адреса подсоединенных узлов, чтобы пересылать пакет только в нужный порт, а не всем. Это повышает пропускную способность сети, подумай почему. Заметь что это не гарантирует безопасность так как узел всегда может посылать пакеты от имени другого. Как и в старые добрые времена когда был кабель вместо коммутатора.
>> Как компьютер получает сетевые настройки > когда подсоединяется например к вайфай сети?
Вот этого я не знаю. Компьютер наверное отправит пару пакетов, получит ответы и готово.
Также как и в случае с любой сетью, не только вайфай, есть 2 варианта:
- ручная конфигурация адинистратором (самый надежный способ но не всегда удобен)
- получение настроек через DHCP (почитай)
DHCP-сервер это программа, слушающая определенные типы широковещательных запросов. Узел может отправить широковещательный запрос с просьбой о выделении ип адреса и настроек сети, и DHCP сервер ему выдает в аренду на время адрес и сообщает настройки сети. Почитай про этот протокол и ответь на вопрос:
- если есть сеть где компьютеры используют DHCP, и в ней есть злоумышленник, может ли он перехватывать чужой трафик? Как можно с этим бороться?
> DHCP-сервер это провайдер? При подключении кабеля, он мне автоматически отправляет ip, dns сервер, шлюз?
нет, это программа. Запущенная возможно на оборуовании провайдера.
> > Есть ли риски безопасности при использовании DHCP в публичной сети?
> Вот этого я не нашел, но логически понятно, что можно перехватить настройки, и как этим воспользоваться, наверное.
Нет риска в перехвате настроек. ЧТо с того что ты узнаешь маску сети, адрес шлюза и днс сервера если ты и так в этой сети? Я говорю про другие риски.Изучи протокол DHCP и поищи уязвимые места.
> > Может ли сетевая карта иметь несколько IP адресов?
> Наверное нет.
Вообще может. Почему нет?
http://blog.evgenmed.com/2010/05/ip-ip.html
https://moonback.ru/page/2ip-linux
при этом в системе это может выглядеть как несколько виртуальных сетевых карт.
При желании можно наверно сделать и карту с несколькими мак-адресами, как бы имитирующую несколько отдельных, но я не знаю, будет ли коммутатор с такой работать - наверно, нет.
http://serverfault.com/questions/223601/multiple-mac-addresses-on-one-physical-network-interface-linux
Еще есть такие вещи, как бриджи - когда 2 сетевых карты как бы объединяют 2 сегмента езернет в один, пересылая пакеты между ними - https://ru.wikipedia.org/wiki/Сетевой_мост
> Если адресат еще неизвестен в коммутаторе, то он отправляет широковещательный запрос на все порты, и ему откликается тот новый хост, передавая мак адрес
Нет, все неправильно. ARP это протокол, который позволяет узлу получить по IP мак-адрес своего собрата находящегося в том же сегменте. Исплоьзуется отправка пакета на широковещательный мак-адрес (ff:ff:ff:ff:ff:ff по моему). То есть выглядит это так:
10.0.0.2 - всем: who-has IP 10.0.0.3 ?
10.0.0.3 - 10.0.0.2: это я
Из ответа первый узел узнает мак второго. Все это работает только внутри одного сегмента езернет.
То что ты написал про коммутатор не имеет отношения. Там описано другое. процесс обучения, в ходе которого коммутатор запоминает мак адреса подсоединенных узлов, чтобы пересылать пакет только в нужный порт, а не всем. Это повышает пропускную способность сети, подумай почему. Заметь что это не гарантирует безопасность так как узел всегда может посылать пакеты от имени другого. Как и в старые добрые времена когда был кабель вместо коммутатора.
>> Как компьютер получает сетевые настройки > когда подсоединяется например к вайфай сети?
Вот этого я не знаю. Компьютер наверное отправит пару пакетов, получит ответы и готово.
Также как и в случае с любой сетью, не только вайфай, есть 2 варианта:
- ручная конфигурация адинистратором (самый надежный способ но не всегда удобен)
- получение настроек через DHCP (почитай)
DHCP-сервер это программа, слушающая определенные типы широковещательных запросов. Узел может отправить широковещательный запрос с просьбой о выделении ип адреса и настроек сети, и DHCP сервер ему выдает в аренду на время адрес и сообщает настройки сети. Почитай про этот протокол и ответь на вопрос:
- если есть сеть где компьютеры используют DHCP, и в ней есть злоумышленник, может ли он перехватывать чужой трафик? Как можно с этим бороться?
> DHCP-сервер это провайдер? При подключении кабеля, он мне автоматически отправляет ip, dns сервер, шлюз?
нет, это программа. Запущенная возможно на оборуовании провайдера.
> > Есть ли риски безопасности при использовании DHCP в публичной сети?
> Вот этого я не нашел, но логически понятно, что можно перехватить настройки, и как этим воспользоваться, наверное.
Нет риска в перехвате настроек. ЧТо с того что ты узнаешь маску сети, адрес шлюза и днс сервера если ты и так в этой сети? Я говорю про другие риски.Изучи протокол DHCP и поищи уязвимые места.
> > Может ли сетевая карта иметь несколько IP адресов?
> Наверное нет.
Вообще может. Почему нет?
http://blog.evgenmed.com/2010/05/ip-ip.html
https://moonback.ru/page/2ip-linux
при этом в системе это может выглядеть как несколько виртуальных сетевых карт.
При желании можно наверно сделать и карту с несколькими мак-адресами, как бы имитирующую несколько отдельных, но я не знаю, будет ли коммутатор с такой работать - наверно, нет.
http://serverfault.com/questions/223601/multiple-mac-addresses-on-one-physical-network-interface-linux
Еще есть такие вещи, как бриджи - когда 2 сетевых карты как бы объединяют 2 сегмента езернет в один, пересылая пакеты между ними - https://ru.wikipedia.org/wiki/Сетевой_мост
> > Может ли сетевая карта иметь несколько IP адресов?
> Наверное нет.
Как я написал, может, однако это могут быть не любые адреса. Подумай, какие там есть ограничения.
> > Видит ли гугл твой MAC адрес когда ты заходишь на его сайт?
> Нет, потому что на канальном уровне заголовок с MAC-адресом перезаписывается на IP.
Верно, гугл видит мак ближайшего к нему роутера. Мак адреса видны только внутри сегмента езернет.
>> Видит ли гугл IP адрес твоей сетевой карты?
> Да, виден. А нет, может и нет. Прочитал следующий вопрос. Прочитал про NAT. Теперь да, смотря как компьютер подключен к сети, через NAT или нет.
верно. Кстати при изучении этой темы, не забывай что НАт скорее костыль - по задумке, должна была быть единая сеть - но из соображений безопасности, а также нехватки ип адресов их начали применять. Ну к примеру корпорация может не хотеть чтобы извне можно было посылать всякие пакеты во внутреннюю сеть, трейсроутить, дудосить и сканировать ее - она делает отдельную сеть и ставит НАТ. Конечно это можно сделать и без ната, грамотно настроив файерволл на границе, но это сложно, плюс легко сделать ошибку и открыть ворота.
IPv6 решает проблему нехватки адресов, но проблема безопасности остается.
Потому сейчас мы имеем огромное число сетей помимо интернета - локальные сети организаций, провайдеров, миллионы домашних сетей, не являющихся частью интернета, использующих серые адреса.
> > Что такое "серые" IP? Легально ли их использование?
> Ну вот как раз айпишники, которые за NAT. И да, более чем легально, я полагаю.
Неточно. Серые адреса = глобально не маршрутизируемые адреса, на которые нельзя сдать пакеты через интернет потому что там нет таких узлов. Также, серые адреса не требуют согласований с IANA, просто берешь и исплоьзуешь. Но слать или получать на них пакеты из интернета нельзя - только внутри твоей сети. Выучи их диапазоны наизусть.
Кстати. а что будет если ты будешь в своей домашней сети использовать не серые, а "белые" IP адреса? Ну например назначишь айпаду адрес google.com? Гугл упадет? Айпад сломается?
> Когда роутер принимает пакет, то он на лету меняется IP-адрес отправителя на свой, а также записывает номер порта, чтобы различать присланные пакеты от разных компьтеров
Всего доступно 65535 портов, верно? Теперь вопрос. Если в локальной сети каждый компьютер открывает 100 соединений наружу через НАТ, сколько компьютеров способен обслужить этот НАТ? Хехе, какой я хороший вопрос придумал.
> запись в которой стирается после закрытия соединения.
А как быть с UDP где нет соединений и ICMP где нет портов?
> А влияет ли это на скорость, ОП?
Да, но если в качестве шлюза ставить профессиональное оборудование а не домашний компьютер с пентиумом, то незначительно. Ты ведь и сам можешь измерить задержку через traceroute.
> > Зачем нужен маршрутизатор/роутер?
> Чтобы соединять сегменты сети друг с другом?
Да, чтобы соединять езернет сегменты.
> > Чем Ipv6 оличается от IPv4?
> Количеством цифр в адресе?
По моему там еще были доработки: что-то ненужное выкинули и что-то добавили. Ну и пользователь будет получать не 1 ип адрес а большую подсеть.
> > Работает ли у твоего провайдера IPv6?
> Да.
А у меня нет ((
> Похоже у вас есть доступ только в IPv4 интернет. У вас не получится зайти на сайты использующие только IPv6.
> Ваш DNS сервер (возможно, предоставляемый вашим провайдером) имеет доступ к IPv6 интернету.
Это просто потому я использую гугловский DNS.
> ОП, я что-то тогда не понимаю. У нас все офисное здание за NAT. Так вот google как то умудряется забанить только один компьютер за спам. С помощью кук получается?
Возможно, зависит от конфигурации ната. Я сам изредка вижу капчу, хотя никогда не спамлю и плохого ничего не делаю.
> > Может ли сетевая карта иметь несколько IP адресов?
> Наверное нет.
Как я написал, может, однако это могут быть не любые адреса. Подумай, какие там есть ограничения.
> > Видит ли гугл твой MAC адрес когда ты заходишь на его сайт?
> Нет, потому что на канальном уровне заголовок с MAC-адресом перезаписывается на IP.
Верно, гугл видит мак ближайшего к нему роутера. Мак адреса видны только внутри сегмента езернет.
>> Видит ли гугл IP адрес твоей сетевой карты?
> Да, виден. А нет, может и нет. Прочитал следующий вопрос. Прочитал про NAT. Теперь да, смотря как компьютер подключен к сети, через NAT или нет.
верно. Кстати при изучении этой темы, не забывай что НАт скорее костыль - по задумке, должна была быть единая сеть - но из соображений безопасности, а также нехватки ип адресов их начали применять. Ну к примеру корпорация может не хотеть чтобы извне можно было посылать всякие пакеты во внутреннюю сеть, трейсроутить, дудосить и сканировать ее - она делает отдельную сеть и ставит НАТ. Конечно это можно сделать и без ната, грамотно настроив файерволл на границе, но это сложно, плюс легко сделать ошибку и открыть ворота.
IPv6 решает проблему нехватки адресов, но проблема безопасности остается.
Потому сейчас мы имеем огромное число сетей помимо интернета - локальные сети организаций, провайдеров, миллионы домашних сетей, не являющихся частью интернета, использующих серые адреса.
> > Что такое "серые" IP? Легально ли их использование?
> Ну вот как раз айпишники, которые за NAT. И да, более чем легально, я полагаю.
Неточно. Серые адреса = глобально не маршрутизируемые адреса, на которые нельзя сдать пакеты через интернет потому что там нет таких узлов. Также, серые адреса не требуют согласований с IANA, просто берешь и исплоьзуешь. Но слать или получать на них пакеты из интернета нельзя - только внутри твоей сети. Выучи их диапазоны наизусть.
Кстати. а что будет если ты будешь в своей домашней сети использовать не серые, а "белые" IP адреса? Ну например назначишь айпаду адрес google.com? Гугл упадет? Айпад сломается?
> Когда роутер принимает пакет, то он на лету меняется IP-адрес отправителя на свой, а также записывает номер порта, чтобы различать присланные пакеты от разных компьтеров
Всего доступно 65535 портов, верно? Теперь вопрос. Если в локальной сети каждый компьютер открывает 100 соединений наружу через НАТ, сколько компьютеров способен обслужить этот НАТ? Хехе, какой я хороший вопрос придумал.
> запись в которой стирается после закрытия соединения.
А как быть с UDP где нет соединений и ICMP где нет портов?
> А влияет ли это на скорость, ОП?
Да, но если в качестве шлюза ставить профессиональное оборудование а не домашний компьютер с пентиумом, то незначительно. Ты ведь и сам можешь измерить задержку через traceroute.
> > Зачем нужен маршрутизатор/роутер?
> Чтобы соединять сегменты сети друг с другом?
Да, чтобы соединять езернет сегменты.
> > Чем Ipv6 оличается от IPv4?
> Количеством цифр в адресе?
По моему там еще были доработки: что-то ненужное выкинули и что-то добавили. Ну и пользователь будет получать не 1 ип адрес а большую подсеть.
> > Работает ли у твоего провайдера IPv6?
> Да.
А у меня нет ((
> Похоже у вас есть доступ только в IPv4 интернет. У вас не получится зайти на сайты использующие только IPv6.
> Ваш DNS сервер (возможно, предоставляемый вашим провайдером) имеет доступ к IPv6 интернету.
Это просто потому я использую гугловский DNS.
> ОП, я что-то тогда не понимаю. У нас все офисное здание за NAT. Так вот google как то умудряется забанить только один компьютер за спам. С помощью кук получается?
Возможно, зависит от конфигурации ната. Я сам изредка вижу капчу, хотя никогда не спамлю и плохого ничего не делаю.
Обычно AS это сеть, контролируемая одним юридическим/физическим лицом. Ну там официально более сложно определение: https://ru.wikipedia.org/wiki/Автономная_система_(Интернет)
За авт. сетью закрепляется диапазон адресов и она добавляется в таблицы маршрутизации, так что роутеры знают через кого можно посылать пакеты в эту сеть. Ну то есть в таблицу вносится диапазон IP этой сети и список шлюзов через которые она связана с другими сетями. Роутер при получении пакета адресованного в ту сеть, определяет ближайший путь к ней и передает пакет дальше.
> > Можешь ли ты кратко (кратко!) написать что происходит когда ты пытаешься соединиться с удаленным хостом, например через telnet google.com 80?
> Отправляю пакеты на шлюз, тот меняет мой айпишник на свой. Отправляет на следующий маршрутизатор, и так до пункта назначения и обратно.
Меняет адреса НАТ (как следует из названия). Обычные роутеры без НАТ не меняют IP адреса.
Алсо, тебе еще маленькая задачка. Если UPD ненадежный протокол, и IP тоже ненадежный то что мешает использовать IP пакеты напрямую? Разницы же нет?
Также, вторая задачка. Можно ли реализовать протокол вроде HTTP поверх IP (без TCP)? Какие подводные камни?
Всмысле кривой? Ничего там не кривое, ты просто что-то неправильно делаешь.
Уточни свой вопрос.
Может у меня апаче на убунту не пускает htaccess? Не могу найти http.conf в папке с апаче.
http://ideone.com/ns79Xy
Неправильно считает: http://ideone.com/fLZtzF
Должно получиться 61270 рублей с копейками при $monthlyPayment = 5000.
>$loan -= ($monthlyPayment - $taxRate);
Чё-т вообще не в ту степь.
Вот такой алгоритм самый простой и естественный:
1. Прибавляем к $creditBalance проценты и $servicePayment.
2. Если получившаяся переменная меньше или равна $monthlyPayment, то выплачиваем именно её и прибавляем её к $paymentTotal. После этого завершаем цикл.
3. Если получившаяся переменная больше $monthlyPayment, то отнимаем от неё $monthlyPayment и продолжаем цикл.
Тогда почему не
$data = "Yoba Boba";
foreach (count_chars($data, 1) as $key => $value) {
echo "chr($key) встречается в строке $value раз(а).\n";
}
?
Проблема в том, что я так и не пойму, что ему надо.
То есть вот так:
$data = "Yoba Boba";
foreach (count_chars($data, 1) as $key => $value) {
$i = chr($key);
echo "$i встречается в строке $value раз(а).\n";
}
>То есть создать таблицу с цветами не пойдет, т.к. цвета могут быть каждый раз разные.
Почему не пойдет и что значит каждый раз разные?
> Есть товар, которому можно задавать цвета. То есть создать таблицу с цветами не пойдет, т.к. цвета могут быть каждый раз разные.
Не рекомендую. Завтра ты захочешь сделать поиск по цвету и их нужно будет как-то унифицировать. Посмотри любой магазин вроде lamoda.ru например - там просто набор цветов.
Соответственно делается сущность "цвета", и связь многие-ко-многим/один-ко-многим в зависимости от логики на товары.
> цветов может быть 1, а может и 10, все их в одном столбце хранить нельзя.
Хорошо, что ты это понимаешь.
почему этот кусок кода всё время возвращает одно и то же значение, даже при перезагрузке сраницы? если что, то я не залогинен
$buf = (isset($_SESSION['test'])) ? $_SESSION['test'] : 0;
$buf++;
var_dump($buf);
$_SESSION['test'] = $buf;
Все хорошо.
>$percent = 1.03; / Банк начисляет 3% в месяц от суммы /
Почему 1.03 если Процент — это одна сотая часть от числа т.е. 0.03
или это просто я тупой ?
Спрашивай что конкретно не понятно.
Готовых студентов тебе может ОП подкинуть, он знает какие нормально сделаны.
Чтобы ты сумму тупо умножал на это число, а не ебался с кучей дополнительных действий.
Ну, скажем, я запилил вот что: страница, которая показывает всех студентов и вторая страница - форма для вбивания нового студента.
Из условий задачи я понимаю, что вбив студента(себя) ты как бы "логинишься" на сайт и уже потом можешь смотреть всех, либо редактировать свои данные. Так вот, как делать это "логинивание"? Вообще нет идей
аа окей тогда, спасибо
Еще раз перечитай условия задачи, там описано как должна работать авторизация.
https://github.com/codedokode/pasta/blob/master/student-list.md#Авторизация
Или ты не понимаешь сам процесс работы с куками?
Пройди, чо.
Такой формат максимум YOBA: "Бесплатный видеокурс по PHP и пошаговый алгоритм по созданию полнофункционального блога с БД и аутентификацией с нуля".
>>694072
Откуда новичку знать последовательность, что за чем, как то и как сё? Есть какие-то гайды, как самому создать пошагово?
Это ты можешь думать, что сейчас вот то, потом вот сё, а новичок не знает ничего абсолютно.
Учебнику ОПа не было бы цены, если бы были подобные гайды. Даже просто описание задачи на список студентов - это мрак и адище. Каждый пункт надо изучать дополнительно, ломается пошаговость.
Ты или ОП можете многое сказать по этому поводу, только факта это не отменяет: это всё равно очень сложно для новичка.
Ну никак у меня не получается hello-world сделать в slim. Единственное, чего я добился с прошлого треда, это иметь возможность взаимодействовать с htaccess запуская код не с phpstorm, а напрямую через браузер из папки apache/htdocs. Вот тогда httacess команды работают. Но у меня до сих пор 404.
То, что папка вверху file-sharing, а в url test - не обращайте внимания, phpstorm здесь уже просто как редактор используется. Файлы в htdocs точно такие же.
> сам процесс работы с куками?
this
никогда не имел с ними дела, а нагуглить нормально не могу
>Каждый пункт надо изучать дополнительно, ломается пошаговость.
>это всё равно очень сложно для новичка
Вот тут кстати соглашусь, как человек который сделал студентов не с нуля (я до этого кое-что знал). Между учебником ОПа и задачей про студентов есть очень большой пробел, но большинство подводных камней и новых понятий объясняется в самом условии (это не отменяет факта что новичку который читал только учебник ОПа придется все это гуглить). Может быть это так задумано ОПом, чтобы шло какое-то самообучение.
Мануал читал? Там все достаточно неплохо описано.
http://php.net/manual/ru/features.cookies.php
index.php в url не нужен, у тебя в ->get('/hello/:name'), значит url должен быть localhost/test/hello/vasya.
Все равно 404.
Видимо не для меня, я что-то совсем там ничего не понимаю. Куки - это какая-то инфа, которую я буду посылать пользователю для того, чтоб он мог не авторизовываться? Так я и начинал с того, что даже не знаю, как делать сам процесс авторизации. Т.е.... что это вообще такое?
Да и как с ними работать, корочи, не ясно, не знаю, как объяснить нормально ,потому как просто тупо не понимаю
Самообучение и так идёт.
Решать задачи ОПа в первой части учебника - это и есть самообучение.
Дело тут всё-таки в подаче материала.
Но ОП и без того огромную работу проделал, чтобы я ещё и этого требовал от него.
>>694210
Ты пока только функцию создал.
Прочитай внимательно про то, как функция возвращает значения. И про то, как уже после вывести это значение через echo.
Что не нравится этой пердельне?
окей пойду читать
Разберись с фигурными скобками.
Для чего они нужны?
Там две фигурных скобки стереть - и всё заработает.
elseif
Посмотри на эту авторизацию с самого начала.
Каждая авторизация на любом сайте требует пароль. В нашем случае чтобы не заставлять пользователя каждый раз вводить свой пароль, ты генерируешь пароль сам, и сохраняешь этот пароль пользователю на компьютер. Для этого тебе нужны куки - чтобы хранить какую-то информацию на компьютере у пользователя. У каждой куки есть свое имя, значение которое она хранит, и время когда она кончится (т.е. удалится с компьютера пользователя). Так же, тебе нужно будет сохранить пароль который ты сгенерировал в базу данных, чтобы потом с помощью этого авторизировать пользователя. Таким образом, тебе на странице с формой нужно будет проверять, присутсвует ли у пользователя кука авторизации, если присутсвует и пользователь с таким паролем есть в базе данных - ты выводишь его данные и позволяешь редактировать информацию, если же какое-то из условий выше не было выполнено (у пользователя нет такой куки, или пользователя с таким паролем не существует в базе даных), ты выводишь форму заполнения данных.
Конечно, как написано в условии, у этого способа есть недостатки, например если пользователь почистит куки или использует другой браузер - он потеряет возможность редактирования своих данных, но данный способ вполне подходит для задачи с студентами.
Как работать с куками (ставить и получать значения) описано в мануале (там же есть и примеры).
http://php.net/manual/ru/function.setcookie.php
>авторизация
Что есть авторизация? Через что её делать? через <form>? Т.е. пользователь заполняет <form>, я создаю new Student и сохраняю его, и, скажем, как его переменную класса ->coockie передаю туда сгенерированную рандомную фразу/cлово через setcoockie()?
А как, собственное, создать "авторизуемость", т.е. как проверять какой куки у пользователя и его так называемый "личный кабинет"? Через что это делается, какими тегами?
я оче плохо объяснил, признаю... Не знаю, как задать вопрос лучше.
Перечитал то, что ты написал. Т.е. делаю так:
1. пользователь заполняет <form>
2. я создаю new Student и сохраняю его инфу
3. как его переменную класса ->coockie передаю туда сгенерированную рандомную фразу/cлово через setcoockie()
4. Перед выдачей формы я проверяю, совпадает ли ->сoockie и кука, которую хранит его браузер
5. если да, то вывожу его данные и он их редактирует
6. если нет, выдаю <form> как обычно
всё верно?
http://ideone.com/8W6bPw
Понятно, что второе действие можно сократить, просто посчитав прибавку от годовых собственноручно, но мне хотелось всё сосчитать внутри кода.
Ideone выдаёт превышение временных лимитов.
Моя ошибка?
>Что есть авторизация?
Пользователь вводит логин и пароль, твое приложение проверяет все ли введено верно. Если все верно - пользователю дается кука в подтверждение того что он авторизирован.
>Через что её делать?
В случае с списком студентов тебе не нужно нагружать пользователя логинами\паролями. Тебе достаточно сгенерировать пароль самому, и записать его в куки пользователя и в базу данных. Тогда эта кука которую ты создал будет как бы "флагом" того, что пользователь авторизирован.
>через <form>?
Через форму пользователь вводит свою информацию (имя, фамилию), а работа с паролями и куками происходит исключительно на стороне сервера.
>>694265
>как его переменную класса ->coockie передаю туда сгенерированную рандомную фразу/cлово через setcoockie()
Ты должен сохранить в $_COOKIE только пароль который ты сгенерировал. И этот же пароль сохраняешь в базу данных вместе с студентом. Потом, когда тебе нужно будет проверить, авторизирован ли пользователь, ты можешь проверять наличие куки с авторизацией у пользователя
>if(isset($_COOKIE['user_authorized']))
И если такая кука у пользователя есть, ты выбираешь из базы данных студента с паролем, который содержится в куке. Если такой студент в базе данных есть - значит пользователь авторизирован. Т.е. твой "пароль" это еще одна колонка в базе данных, а не переменная.
Изучи эту страницу и спрашивай что осталось непонятным: https://ru.wikipedia.org/wiki/HTTP_cookie
Идея такая куки- это кусочки информации в формате key=value которые браузер сохраняет у себя и отправляет на сервер вместе с каждым запросом. Когда браузер запрашивает страницу по протоколоу HTTP, сервер может в дополнение к самой странице отправить заголовок Set-Cookie содержащий куки и информацию о них: домен, путь, срок хранения. Браузер получив этот заголовок, добавляет куки в свое хранилище и в дальшейшем отсылает их вместе с каждым запросом.
Куки разграничены по доменам. браузер посылает на сервер только куки относящиеся к домену сайта. Сервер может ставить куки только для своего домена.
Мы используем куки для беспарольной авторизации. При регистрации генерируется случайный длинный сложноподбираемый код, сохраняется в БД и ставится в куки. При попытке редактирвоания код и кук сверяется с кодом в БД и таким образом подтверждается что это тот же пользователь который ранее зарегистрировался. Злоумышленник не может редактировать чужие профили так как не знает их секретный код.
Авторизация это проверка прав на выполнение каких-то действий (например удалять посты может только админ).
https://ru.wikipedia.org/wiki/Авторизация
Спасибо!
Return не в том месте.
С ним ты можешь получить только окончательный результат работы функции.
$creditSum там к чему возвращается? Там должна возвращаться окончательная сумма заплаченного, а не 0 ($creditSum станет нулём же в итоге).
Хм... начинаю понимать, спасибо, что объясняешь такому долбоёбу, как я.
Т.е., скажем, пользователь ввёл свои данные. Нажал на submit, я создаю new Student и также создаю $password = рандомное вырадение и успешно записываю студента с его паролем-куки в таблицу sql.
Потом я делаю
setcoockie('student_password', $password); (теперь я правильно понимаю, что передаю куки равное тому сгенерированному выражению, браузеру чела, который только что зарегался?.)
И потом проверять, если у него в браузере есть такой куки под названием student_password, то смотрю по своей таблице sql и даю ему редактировать того, с чьим password совпало?боже, кажется, я понял
Что там?
цикл будет идти до тех пор пока $i<=1000000, условие внутри цикла $i>=1000000 никогда не выполнится, потому что к тому моменту цикл уже завершится.
Ответьте кто-нибудь
Почему в адресной строке localhost/test ?
Должно быть что-то вроде
http://localhost/hello/anon
http://example.dev/hello/anon (если ты сделал отдельный вирт. хост)
Куда в конфиге сервера Апач указывает DocumentRoot? Я вижу у тебя код где-то в c:\users, это ведь не корневая папка веб-сервера?
Алсо, может тебе что-то поможет из этих уроков:
https://github.com/codedokode/pasta/blob/master/soft/web-server.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Так, другое недоразумение с этим кодом http://ideone.com/7neVzL
Сначала в цикле присваивается значение переменным, затем проверяется условие (оно верно), потом выполняется тело цикла. Тогда в результате кода должно выехать несколько строк, начиная с "The guy is 16 while he's got USD 10000 in the bank", разве не так?
Секрет прост: ОП пока не написал промежуточных уроков. Единственное на что хватило времени - сделать задание + комментарии, а ведь раньше их не было и было еще хуже.
То есть имея ограниченное время я постарался начать с самого важного - сделать хоть что-то для изучения архитектуры веб приложений.
Алсо есть такой вариант промежуточного урока - что скажете? https://github.com/codedokode/pasta/blob/master/soft/web-server.md
>>694258
Тебе надо выучить и прочитать в мануале 2 метода работы с куками в PHP
- функция setcookie добавляет в ответ сервера заголовок Set-Cookie который добавит куку в хранилище браузера
- перед запуском скрипта PHP анализирует пришедшие от браузера заголовки, ищет там заголовок Cookie и заполняет пришедшими от браузера куками массив _COOKIE
Обрати внимание, если ты меняешь _COOKIE то ты меняешь только этот массив, никаких заголовков не отправляется. Если ты делаешь setcookie то кука не добавляется в COOKIE так как это просто массив.
Веб сервер не обрабатывает PHP код. Проверь что файл имеет правильное расширение, а сервер правильно настроен.
>Алсо есть такой вариант промежуточного урока - что скажете?
Вот я думаю это как раз то, чего не хватало, я помню в прошлых тредах некоторые люди закончили учебник в шапке, брались за студентов и совсем не могли понять с чего начать.
Там кстати и про куки задание есть, может этому >>694258 анону стоит попробовать его сделать?
https://github.com/codedokode/pasta/blob/master/soft/web-server.md#Я-тебя-помню
ойй
спасибо, анон!
Мод реврайт то хоть включен? Я имею ввиду активацию самого модуля, в дебиане это sudo a2enmod rewrite.
Еще может быть нужно AllowOverride All в apache2.conf
Выложи сразу весь php.ini и apache2.conf, чтобы не засорять тред угадыванием причин.
О боже, оно работает. Тонны нефти анон, часами мучился.
Нет примера. Есть только один выход: попробовать самому и сказать, что конкретно не получается
ойй ну всм цикл.
Я скопипастил старый код из задачки с айфоном но чт он не работает, а еще я не совсем понимаю как тут должен работать return
Return дает понять функции, что именно она должна вернуть в качестве своего результата. Мы можем делать разные вычисления в функции с разными переменными, но результат, как правило, нам нужен только один.
http://ideone.com/jcefOw
окей я понял что он делает,но я до сих пор не понимаю куда мне его сунуть,сейчас попробую разобраться, ну а код у меня хотя бы работать будет?
За циклом поставь echo - это как раз то, что нужно будет, последний результат.
Может поставить его в самый конец после цикла, так как return сразу заканчивает работу функции и возвращает значение, для функции он примерно как break для цикла.
нууу а с кодом то мне что делать он до сих пор не работает, он хоть правильно написан?
Ты так и не сделал там $paymentTotal.
Без него и возвращать нечего будет.
return там должен быть после основного цикла в функции - тебе же только последнее значение нужно.
Я поэтому и писал тебе, что ты будто не сам решал эту задачу - это же элементарно. И странно не понять этого, когда решил эту сложную задачу.
>>694421
Так тебе это и нужно.
Что значит "подумал так сойдет?". Ты случайные куски кода вставляешь наугад и ждешь, что оно само поймет, что тебе от него нужно? Ты ведь должен понимать что ты делаешь, когда решаешь задачу. Тебе нужно написать функцию, которая возвращает количество выплаченных денег, но где их взять, если ты даже никуда их не записываешь?
да знаю я просто подумал что можно сунуть все в $creditSum. Не знаю не спрашивай почему я так решил.
Спасибо. Сейчас пробую сделать задачу. Столкнулся с проблемой. Вот, скажем, я записываю все пары куки -- кол-во раз в массив.
Но как быть с тем, что при каждом обновлении страницы мой массив перезаписывается? Иными словами, как создать переменную, которая бы не перезаписывалась каждый бы раз?
ту задачку я делал недели 2 назад, наверное слишком большой перерыв.
Короче, вот лучше сформулированный вопрос: каким образом лучше всего хранить массив объектов с парами куки-пароль?
Я создал класс Coockie с переменными ->password(тут сама кука) и ->times(счётчик разов).
Как хранить эти объекты? Записываю их в массив - при каждом обновлении страницы всё сбрасывается.
Получается, в базе данных только?
то есть базы данных - это единственное решение? Через php и переменные нельзя извернуться, чтоб они не сбрасывались после окончания скрипта?
У меня работает, только если на отдельынй файл отправлять, а нужно на роутер.
$.post("ajax.php",
Правильно все ли я сделал?Есть замечания?
Код по ссылке.
http://pastebin.com/bFdzVPWW
Заранее спасибо
Все-таки плохая у yii документация, годится только на хелловорлды.
Чувак выше спрашивал про сессии в yii >>694117
я его код скопировал, у меня все работает, число инкрементируется при обновлении страницы, так что у него скорее всего дело в кешировании.
У меня возник другой вопрос, а где собственно фреймворк вызывает session_start?
В гайдах описывают 2 способа работы с сессией:
1. Через компонент session, будут вызовы вида
Yii::app()->session->add('key', 'value');
Yii::app()->session->get('key', 'notFoundValue');
Требует конфига в main.php (или это опционально?)
Правда непонятно что туда писать, если мне не нужны никакие параметры: autoStart по-дефолту true, cookieParams и cookieMode нужны только если включить режим сохранения данных сессии в куки.
2. Создать "независимый" объект класса CHttpSession и уже у него явно вызывать метод open.
$session = new CHttpSession;
$session->open(); // внутри этого метода session_start
$session->add('key', 'value');
echo $session->get('key');
Вопрос у меня возник в связи с тем, что у меня сессии "работают" (то есть вызывается session_start) во всех 3 случаях. И когда я обращался к сессии первым способом (но не прописывал конфиг для компонента session!); и когда обращался вторым способом, через создание нового экземпляра CHttpSession (но не вызывал $session->open()!); и даже через родной $_SESSION не нужно вызывать session_start, более того фреймворк сообщает об ошибке, мол 500 A session had already been started - ignoring session_start()
Где же он (фреймворк) ее (сессию) стартовал?
После хождения по коду фреймворка, оказалось, что существуют некие базовые компоненты, которые всегда подгружаются.
https://github.com/yiisoft/yii/blob/8c9b5114db3ee524d23e985c637b52f329ca5bda/framework/web/CWebApplication.php#L149
Подгружаются и все. Нужны они тебе или нет, они уже есть.
Вот компонент session в их числе.
CModule::setComponent вызывает CHttpSession::init (внутри которого open, внутри которого золотое яичко, внутри которого session_start)
https://github.com/yiisoft/yii/blob/083d36127de7298f03c0a701d88a5068dddb2a02/framework/base/CModule.php#L426
https://github.com/yiisoft/yii/blob/485c001e99ba1e60eabd496027e69eecdee5ed72/framework/web/CHttpSession.php#L88
Почему в доках такие моменты не разбираются, я имею ввиду например как приложение работает с сессией? Нá тебе голый апи и дергай ->add и ->get как обезьяна.
Это что мне, самому перечитывать исходный код фреймворка, чтобы понять что происходит?
Вроде уже сам разобрался, нет смысла постить, но не зря же я это набирал, хоть пожалуюсь на плохую документацию и похвастаюсь что сам дошел.
Все-таки плохая у yii документация, годится только на хелловорлды.
Чувак выше спрашивал про сессии в yii >>694117
я его код скопировал, у меня все работает, число инкрементируется при обновлении страницы, так что у него скорее всего дело в кешировании.
У меня возник другой вопрос, а где собственно фреймворк вызывает session_start?
В гайдах описывают 2 способа работы с сессией:
1. Через компонент session, будут вызовы вида
Yii::app()->session->add('key', 'value');
Yii::app()->session->get('key', 'notFoundValue');
Требует конфига в main.php (или это опционально?)
Правда непонятно что туда писать, если мне не нужны никакие параметры: autoStart по-дефолту true, cookieParams и cookieMode нужны только если включить режим сохранения данных сессии в куки.
2. Создать "независимый" объект класса CHttpSession и уже у него явно вызывать метод open.
$session = new CHttpSession;
$session->open(); // внутри этого метода session_start
$session->add('key', 'value');
echo $session->get('key');
Вопрос у меня возник в связи с тем, что у меня сессии "работают" (то есть вызывается session_start) во всех 3 случаях. И когда я обращался к сессии первым способом (но не прописывал конфиг для компонента session!); и когда обращался вторым способом, через создание нового экземпляра CHttpSession (но не вызывал $session->open()!); и даже через родной $_SESSION не нужно вызывать session_start, более того фреймворк сообщает об ошибке, мол 500 A session had already been started - ignoring session_start()
Где же он (фреймворк) ее (сессию) стартовал?
После хождения по коду фреймворка, оказалось, что существуют некие базовые компоненты, которые всегда подгружаются.
https://github.com/yiisoft/yii/blob/8c9b5114db3ee524d23e985c637b52f329ca5bda/framework/web/CWebApplication.php#L149
Подгружаются и все. Нужны они тебе или нет, они уже есть.
Вот компонент session в их числе.
CModule::setComponent вызывает CHttpSession::init (внутри которого open, внутри которого золотое яичко, внутри которого session_start)
https://github.com/yiisoft/yii/blob/083d36127de7298f03c0a701d88a5068dddb2a02/framework/base/CModule.php#L426
https://github.com/yiisoft/yii/blob/485c001e99ba1e60eabd496027e69eecdee5ed72/framework/web/CHttpSession.php#L88
Почему в доках такие моменты не разбираются, я имею ввиду например как приложение работает с сессией? Нá тебе голый апи и дергай ->add и ->get как обезьяна.
Это что мне, самому перечитывать исходный код фреймворка, чтобы понять что происходит?
Вроде уже сам разобрался, нет смысла постить, но не зря же я это набирал, хоть пожалуюсь на плохую документацию и похвастаюсь что сам дошел.
Интересно, а как работает сессия? Этот механизм отвечает за то, что авторизация не сбрасывается при смене страницы?
Всё же не верю, что нет способа, кроме баз данных. Как-то это слишком странно. Обращаюсь с просьбой помочь решить задачу Я тебя помню https://github.com/codedokode/pasta/blob/master/soft/web-server.md
Я написал такое решение:
0. Создаю class Coockie { public $pass; public $count = 1; }
1. Проверяю, есть ли у пользователя кука с названием "pass" --- isset($_COOKIE['pass']).
2. Если если нет, то создаю $coockie = new Cookie,генерирую пароль из 10 символов, передаю его в $coockie->pass и показываю "привет в 1-й раз".
Сохраняю полученный объект в массив.
3. Если есть такая кука, то перебираю массив с объектами и сравниваю его с кукой. Если совпадает, пишу "привет в такой-то раз" и всё.
Вроде, всё логично и должно работать. Однако на практике я вижу, что мой массив каждый раз перезаписывается благодаря этой строке $allc = [];
А без неё не могу, т.к. не задав переменную нельзя foreach по ней делать. Картинку прилагаю. Как быть?
Передача по ссылке не нужна, только по значению.
Придерживайся функциональной чистоты: функция принимает значения, обрабатывает их, возвращает результат, не изменяя никакие другие данные. С результатом можно делать всё что нужно.
Для упрощения можно использовать глобальные переменные.
еще,если я хочу присвоить результат работы функции в переменную,то return обязат нужен?
а как реализовать ввод ,допустим чисел на хтмл странице и передать результат в функцию с дальнейшим выводом.я так понимаю напрямую в пыхе такой функции нет?
книга не понравилась
Стоп, но если сессия стартует всегда, то зачем в мануале (не в мануале а в апи) дается пример с явным началом сессии?
http://www.yiiframework.com/doc/api/1.1/CHttpSession
$session=new CHttpSession;
$session->open();
Зачем там open если сессия всегда стартует?
Может это для тех чуваков, которые насильно в конфиге выставляют autoStart в false?
Непонятно. У меня этот способ работает без open.
>>694612
Почитай статьи из гугла, я могу только кратко пересказать в сотый раз.
Сессии в абстрактном виде это некая информация от пользователя, которую необходимо передавать между скриптами.
Допустим у тебя есть какой-то тест, типа психологический, или на уровень icq.
Каждый вопрос сделан отдельной страницей (ну или сгруппированы по 10-20). После того как юзер расставит чекбоксы, он сабмитит форму (кнопка "Дальше").
Ему выдается страница со следующей порцией ответов и т.д. В итоге он приходит на последнюю страницу, которая должна собрать результат работы всех предыдущих скриптов, обработать и выдать результат.
Как передать данные от одного скрипта другому?
Можно через куки. Кто-то выше уже писал, куки это пары 'имя'=>'значение', которые сохраняются в браузере.
Но пользователь может отключить куки, он может их почистить, плюс может быть некоторую конфиденциальную информацию просто нельзя сохранять в куках.
Тогда сохраняют на сервере в специальных файлах. Чтобы связать эти файлы с конкретным пользователем, посылающим запрос, создается сессионная кука с идентификатором (фактически с названием этого файла).
Что это дает? Пользователь прошел первую страницу теста и сабмитит эту форму. Данные сохраняются в файл с определенным именем, пользователю ставится кука с таким именем.
Редирект на вторую страницу. Пользователь заполняет форму и сабмитит. Поскольку у него есть кука с названием сессии, то сервер не создает новый файл, а дописывает в старый.
Наконец на последней странице, на которой должен быть показан результат, скрипт выгребает из сессии все ответы пользователя, обрабатывает и отдает html.
Сессионные данные кроме собственно сессионных файлов и кук можно еще хранить в бд, или в кастомных файлах на сервере (черт его знает, зачем это может понадобиться). Но вот например для юи зачем-то описывают и такое извращение http://styleroom-ya.livejournal.com/618998.html
Авторизация делается обычно куками, хотя опять-таки it depends.
Стоп, но если сессия стартует всегда, то зачем в мануале (не в мануале а в апи) дается пример с явным началом сессии?
http://www.yiiframework.com/doc/api/1.1/CHttpSession
$session=new CHttpSession;
$session->open();
Зачем там open если сессия всегда стартует?
Может это для тех чуваков, которые насильно в конфиге выставляют autoStart в false?
Непонятно. У меня этот способ работает без open.
>>694612
Почитай статьи из гугла, я могу только кратко пересказать в сотый раз.
Сессии в абстрактном виде это некая информация от пользователя, которую необходимо передавать между скриптами.
Допустим у тебя есть какой-то тест, типа психологический, или на уровень icq.
Каждый вопрос сделан отдельной страницей (ну или сгруппированы по 10-20). После того как юзер расставит чекбоксы, он сабмитит форму (кнопка "Дальше").
Ему выдается страница со следующей порцией ответов и т.д. В итоге он приходит на последнюю страницу, которая должна собрать результат работы всех предыдущих скриптов, обработать и выдать результат.
Как передать данные от одного скрипта другому?
Можно через куки. Кто-то выше уже писал, куки это пары 'имя'=>'значение', которые сохраняются в браузере.
Но пользователь может отключить куки, он может их почистить, плюс может быть некоторую конфиденциальную информацию просто нельзя сохранять в куках.
Тогда сохраняют на сервере в специальных файлах. Чтобы связать эти файлы с конкретным пользователем, посылающим запрос, создается сессионная кука с идентификатором (фактически с названием этого файла).
Что это дает? Пользователь прошел первую страницу теста и сабмитит эту форму. Данные сохраняются в файл с определенным именем, пользователю ставится кука с таким именем.
Редирект на вторую страницу. Пользователь заполняет форму и сабмитит. Поскольку у него есть кука с названием сессии, то сервер не создает новый файл, а дописывает в старый.
Наконец на последней странице, на которой должен быть показан результат, скрипт выгребает из сессии все ответы пользователя, обрабатывает и отдает html.
Сессионные данные кроме собственно сессионных файлов и кук можно еще хранить в бд, или в кастомных файлах на сервере (черт его знает, зачем это может понадобиться). Но вот например для юи зачем-то описывают и такое извращение http://styleroom-ya.livejournal.com/618998.html
Авторизация делается обычно куками, хотя опять-таки it depends.
на роутер не отправляется, а на просто файл пхп отправляется, в глаза долбишься, мразь?
Переменные хранятся в оперативной памяти. При завершении скрипта вся эти память очищается. Так что новый скрипт всегда начинает с "чистой страницы". Это хорошо.
Тебе надо изучить что такое куки. Ты прочел и понял всю статью про них в википедии?
Также отлаживать куки удобно developer tools в Хроме или ФФ (ctrl + shift + i). В Хроме куки, хранящиеся в браузере, выводятся на вкладке resources. Запросы можно увидеть на вкладке network.
Алгоритм надо упросить. Например что мешает тебе хранить число посещений в самой куке?
Ответь-ка также на вопросы для проверки:
- напиши какой-нибудь простой скрипт на php который выставляет куку, например x=1. Затем открой в браузере dev tools (Ctrl + Shift + I) на вкладке network и перезагрузи страницу пару раз. Посмотри какой запрос посылается и какой ответ приходит, и выпиши тут заголовки которые содержат эту куку, если таковые имеются
- как в PHP выставить куку не используя функцию setcookie ? (например можно ли это сделать функцией header?)
- допустим мы хотим на некоем сайте разрешить пользователям просматривать не более 3 статей бесплатно. Для этого мы при каждом просмотре берем куку view_count, увеличиваем ее значение на 1 и отдаем обратно пользователю с новым значением. Если кука в итоге больше или равна 3, мы вместо статьи показываем сообщение об ограничении доступа. Есть ли подвохи в нашей безупречной схеме? Попробуй написать скрипт который это реализует. Там должно быть несколько строк, ООП не нужен.
- в одной вкладке браузера мы открываем страницу page1.php, которая выставляет куку x =1. Во второй вкладке мы открываем страницу page2.php, которая выставляет куку x=2. затем мы обновляем страницу в первой вкладке. Какое значение куки отправит на сервер браузер? Проверь себя с помощью dev tools.
> Создаю class Coockie { public $pass; public $count = 1; }
Непонятно зачем он нужен и что хранит
> Проверяю, есть ли у пользователя кука с названием "pass" --- isset($_COOKIE['pass']).
Зачем она нужна, с таким странным именем? Пароль? Зачем нам пароль чтобы просто посчитать число посещений?
> Если есть такая кука, то перебираю массив с объектами
Он же пустой.
Переменные хранятся в оперативной памяти. При завершении скрипта вся эти память очищается. Так что новый скрипт всегда начинает с "чистой страницы". Это хорошо.
Тебе надо изучить что такое куки. Ты прочел и понял всю статью про них в википедии?
Также отлаживать куки удобно developer tools в Хроме или ФФ (ctrl + shift + i). В Хроме куки, хранящиеся в браузере, выводятся на вкладке resources. Запросы можно увидеть на вкладке network.
Алгоритм надо упросить. Например что мешает тебе хранить число посещений в самой куке?
Ответь-ка также на вопросы для проверки:
- напиши какой-нибудь простой скрипт на php который выставляет куку, например x=1. Затем открой в браузере dev tools (Ctrl + Shift + I) на вкладке network и перезагрузи страницу пару раз. Посмотри какой запрос посылается и какой ответ приходит, и выпиши тут заголовки которые содержат эту куку, если таковые имеются
- как в PHP выставить куку не используя функцию setcookie ? (например можно ли это сделать функцией header?)
- допустим мы хотим на некоем сайте разрешить пользователям просматривать не более 3 статей бесплатно. Для этого мы при каждом просмотре берем куку view_count, увеличиваем ее значение на 1 и отдаем обратно пользователю с новым значением. Если кука в итоге больше или равна 3, мы вместо статьи показываем сообщение об ограничении доступа. Есть ли подвохи в нашей безупречной схеме? Попробуй написать скрипт который это реализует. Там должно быть несколько строк, ООП не нужен.
- в одной вкладке браузера мы открываем страницу page1.php, которая выставляет куку x =1. Во второй вкладке мы открываем страницу page2.php, которая выставляет куку x=2. затем мы обновляем страницу в первой вкладке. Какое значение куки отправит на сервер браузер? Проверь себя с помощью dev tools.
> Создаю class Coockie { public $pass; public $count = 1; }
Непонятно зачем он нужен и что хранит
> Проверяю, есть ли у пользователя кука с названием "pass" --- isset($_COOKIE['pass']).
Зачем она нужна, с таким странным именем? Пароль? Зачем нам пароль чтобы просто посчитать число посещений?
> Если есть такая кука, то перебираю массив с объектами
Он же пустой.
Нету, да. Для ввода чисел можно реализовать форму (это фронтенд), которая будет по кнопке submit передавать данные в пхп-скрипт (бекэнд), где к ним можно особым образом доступаться, например:
$first=$_POST['firstNumber'];
$second=$_POST['secondNumber'];
$third=callSum($first,$second);
спасибо
Вот такая программа у меня получилась.
http://ideone.com/mIYZwn
> $youGotDis = array_rand($answers,7);
Вот эта строка значит, что я создал еще 1 массив в котором я рандомно перемешал всё элементы из массива $answers, я правильно понял ?
А можно просто переменной присвоить рандомный элемент массива ?
И еще, я не совсем понимаю, как работает следующая строчка
> echo $answers[$youGotDis[0]]. "\n";
Просто скопировал её с пхп.нет
Мне нравится что у кота есть свой, отдельный, диван.
>>694628
Ты по моему переусложнил. Сессия это данные которые хранятся на сервере, индивидуальные для каждого пользвоателя. Пользователям каждому выдается кука с индивидуальным кодом (вроде hd6d5d4d8d9s9ds9ds0d0s0ds0d), а на сервере например создается файл с таким же именем (или запись в базе с таким идентификатором). Соответственно, когда пользователь в следующий раз заходит на сайт, по команде session_start() по этой куке ищется файл, и данные из него загружаются в массив SESSION. А по завершении скрипта - выгружаются из массива в файл. Сессии временные и файлы на сервере удаляются через 15-30 минут неактивности.
У сессий много особенностей и недостатков и они почти всегда не нужны. Авторизация делается и без них и может быть даже проще.
>Чтобы связать эти файлы с конкретным пользователем, посылающим запрос, создается сессионная кука с идентификатором (фактически с названием этого файла).
Очень умно. Теперь я знаю, как можно реализовать сохранения для незарегистрированных пользователей моей ненаписанной игры на JavaScript
ОП-няша об этом где-то пишет?
Сессии долго не живут. Для твоей игры наверно лучше хранить данные в базе данных. А чтобы не забивать базу зря, сохранять их туда если есть что сохранять. чтобы боты от гугла или зашедшие посмотреть не создавали тысячи пустых записей.
Я же так и сказал. Сессии для частных случаев, когда нужно передать данные между php-скриптами, но нет возможности использовать базы данных или куки.
Зацени регулярку. Чуток не влезла в 80 символов
https://github.com/yiisoft/yii/blob/53d9f95ff236fcad1580ab75db83d60fc2fa4a6c/framework/vendors/TextHighlighter/Text/Highlighter/CSS.php#L280
Твой подход с тестом имеет недостаток - если открыть 2 теста в 2 вкладках и заполнять параллельно, все перемешается. Это один из недостатков стандартных сессий. Для борьбы с ним придется сделать свою систему сессий, то есть генерировать идентификатор и передавать его не в куках, а через POST или GET параметры.
"передавать" плохой термин. Лучше сказать "хранить".
> Зацени регулярку.
> Auto-generated class. CSS syntax highlighting
Скорее всего в исходнике генератора синтаксис описан в нормальном виде, а по нему генерируется код. Так что претензий нет.
Блин... До чего же еще докопаться?
А тут? https://github.com/yiisoft/yii/blob/485c001e99ba1e60eabd496027e69eecdee5ed72/framework/web/CHttpSession.php#L114
Куча собачек для подавления ошибок, это точно нехорошо.
Зачем вообще нужен этот оператор @?
Зачем подавлять ошибки, в какой ситуации такое может быть оправдано?
Практически ни в какой. Очень редкие случаи - это когда надо обрабатывать ошибки, например ошибку чтения файла функцией file_get_contents:
$x = file_get_contents($y);
к примеру, даже если мы проверили что файл существует, тут может возникнуть какая-то редкая ошибка в процессе чтения (особенно если файл на сетевом диске), ошибка прав доступа. Эта ошибка приведет к варнингу который пишется в логи, и может быть мы хотели бы этого избежать (то есть мы знаем что файл может не прочитаться и это штатная ситуация).
Правильное решение проблемы - использовать исключения. Ну например в Питоне или JS при каких-то ошибках чтения файла выбрасывается исключение, которое можно поймать и обработать.
В PHP можно заставить код превращать ошибки в исключения в помощью обработчика ошибок: https://github.com/codedokode/pasta/blob/master/php/exceptions.md#Поддержка-исключений-везде
но ради одной функции это может быть слишком много возни.
В общем в 99% случаев собака не нужна и только вредит.
Там очень плохо сделано.
session_start может давать ошибки при повторном вызове, при вызове слишком поздно (что она уже не может выставить куку), при ошибке файловой системы (переполнен диск). Игнорировать все эти ошибки и притворяться что все ок абсолютно не правильно. Такой подход приводит к тому что при отладке программист потратит больше времени на выяснение причин чем если бы он знал о произошедших ошибках сразу. Это называется подход fail fast.
В Юи 1 много странностей, авторы часто пытаются проявлять оригинальность там где не следует.
Точнее, они там не игнорируют ошибки, они просто пишут ее в лог вместо того чтобы сделать фатальную ошибку и завершить скрипт. Это неправильно, ведь фактически мы не смогли открыть сессию, а скрипт продолжает работать. Что если на сессию завязан какой-то важный функционал, связанный с оплатой например?
Быдлокодинг в общем.
Да уж, перемудрил я. Спасибо тебе(ты ОП? похоже по стилю письма) Перечитал на вики и твоё сообщение пять раз и наконец понял. Решил задачу и довольно просто. Пикрилейтед (проверь, пожалуйста, верно?)
Теперь наконец применю знание по кукам на студентах.
Вопрос: правильно я понимаю, что там нужно генерировать каждому студенту куки-пароль и записывать его в БД. При каждом заходе проверяю куку - если совпадает с кукой-паролем от какого-либо студента, то позволяю править инфу, связанную с этим студентом? Т.е. подход будет отличаться от этой задачи довольно сильно?
Да, ОП
совет по коду:
-нехорошо 2 раза писать setookie когда мы можем вынести ее из ифа
- для кук желательно ставить путь и время жизни. Почитай про параметр path у кук: http://citforum.ru/internet/html/cookie.shtml
Также, поломай голову и попробуй ответить на мои вопросы выше. Нужно хорошо закрепить знание кук прежде чем переходить дальше.
> При каждом заходе проверяю куку - если совпадает с кукой-паролем от какого-либо студента, то позволяю править инфу, связанную с этим студентом? Т.е. подход будет отличаться от этой задачи довольно сильно?
да, в данном случае мы можем использовать куку с токеном (это обычно называют токен), чтобы и идентифицировать студента (то есть понять кто перед нами) и аутентифицировать (подвердить что он тот за кого себя выдает).
В случае обычной регистрации используют 2 куки: первая, идентификационная, хранит id или email пользователя, вторая, аутентификационная, - токен или хеш от пароля.
как проверить кол-во этих чекбоксов7
Присвоить этим элементам какой-то класс и посчитать, например:
класс .sevencheckboxes
и потом:
$(".sevencheckboxes").size()
Cпасибо опять. Я тот кун, что чёрно-белые фото прикладывал ко всем задачам, когда твой учебник проходил где-то месяц назад, если помнишь ещё. Вот до студентов добрался и карабкаюсь вверх потихоньку.
Т.е. в студентах мыслить в сторону модели:
1. человек заполняет форму.
2. генерирую куку-пароль, заношу в БД вместе с именем отдельной колонкой.
3. передаю этому пользователю ДВЕ куки: 1. id 2. куку-пароль(из БД).
Ты пишешь
>чтобы и идентифицировать студента
но разве Разве не будет достаточно лишь уникального пароля(из БД)? Зачем нам кука-id?
nope
В случае с студентами хватит одной куки. Один токен служит и для идентификации (благодаря тому что он уникален) и для аутентификации (так как его сложно подобрать).
Две куки нжны в традиционных системах регистрации с паролем и логином, одна кука для идентификации, вторая для аутентификации.
всё понял, добра
Хочу иметь 2 профиля: на апворке и фрилансим, где я не прав?
Это не тред поиска работы, но на правах оффтопа скажу что я бы не советовал работать на русскоязычных сайтах. Совсем.
https://ideone.com/qiudsB Ура, я ебанат и не делал вычитание, но break есть последний шаг, поэтому пришлось поставить $month = 20.
ест*
var start=1;
var end=4;
var i = 0;
while (true){
for (start;start<end;start++) {
alert(start);
}
}
Меня интересует насколько это ресурсозатратно.
Вытащить 100 строк (select *) из мускула или таких же 100 строк из csv файла.
Проверить сам — слишком ленивый.
1. Картинка в фоне (из спрайта)
2. Иконка со спецсимволом ( ∆ ) и через transition: rotate поворачиваем набок
Какой лучше?
Есть текст вида:
>66006 33764 18799 4//// 3//// 1//// 8//// 9//// 00000=3D
>HUI=3D13.9CM
>PIZDA=3D335mm
>GO to HOME:
>error:69
>SPERM=3D0.0ml
>TIME=3D22-03-2016T09:00:09:+03:00
Нужно выдернуть значение хуя, пизды, спермы и времени, либо элементами массива, либо присвоив их неким переменным.
Причем желательно дропнуть "3D" злоебучее.
Поставь в условие цикла, что всё должно продолжаться при $creditBalance большем нуля.
Базарю, ещё захочешь, поцене 38 рублей.
parse_ini_file для получения массива настроек
array_map с вложенным preg_replace для удаления нежелательных подстрок
>parse_ini_file
Он только файлы жрет? Пытался подсунуть ему переменную с нужным текстом, пиздит, ругается. Можно наебать как-то?
писать/читать 12к файлов желания нет.
Напиши свою функцию.
Тогда сначала разбить текст на строки через explode или preg_split. У меня почему-то explode по \n не сработал, помогло использование PHP_EOL в качестве разделителя.
Потом разбить по символу =.
Аноны, задача сделать из полученных слогов массива целое слово. Как я понял, надо из выпавших слогов создать ещё один массив и с помощью implode составить имя. Как реализовать?
А код? Чисто по-братски.
class PostForm {
public $text;
...
}
form.php:
<form ...>
Text <input ... value="<?= isset($postForm->text) ? htmlspecialchars($postForm->getText(), ENT_QUOTES) : '' ?>">
...
</form>
Так можно писать?
Можно, но разве в классе может отсутствовать поле? Или это такая странная проверка на null?
Если форма не отправлена то свойство будет пустое и htmlspecialchars будет получать ошибку^
<br /><b>Notice</b>: Undefined variable: postForm in <b>form.php</b> on line <b>2</b><br /><br /><b>Notice</b>: Trying to get property of non-object in <b>form.php</b> on line <b>2</b><br />
Это доставляет мне много проблем из-за которых мне приходиться придумывать такие костыли.
Мне вот непонятно, вот сейчас, никто же не пишет на __чистом__ PHP? У каждой компании у каждого программиста свой набор инструментов, ведь так?
Он же поле класса проверяет на отсутствие, а не саму $postForm.
Я бы написал как if($postForm->text != null), хотя на практике isset так же проверяет не равняется ли переменная null.
Я в замешательстве, проверять на отсутствие переменной и на её нулевое значение это разные вещи?
Проверять на то что переменная пустая надо так:
if ($something)
или
$something ? ... : ...
Мой код читается так: "если переменная не пуста, ..."
Твой код читается: "если существует переменная и у нее есть поле". Вместо того чтобы прямо написать что ты хочешь сделать, ты ищешь какие-то обходные пути и проверяешь совсем другие вещи. делаешь код тяжело читаемым и засталяешь того, кто его разбирает, тратить лишнее время.
Да и вообще я не понял почему ты так написал. Ни одной убедительной причины найти не могу.
Алсо в твоем коде я не вижу причин по которым переменная может быть пуста. Если у тебя класс представляет данные из формы, то он должен существовать всегда когда есть эта форма.
Ок, я там мог ошибиться так как ты показал только кусок кода и не видно откуда берется эта переменная. Но все равно, isset это ненормально и ненормально что ты обращаешься то к полю, то к методу.
Анон, пока трнед совсем не смыло, покажи писечку КОД, с меня, естественно, нихуя, кроме благодарности.
У тебя палиндром не работает, лел.
такая проблема:
Allowed memory size of 134217728 bytes exhausted (tried to allocate 80732160 bytes)
на такой строчке echo file_get_contents('filename.7z');
Вопрос: есть ли способ из пхп выдать файл клиенту не загрузив его в память? Редирект не катит сразу. Щас склоняюсь к варианту настроить htaccess чтоб если правильный айпи то отправляло сразу на файл в обход пхп.
>Меня интересует насколько это ресурсозатратно.
>Вытащить 100 строк (select *) из мускула или таких же 100 строк из csv файла.
>Проверить сам — слишком ленивый.
Ну просто вытащить - хз, а вот более сложные вещи явно затратнее.
> В ICMP пакетах нет номера порта. Он посылает TCP пакет.
https://ru.wikipedia.org/wiki/Traceroute
> Достижение пункта назначения определяется следующим образом: отсылаемые traceroute датаграммы содержат UDP-пакет с заведомо неиспользуемым номером порта на адресуемом хосте. Номер порта будет равен 33434 + (максимальное количество транзитных участков до узла) — 1.
Значит там не TCP-пакеты, а UDP?
> Зачем это нужно? Выглядит как ненужное усложнение.
Ну сеть же делится на несколько подсетей. Вот маска подсети как раз и нужна, чтобы маршрутизатор мог определить в какую подсеть слать пакет.
> Как узел узнает мак-адрес другого узла - узнай самостоятельно.
Ну узел же получает от DHCP-сервера все настройки и наверное mac-адрес устройства куда передавать пакеты. Ну или оно вручную забивается.
Нужна конкатенация переменной $name в цикле.
При каждом проходе надо приклеивать новый слог к имени, а потом в итоге просто вывести $name в echo.
> Значит там не TCP-пакеты, а UDP?
да
>> Зачем это нужно? Выглядит как ненужное усложнение.
> Ну сеть же делится на несколько подсетей. Вот маска подсети как раз и нужна, чтобы маршрутизатор мог определить в какую подсеть слать пакет.
Неверно. Маска нужна чтобы определить: находится ли другой узел в одной сети с нами и можно слать ему пакет напрямую или же он в другой и надо слать пакет на шлюз.
Когда-то маски вычислялись напрямую из адресов: https://ru.wikipedia.org/wiki/Классовая_адресация
Но это давно не используется.
>> Как узел узнает мак-адрес другого узла - узнай самостоятельно.
> Ну узел же получает от DHCP-сервера все настройки и наверное mac-адрес устройства куда передавать пакеты. Ну или оно вручную забивается.
Нет, не получает, только IP шлюза. Аналогично при ручной настройке указывается только IP. Подумай еще.
> Ну или оно вручную забивается.
Тогда тебе надо забивать вручную мак адреса всех соседей в езернет-сегменте и как-то отслеживать их изменение.
Спасибо анон. Всё получилось с помощью оператора .=
http://ideone.com/i6DutH
Хакиры, посоветуйте оптимизацию, ибо чую, что в регулярках хуйня полная, да и вообще.
На красоту похуй, главное чтобы отрабатывалось как можно быстрее.
вот этот вот >>695120 хуй
Это так? Как же тогда верно?
Из контроллера, он для этого и предназначен вроде.
В любом фреймворке так все реализовано.
Ну слим например как самый примитивный
Смотри секции request и response
http://docs.slimframework.com/request/variables/
Идея в том что каждый класс и функция должны заниматься своим делом. Разбирать пришедшие из формы данные - это одна задача, а например что-то по ним считать - другая, потому этот код должен быть разнесен.
Также, важно избегать побочных эффектов - я написал про это тут: https://github.com/codedokode/pasta/blob/master/good-code.md#Избегай-побочных-эффектов
Потому твои функции и классы скорее всего не должны лезть ни в какие суперглобальные массивы. Все, что им нужно, ты передаешь через аргументы.
>>695703
Так нет, я про сам код фреймворка спрашивал.
В Yii например, класс реквеста при инициализации тащит все эти
массивы в себя.
Ну он как бы инкапсулирует в себе эти данные, потому для сокращения кода там добавлен метод который позволяет загрузить данные из суперглобальных массивов. думаю, это вполне ок, в Симфони у класса Request есть аналогичный метод https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L265
Также, обрати внимание, вышла рекомендация PSR c интерфейсами для описания ответов и запросов в HTTP:
http://www.php-fig.org/psr/psr-7/
(там много букв может тебе проще глянуть сам код): https://github.com/php-fig/http-message/tree/master/src
https://ideone.com/X2AhDq
Вопрос снят. mb_ забыл добавить.
>ненормально что ты обращаешься то к полю, то к методу.
Если в isset обращаться к методу, то выдается ошибка что не может проверить результат метода. Что я могу поделать? Приходиться как-то выходить из этого положения. Я бы так обращался всегда через метод.
Вообще, я очень часто замечаю странные вещи в php. Это проблема языка или только у меня такое? Какие языки по-вашему мнению самые простые в написании?
Я, например, считаю что символ $ для объявления переменной лишний, точка с запятой ; - тоже. С радостью бы поставил плагин который фиксит это, если такое возможно.
Просыпается интерес к другим языкам и его синтаксису. Думаю, по логике везде тоже самое. Очень интересует Haskell. У кого-нибудь есть опыт в работе с ним? Интересен ваш фидбэк.
Нет ничего лучше чем самому попробовать язык. Возьми и попробуй на хаскелле написать код делающий то же самое что твой код на PHP - выводящий форму и обрабатывающий данные из нее.
Насчет isset, он все равно неправильный. isset нет смысла использовать для проверки есть ли поле в объекте так как оно всегда есть, если есть сам объект.
> Я, например, считаю что символ $ для объявления переменной лишний, точка с запятой ; - тоже
А как тогда обозначать конец команды? Как сделать чтобы команда занимала несколько строк?
> \b\w+[,;!?:]\S+\b
На мой взгляд регулярку можно упростить еще. Ну например, зачем \b перед \w? Без нее все будет точно так же прекрасно искаться. Или зачем \b после \S?
> v\b\w★[жш]ы\w★\b
То же самое - тут на мой взгляд много лишнего - надо бы упростить
> [^.!?;:—,]\s\b(но|а)\b
Здесь ты предполагаешь что пробел всегда стоит ровно один - но это может быть не так. Например пробелов может быть 2, и первый может оказаться захваченным квадратными скобками. Лучше всего сделать выражение вроде "слово", "пробелы", "а или но"
> Задание на поиск "опечаток" на коррумпированных сайтах.
Не видит русских букв в английских словах: http://ideone.com/DZlzuK
Я думаю, задачу можно свести к такому условию: надо искать русские буквы в английских словах и английские в русских, то есть слово с буквами 2 алфавитов. Определять, русское слово или английское, можно либо по первой букве либо по большинству букв.
Опять же регулярка какая-то сложная, достаточно ведь искать слова где есть буквы разных алфавитов, а дальше такие слова можно уже как-то вручную проанализирвоать.
> (?(4)|[а-яё])
Как это должно работать? Если это вот это http://php.net/manual/ru/regexp.reference.conditional.php то по моему это что-то не то и вообще не работает.
> Не согласен, зайчик. А вдруг слово начинается с большой латинской буквы, например [K]алининградская область, или [M]агнитогорск.
Тогда можно по тому каких букв больше. Или по буквам у которых нет аналогов в другом алфавите. ну вообще меня устроило бы и по первой букве.
> а эту дырочку на сайте госзаказов хоть прикрыли за эти годы?
Там теперь цветом выделяют такие буквы. А так, никакой ответственности вроде никто не понес.
>>690413
> Кстати, нельзя ли в регулярках писать код типа U+2014.
Нет, пока единственный способ - закодировать символ 16-чными кодами в utf-8 вроде \xd1\xc8. В PHP7 (не в регулярках, а вообще в строках) появится возможность писать "..\u{2014}...": https://wiki.php.net/rfc/unicode_escape
> \b\w+[,;!?:]\S+\b
На мой взгляд регулярку можно упростить еще. Ну например, зачем \b перед \w? Без нее все будет точно так же прекрасно искаться. Или зачем \b после \S?
> v\b\w★[жш]ы\w★\b
То же самое - тут на мой взгляд много лишнего - надо бы упростить
> [^.!?;:—,]\s\b(но|а)\b
Здесь ты предполагаешь что пробел всегда стоит ровно один - но это может быть не так. Например пробелов может быть 2, и первый может оказаться захваченным квадратными скобками. Лучше всего сделать выражение вроде "слово", "пробелы", "а или но"
> Задание на поиск "опечаток" на коррумпированных сайтах.
Не видит русских букв в английских словах: http://ideone.com/DZlzuK
Я думаю, задачу можно свести к такому условию: надо искать русские буквы в английских словах и английские в русских, то есть слово с буквами 2 алфавитов. Определять, русское слово или английское, можно либо по первой букве либо по большинству букв.
Опять же регулярка какая-то сложная, достаточно ведь искать слова где есть буквы разных алфавитов, а дальше такие слова можно уже как-то вручную проанализирвоать.
> (?(4)|[а-яё])
Как это должно работать? Если это вот это http://php.net/manual/ru/regexp.reference.conditional.php то по моему это что-то не то и вообще не работает.
> Не согласен, зайчик. А вдруг слово начинается с большой латинской буквы, например [K]алининградская область, или [M]агнитогорск.
Тогда можно по тому каких букв больше. Или по буквам у которых нет аналогов в другом алфавите. ну вообще меня устроило бы и по первой букве.
> а эту дырочку на сайте госзаказов хоть прикрыли за эти годы?
Там теперь цветом выделяют такие буквы. А так, никакой ответственности вроде никто не понес.
>>690413
> Кстати, нельзя ли в регулярках писать код типа U+2014.
Нет, пока единственный способ - закодировать символ 16-чными кодами в utf-8 вроде \xd1\xc8. В PHP7 (не в регулярках, а вообще в строках) появится возможность писать "..\u{2014}...": https://wiki.php.net/rfc/unicode_escape
В ОП посте есть задания на SQL/MySQL. Освоив их, ты будешь понимать базы данных и остается только освоить библиотеку вроде PDO чтобы делать запросы к базе данных не руками, а из php скрипта. Ну а дальше, если захочешь, можно уже за паттерны работы с БД браться (TableGateway, ACtiveRecord).
>>691392
тут нет ответа? https://netbeans.org/kb/docs/php/remote-hosting-and-ftp-account_ru.html
>>691482
Ты всегда заменяешь латинницу на кириллицу. Но латинница может быть частью английского слова. Надо замену делать только в ловах со смешанными алфавитами. Если это урсское слово - подсвечивать и менять в нем только латинские буквы, и наоборот.
>>691501
Анончик, переусложнил ты все. Ну посмотри сколько кода, причем с копипастой, сложно и запутанно. Там раза 3 одно и то же скопировано. Плохо.
Вот правильный алгоритм
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
>>691514
Скорее всего проблема в пробелах или кавычках в пути к текущему каталогу. Хотя я могу ошибаться.
В ОП посте есть задания на SQL/MySQL. Освоив их, ты будешь понимать базы данных и остается только освоить библиотеку вроде PDO чтобы делать запросы к базе данных не руками, а из php скрипта. Ну а дальше, если захочешь, можно уже за паттерны работы с БД браться (TableGateway, ACtiveRecord).
>>691392
тут нет ответа? https://netbeans.org/kb/docs/php/remote-hosting-and-ftp-account_ru.html
>>691482
Ты всегда заменяешь латинницу на кириллицу. Но латинница может быть частью английского слова. Надо замену делать только в ловах со смешанными алфавитами. Если это урсское слово - подсвечивать и менять в нем только латинские буквы, и наоборот.
>>691501
Анончик, переусложнил ты все. Ну посмотри сколько кода, причем с копипастой, сложно и запутанно. Там раза 3 одно и то же скопировано. Плохо.
Вот правильный алгоритм
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
>>691514
Скорее всего проблема в пробелах или кавычках в пути к текущему каталогу. Хотя я могу ошибаться.
Не использовать статические методы. Конечно с ними никакой DI не получится. Надо использовать либо такие контроллеры, где ты создаешь их сам и можешь передать что-то в конструктор:
http://silex.sensiolabs.org/doc/providers.html#controller-providers
либо анонимные функции котоые могут видеть переменные через use.
А статические методы ты зря используешь.
>>691559
Спроси у них.
>>691603
Почитай про callable https://habrahabr.ru/post/259991/ http://php.net/manual/ru/language.types.callable.php
Надо либо передавать анонимную функцию в качестве обработчка, либо ссылку на метод объекта:
$ctrl = new Ctrl(....);
$app->get('/', [$ctrl, 'indexAction']);
> function inclineWord($number, $word) {
Функция искуственно переусложнена на мой взгляд. Во-первых ты исукственно ввел ограничение что она склоняет только 3 слова (рубли, тысячи, миллионы) хотя проще сделать универсальную функцию, склоняющую любое слово. Пусть функция принимает на вход 3 варианта слова и выбирает один из них.
Далее, тут ошибка в создании переменной:
if (...) {
$incline = 5;
} elseif (...) {
$incline = 2;
}
Если ты создаешь переменную внутри ветки в ифе, ты не должен ее исплоьзовать снаружи так как есть шанс что ни одно из условий не выполнится и переменная не будет существовать.
Далее, программа склоняет неправильно:
> На вашем счету 1571887 один миллионов пятьсот семьдесят одна тысяча восемьсот восемьдесят шесть рублей
> function smallNumberToText($number, $isFemale) {
тут аж 4 уровня вложенности ифов. Слишком сложно разбирать такой код, надо упрощать. Более того, там есть копипаста из-за чего функция стала огромной и нечитаемой. Избавься от копипасты. Ну например вместо того чтобы делать огромные ветки, попробуй обрабатывать части слова по очереди:
- если в числе есть сотни, добавляем слово для сотен
- ... слово для 11-19
- ... слово десятков
- ... слово единиц
Части строки удобно складывать в массив.
> $number000 = strtr($number000, $spelling);
Странная конструкция. Для поиска в массиве по индексу есть оператор - квадратные скобки
> function bitNumber ($number) {
имя функции должно начинаться с глагола
> while ($number>=10) {
> $number = $number/10;
> $bitNumber++;
Тут можно использовать логарифм по основанию 10 вместо цикла. Логарифм показывает в какую степень надо возвести основание (10) чтобы получить данное число.
> if (((mb_strlen($number) - $position) % 3) == 0 ) {
> $pieceNumber = mb_substr($number, $position, $len);
Не используй строковые функции с числами
> if ($bitNumber >= 7) {
Гораздо проще просто проверить что число больше или равно миллиону
В общем, код пока не годится - надо исправлять.
> конструкция из IF в в функции переименования маленьких чисел похожа на фрактал. Но совершенно не редактируема, как литой кусок говна
В таких случаях можно выносить блоки в отдельные функции с понятными именами. Но в твоем случае надо вообще менять алгоритм как я описал выше - там будет всего несколько последовательно идущих ифов.
> Каждый раз, после ошибки, приходится переписывать ее занаво, т.к. не получается разобраться. Даже с комментами. Просто количество скобочек сбивает с толку
Ну вот, ты сам видишь что такой код не годится. Код должен быть понятен.
> function inclineWord($number, $word) {
Функция искуственно переусложнена на мой взгляд. Во-первых ты исукственно ввел ограничение что она склоняет только 3 слова (рубли, тысячи, миллионы) хотя проще сделать универсальную функцию, склоняющую любое слово. Пусть функция принимает на вход 3 варианта слова и выбирает один из них.
Далее, тут ошибка в создании переменной:
if (...) {
$incline = 5;
} elseif (...) {
$incline = 2;
}
Если ты создаешь переменную внутри ветки в ифе, ты не должен ее исплоьзовать снаружи так как есть шанс что ни одно из условий не выполнится и переменная не будет существовать.
Далее, программа склоняет неправильно:
> На вашем счету 1571887 один миллионов пятьсот семьдесят одна тысяча восемьсот восемьдесят шесть рублей
> function smallNumberToText($number, $isFemale) {
тут аж 4 уровня вложенности ифов. Слишком сложно разбирать такой код, надо упрощать. Более того, там есть копипаста из-за чего функция стала огромной и нечитаемой. Избавься от копипасты. Ну например вместо того чтобы делать огромные ветки, попробуй обрабатывать части слова по очереди:
- если в числе есть сотни, добавляем слово для сотен
- ... слово для 11-19
- ... слово десятков
- ... слово единиц
Части строки удобно складывать в массив.
> $number000 = strtr($number000, $spelling);
Странная конструкция. Для поиска в массиве по индексу есть оператор - квадратные скобки
> function bitNumber ($number) {
имя функции должно начинаться с глагола
> while ($number>=10) {
> $number = $number/10;
> $bitNumber++;
Тут можно использовать логарифм по основанию 10 вместо цикла. Логарифм показывает в какую степень надо возвести основание (10) чтобы получить данное число.
> if (((mb_strlen($number) - $position) % 3) == 0 ) {
> $pieceNumber = mb_substr($number, $position, $len);
Не используй строковые функции с числами
> if ($bitNumber >= 7) {
Гораздо проще просто проверить что число больше или равно миллиону
В общем, код пока не годится - надо исправлять.
> конструкция из IF в в функции переименования маленьких чисел похожа на фрактал. Но совершенно не редактируема, как литой кусок говна
В таких случаях можно выносить блоки в отдельные функции с понятными именами. Но в твоем случае надо вообще менять алгоритм как я описал выше - там будет всего несколько последовательно идущих ифов.
> Каждый раз, после ошибки, приходится переписывать ее занаво, т.к. не получается разобраться. Даже с комментами. Просто количество скобочек сбивает с толку
Ну вот, ты сам видишь что такой код не годится. Код должен быть понятен.
Надо просто описать действия вкладчика, примерно так:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
>>691817
Не возникнет. last id считается отдельно для каждого соединения с базой данных, так что 2 скрипта увидят каждый свой id.
Насчет доктрины - тут такая штука, что это уже готовый маппер. Ты только описываешь каким колонкам соответствуют поля объекта, а она за тебя генерирует маппер. Плюс умеет делать связи между объектами. Когда у тебя боьше одной таблицы, это здорово упрощает жизнь и избавляет от рутинного кода. Потому было бы неплохо повозиться с ней. Ну нет, так нет, лишаешь себя полезного инструмента.
>>691836
Обычно
/var/www/example.com
Я открыл страницу с отключенным яваскриптом и у меня первый экран черный целиком, кроме пустого красного квадрата слева. И только прокрутив, появляется какой-то контент. Зачем так делать? Надо сначала сверстать нормальную страницу, а потом добавлять на нее эффекты - это называется progressive enhancement. Тут нет никакой причины делать черный блок в шапке.
Более того, у меня подозрение что анимацию выезжающей картинки можно сделать вообще средствами CSS. А еще лучше конечно ее вообще не делать.
Дизайн мне не нравится - на моем экране он слишком большой и информации на экране помещается мало. Ну и вообще я любитель черных букв на белом фоне. При том что все гигантское, во многих местах шрифт мелкий и серый, так что надо вглядываться - даже человеку с нормальным зрением. Этот диазйнер по моему ничего не смыслит в дизайне и подаче информации. Если он считает что текст настолько не нужен, то пусть не помещает его на страницу вообще.
На макете поля вокруг страницы сделаны градиентом - а на странице нет градиента, просто черные поля.
> 10 Respirators
Тут у тебя цифра сливается с текстом в блоке тарифов
Фон на блоке outr skills у тебя черный, а на макете там что-то размытое.
Эффекты ужасные, они затрудняют восприятие сайта. Только я прокрутил и пытаюсь прочесть надписи, как прямо поверх них едет картинка или что-нибудь анимируется и взгляд срывается с текста. Зачем так делать? Анимация позвляет направлять внимание пользователя в нужную сторону, но тут она использована бездумно - просто чтобы было.
Кнопка с меню не работает. Более того, прятать меню на большом экране - глупая на мой взгляд идея так как:
- пользователь не видит что в меню
- надо делать лишний клик чтобы куда-то перейти
Форма обратной связи не выглядит как форма. Пользователь может и не понять что это такое.
Если уменьшить масштаб в браузере то почему-то верстка разваливается. блоки с тарифами становятся узкими и текст в них начинает переноситься. В Our skills съезжают графиики.
Если увеличить масштаб, то при наведении на картинку, плашка над надписью view more вываливается из блока. Блок our clients разваливается.
Если сделать окно узким, появляется вторая вертикальная линейка прокрутки.
> <h2 class="page-header-hgroup__title">we’re sarbat</h2>
> <h3 class="page-header-hgroup__slogan">a creative design agency</h3>
Где это видано чтобы текст состоял из 4 заголовков подряд?
> <div class="row m-b-100">
> <div class="col-md-4">
2 бесполезных дива. Зачем они тут нужны? Также, ты закладываешь что в гриде будет ровно 3 колонки и делаешь его неадаптивным.
> <hr/>
Где мой 2000 год. И что это за слеш в конце? Ты часом XML с HTML не путаешь?
> <section class="feedback">
> <div class="feedback-slider">
> <div class="page-wrapper">
> <div class="grid">
> <div class="row">
> <div class="col-sm-6">
> <div class="feedback-comment">
> <div class="feedback-comment__avatar f-l"><img src="img/content/feedback-avatar-2.jpg"/></div>
> <div class="feedback-comment-details">
> <h2 class="feedback-comment__headi
такое ощущение что верстальщику платят за дивы. Это же надо такую лестницу нагородить ради примитивного блока с картинкой и текстом.
> font-family: "Notosans italic";
> font-family: "Notosans bold italic";
> font-family: "Montserrat bold";
Непраивльно объявлены шрифты - это одно семейство.
> src: url(../fonts/montserrat-bold.otf)
Всего один формат - почему?
> html, body, p, button, h1, h2, h3, h4, h5, h6, div, input, ul, li {
> margin: 0;
Это кошмар
> html, body {
> overflow-x: hidden;
Это тоже кошмар
> ul {
> list-style-type: none; }
Теперь все списки на странице останутся без точек
В ксс коде куча копипасты. Нет вендорных префиксов.
В общем, я надеюсь что ты просто пока начинающий и первый блин комом. Это конечно надо переделывать все, от HTML до JS, в идеале вместе с дизайном. Пока качество ниже плинтуса.
Я открыл страницу с отключенным яваскриптом и у меня первый экран черный целиком, кроме пустого красного квадрата слева. И только прокрутив, появляется какой-то контент. Зачем так делать? Надо сначала сверстать нормальную страницу, а потом добавлять на нее эффекты - это называется progressive enhancement. Тут нет никакой причины делать черный блок в шапке.
Более того, у меня подозрение что анимацию выезжающей картинки можно сделать вообще средствами CSS. А еще лучше конечно ее вообще не делать.
Дизайн мне не нравится - на моем экране он слишком большой и информации на экране помещается мало. Ну и вообще я любитель черных букв на белом фоне. При том что все гигантское, во многих местах шрифт мелкий и серый, так что надо вглядываться - даже человеку с нормальным зрением. Этот диазйнер по моему ничего не смыслит в дизайне и подаче информации. Если он считает что текст настолько не нужен, то пусть не помещает его на страницу вообще.
На макете поля вокруг страницы сделаны градиентом - а на странице нет градиента, просто черные поля.
> 10 Respirators
Тут у тебя цифра сливается с текстом в блоке тарифов
Фон на блоке outr skills у тебя черный, а на макете там что-то размытое.
Эффекты ужасные, они затрудняют восприятие сайта. Только я прокрутил и пытаюсь прочесть надписи, как прямо поверх них едет картинка или что-нибудь анимируется и взгляд срывается с текста. Зачем так делать? Анимация позвляет направлять внимание пользователя в нужную сторону, но тут она использована бездумно - просто чтобы было.
Кнопка с меню не работает. Более того, прятать меню на большом экране - глупая на мой взгляд идея так как:
- пользователь не видит что в меню
- надо делать лишний клик чтобы куда-то перейти
Форма обратной связи не выглядит как форма. Пользователь может и не понять что это такое.
Если уменьшить масштаб в браузере то почему-то верстка разваливается. блоки с тарифами становятся узкими и текст в них начинает переноситься. В Our skills съезжают графиики.
Если увеличить масштаб, то при наведении на картинку, плашка над надписью view more вываливается из блока. Блок our clients разваливается.
Если сделать окно узким, появляется вторая вертикальная линейка прокрутки.
> <h2 class="page-header-hgroup__title">we’re sarbat</h2>
> <h3 class="page-header-hgroup__slogan">a creative design agency</h3>
Где это видано чтобы текст состоял из 4 заголовков подряд?
> <div class="row m-b-100">
> <div class="col-md-4">
2 бесполезных дива. Зачем они тут нужны? Также, ты закладываешь что в гриде будет ровно 3 колонки и делаешь его неадаптивным.
> <hr/>
Где мой 2000 год. И что это за слеш в конце? Ты часом XML с HTML не путаешь?
> <section class="feedback">
> <div class="feedback-slider">
> <div class="page-wrapper">
> <div class="grid">
> <div class="row">
> <div class="col-sm-6">
> <div class="feedback-comment">
> <div class="feedback-comment__avatar f-l"><img src="img/content/feedback-avatar-2.jpg"/></div>
> <div class="feedback-comment-details">
> <h2 class="feedback-comment__headi
такое ощущение что верстальщику платят за дивы. Это же надо такую лестницу нагородить ради примитивного блока с картинкой и текстом.
> font-family: "Notosans italic";
> font-family: "Notosans bold italic";
> font-family: "Montserrat bold";
Непраивльно объявлены шрифты - это одно семейство.
> src: url(../fonts/montserrat-bold.otf)
Всего один формат - почему?
> html, body, p, button, h1, h2, h3, h4, h5, h6, div, input, ul, li {
> margin: 0;
Это кошмар
> html, body {
> overflow-x: hidden;
Это тоже кошмар
> ul {
> list-style-type: none; }
Теперь все списки на странице останутся без точек
В ксс коде куча копипасты. Нет вендорных префиксов.
В общем, я надеюсь что ты просто пока начинающий и первый блин комом. Это конечно надо переделывать все, от HTML до JS, в идеале вместе с дизайном. Пока качество ниже плинтуса.
Вот еще задачки
https://ideone.com/fKYM51 - кредитный калькулятор с функциями
https://ideone.com/9wJors - проверка автомобильного номера
https://ideone.com/PXYHmh - проверка номеров
Все интересней становится :3
Vot eto da.
> такое ощущение что верстальщику платят за дивы. Это же надо такую лестницу нагородить ради примитивного блока с картинкой и текстом.
Объясни, пожалуйста, как сделать лучше.
> Непраивльно объявлены шрифты - это одно семейство.
Это критично?
другой-начинающий-верстальщик
>github.com/foobar1643/student-list/
Ну офигеть, я чет думал там все намного проще будет.
Оп, можешь выложить список решений этой задачки? Очень интересно посмотреть как аноны делали.
Я решил все задачи, кроме "Навигатора" в бонусных.
Филолог, 32 года, изучаю с декабря.
Сейчас вожусь с ООП, сделал также все задачи на HTML+CSS.
> Их даже не все "специалисты" решить могут, лол.
Если ты про учебник то задачи там элементарные. Профессиональный программист их в уме решит и ни одного сложного места для него нет.
Кстати спасибо ОПу за такой подробный гайд :3 Кота запостил.
В твоем коде на самом деле несколько ошибок которые ты допустил по невнимательности.
Первая из них на 11 строке
>echo "У анона выпало {$anonDice1} и {$anonDice2}\nУ компьютера выпало {$compDice1} и {$compDice2}\n;
Тут ты не закрыл кавычки, из-за этого интепретатор PHP воспринимает весь код дальше как строку. Нужно всегда быть внимательным и закрывать кавычки.
Вторая ошибка на 16 строке
>$doubles = Даблы. Игра закончена.;
Тут ты объявить переменную $doubles как строку, но не используешь кавычки.
Третья ошибка на 27 строке
>} else ($anonSum == $compSum) {
В else не может быть условия, условие может быть в else if.
https://github.com/someApprentice/Students/blob/master/app/Model/Gateway/StudentGateway.php#L9
>> public function getStudentById($id) {
>Почему метод возвращает массив, а не модель студента? Чем массив удобнее?
Нужно по среди метода создавать модель студента?
У Студента слишком много свойств чтобы передавать их все в конструктор, меня смущает что нужно создавать класс студента посреди класса отвечающего за работу с ДБ:
public function getStudentById($id) {
...
$result = $student->fetch(\PDO::FETCH_ASSOC);
$student = new Student()
$student->setName($result['name']);
...
return $student;
}
А на второй что не так?
>>663578
https://github.com/someApprentice/Students/blob/6471191b2bd63bb5aa3205369cfb26adb5a0067d/app/Model/Gateway/StudentGateway.php#L103
>> return $insert;
>Нарушение инкапсуляции. С базой работает только Gateway, зачем ты выдаешь наружу объект-запрос? Все что относится к базе должно быть внутри.
А как узнать потом что функция работает правильно?
Ну что ты в самом деле, как будто в сурьезном энтырпрайзе на джаве или шарпе никогда не пишут велосипедов и костылей.
Давай разберем вопрос объектов и массивов. Очевидно, что функции которые принимают или возвращают студента, должны хранить его в переменной в каком-то виде.
Вот мы можем представить студента в таком виде:
$student = [
'name' => 'Ivan',
'birthYear' => 1990
];
или таком:
$student = new Student;
$student->name = 'Ivan'; // или setName()
$student->birthYear = 1990;
Что мне очевидно, так это то что выгоднее выбрать какой-то единый способ, чем сделать чтобы в половине функций использовался массив, а в половине объект. Иначе нам придется делать лишние преобразования.
Соответственно вопрос: подумай, какие преимущества и недостатки есть у каждого способа. И когда какой лучше использовать.
Насчет этого:
> меня смущает что нужно создавать класс студента посреди класса отвечающего за работу с ДБ:
Ну ведь метод должен вернуть что-то что хранит информацию о студенте. Либо массив либо объект. Что-то все равно придется создать. В этом и есть смысл метода getStudentById.
> У Студента слишком много свойств чтобы передавать их все в конструктор,
Их и не требуется передавать. Можно сделать пустой конструктор и заполнять свойства позднее. В конструктор обычно передают вещи без которых объект работать не может, но студента вполне можно создать не заполняя его поля, с значениями по умолчанию.
Давай разберем вопрос объектов и массивов. Очевидно, что функции которые принимают или возвращают студента, должны хранить его в переменной в каком-то виде.
Вот мы можем представить студента в таком виде:
$student = [
'name' => 'Ivan',
'birthYear' => 1990
];
или таком:
$student = new Student;
$student->name = 'Ivan'; // или setName()
$student->birthYear = 1990;
Что мне очевидно, так это то что выгоднее выбрать какой-то единый способ, чем сделать чтобы в половине функций использовался массив, а в половине объект. Иначе нам придется делать лишние преобразования.
Соответственно вопрос: подумай, какие преимущества и недостатки есть у каждого способа. И когда какой лучше использовать.
Насчет этого:
> меня смущает что нужно создавать класс студента посреди класса отвечающего за работу с ДБ:
Ну ведь метод должен вернуть что-то что хранит информацию о студенте. Либо массив либо объект. Что-то все равно придется создать. В этом и есть смысл метода getStudentById.
> У Студента слишком много свойств чтобы передавать их все в конструктор,
Их и не требуется передавать. Можно сделать пустой конструктор и заполнять свойства позднее. В конструктор обычно передают вещи без которых объект работать не может, но студента вполне можно создать не заполняя его поля, с значениями по умолчанию.
Не путай одиночные костыли с проектом, который уродлив от начала и до конца.
Получается, с этой функцией можно отправлять письма даже от "дикого" адреса например с abu3n3nyashaANUSu-+2chPUNCTUM*ffhk
Она требует какой-то доп. настройки сервера или работает с plain Apache?
Я хотел сказать что можно возвращать сам id или прописывать его в объект-студента. А тут нарушение инкапсуляции. Инкапсуляция подразумевает сокрытие внутри класса деталей его работы. То есть когда мы вызываем метод вставитСтудентаВТаблицу нас не интересует какой именно библиотекой (PDO/mysqli) это делается, какие параметры соединения с БД, какая это БД (mysql или mongodb). Это внутреннее дело класса TDGateway. Мы лишь знаем что можем дать ему объект и он его сохранит.
И возвращая из него наружу объект связанный с PDO, ты нарушаешь этот принцип. Ты раскрываешь внутреннюю реализацию окружающему коду и делаешь его зависящим от нее.
Чем это плохо? Ну тем что функционал работы с базой данных вытекает из класса в окружающий код и смешивается с другим функционалом.
Ну к примеру если мы завтра решим перейти с PDO на mysqli нам придется править не только класс TDG, а еще искать где используется этот утекший объект PDO и менять код там.
И даже если мы никуда не переходим, а просто хотим разобраться как работает класс, это может доставить неудобства.
Конечно на твоем простом приложении это не чувствуется. Но представь большое приложение над которым работает 100 человек. Сегодня ты выдал наружу объект PDO - завтра он уже используется в 50 местах и отрефакторить код становится намного сложнее.
Нет, это серьезная ошибка и она показывает что ты пока не понял концепцию инкапсуляции и разбиения кода на независимые части.
>>696266
Так плохо написать на Яве вряд ли получится. Плюс она требует больше усилий для изучения что отсеивает ленивых и плохих кодеров. Там ведь без ООП тебя даже на стажера не возьмут.
>для хранения телефонов
char(10), с проверкой перед записью или с дерзким триггером
>Координат
http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html
по одному на измерение
>Булевых значений
Вот тут всё сложно. Или вот эта экзотика
http://dev.mysql.com/doc/refman/5.7/en/bit-type.html
Или
tinyint(1)
Проблема тут только в том что человек не доучился. Он изучил синтаксис, но не дошел даже до ООП, архитектуры, не говоря хотя бы про умение писать читабельный и поддерживаемый код. То есть написать скрипт на 15 строк этот человек способен. а на большое приложение его знаний не хватает.
Увы, в нашей сфере такого много. Даже люди с опытом часто плохо разбираются в тонкостях ООП дизайна или исключениях. плохо знают обработку ошибок в PHP, а некоторые даже не могут объяснить как правильно экранировать данные.
Разумеется если вы будете учится по нашим задачам, вам придется во всем этом разобраться и код как на скриншотах вам тут никто не позволит писать.
И хочу еще добавить, что я тут такое часто вижу, люди не хотят учиться всерьез, а хотят побыстрее освоить основы и куда-нибудь устроиться.
Ну зато на работе тебе платят деньги в отличие от нашего треда. А что код будет красивый никто не обещал. Старайся сам такой не писать.
Есть 2 таблицы, допустим таблиза `user` с айдишником юзера и его именем и допустим таблица `user_age` в которой есть id, user_id (внешний ключ) и age. Понятно, что возраст можно тоже в первую таблицу, но чисто для примера. Так вот. Добавляется пользователь на сайт, заполняя форму с именем и возрастом, в таблицу user он норм добавляется, там его id автоинкремент и все ок, но как тут же добавлять его во вторую таблицу если мы еще не знаем его id? Можно конечно написать какой-то костыль, но мне кажется логичным если бы это можно было делать средствами SQL
>>код как на скриншотах вам тут никто не позволит писать
Вроде бы у вас тут все такие няшечки почти как доброчан но вот от таких утверждений "холодок" пробирает. Может, все-таки дать возможность выбора стиля? На работе приходится писать код вместе с другими людьми, а в этом треде люди просто наслаждаются кодом.
Создать триггер
Вот тут есть специфический костыль:
http://dev.mysql.com/doc/refman/5.7/en/getting-unique-id.html
INSERT INTO foo (auto,text)
VALUES(NULL,'text'); # generate ID by inserting NULL
INSERT INTO foo2 (id,text)
VALUES(LAST_INSERT_ID(),'text'); # use ID in second table
Ты сам бы хотел ковырять вилкой подобный код от того, кто особо не заморачивался?
Давай теперь по тротуарам ездить и переходить улицы где попало, шишка встанет, возбудимся.
Ковырял код сайта на Битриксе, по чужому примеру написал нужный мне компонент. Мне норм. Можно разобраться, если есть комментарии и код хоть как-нибудь структурирован (хоть в виде цельных функций с небольшим количеством точек входа, а не просто слабосвязные фрагменты в разных файлах). Тот код ещё tolerable
Аноны, объясните, что делает function mb_ucfirst и так далее? Почему в уроке об этом ничего вообще?
Нет, не дадим. Надо с самого начала приучать писать правильно. Как бонус, если вы научитесь ваш код в тестовом задании или собеедовании будет выгодно выделяться.
>>696350
Если уметь то на автомате пишется. А если не уметь то хоть неделю проектируй ничего не получится.
>>696344
Через last insert id. Вставляешь первую запись, получаешь id, вставляешь вторую.
>>696419
В уроке описаны функции работы со строками mb_substr и mb_strtoupper - ты читал? mb_usfirst это функция которую написал автор кода, с вопросами надо к нему обращаться.
И не копируй этот код - мало того что он неряшливо отформатирован, он еще и написан неэффективно, неправильные циклы использвоаны, много лишних вещей.
Функции вроде mb_strtoupper должны знать в какой кодировке текст чтобы его обработать. Потому что в одной кодировке одна буква кодируется одним байтом, а в другой та же самая буква обозначается другим байтом в памяти. Соответственно без знания кодировки текста функции не могут выполнять свою работу.
Автоматически определить кодировку нельзя, текст в памяти это просто набор байтов (чисел).
И ты не должен брать код по ссылке за основу. Он довлоьно плох. Лучше перечитай урок про строки, мануал, и напиши все сам.
А я вот где-то читал другое мнение, может быть даже в этом треде. Суть была в том что кто-то жаловался на то, что новички используют всякие ORM типа доктрины, а потом когда нужно написать TDG или EntityMapper руками, они ничего не могут и тупят.
У меня подозрение есть, что вот мол на странице будет десяток отдельных типа плагинов выводы товаров, комментариев и на каждый надо свой контроллер, который использует какие то общие штуковины, например соединение с бд и типа удобно все это в одном месте держать. Я правильно понял? Ну там ошибки например в нем собирать, да-да?
Вообще с вью и моделью вроде все очевидно и понятно, а как обращаться с этими контроллерами нет. Весь день эту штуку курю, хочется разобраться как следует перед тем как начать.
>удобно все это в одном месте держать. Я правильно понял?
Да. Так же, в контейнере объект создается один раз, и каждый раз когда ты вызываешь метод get(), то получаешь уже созданный экземпляр объекта, а не создаешь его каждый раз заново.
Еще контейнеры удобно использовать при Dependency Injection в контроллерах. Если делать контроллеры зависимыми от контейнера, это позволит убрать завязку контроллера на определенный класс, и в будущем сделать код более удобным для масштабирования.
>Ну там ошибки например в нем собирать, да-да?
Нет, ошибки в нем собирать не нужно. Контейнер существует только для того чтобы хранить объекты, и отдавать эти объекты по необходимости. Для ошибок существуют исключения, у ОПа есть урок на эту тему
https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
И если ты не читал, почитай про Dependency Injection вот тут
https://gist.github.com/codedokode/e1d31a31b37d5f635057
>И если ты не читал, почитай про Dependency Injection вот тут
Это походу мне и надо. Спасибо большое.
git pull в репозитории с пректом. Или git clone, но это через задницу.
КАК СТРАННО-ТО, ДА?
Нет чтоб сидеть, учить, дрочить, изучать годами, живя под мостом или на дошираках, так эти пидоры НА РАБОТУ ХОТЯТ, да побыстрее.
Согласен, да, степень охуевания крайняя.
Пиздить их надо. Ногами.
>> Непраивльно объявлены шрифты - это одно семейство.
> Это критично?
Да, из-за этого например не будет такая штука работать:
<div>hello <em>world</em></div>
Так как у него курсивная версия шрифта объявлена как другой шрифт с другим font-family, то текст в em не станет курсивным или может получит "искуственный" наклон, сгенерированный браузером вместо настощяего курсивного шрифта.
Также, используется всего один формат шрифтов, не предоставляется напрмер современный woff для современных браузеров. Ну и вообще код подключения шрифтов там плохой, человек явно пропустил изучение этой темы.
>> такое ощущение что верстальщику платят за дивы. Это же надо такую лестницу нагородить ради примитивного блока с картинкой и текстом.
> Объясни, пожалуйста, как сделать лучше.
Надо начинать с семантичной верстки в HTML. То есть в HTML мы размечаем текст тегами по смыслу, а все оформление выносим в CSS.
Условно говоря, если там есть отзыв с фото, заголовком и текстом, как его можно разметить? Ну наверно так:
<div class="testimonial">
<h2>заголовок</h2>
<div class="testimonial__text">текст</div>
<img src=... alt=... class="testimonial__avatar">
</div>
Посмотри на эту разметку: у нас есть отзыв (testimonial), внутри в него вложен заголовок, текст и картинка. Согласись, это логичный и минимальный вариант - дальше упрощать некуда.
Заметь что я использовал БЭМ-стиль для именования классов.
А только после этого мы с помощью CSS задаем оформление этих блоков. При этом нам может быть придется внести небольшие поправки. Ну например, если мы хотим вынести картинку вбок флоатом, нам придется переставить ее в начало блока, и может для сложной верстки нам где-то придется добавить один-другой див. Ну к примеру если у нас есть 3 колонки:
<div class="column">...</div>
<div class="column">...</div>
<div class="column">...</div>
Нам может быть также придется завернуть их в див или section чтобы сделать clearfix.
То есть я понимаю, что CSS не всесилен, флексбокс пока не везде работает, и иногда HTML приходится чуть-чуть подправлять ради верстки. Но этого должно быть как можно меньше. Порядок всегда должен быть такой:
1) смысловая разметка текста тегами
2) написание CSS
В идеале мы бы хотели чтобы при смене дизайна HTML требовал минимальные изменения (кстати это помогает при адаптивной верстке так как адаптивная версия это фактически другой дизайн для той же страницы).
В макете мы видим что это не соблюдается. Если ты откроешь HTML то увидишь что он переполнен быссмыссленными вмпомогательными дивами, которые нужны только для того чтобы на них повесить какой-нибудь стиль. Большое число этих дивов говорит о слабом уровне автора. Он не смог отделить оформление от разметки и оформление из CSS вытекло в HTML. Плохо.
>> Непраивльно объявлены шрифты - это одно семейство.
> Это критично?
Да, из-за этого например не будет такая штука работать:
<div>hello <em>world</em></div>
Так как у него курсивная версия шрифта объявлена как другой шрифт с другим font-family, то текст в em не станет курсивным или может получит "искуственный" наклон, сгенерированный браузером вместо настощяего курсивного шрифта.
Также, используется всего один формат шрифтов, не предоставляется напрмер современный woff для современных браузеров. Ну и вообще код подключения шрифтов там плохой, человек явно пропустил изучение этой темы.
>> такое ощущение что верстальщику платят за дивы. Это же надо такую лестницу нагородить ради примитивного блока с картинкой и текстом.
> Объясни, пожалуйста, как сделать лучше.
Надо начинать с семантичной верстки в HTML. То есть в HTML мы размечаем текст тегами по смыслу, а все оформление выносим в CSS.
Условно говоря, если там есть отзыв с фото, заголовком и текстом, как его можно разметить? Ну наверно так:
<div class="testimonial">
<h2>заголовок</h2>
<div class="testimonial__text">текст</div>
<img src=... alt=... class="testimonial__avatar">
</div>
Посмотри на эту разметку: у нас есть отзыв (testimonial), внутри в него вложен заголовок, текст и картинка. Согласись, это логичный и минимальный вариант - дальше упрощать некуда.
Заметь что я использовал БЭМ-стиль для именования классов.
А только после этого мы с помощью CSS задаем оформление этих блоков. При этом нам может быть придется внести небольшие поправки. Ну например, если мы хотим вынести картинку вбок флоатом, нам придется переставить ее в начало блока, и может для сложной верстки нам где-то придется добавить один-другой див. Ну к примеру если у нас есть 3 колонки:
<div class="column">...</div>
<div class="column">...</div>
<div class="column">...</div>
Нам может быть также придется завернуть их в див или section чтобы сделать clearfix.
То есть я понимаю, что CSS не всесилен, флексбокс пока не везде работает, и иногда HTML приходится чуть-чуть подправлять ради верстки. Но этого должно быть как можно меньше. Порядок всегда должен быть такой:
1) смысловая разметка текста тегами
2) написание CSS
В идеале мы бы хотели чтобы при смене дизайна HTML требовал минимальные изменения (кстати это помогает при адаптивной верстке так как адаптивная версия это фактически другой дизайн для той же страницы).
В макете мы видим что это не соблюдается. Если ты откроешь HTML то увидишь что он переполнен быссмыссленными вмпомогательными дивами, которые нужны только для того чтобы на них повесить какой-нибудь стиль. Большое число этих дивов говорит о слабом уровне автора. Он не смог отделить оформление от разметки и оформление из CSS вытекло в HTML. Плохо.
Контейнер создает и хранит сервисы. Он же следит чтобы они были в одном экземпляре, а не создавались каждый раз заново.
Сервис - это объект, который обычно существует в одном экземпляре и выполняет какие-то действия. Ну например, валидатор, класс TDG для работы с БД, объект PDO. Модель студента - это не сервис, это как раз противоположная вещь, модель, или говоря по-умному "модель предметной области" (Domain model). Она может быть в нескольких экземплярах, а может вообще не быть.
О, я не заметил, а там в коде такой шедевр:
explode("<br />", ...)
Стоит добавить или убрать слеш или пробел - и все сломается. Прекрасно - с таким кодом, постоянно требующим поддержки, разработчику явно не грозит увольнение.
Алсо как я вижу там идет SQL инъекция через куки.
В шапке есть пара книг, не очень новых, а других я не знаю.
>>691932
Установи и настрой xdebug. Либо старый добрый var_dump. Твой способ с консолью имеет недостатки, что если например вызвать функцию внутри HTML атрибута, то тег скрипт разломает атрибут и сломает верстку.
>>691990
Ява, C#.
>>692038
Если подставить сумму в 1000 р то считает неверно: http://ideone.com/6egR2l
Да и код не очень правильный, ты же фактически сделал 2 копии кода, который считает выплат за месяц, а зачем делать 2 копии когда можно сделать универсальный код.
>>692046
Не работает для 1000 р: http://ideone.com/C3KDmi
Много копипасты в коде.
Например можно использовать метод деления пополам, пробуя разные размеры шрифта и меряя размер получившегося текста.
>>692065
У тебя алгоритм выглядит так:
- увеличить долг и выплатить 5000
- если в следующем месяце будет меньше 5000, то увелчиить долг и выплатить сколько осталось
А надо так:
- увеличить долг и выплатить сколько нужно
- если долг <= 0 то завершить цикл
>>692131
> Вот задача на игру в кубики. https://ideone.com/uufpgm
Все правильно сделано
Фигурные скобки не обязательны, но они помогают когда надо написать обращение к массиву или отделить переменную от окружающего текста.
> Айфон в кредит https://ideone.com/XBhKRi
Считает верно, но код можно чуть улучшить.
> $creditBalance = $creditBalance - $monthlyPayment;
> $paymentTotal = $paymentTotal + $monthlyPayment;
Вот это скопировано 2 раза. Попробуй избавиться от копирования, вынеся это наружу из ифа и заменив иф на функцию min или max.
>>692142
Скобки ради читабельности и выделения 2 отдельных условий визуально.
>>692208
Твой запрос ищет записи у которых есть filter_id = 1 или 2. А надо найти записи у которых есть одновременно* оба этих значения. Ну например посты с тегами "юмор" и "политика" одновременно.
Например можно использовать метод деления пополам, пробуя разные размеры шрифта и меряя размер получившегося текста.
>>692065
У тебя алгоритм выглядит так:
- увеличить долг и выплатить 5000
- если в следующем месяце будет меньше 5000, то увелчиить долг и выплатить сколько осталось
А надо так:
- увеличить долг и выплатить сколько нужно
- если долг <= 0 то завершить цикл
>>692131
> Вот задача на игру в кубики. https://ideone.com/uufpgm
Все правильно сделано
Фигурные скобки не обязательны, но они помогают когда надо написать обращение к массиву или отделить переменную от окружающего текста.
> Айфон в кредит https://ideone.com/XBhKRi
Считает верно, но код можно чуть улучшить.
> $creditBalance = $creditBalance - $monthlyPayment;
> $paymentTotal = $paymentTotal + $monthlyPayment;
Вот это скопировано 2 раза. Попробуй избавиться от копирования, вынеся это наружу из ифа и заменив иф на функцию min или max.
>>692142
Скобки ради читабельности и выделения 2 отдельных условий визуально.
>>692208
Твой запрос ищет записи у которых есть filter_id = 1 или 2. А надо найти записи у которых есть одновременно* оба этих значения. Ну например посты с тегами "юмор" и "политика" одновременно.
>>692315
> $number = 0;
> $op = $char;
Эти 2 команды повторяются, можно вынести их из ифа чтобы не повторялись.
> (is_numeric($char) | $char=='.')
Логическое ИЛИ пишется как ||, а у тебя тут битовое ИЛИ, которое может давать совсем другие результаты.
Также, лучше избегать exit внутри функции, так как это получается какая-то нехорошая функция которая может завершить скрипт и не вернуть нам управление.
Так, в остальном, все верно.
проверяю только новый код.
Я все-таки подумал, надо бы при ошибке CSRF выводить соотв. сообщение и показывать заполненную форму. То есть относиться к ней как к обычной ошибке. Ну вдруг по какому-то стечению обстоятельств у пользователя куки отключены или он их почистил в процессе заполнения формы?
Плюс браузер имеет право удалять куки если их слишком много.
Ты же при ошибке CSRF теряешь введенные данные.
Я бы сделал так:
$errors = $regHelper->validateStudent($student);
Если ошибка в токене, добавляем ее в errors.
....
> $student = $this->getFormData($student);
Тут нет смысла возвращать студента так как объект передается в функцию как бы по ссылке
https://github.com/foobar1643/student-list/blob/d9cc915228d101ae0ac26b65f1fad5eadfcc5501/app/Controller/ControllerIndex.php#L23
> $tableHelper = $this->container["tableHelper"];
Что-то я не уверен что TableHelper это сервис. Это ведь объект представляющий информацию о выбранных фильтрах в таблице - тогда он не может быть сервисом, а должен быть обычным объектом. Сервис это объект который обычно есть в одном числе и выполняет какие-то действия над другими объектами или чем-то еще, а тут обычный объект не-сервис. Его надо просто создавать через new.
По идее концепция такая, что сервисы не хранят состояние, зависящее от текущего запроса. То есть один и тот же объект-сервис можно использовать для обработки нескольких запросов от разных пользователей. И TableHelper тогда не может быть сервисом так как для каждого запроса у нас свои параметры фильтрации таблицы.
Но тогда в эту концепцию не впишется сервис авторизации. Что-то я сам немного начинаю запутываться. Да, правильный сервис авторизации не должен хранить внутри себя текущего пользователя так как в разных запросах он может быть разный. Он может только предоставлять функцию которая смотрит на куки и возвращает текущего пользвоателя, но не хранит его внутри себя.
Вообще, состояние в сервисах это проблема. Вот например в Симфони 2 объект Request, хранящий информацию о запросе (GET/POST/COOKIE) хранился в контейнере как сервис. Но с ним была проблема, что до определенного момента он мог быть еще не заполнен данными. А в режиме командной строки GET или POST вообще нет. Более того, там можно было создавать искуственный объект Request для вложенной обработки подзапроса и все становилось запутанным, так как в один момент времени это был один объект, а в другой момент - другой.
Они там начали усложнять все и в итоге ввели "scope", области когда сервис доступен (http://symfony.com/doc/2.7/cookbook/service_container/scopes.html ). Я считаю, это неудачное решение.
Вот у тебя если подумать, есть та же проблема - пока TableHelper не заполнен информацией из GET, он будет возвращать неактуальные данные. И самое простое решение - превратить его из сервиса в обычный объект.
Сервисы не должны зависеть от того, что какойто контроллер должен заполнить их данными.
Но в любом случае, TableHelepr это не сервис, который может быть полезен в разных местах кода. Это объект представляющий состояние фильтров таблицы и нужный только в контроллере который с ней работает. Это что-то вроде модели студента, обычный объект.
https://github.com/foobar1643/student-list/blob/d9cc915228d101ae0ac26b65f1fad5eadfcc5501/app/Controller/ControllerIndex.php#L17
Тут стена кода. Учись разбивать ее на методы. Например, вынести в отдельный метод можно:
- функцию анализа GET-параметров сортировки таблиц, поиска, и возвращающую экземпляр TableHelper
> public function authorizeStudent(Student $student) {
Плохая идея сигнализировать об ошибке через return false так как никто это не будет проверять. Да ты сам не проверяешь. Лучше исплоьзовать исключения.
> public function isAuthorized() {
Копипаста функции getAuthorizedStudent
https://github.com/foobar1643/student-list/blob/d9cc915228d101ae0ac26b65f1fad5eadfcc5501/templates/form.html#L3
> <?php if(isset($errors)): ?>
Что это? Переменная может и не существовать? Если это проверка на null то делай ее явно.
Выбор пола и местный ли житель лучше сделать радиокнопками - селект требует больше кликов и скрывает варианты от глаз пользователя.
Я вижу, ты там getopt освоил? Молодец что не стал велосипед изобретать.
Также. тебе небольшая задачка чтобы подумать. Вот у тебя есть регулярные выражения для имени или фамилии в 2 местах кода. Разве это хорошо? Подумай, что можно сделать чтобы это исправить.
При попытке запустить CLI скрипт я получаю:
> php filler/databaseFiller.php
> Warning: include(../app/init.php): failed to open stream: No such file or directory in /home/ubuntu/workspace/filler/databaseFiller.php on line 3
Надо писать абсолютные пути через __DIR__.
Также, совет. Если в первой строке скрипта написать
#!/usr/bin/php
или лучше
#!/usr/bin/env php
И сделать файл исполняемым (chmod a+x file) то в линуксе можно его запускать напрямую, командой
./filler/file.php
Также, вставка большого числа записей скорее всего будет быстрее если вставлять их не по 1 записи за транзакцию а например по 100 или 1000. ну это так, скорее на будущее, чтобы ты знал.
Ну и при вставке большого числа записей пагинация превращается в спортлото. стило бы конечно ограничить ее. Можно в пагинаторе сделать метод, возвращающий номера страниц которые надо вывести и выводить только певрую, последнюю и несколько страниц рядом с текущей (например +1, +2 и +10).
https://github.com/foobar1643/student-list/blob/d9cc915228d101ae0ac26b65f1fad5eadfcc5501/app/Helper/PaginationHelper.php#L35
> while(0 < $page) {
> $page -= $this->recordsPerPage;
Используй деление.
Вообще, проект произвел хорошее впечатление. Давай уже на фреймворки переходить.
> 1. Я сделал поиск через сфинкс, нужно ли в репозиторий включать мой sphinx.conf с настроенными индексами, или лучше оставить все заполнение для людей которые будут устанавливать приложение?
Да, а как иначе? не самому же этот конфиг писать. Не забудь в установке упомянуть что надо запустить индексатор.
> 2. Так же, переиндексацию я сделал через cron, для этого пришлось написать CLI скрипт на PHP который очищает реалтайм индекс при переиндексации (как очистить rt индексы из командной строки я не нашел). Нужно ли включать его в репозиторий (с bash скриптом для крона) или опять же, это оставить для тех кто устанавливает?
Да, нужно, конечно. И незабыть упомянуть все это в ридми. Переиндексацию желательно делать без остановки работы поиска.
> 3. Если приложению не удалось подключится к поисковому демону (сфинкс просто не устанавливали, например), в этом случае достаточно будет вывести ошибку 503 и написать что подключения к демону нет, или лучше будет на странице с поиском вывести заглушку "Поиск временно недоступен" с кодом 200 и основной навигацией приложения?
Выкинуть исключение которое поймает общий обработчик исключений. Навигацию можно поместить на заглушку страницы 503. Не надо делать частный случай для неработающего демона.
Выдавать страницу с кодом 200 точно неправильно так как роботы могут ее проиндексировать.
проверяю только новый код.
Я все-таки подумал, надо бы при ошибке CSRF выводить соотв. сообщение и показывать заполненную форму. То есть относиться к ней как к обычной ошибке. Ну вдруг по какому-то стечению обстоятельств у пользователя куки отключены или он их почистил в процессе заполнения формы?
Плюс браузер имеет право удалять куки если их слишком много.
Ты же при ошибке CSRF теряешь введенные данные.
Я бы сделал так:
$errors = $regHelper->validateStudent($student);
Если ошибка в токене, добавляем ее в errors.
....
> $student = $this->getFormData($student);
Тут нет смысла возвращать студента так как объект передается в функцию как бы по ссылке
https://github.com/foobar1643/student-list/blob/d9cc915228d101ae0ac26b65f1fad5eadfcc5501/app/Controller/ControllerIndex.php#L23
> $tableHelper = $this->container["tableHelper"];
Что-то я не уверен что TableHelper это сервис. Это ведь объект представляющий информацию о выбранных фильтрах в таблице - тогда он не может быть сервисом, а должен быть обычным объектом. Сервис это объект который обычно есть в одном числе и выполняет какие-то действия над другими объектами или чем-то еще, а тут обычный объект не-сервис. Его надо просто создавать через new.
По идее концепция такая, что сервисы не хранят состояние, зависящее от текущего запроса. То есть один и тот же объект-сервис можно использовать для обработки нескольких запросов от разных пользователей. И TableHelper тогда не может быть сервисом так как для каждого запроса у нас свои параметры фильтрации таблицы.
Но тогда в эту концепцию не впишется сервис авторизации. Что-то я сам немного начинаю запутываться. Да, правильный сервис авторизации не должен хранить внутри себя текущего пользователя так как в разных запросах он может быть разный. Он может только предоставлять функцию которая смотрит на куки и возвращает текущего пользвоателя, но не хранит его внутри себя.
Вообще, состояние в сервисах это проблема. Вот например в Симфони 2 объект Request, хранящий информацию о запросе (GET/POST/COOKIE) хранился в контейнере как сервис. Но с ним была проблема, что до определенного момента он мог быть еще не заполнен данными. А в режиме командной строки GET или POST вообще нет. Более того, там можно было создавать искуственный объект Request для вложенной обработки подзапроса и все становилось запутанным, так как в один момент времени это был один объект, а в другой момент - другой.
Они там начали усложнять все и в итоге ввели "scope", области когда сервис доступен (http://symfony.com/doc/2.7/cookbook/service_container/scopes.html ). Я считаю, это неудачное решение.
Вот у тебя если подумать, есть та же проблема - пока TableHelper не заполнен информацией из GET, он будет возвращать неактуальные данные. И самое простое решение - превратить его из сервиса в обычный объект.
Сервисы не должны зависеть от того, что какойто контроллер должен заполнить их данными.
Но в любом случае, TableHelepr это не сервис, который может быть полезен в разных местах кода. Это объект представляющий состояние фильтров таблицы и нужный только в контроллере который с ней работает. Это что-то вроде модели студента, обычный объект.
https://github.com/foobar1643/student-list/blob/d9cc915228d101ae0ac26b65f1fad5eadfcc5501/app/Controller/ControllerIndex.php#L17
Тут стена кода. Учись разбивать ее на методы. Например, вынести в отдельный метод можно:
- функцию анализа GET-параметров сортировки таблиц, поиска, и возвращающую экземпляр TableHelper
> public function authorizeStudent(Student $student) {
Плохая идея сигнализировать об ошибке через return false так как никто это не будет проверять. Да ты сам не проверяешь. Лучше исплоьзовать исключения.
> public function isAuthorized() {
Копипаста функции getAuthorizedStudent
https://github.com/foobar1643/student-list/blob/d9cc915228d101ae0ac26b65f1fad5eadfcc5501/templates/form.html#L3
> <?php if(isset($errors)): ?>
Что это? Переменная может и не существовать? Если это проверка на null то делай ее явно.
Выбор пола и местный ли житель лучше сделать радиокнопками - селект требует больше кликов и скрывает варианты от глаз пользователя.
Я вижу, ты там getopt освоил? Молодец что не стал велосипед изобретать.
Также. тебе небольшая задачка чтобы подумать. Вот у тебя есть регулярные выражения для имени или фамилии в 2 местах кода. Разве это хорошо? Подумай, что можно сделать чтобы это исправить.
При попытке запустить CLI скрипт я получаю:
> php filler/databaseFiller.php
> Warning: include(../app/init.php): failed to open stream: No such file or directory in /home/ubuntu/workspace/filler/databaseFiller.php on line 3
Надо писать абсолютные пути через __DIR__.
Также, совет. Если в первой строке скрипта написать
#!/usr/bin/php
или лучше
#!/usr/bin/env php
И сделать файл исполняемым (chmod a+x file) то в линуксе можно его запускать напрямую, командой
./filler/file.php
Также, вставка большого числа записей скорее всего будет быстрее если вставлять их не по 1 записи за транзакцию а например по 100 или 1000. ну это так, скорее на будущее, чтобы ты знал.
Ну и при вставке большого числа записей пагинация превращается в спортлото. стило бы конечно ограничить ее. Можно в пагинаторе сделать метод, возвращающий номера страниц которые надо вывести и выводить только певрую, последнюю и несколько страниц рядом с текущей (например +1, +2 и +10).
https://github.com/foobar1643/student-list/blob/d9cc915228d101ae0ac26b65f1fad5eadfcc5501/app/Helper/PaginationHelper.php#L35
> while(0 < $page) {
> $page -= $this->recordsPerPage;
Используй деление.
Вообще, проект произвел хорошее впечатление. Давай уже на фреймворки переходить.
> 1. Я сделал поиск через сфинкс, нужно ли в репозиторий включать мой sphinx.conf с настроенными индексами, или лучше оставить все заполнение для людей которые будут устанавливать приложение?
Да, а как иначе? не самому же этот конфиг писать. Не забудь в установке упомянуть что надо запустить индексатор.
> 2. Так же, переиндексацию я сделал через cron, для этого пришлось написать CLI скрипт на PHP который очищает реалтайм индекс при переиндексации (как очистить rt индексы из командной строки я не нашел). Нужно ли включать его в репозиторий (с bash скриптом для крона) или опять же, это оставить для тех кто устанавливает?
Да, нужно, конечно. И незабыть упомянуть все это в ридми. Переиндексацию желательно делать без остановки работы поиска.
> 3. Если приложению не удалось подключится к поисковому демону (сфинкс просто не устанавливали, например), в этом случае достаточно будет вывести ошибку 503 и написать что подключения к демону нет, или лучше будет на странице с поиском вывести заглушку "Поиск временно недоступен" с кодом 200 и основной навигацией приложения?
Выкинуть исключение которое поймает общий обработчик исключений. Навигацию можно поместить на заглушку страницы 503. Не надо делать частный случай для неработающего демона.
Выдавать страницу с кодом 200 точно неправильно так как роботы могут ее проиндексировать.
> $regexpArray[$key]['regexp']
У тебя же есть переменная $value которую только надо переименовать нормально.
> в тексте есть слово «кардинально» или «здесь», «сдела», «сдела», «сдела»
Окончание потерялось
> (\\S)([ ])(\\S)(ж|ш)ы(\\S)([ ])(\\S)
Слишком сложно - зачем тут 7 пар скобок?
> (координально)
А зачем скобки?
> '/(сдесь)/u'
А если оно с большой буквы написано? А, хотя тогда придется заморачиваться с правильной заменой... лучше наверно в это не лезть.
> ([^,])([ ])(но|а)
Ненадежно рассчитывать что будет ровно один пробел - а если два?
> (но|а)(\\s)
После может быть не только пробел, а например запятая. Тут лучше вообще \\b исплоьзовать.
>>692534
Надежнее все же через HAVING ... AND ... проверять наличие всех нужных строк. Также, добавить то же условие в WHERE через OR или IN в надежде что может как-то удастся задействовать индексы для отсева заведомо не подходящих строк.
>>692541
Все команды внутри цикла выполняются несколько раз. Он для этого и придуман.
>>692576
Заведи переменную, положи в нее 1 и пиши в нее 0 если буквы не совпали. В конце проверяй, что в ней и выводи ответ.
> $regexpArray[$key]['regexp']
У тебя же есть переменная $value которую только надо переименовать нормально.
> в тексте есть слово «кардинально» или «здесь», «сдела», «сдела», «сдела»
Окончание потерялось
> (\\S)([ ])(\\S)(ж|ш)ы(\\S)([ ])(\\S)
Слишком сложно - зачем тут 7 пар скобок?
> (координально)
А зачем скобки?
> '/(сдесь)/u'
А если оно с большой буквы написано? А, хотя тогда придется заморачиваться с правильной заменой... лучше наверно в это не лезть.
> ([^,])([ ])(но|а)
Ненадежно рассчитывать что будет ровно один пробел - а если два?
> (но|а)(\\s)
После может быть не только пробел, а например запятая. Тут лучше вообще \\b исплоьзовать.
>>692534
Надежнее все же через HAVING ... AND ... проверять наличие всех нужных строк. Также, добавить то же условие в WHERE через OR или IN в надежде что может как-то удастся задействовать индексы для отсева заведомо не подходящих строк.
>>692541
Все команды внутри цикла выполняются несколько раз. Он для этого и придуман.
>>692576
Заведи переменную, положи в нее 1 и пиши в нее 0 если буквы не совпали. В конце проверяй, что в ней и выводи ответ.
> (mb_substr($i, 0, 1)
первым параметром должна идти строка а не номер символа. Почитай мануал по этой функции.
>>692679
Если в вершине кроме суммы писать еще остаток запаса банкнот то вполне рабочий. В нашей задаче остаток банкнот тоже часть состояния, в отличие от задачи без ограничения.
И кстати когда ты это сделаешь можно будет обсудить варианты оптимизации, как выбирать путь по графу. ну к примеру вместо того чтобы 2 раза взять по 500 мы можем попробовать сначала сделать это одним прыжком. А если не получится, вернуться и попробовать другие варианты.
>>693075
Плохо что имена переменных непонятные:
> random
> random11
> random2
> random22
Лучше просто random1, random2 и тд. И не стоит писать цифры числами вроде wordfive.
Также, тут можно немного оптимизировать код если первые 2 строки генерировать циклом. Там ведь один и тот же код фактически 2 раза скопипащен.
>>693093
Не знаю почему, решение верное, хотя стоит сделать цикл чтобы не копипастить код вывода первых 2 строк.
> (mb_substr($i, 0, 1)
первым параметром должна идти строка а не номер символа. Почитай мануал по этой функции.
>>692679
Если в вершине кроме суммы писать еще остаток запаса банкнот то вполне рабочий. В нашей задаче остаток банкнот тоже часть состояния, в отличие от задачи без ограничения.
И кстати когда ты это сделаешь можно будет обсудить варианты оптимизации, как выбирать путь по графу. ну к примеру вместо того чтобы 2 раза взять по 500 мы можем попробовать сначала сделать это одним прыжком. А если не получится, вернуться и попробовать другие варианты.
>>693075
Плохо что имена переменных непонятные:
> random
> random11
> random2
> random22
Лучше просто random1, random2 и тд. И не стоит писать цифры числами вроде wordfive.
Также, тут можно немного оптимизировать код если первые 2 строки генерировать циклом. Там ведь один и тот же код фактически 2 раза скопипащен.
>>693093
Не знаю почему, решение верное, хотя стоит сделать цикл чтобы не копипастить код вывода первых 2 строк.
> $testText = preg_split("//u", $testText);
Там надо еще флаг PREG_SPLIT_NO_EMPTY добавлять а то он 2 лишних пустых элемента добавляет. Вот паста:
-----
Для разбиения на буквы можно использовать
$letters = preg_split("//u", $text, null, PREG_SPLIT_NO_EMPTY);
Это работает за счет того, что пустая регулярка соответствует "промежуткам" между буквами (пустая регулярка соответствует вообще любой строке) и разбивает по ним строку на буквы. Флаг PREG_SPLIT_NO_EMPTY в конце нужен чтобы удалить 2 пустых элемента в начале и конце массива.
Если вдаваться в детали, то работает это так:
preg_split идет по строке слева направо, начиная с 0-го символа и пытается проверить, подходит ли строка начиная с текущей позиции, под регулярку. Если нет, он переходит к следующему символу, если да, то вырезает часть текста совпавшую с регуляркой, а то что шло перед ней, добавляет в массив результатов и движется дальше.
Ну например вот дана такая строка:
$x = preg_split("/[0-9]+/u", "a123b456");
- проверяется совпадение строки начиная с первого символа, "a123b456", с регуляркой. Совпадения нет, так как регулярка требует наличия 1 или более цифр, потому preg_split переходит к следующему символу строки
- проверяется совпадение строки, начиная со второго символа ("123b456"), c регуляркой. Совпадение есть - регулярка соответствует символам 123 (квантификатор плюс жадный и всегда стремится захватить максимум символов). Так как совпадение есть, то preg_split проскакивает совпавшую часть ("123"), а то что шло перед ней, добавляет в массив результатов ("a").
- проверяется совпадение оставшейся части строки "b456" с регуляркой - совпадения нет, потому preg_split переходит к следующему символу
- проверяется совпадение строки "456" с регуляркой. Совпадение есть, потому preg_split добавляет в массив результатов "b", проскакивает цифры
- обнаружен конец строки. Preg_split добавляет в массив результатов, все что от нее осталось, это пустая строка, и получается результат ["a", "b", ""]
Теперь вернемся к хаку.
Пустая регулярка соответствует любому тексту, потому на каждой позиции она дает совпадение. Но она не захватывает ни одного символа, потому preg_split просто отрезает буквы по одной и сохраняет в массив. Также, в массив попадают 2 пустых строки из начала и конца слова.
Обрати внимание на флаг u. Он говорит что текст в utf-8 и заставляет разбивать строку именно на буквы по границам utf-8 символов, а не на куски по 1 байту (в utf-8 1 символ кодируется несколькими байтами).
-----
Если ты разбил строку на символы, то проще их перевернуть через array_reverse, склеить обратно и сравнить с исходной строкой.
> if ($testText[$i] == $testText[count($testText) - $i - 1]) {} else {
тут надо просто заменить равно на не-равно.
> $testText = preg_split("//u", $testText);
Там надо еще флаг PREG_SPLIT_NO_EMPTY добавлять а то он 2 лишних пустых элемента добавляет. Вот паста:
-----
Для разбиения на буквы можно использовать
$letters = preg_split("//u", $text, null, PREG_SPLIT_NO_EMPTY);
Это работает за счет того, что пустая регулярка соответствует "промежуткам" между буквами (пустая регулярка соответствует вообще любой строке) и разбивает по ним строку на буквы. Флаг PREG_SPLIT_NO_EMPTY в конце нужен чтобы удалить 2 пустых элемента в начале и конце массива.
Если вдаваться в детали, то работает это так:
preg_split идет по строке слева направо, начиная с 0-го символа и пытается проверить, подходит ли строка начиная с текущей позиции, под регулярку. Если нет, он переходит к следующему символу, если да, то вырезает часть текста совпавшую с регуляркой, а то что шло перед ней, добавляет в массив результатов и движется дальше.
Ну например вот дана такая строка:
$x = preg_split("/[0-9]+/u", "a123b456");
- проверяется совпадение строки начиная с первого символа, "a123b456", с регуляркой. Совпадения нет, так как регулярка требует наличия 1 или более цифр, потому preg_split переходит к следующему символу строки
- проверяется совпадение строки, начиная со второго символа ("123b456"), c регуляркой. Совпадение есть - регулярка соответствует символам 123 (квантификатор плюс жадный и всегда стремится захватить максимум символов). Так как совпадение есть, то preg_split проскакивает совпавшую часть ("123"), а то что шло перед ней, добавляет в массив результатов ("a").
- проверяется совпадение оставшейся части строки "b456" с регуляркой - совпадения нет, потому preg_split переходит к следующему символу
- проверяется совпадение строки "456" с регуляркой. Совпадение есть, потому preg_split добавляет в массив результатов "b", проскакивает цифры
- обнаружен конец строки. Preg_split добавляет в массив результатов, все что от нее осталось, это пустая строка, и получается результат ["a", "b", ""]
Теперь вернемся к хаку.
Пустая регулярка соответствует любому тексту, потому на каждой позиции она дает совпадение. Но она не захватывает ни одного символа, потому preg_split просто отрезает буквы по одной и сохраняет в массив. Также, в массив попадают 2 пустых строки из начала и конца слова.
Обрати внимание на флаг u. Он говорит что текст в utf-8 и заставляет разбивать строку именно на буквы по границам utf-8 символов, а не на куски по 1 байту (в utf-8 1 символ кодируется несколькими байтами).
-----
Если ты разбил строку на символы, то проще их перевернуть через array_reverse, склеить обратно и сравнить с исходной строкой.
> if ($testText[$i] == $testText[count($testText) - $i - 1]) {} else {
тут надо просто заменить равно на не-равно.
$var=содержимое файла.
$var=iconv ("CP1251", "UTF-8", $var);
$var=iconv ("ISO-8", "UTF-8", $var);
Кракозябра на выходе не вылетит?
Первая кодировка (CP1251), вторая (UCS-2 LE BOM);
mb_detect_encoding определяет обе как ASCII ибо это файлы из эхеля.
Если буду действовать как описал постом выше будет на выходе потеря данных.
$var= iconv('ASCII', 'UTF-8//IGNORE', $var); Тоже не работает
HELP
$homepage = file_get_contents('csv/1502.csv');
echo mb_detect_encoding($homepage).'вариант1<br>';
$homepage1 = file_get_contents('csv/1502openandsave.csv');
echo mb_detect_encoding($homepage1).'вариант2';
на выходе:
вариант1
UTF-8вариант2
> Так как у него курсивная версия шрифта объявлена как другой шрифт с другим font-family, то текст в em не станет курсивным или может получит "искуственный" наклон, сгенерированный браузером вместо настощяего курсивного шрифта.
Понял, спасибо.
> Ну и вообще код подключения шрифтов там плохой, человек явно пропустил изучение этой темы.
Взял на заметку.
> Порядок всегда должен быть такой:
Оно логично, но тут имхо нужен опыт, чтоб суметь наперед построить всю структуру страницы в HTML. Впрочем, оно приходит со временем наверное.
> Заметь что я использовал БЭМ-стиль для именования классов.
Заметил, но кмк мне пока рановато вскрывать эту тему.
Большое спасибо за ответы.
mb_detect_encoding никогда не работал. Нельзя его использовать вообще: https://habrahabr.ru/post/107945/
Нужно найти или написать свою функцию. Кодировку в произвольном случае определить по тексту невозможно. Однако в реальности можно статистически ее определить по частоте упоминания разных байтов и наличию невозможных в некоторых кодировках их сочетаний.
Погугли в интернете на эту тему. Разберись в предлагаемых решениях. Учти что они могут быть неправильными.
> Или можно два подряд iconv написать из 1251 в utf и потом сразу же из iso в utf.
Тебе надо изучить что такое кодировки. Кодировка это таблица показывающая какими байтами кодируется символ. Бездумно применяя перекодировки ты только все сломаешь.
Вообще конечно, лучше было поручить эту задачу более опытному разработчику. Ведь ты не знал даже что detect encoding никогда не работала. Ну либо добавить в интерфейсе поля для выбора кодировки вручную.
>>696922
> но тут имхо нужен опыт, чтоб суметь наперед построить всю структуру страницы в HTML
Ну так давайте набирать опыт в этом треде.
> кмк мне пока рановато вскрывать эту тему.
ну не знаю, это не так сложно, и лучше сразу приучаться к какой-то системе именования.
>>696587
ServiceLocator - это создаем класс и в нем складываем все хелперы, а в классе, имеющем зависимости, обращаемся к сл и берем у него что нужно.
Dependency Injection - это то же самое, только попадает в зависимый класс через конструктор.
Я правильно разницу понял?
>Он же следит чтобы они были в одном экземпляре
Это типа создает объекты по мере необходимости? Круто придумали, чет не догадался бы до этого.
> Ну так давайте набирать опыт в этом треде.
Давайте. Мне пока званий не совсем хватает, точнее СОВСЕМ не хватает, хотя я вроде стараюсь и 8 часов уделяю. С 1 апреля начну верстать макеты, там уже и начну вас заебывать надоедать
> ну не знаю, это не так сложно, и лучше сразу приучаться к какой-то системе именования.
Логично, лучше чем никак. Принято, надеюсь что аукнется в дальнейшем.
> Это типа создает объекты по мере необходимости?
Да. Посмотри исходники pimple.
> ServiceLocator - это создаем класс и в нем складываем все хелперы, а в классе, имеющем зависимости, обращаемся к сл и берем у него что нужно.
Да, вроде того, и это обычно плохая штука когда в конструктор мы передаем сервис локатор вместо передачи конкретных сервисов.
Я тут нагуглил сайтик про паттерны с примерами кода кстати: http://designpatternsphp.readthedocs.org/ru/latest/README.html
Там есть SL: http://designpatternsphp.readthedocs.org/ru/latest/More/ServiceLocator/README.html
>и это обычно плохая штука когда в конструктор мы передаем сервис локатор вместо передачи конкретных сервисов
> new Class($container->bdConnect, $container->helpUser);
Да? За ссылки спасибо, буду курить.
Что почитать, посмотреть?
У меня стажировка со вторника, там как раз в продакшене yi2 + posgre.
По уи что посоветуешь?
inb4 оф сайт.
Читаю материал, а умнее себя не чувствую, это норма?
Каково должно быть соотношение теории/практики?
Часто ли оперившиеся кодеры лезут в гугл за советами?
Как иностранные клиенты/конторы относятся к русскоязычным погромистам? Нету выражения "русский код", случайно?
Это говно какое-то, нахер я туда полез.
Создателя курса надо за яйца подвесить и линчевать после этого за то, что ни хера не объясняет толком.
Антоша, что я делаю не так?
Вызываешь несуществующую функцию ads(), об этом написано в ошибке.
>PHP Fatal error: Call to undefined function ads() in /home/Kw5nGw/prog.php on line 10
Может ты хотел вызвать функцию abs()?
http://php.net/manual/en/function.abs.php
Учись понимать ошибки интерпретатора, тогда ты сам сможешь сказать что ты делаешь не так.
А что ты там навертел, я не понял ничего.
Считает неправильно вроде, я не могу уловить логику вообще.
Давно хотел спросить, почему Symfony так пишется?
По-английски пишется через ph.
По-французски symphonie.
Не могу допустить, что могли допустить такую ошибку, может это связано с авторскими правами, типа кто-то застолбил право на название раньше.
Сообщения идут через жопу, курсы бесплатные - просто говно, юзабилити на нуле (зачем мне видеть постоянно, кто мне лайки поставил или оповещения об ответах). Прочитаешь сообщение - а оповещение о нём все висит на главной панели.
Говно, яростно нерикаминдую.
Если бесплатный курс настолько плох, то это не значит, что платный будет хорош. Сомневаюсь уже в этом.
Сайт про паттерны шикарный. (Интересно, как ты находишь такую годноту? Я вбил "паттерны проектирования примеры", выдало неудобоваримые фекалии типа википедии или хабра).
Хотя если честно код примеров который они приводят был бы более полезным, если бы они выводили их как физическую формулу, а не давали готовый код. Тут ведь нужно понять принцип, почему именно такая структура кода, а не выучить наизусть свойства и методы приведенных классов.
Потом попробую сам написать такой пост с "выведением" паттерна из жизненного случая.
Пока такой технический вопрос: вот в описании простой фабрики они приводят пример, где у класса есть белый список объектов, которые фабрика может возвращать.
http://designpatternsphp.readthedocs.org/ru/latest/Creational/SimpleFactory/README.html
Это реализовано защищенным свойством protected $typeList, которому почему-то внутри конструктора присваивается значение массивом.
А почему было не написать сразу значение по-умолчанию?
protected $typeList = array('bicycle', 'scooter');
Я бы еще понял, если бы в конструктор можно было передать этот массив в виде аргумента и потом присвоить свойству.
Может в ранних версиях php такое не воспринимал (принимал только простые значения типа строк или чисел). В 5.5 только что проверил, такая запись валидна.
Еще я видел что иногда такие вещи хранят в методах. Например в yii это набор правил валидации формы http://www.yiiframework.com/doc/api/1.1/CModel#rules-detail
Но это пожалуй действительно неправильно, метод должен что-то делать, а не возвращать неизменяемое значение.
>You can imagine to inject your own type list
Виноват, привык не обращать внимания на phpdocs, а там оказывается иногда тоже бывает полезная информация.
Прошу принять во внимание решение моей задачи
Имей в виду что паттерны мало полезны без примеров использования, а для них надо изучать исходники фреймворков.
> Хотя если честно код примеров который они приводят был бы более полезным, если бы они выводили их как физическую формулу, а не давали готовый код.
для этого попробуй поставить себе вопрос: как реализовать ту или иную вещь. Не знаю, что привести в пример, ну возьмем например паттерн NullObject: допустим у тебя класс зависит от класса логгирования, но ты не хочешь никуда выводить этот лог. Паттерн NullObject придет в голову сам собой.
> А почему было не написать сразу значение по-умолчанию?
> protected $typeList = array('bicycle', 'scooter');
Потому что там использован оператор точка и ты не можешь в значении поля по умолчанию использовать выражения:
> 'bicycle' => __NAMESPACE__.'\Bicycle',
> Еще я видел что иногда такие вещи хранят в методах. Например в yii это набор правил валидации формы
Там другая ситуация. В Юи правила валидации описываются в классе-наследнике, потому в базовом классе под них оставлены методы для возможности их определить.
> Но это пожалуй действительно неправильно, метод должен что-то делать, а не возвращать неизменяемое значение.
Метод может возвращать значение. Более того, методы можно сделать абстрактными и таким образом заставить пользователя их определять, чтобы он точно не забыл.
Попробовал самостоятельно сделать сравнение, результат какой-то странный.
http://ideone.com/DtqlJe
На ideone клонирование занимает больше времени. На моем слабом ноутбуке почти одинаково (около секунды). Не знаю, о чем это говорит.
И про метод __clone на php.net непонятное описание.
>Копия объекта создается с использованием ключевого слова clone (который вызывает метод __clone() объекта, если это возможно).
Что значит "когда возможно"?
Метод __clone обязательно должен быть объявлен?
Проверил, объявлять необязательно.
А, вот
>По завершении клонирования, если у класса был определен метод __clone(), то этот метод __clone() вызывается у свежесозданной копии объекта, для возможного изменения всех необходимых свойств.
Назвали бы тогда __after_clone или как-то так, чтобы было понятно, что это необязательный метод для пост-обработки.
Зачем в примере
http://designpatternsphp.readthedocs.org/ru/latest/Creational/Prototype/README.html
они объявляют пустой метод __clone? Или это намек, что если нам понадобится, там внутри можно добавить что-то свое? Ну так и написали бы в комментариях, не пришлось бы гадать.
Метод clone позволяет переопределить поведение при копировании, а также запретить его (если его сделать приватным или выбрасывать исключение, или и то и другое).
> Метод __clone обязательно должен быть объявлен?
только если ты хочешь делать что-то нестандартное при клонирование.
Ну например: можно запретить клонирование. Можно обнулять ссылку на какой-то объект чтобы клон на него не ссылался. Можно генерировать новый уникальный идентификатор.
> они объявляют пустой метод __clone
Потому что он абстрактный в родителе. Ты невнимательно изучил код.
А почему он абстрактный? Ну наверно чтобы сказать что объект предназначен для клонирования и надо не забыть определить поведение при клонировании.
> На ideone клонирование занимает больше времени. На моем слабом ноутбуке почти одинаково (около секунды). Не знаю, о чем это говорит.
Чтобы была разница надо чтобы при создании что-то делалось относительно тяжелое. Ну например заполняется множество полей, или что-то считается.
Вчера в полусонном состоянии почему-то не сохранился 71 тред. Есть у кого-нибудь сохранённый тред? Там очень важные посты!
А ты каким файлообменником пользуешься?
Странный вопрос. На дваче взял и сохранил с неделю назад.
https://www.dropbox.com/s/x2pqq14sflw48x7/71.rar?dl=0
Чтобы я уменьшал масштаб, а всё не расползалось, а так же уменьшалось?
2 задача: https://jsfiddle.net/13Lkpwtc/
3 задача: https://jsfiddle.net/8gcbwyc5/
4 задача: https://jsfiddle.net/5qotwgrr/
5 задача: https://jsfiddle.net/skemuf9g/
6 задача: https://jsfiddle.net/as3yrj0y/
7 задача: https://jsfiddle.net/t7d5x54r/
8 задача: https://jsfiddle.net/74398gsy/
9 задача: https://jsfiddle.net/bmsof3d1/
10 задача: https://jsfiddle.net/sfybve16/
11 задача: https://jsfiddle.net/3uhzjytk/
Главная задача - макет сайта - готова в общих чертах, но домен пока не доступен.
А вообще её же можно выложить просто на Гитхаб...
Сегодня попробую разобраться с этим.
Всё правильно делаю?
Вот есть Специалист с овер 1к баксов за курс и со слитыми на nmm-club всеми курсами без возможности фидбека.
Есть myrusakov за курсы по паре тыщ рублей и 2500 видосами от прошедших курсы, его хвалят, наверняка всё это есть на торрентах.
Есть нетология и гикбрейнс.
А есть наш ОП с отличным учебником до ООП (только вкатываюсь в ООП, пока не смотрел, что там).
Наш ОП - по-любому, но, может, ещё что-нибудь в нагрузку посоветуете посмотреть?
Часто иной подход помогает закрепить и лучше понять пройденное, вот к этому стремлюсь.
В курсах все галопом по верхам. Я посмотрел только специалиста и то, потому что под капельницами лежал и больше занять себя было нечем. Информация подается ну ооочееешь медленно. Но такова суть массовых курсов, они должны покрывать наибольшую массу людей, иначе не будет восторженного фидбека и продаж.
У меня знакомый преподает яву в Беларуси на подобных курсах. Так от статистики я немного прифигел. Почти треть бросает не доучившись и до половины. Это при том что оплачивается весь курс сразу. Финальный экзамен сдает где то половина от оставшихся и только единицы доделывают индивидуальный проект (что то вроде задачи про файлообменник от ОПа). Мое мнение: если времени навалом, то почему бы и нет. Главное понимать, что некоторые сложные моменты будут опускаться в угоду доступности для понимания более широким кругом лиц.
Как пхп ищет что либо по нейспейсу и просто по имени класса?
Спасибо за ответ, братишка.
Я думаю, что статистика подобная была бы и у нашего ОПа, если бы он как-то её отслеживал.
Я как-то обратил внимание на то, что количество форков у задач ОПа чем дальше, тем меньше.
Но братишки совершенно разумно объяснили это тем, что дальше люди стараются установить IDE, Apache, MySQL, вот это всё, уже нет нужды писать код на Ideone.
Хотя я сам только сейчас всё устанавливаю, начиная осваивать ООП.
>некоторые сложные моменты будут опускаться в угоду доступности для понимания более широким кругом лиц.
Я чувствую себя достаточно неуверенно и после большинства решённый бонусных задач, мне чем проще, тем лучше.
А как у Специалиста всё идёт: каждое занятие объясняет какой-то этап по созданию сайта?
Пошаговости мне не хватает крайне.
Еще немного задач
http://ideone.com/kr3ibA - имейлы в тексте
http://ideone.com/TujCVy - автозамена
http://ideone.com/bEr5sE - проверка номеров и приведение их к одной форме
http://ideone.com/munQVK - тире может быть и в домене.
Ещё:
>Номер + 7 999 123 4567 - верный
>79991234567
Исправление неправильное. Или 8, или +7.
Чёрт, вижу, некоторые задачи не в окончательном варианте сохранены, а в промежуточных. Особенность jsfiddle - прибавляет цифру к УРЛу, сохраняет отдельно важные изменения. Я там и делал, а потом всё равно сохранил без цифр.
1 задача: https://jsfiddle.net/te5t987m/3/ - например.
Ну да чёрт с ними совсем, целый месяц на разбор этого всего ушёл, хотя всё равно лёгкости и понимания нет.
> мне чем проще, тем лучше.
Тяжело в учении - легко в бою. Слишком "простые" объяснения могут привести к тому, что ты какую-то тему не освоишь и потом не сможешь понять что не работает.
Вот там где-то в треде люди не понимали как куки или сессии работают например.
А так, конечно, может быть полезно посмотреть еще какие-то другие курсы. Может ты что-то подзабыл, а тут вспомнишь. Только код не забывай писать, слишком много теории тоже плохо.
На фрилансе?
Всегда должно быть чёткое ТЗ с пунктиками, иначе будет свистопляска. И для заказчика, и для фрилансера.
//Форма регистрации которая не содержит $id поля и которое будет получатся в классе User'а
class RegisterForm
{
public $login;
public $password;
}
class User
{
//Присваиваем значение null чтобы удобней было передавать данные при передачи их в БД
public $id = null;
public $login;
public $password;
//Внедряем значения из Формы или получаем их из ДБ
public function __construct($properties)
{
$this->setProperties($properties);
}
//Создаем универсальную функция для получения всех значений
public function setProperties($properties)
{
//Преобразовываем в объект на случай если данные берутся из архива возвращающегося из БД
$properties = (object) $properties;
foreach ($properties as $property => $value) {
//Проверяем на то что существует ли свойство с таким же названием как и свойства полученных данных
if (isset($this->$property) {
$this->$property = $value;
}
}
}
}
class DataMapper
{
public function getUserById($id)
{
$query = ...
$result = $query->fetch(\PDO::FETCH_ASSOC);
$user = new User($result);
return $user;
}
public function addUser(User $user)
{
$insert = $pdo->prepare("INSERT INTO students (id, login, surname) VALUES (NULL, :name, :password)");
$insert->execute(array(':login' => $user->login, ':password' => $user->password));
}
}
____
isset не проверяет что существует переменная, она проверяет не изменена ли переменная на значение отличное от NULL. Собственно, вытекает такой вопрос, как проверять на то что существует ли переменная?
//Форма регистрации которая не содержит $id поля и которое будет получатся в классе User'а
class RegisterForm
{
public $login;
public $password;
}
class User
{
//Присваиваем значение null чтобы удобней было передавать данные при передачи их в БД
public $id = null;
public $login;
public $password;
//Внедряем значения из Формы или получаем их из ДБ
public function __construct($properties)
{
$this->setProperties($properties);
}
//Создаем универсальную функция для получения всех значений
public function setProperties($properties)
{
//Преобразовываем в объект на случай если данные берутся из архива возвращающегося из БД
$properties = (object) $properties;
foreach ($properties as $property => $value) {
//Проверяем на то что существует ли свойство с таким же названием как и свойства полученных данных
if (isset($this->$property) {
$this->$property = $value;
}
}
}
}
class DataMapper
{
public function getUserById($id)
{
$query = ...
$result = $query->fetch(\PDO::FETCH_ASSOC);
$user = new User($result);
return $user;
}
public function addUser(User $user)
{
$insert = $pdo->prepare("INSERT INTO students (id, login, surname) VALUES (NULL, :name, :password)");
$insert->execute(array(':login' => $user->login, ':password' => $user->password));
}
}
____
isset не проверяет что существует переменная, она проверяет не изменена ли переменная на значение отличное от NULL. Собственно, вытекает такой вопрос, как проверять на то что существует ли переменная?
Не думаю, а тебе зачем?
Надо брать почасовую оплату в таких случаях. Либо предлагать сначала сдать основную задачу, а потом оговорить доработки за отдельные деньги.
>>698248
А что ты знаешь? С нуля тут много тем надо изучить: PHP, html , css, js, sql , базы данных, архитектуру, mvc, ооп, какой-нибудь фреймворк. Большинству из этого можно научиться, кое-какие ссылки есть в шапке, но это не быстро. Ты сам-то понимаешь, во что ввязался?
>>698276
> $properties = (object) $properties;
Ерунда какая-то. Как можно преобразовать что-то в объект когда не указан даже класс этого объекта?
И вообще ненормально когда ты не знаешь данные какого типа даются функции.
> isset не проверяет что существует переменная, она проверяет не изменена ли переменная на значение отличное от NULL.
Это в мануале описано ведь.
> Собственно, вытекает такой вопрос, как проверять на то что существует ли переменная?
Это не требуется. В объекте всегда известно какие поля есть, а каких нет. Если ты не уверен то есть property_exists или что-то такое.
Также, я бы убрал prperties из конструктора - setProperties можно и так вызвать.
>А что ты знаешь? С нуля тут много тем надо изучить: PHP, html , css, js, sql , базы данных, архитектуру, mvc, ооп, какой-нибудь фреймворк. Большинству из этого можно научиться, кое-какие ссылки есть в шапке, но это не быстро. Ты сам-то понимаешь, во что ввязался?
Я знаком с пхп и делал, что-то вроде задачи про студентов на нем. Но начав копать в стороун серевлетов, понял что инфы очень мало. Намного меньше, чем по пхп. При этом разработка на джаве сложнее(с ее синтаксисом тоже знаком был курс в пол семестра в шаражке). И пока что я в тупике.
Потому что нгинкс сложнее в итоге настраивать - надо еще php-fpm поднимать, настраивать запуск всего этого. Для разработки Апач проще поставить.
Очень хочется понять, что именно в коде не так. Я только-только начал учиться и уже на 2-й задачке у меня траблы. Объясните плз, ПХПшники!
>Ерунда какая-то. Как можно преобразовать что-то в объект когда не указан даже класс этого объекта?
Он будет преобразован в stdClass
https://secure.php.net/manual/ru/language.types.object.php#language.types.object.casting
Что плохого в использовании этого? Не вижу ничего плохого в том, чтобы пользоваться этой возможностью.
>И вообще ненормально когда ты не знаешь данные какого типа даются функции.
Почему не знаю? Это как раз и сделано потому что я знаю, что будет передаваться либо массив, либо объект.
>>698298
>> isset не проверяет что существует переменная, она проверяет не изменена ли переменная на значение отличное от NULL.
>Это в мануале описано ведь.
По первой ссылке в гугле пишут что это именно метод проверки на то что переменная существует
>>698298
>> Собственно, вытекает такой вопрос, как проверять на то что существует ли переменная?
>Это не требуется. В объекте всегда известно какие поля есть, а каких нет. Если ты не уверен то есть property_exists или что-то такое.
Без этого программа может не работать, потому что на вход могут придти данные не соответствующие полям объекта. Например, из класса формы регистрации могут прийти свойства пароля и повторного пароля, и они не должны содержаться в объекте пользователя, за место них будут свойства хэша, токена и соли.
Херась, ты навертел!
Проще всё надо.
Цикл for, прибавляем к $i = 16 единицу, а сумму вклада каждую итерацию умножаем на 1.1.
Останавливается цикл, когда у анона образовалось больше или равно одному миллиону.
> Он будет преобразован в stdClass
А что такое stdClass? Зачем вообще нужен такой класс когда есть массив который может все то же самое только к нему прилагается куча функций для работы с ним?
stdClass это ошибка проектирования PHP и незачем его вообще использовать.
> Что плохого в использовании этого
В том что в языке есть массивы, ты берешь вместо них дурно спроектированный аналог с урезанными возможностями и непонятно какая в этом выгода.
> По первой ссылке в гугле пишут
Мало ли что в гугле пишут, ты мануал читай всегда в первую очередь.
> Без этого программа может не работать, потому что на вход могут придти данные не соответствующие полям объекта. Например, из класса формы регистрации могут прийти свойства пароля и повторного пароля, и они не должны содержаться в объекте пользователя, за место них будут свойства хэша, токена и соли.
Вообще, лучше всего это делать снаружи модели. В случеа с формой ты вообще не должен смотреть какие поля в модели, а должен иметь белый список полей которые разрешено обновлять через форму. В случае с Бд код создания объекта из данных БД должен быть в классе-маппере.
Проверь что модель не знает ничего ни про базы данных ни про формы. Она должна быть отвязана от этого, маппингом в базу данных или обновлением модели из формы должны заниматься другие классы.
У меня это по моему написано в комментариях к задаче: гитхаб однажды взломали как раз из-за того что они данные из формы записвали прямо в модель без ограничений - и взломщик себе выставил как-то повышенные привилегии, хотя поля для них в форме конечно не было.
>($a = 10000)&&($age = 16); ($a = 1000000); ($a = $a * 0.10 + $a)&&($age++)
Где ты такое взял? Я не разу не видел чтобы в наших уроках такое было написано.
Тебе нужно писать как написано на пикрелейтед >for ($i = 0; $i <= 10; $i++), только заменить на for ($age = 16; ... ) {
Затем высчитать проценты и проверить есть ли уже миллион
$money = ... ;
if (...) {
echo "Миллион будет через {$age} лет";
И затем остановить цикл break;
Он там напутал. Вот смотрите, в уроке про циклы написано:
> for (действие1; условие; действие2) { ... тело цикла ... }
и ниже:
> Условия и действие в шапке цикла не обязаны быть связаны друг с другом и работать с одной и той же переменной. Например, можно написать for ($a = 1; $b < 10; $c++) { ... }
Видно что анон перепутал места где пишутся условия и где действия перед циклом и после каждого шага.
Далее, условия можно объединять через && или ||, это написано в уроке про кубики. только вот объединять надо именно условия. То есть можно так писать:
....($a > 10000)&&($age > 16)....
То,что у анона - это конечно неправильно. Ну например в условии надо писать ==, а не =. Он написал
$a = 1000000
получается присваивание вместо сравнения, и это условие всегда будет верным, а цикл - бесконечным.
В качестве действия можно указать несколько выражений, перечилив их через запятую:
for ($a =1 , $b =2; .....
Но злоупотреблять этим не стоит так как снижается читабельность, когда шапка огромная, и становится непонятно что тут является счетчиком.
Он связал действия через &&. С таким же услпехом их можно связать любой другой операцией например
($a = 10000) + ($age = 16)
($a = 10000) - ($age = 16)
То есть это только запутывает понимание и смысла никакого не несет так как результат операции никуда не сохраняется. Надо было просто написать оба присваивания через запятую.
Также плохо что есть 2 переменныхз с похожими именами age и age1 - это путает
Плохо что число 16 и 10000 написано 2 раза и его неудобно менять.
В общем, код надо улучшать.
Он там напутал. Вот смотрите, в уроке про циклы написано:
> for (действие1; условие; действие2) { ... тело цикла ... }
и ниже:
> Условия и действие в шапке цикла не обязаны быть связаны друг с другом и работать с одной и той же переменной. Например, можно написать for ($a = 1; $b < 10; $c++) { ... }
Видно что анон перепутал места где пишутся условия и где действия перед циклом и после каждого шага.
Далее, условия можно объединять через && или ||, это написано в уроке про кубики. только вот объединять надо именно условия. То есть можно так писать:
....($a > 10000)&&($age > 16)....
То,что у анона - это конечно неправильно. Ну например в условии надо писать ==, а не =. Он написал
$a = 1000000
получается присваивание вместо сравнения, и это условие всегда будет верным, а цикл - бесконечным.
В качестве действия можно указать несколько выражений, перечилив их через запятую:
for ($a =1 , $b =2; .....
Но злоупотреблять этим не стоит так как снижается читабельность, когда шапка огромная, и становится непонятно что тут является счетчиком.
Он связал действия через &&. С таким же услпехом их можно связать любой другой операцией например
($a = 10000) + ($age = 16)
($a = 10000) - ($age = 16)
То есть это только запутывает понимание и смысла никакого не несет так как результат операции никуда не сохраняется. Надо было просто написать оба присваивания через запятую.
Также плохо что есть 2 переменныхз с похожими именами age и age1 - это путает
Плохо что число 16 и 10000 написано 2 раза и его неудобно менять.
В общем, код надо улучшать.
Удобнее. Но если кто-то хочет поставить и настроить нгинкс + php-fpm, готов их изучить и разобраться, я не против, хотя не вижу выгоды настраивать среду для разработки как продакшен.
Также, поясню еще кое-что. В PHP (как и в Си) оператор = это именно оператор, который возвращает результат (присвоенное число). Потому можно писать всякие адские конструкции вроде
echo $a = 1; // выведет 1 и создаст переменную
это эквивалентно
$a = 1;
echo $a;
или
$a = ($b = ($c = 1)); // создает 3 переменных с значением 1
или даже так
$a = $b = 1; // присваивания выполняются справа налево, так как = это правоассоциативный оператор
или так:
echo ($a = 1) + ($b = 2); // -> 3
разберем еще такой интересный случай:
if ($a = 10) ....
Это эквивалентно такой псоледовательности:
$a = 10;
if ($a) ....
if срабатывает если в скобках получается не-пустое (не равное 0, '', false, null, '0') выражение. То есть в данном случае - срабатывает всегда. Потому если ты путаешь == и = то программа формально имеет верный синтаксис но работает неправильно.
Защититься от этого можно если поменять местами переменную и число:
if (10 == $a)
тогда при опечатке выпадет ошибка.
Мне кстати не нравится эта особенность Си и PHP, от нее вреда больше чем пользы.
Также операторы += , ++ и подобные тоже возвращают результат и могут использоваться как часть выражения:
echo $a ++;
echo ++$a;
и так далее. Разумеется, читабельность программы катастрофически ухудшается при таком использовании.
Также, поясню еще кое-что. В PHP (как и в Си) оператор = это именно оператор, который возвращает результат (присвоенное число). Потому можно писать всякие адские конструкции вроде
echo $a = 1; // выведет 1 и создаст переменную
это эквивалентно
$a = 1;
echo $a;
или
$a = ($b = ($c = 1)); // создает 3 переменных с значением 1
или даже так
$a = $b = 1; // присваивания выполняются справа налево, так как = это правоассоциативный оператор
или так:
echo ($a = 1) + ($b = 2); // -> 3
разберем еще такой интересный случай:
if ($a = 10) ....
Это эквивалентно такой псоледовательности:
$a = 10;
if ($a) ....
if срабатывает если в скобках получается не-пустое (не равное 0, '', false, null, '0') выражение. То есть в данном случае - срабатывает всегда. Потому если ты путаешь == и = то программа формально имеет верный синтаксис но работает неправильно.
Защититься от этого можно если поменять местами переменную и число:
if (10 == $a)
тогда при опечатке выпадет ошибка.
Мне кстати не нравится эта особенность Си и PHP, от нее вреда больше чем пользы.
Также операторы += , ++ и подобные тоже возвращают результат и могут использоваться как часть выражения:
echo $a ++;
echo ++$a;
и так далее. Разумеется, читабельность программы катастрофически ухудшается при таком использовании.
>А что такое stdClass? Зачем вообще нужен такой класс когда есть массив который может все то же самое только к нему прилагается куча функций для работы с ним?
>
>stdClass это ошибка проектирования PHP и незачем его вообще использовать.
Аргумент понятен, противопоставить ему можно разве то, что мы программируем на ООП и работаем с объектами, но какой в этом смысл, если это просто уступает перед массивом? В любом случае это ничего не меняет, ведь можно так же преобразовывать тип но только уже в массив, и подстраивать код уже под это, но даже это будет лишним потому что весь этот подход никуда не годиться, в силу того что надежнее будет иметь белый список полей.
>>698349
М, я читал об этом. Выходит что лучше в ручную вбивать свойства. Это же будет белым списком полей.
К этому вопросу меня привело то что я не захотел вбивать много свойств в ручную. Похоже мне все таки стоит научиться пользоваться Symphony Forms. То что я сейчас делаю никуда не годиться.
Подробнее про особенности операторов расписано в мануале:
http://php.net/manual/ru/language.operators.php
http://php.net/manual/ru/language.operators.assignment.php
> противопоставить ему можно разве то, что мы программируем на ООП и работаем с объектами,
В ООП объекты имеют классы и в классе описаны их поля и методы. stdClass это не часть ООП на классах, а какая-то пародия на него.
Есть впрочем языки, где нет классов (JS), а поля и методы добавляются динамически (как в stdClass). Такой подход имеет право на жизнь, но не надо называть его ООП. И насколько я знаю, особо смысла он не имеет.
> ведь можно так же преобразовывать тип но только уже в массив,
Можно подавать на вход функции только массив и прописать это ограничение в тайп хинте. Это будет праильный способ. Как можно надежно поддерживать код, в котором могут приходить на вход переменные любых типов? Как с такими переменными работать если ты не знаешь какого она типа и что с ней можно, а что нельзя делать?
> Похоже мне все таки стоит научиться пользоваться Symphony Forms
Это очень мощный и сложный компонент. Вниматеьное изучение его исходного кода несомненно даст тебе много новых знаний, может быть познакомит с какими-то паттернами и вообще будет полезно для начинающего. Всячески рекомендую. Но исходники придется изучать, документация там уровня для чайников.
>>698376
Классно пояснил, ОП, спасибо!
Вот тут, смущаясь и подрагивающими руками, после месяца ковыряния HTML+CSS попробовал ООП: http://ideone.com/0jxhaj
Сначала казалось тёмным лесом и непонятным усложнением, а потом вдруг как осенило - удобнота-то какая!
>>698369
>>698376
>>698383
Это даже для меня было бы высокой нагрузкой столько информации, учитывая что я уже даже что-то умею писать. Для меня это легко понять, но я не уверен что новички справиться с этим сразу. Скорее всего они даже не поймут как им применить эти знания.
>>698359 - кун
> foreach ($question->answers as $letter => $givenAnswer) {
> if ($answer == $letter) {
Цикл использовать для поиска одного элемента странно, для поиска по ключу в массиве есть скобки, для поиска по значению array-search, для проверки наличия ключа или значения тоже есть функции - все это есть в уроке по массивам.
В остальном верно.
>для поиска по ключу в массиве есть скобки
Как так? Я не соображу что-то.
Просто всегда foreach использовал для разложения массива.
>для поиска по значению array-search
Спасибо, интересная функция, тут тоже её можно применить.
Перечитай-ка урок про массивы, там ниже картинки есть кратко список примеров основных действий с массивами.
> >для поиска по ключу в массиве есть скобки
> Как так? Я не соображу что-то.
Стыдно. echo $array[$key];
>Как можно надежно поддерживать код, в котором могут приходить на вход переменные любых типов? Как с такими переменными работать если ты не знаешь какого она типа и что с ней можно, а что нельзя делать?
Если это не риторический вопрос, то я бы ответил, что на переменные можно смотреть как на что-то абстрактное. Я не очень долго изучаю этот язык, но я могу даже не задаваться вопросом какого она типа, ведь любую запись например '0123456789' я могу представить и как массив array([0] => '0', ...), и как число intval('0123456789'), и даже, как мы только что видели, как класс. Однако, для меня это особо не имеет значения потому что в большинстве случаев операторы и функции автоматически преобразовывают значения в нужный тип.
Иногда преобразовывают, иногда нет, иногда не так как ты думал. твой подход - верный способ заминировать программу.
https://ideone.com/txEeY6
А, я - ультрадаун, извините. Я "вычислятель" длины массива поставил перед самим массивом, блять.
Для перебора значений в массиве лучше использовать foreach - for плохо подходит.
имена переменным стоит давать нормальные, а не странные сокращения и транслит.
Для поиска объединений/перечечений и разниц массивов есть array_merge, array_intersect и array_diff.
Вот сложный вопрос, что не говори. В основном они нужны в фреймворках и библиотеках и вы вряд ли будете их писать сами. Но я придумал несколько вариантов, где они полезны:
- трейт для логгера: добавляет методы setLogger, getLogger, если логгер не задан возвращает NullLogger (желательно не создавать его каждый раз, а хранить где-то статически один экземпляр или использовать синглтон! о мы нашли редкий пример когда этот паттерн полезен), соответственно использующий его класс может делать просто
$this->getLogger()->info(...);
не проверяя, задан логгер или нет.
- трейт для объединения объектов в дерево. Многие объект можно объединить в дерево, например:
- категории товаров часто являются деревом
- форма и ее поля могут представлять дерево
Соответственно, этот трейт добавляет стандартные методы вроде getParent, getChildren, isRoot, getDepth, appendChild, removeChild, insertBefore тд.
- трейт для реализации интерфейсов коллекций вроде get/has/count/all/remove/add
Многие объекты содержат в себе коллекцию чего-то, там этот трейт может быть полезен.
>логгер возвращает NullLogger
>$this->getLogger()->info(...);
Это зачем нам такая сбивающая с толку конструкция? Функция логгера - лог писать. Т.е. в использующем классе через трейт только $this->log('данные') должен доступен быть, ну и $this->attachLogger($logger) для внешней фабрики. В случае отсутствия логгера $this->log() просто ничего не пишет или кидает Exception в зависимости от критичности наличия лога для наших целей.
Спасибо*
Там в PSR-7 (а делать логгер не по нему глупо) есть несколько уровней логгирования, и методы вроде info(), warning(), error(). Дублировать их все в трейте - тоже не очень хорошая идея. Конечно, напрямую было бы проще. можно конечно ограничить число этих методов, например только info и warning.
> В случае отсутствия логгера $this->log() просто ничего не пишет или кидает Exception в зависимости от критичности наличия лога для наших целей.
У нас предполагается что логгер - не обязателен. Ну например логгер тебе нужен когда ты в cli скрипте тестируешь класс, а так в общем для работы не требуется. Или требуется, но не всегда.
У меня по крайней мере такое было что логгер нужен только для отладки/тестирования, а так не нужен (да и генерировал бы огромное число сообщений).
Несколько уровней логгирования делаются через константы интерфейса, который имплементирует использущий класс.
interface LogLevels
{
const LOG_INFO = 'info';
const LOG_WARNING = 'warning';
const LOG_ERROR = 'error';
}
interface LoggerAware extends LogLevels
{
public function attachLogger(Logger $logger);
public function log($data, $type);
}
trait LoggerTrait
{
public function log($data, $type)
{
if ($this->logger !== null) {
$this->logger->log($data, $type);
}
}
public function attachLogger(Logger $logger)
{
$this->logger = $logger;
}
}
class Logger implements LogLevels
{
public function log($data, $type)
{
switch ($type){
//решения о логгировании по типу сообщения
case LOG_INFO:
case LOG_WARNING:
case LOG_ERROR:
}
}
}
class Client implements LoggerAware
{
use LoggerTrait;
public function someAction()
{
$this->log('message', LOG_INFO);
}
}
Тогда в использующем классе просто делаем $this->log('данные', LOG_WARNING); Логгер сам разбирается, как логгировать каждый тип, разные типы логгеров и NullLoggerы не нужны. Если логгер не подключен, ничего не логгируется.
>У нас предполагается что логгер - не обязателен.
Тогда он просто ничего не возвращает, NullLogger не нужен.
Несколько уровней логгирования делаются через константы интерфейса, который имплементирует использущий класс.
interface LogLevels
{
const LOG_INFO = 'info';
const LOG_WARNING = 'warning';
const LOG_ERROR = 'error';
}
interface LoggerAware extends LogLevels
{
public function attachLogger(Logger $logger);
public function log($data, $type);
}
trait LoggerTrait
{
public function log($data, $type)
{
if ($this->logger !== null) {
$this->logger->log($data, $type);
}
}
public function attachLogger(Logger $logger)
{
$this->logger = $logger;
}
}
class Logger implements LogLevels
{
public function log($data, $type)
{
switch ($type){
//решения о логгировании по типу сообщения
case LOG_INFO:
case LOG_WARNING:
case LOG_ERROR:
}
}
}
class Client implements LoggerAware
{
use LoggerTrait;
public function someAction()
{
$this->log('message', LOG_INFO);
}
}
Тогда в использующем классе просто делаем $this->log('данные', LOG_WARNING); Логгер сам разбирается, как логгировать каждый тип, разные типы логгеров и NullLoggerы не нужны. Если логгер не подключен, ничего не логгируется.
>У нас предполагается что логгер - не обязателен.
Тогда он просто ничего не возвращает, NullLogger не нужен.
С константами писать длинее. Плюс, ты читал PSR-7? Я выше написал что логгер должен ему соответсовать, и изобретать велоипеды тут точно не стоит.
Твой - именно что велосипед.
То есть PSR-3, перепутал. Ну и у тебя какое-то странное наследвоание интерфейса только ради импорта констант - мне оно не нравится. Интерфейсы ведь не для этго.
И перед константой надо будет писать LogLeves::LOG_WARNING
> } elseif ($aiResult = $humanResult) {
Ты забыл что при сравнении надо писать ==, а не =. Одиночное равно просто присваивает значение переменной и так как оно не нулевое, то условие получается всегда истинно.
Ну и к тому же в последнем блоке незачем писать условие, а нужно просто писать else без условия - то есть этот блок будет срабатывать если ни один из вышестоящих блоков не сработал.
В остальном верно.
> 5.1 http://ideone.com/sMgDgr
> PHP Notice: Undefined variable: halfLength in /home/1kSN4e/prog.php on line 13
Ты обращаешься к не существующей переменной. Ты там опечатался в последних буквах halfLenght, посмотри внимательно.
Также, при несовпадении букв надо выходить из цикла, а не продолжать его. Для выхода есть команда break, а хаки с подменой значения счетчика усложняют понимание кода.
> Не то скопировал. 5.1 https://ideone.com/PGq5Ja (но там тоже что-то не так)
Там ответ неправильынй - должно быть 61270. Ну и алгоритм, ты в последний месяц, когда осталось 4138, не начисляешь проценты и комиссию.
Когда исправишь, проверь свой код на сумме кредита 4000 и 1000.
> 5.2 http://ideone.com/OEDO0b
> $money <= 1000000;
Если мы набрали ровно миллион, надо все равно продолжать цикл?
Алсо ты неправильно набрал <?php в начале.
В остальном верно.
> 5.3 http://ideone.com/LKM2eh
Тут все верно
> 5.4 http://ideone.com/sw6DJA
> if ($height > 169){
тут надо было переменную написать вместо числа. В остальном верно.
> 5.5 http://ideone.com/SUvW2G
Все правильно.
Верно.
> http://ideone.com/O8hBUP - шифровка\дешифровка
Правильно.
> http://ideone.com/kG9U2m - полиндром
> PHP Notice: Undefined variable: halfLength in /home/1WOGIM/prog.php on line 1
Посмотри внимательно, ты там length/lenght путаешь. Будь внимательнее.
> } elseif ($aiResult = $humanResult) {
Ты забыл что при сравнении надо писать ==, а не =. Одиночное равно просто присваивает значение переменной и так как оно не нулевое, то условие получается всегда истинно.
Ну и к тому же в последнем блоке незачем писать условие, а нужно просто писать else без условия - то есть этот блок будет срабатывать если ни один из вышестоящих блоков не сработал.
В остальном верно.
> 5.1 http://ideone.com/sMgDgr
> PHP Notice: Undefined variable: halfLength in /home/1kSN4e/prog.php on line 13
Ты обращаешься к не существующей переменной. Ты там опечатался в последних буквах halfLenght, посмотри внимательно.
Также, при несовпадении букв надо выходить из цикла, а не продолжать его. Для выхода есть команда break, а хаки с подменой значения счетчика усложняют понимание кода.
> Не то скопировал. 5.1 https://ideone.com/PGq5Ja (но там тоже что-то не так)
Там ответ неправильынй - должно быть 61270. Ну и алгоритм, ты в последний месяц, когда осталось 4138, не начисляешь проценты и комиссию.
Когда исправишь, проверь свой код на сумме кредита 4000 и 1000.
> 5.2 http://ideone.com/OEDO0b
> $money <= 1000000;
Если мы набрали ровно миллион, надо все равно продолжать цикл?
Алсо ты неправильно набрал <?php в начале.
В остальном верно.
> 5.3 http://ideone.com/LKM2eh
Тут все верно
> 5.4 http://ideone.com/sw6DJA
> if ($height > 169){
тут надо было переменную написать вместо числа. В остальном верно.
> 5.5 http://ideone.com/SUvW2G
Все правильно.
Верно.
> http://ideone.com/O8hBUP - шифровка\дешифровка
Правильно.
> http://ideone.com/kG9U2m - полиндром
> PHP Notice: Undefined variable: halfLength in /home/1WOGIM/prog.php on line 1
Посмотри внимательно, ты там length/lenght путаешь. Будь внимательнее.
Уменьшать долг ты забыл, также у тебя число 5000 несколько раз повторяется - неудобно будет менять его, надо использовать переменную, а не копипастить числа.
>>693221
> Только перечитав дошло, что в отличие от JS функции в PHP не видят внешних переменных.
Да, и это упрощает анализ кода функции, так как все входящие данные приходят только через аргументы и не надо искать по всему коду откуда тут эта переменная.
> if ($sum >= $payout) {
> $sum -= $payout;
Этот иф можно заменить на вызов функций min/max. Будет наверно короче код. А так, в общем, верно.
>>693309
> function inclineWord($declension, $latterFigure, $end) {
Давай посмотрим на эту функцию. Параметр $declension используется только с одной целью: взять подмассив из $end:
> $end[$declension][0];
> $end[$declension][1];
Раз так, может вместо этих 2 переменных сразу передавать подмассив с нужными 3 формами числа?
Также, ты не учел в этой функции что для чисел 11-19 используется другое окончание: 11 котов, а не 11 кот. Ты там где-то в другом месте это делаешь, но это вообще плохо. Алгоритм выбора формы слова должен быть целиком в одной функции, а не размазан по программе.
> return($text);
return это не функция, а оператор (команда), и скобки тут не нужны.
> return($text);
> break;
Ошибка: break можно использовать только внутри цикла. Также, return выходит из функции и идущие за ним команды никогда не выполнятся.
> function writeThousand($declension, $discharge, $text, $spelling) {
> $text = $text.' одна';
> return($text);
Тут не очень понятно зачем ты передаешь в функцию $text. Вместо того чтобы приклеивать число к строке, проще возвращать только его, а text не передавать вообще.
> $thousand = $number % 1000000 * 0.001;
тут вместо умножения наверно логчинее написать "поделить на 1000"
Собирать текст по словам удобнее, складывая слова в массив. Так будет проще чем возиться с правильной расстановкой пробелов.
Алгоритм в smallNumberToText сложноват. Я думаю, его проще переписать примерно так:
- если в числе есть сотни, добавить слово для них
- если в числе есть 11-19, добавить слово
- если в числе есть десятки, добавить слово
- если в числе есть единицы, ....
То есть записать как последовательные ифы - будет более простая структура кода.
> if ($number == 0) {
> $text = " ноль рублей";
Это логичнее в самое начало функции ставить, а не в конец.
> } elseif ($number % 1000 == 0) {
> $text = $text.' '.'рублей';
Это какой-то хак? Лучше бы без него
В общем. код требует доработки.
Уменьшать долг ты забыл, также у тебя число 5000 несколько раз повторяется - неудобно будет менять его, надо использовать переменную, а не копипастить числа.
>>693221
> Только перечитав дошло, что в отличие от JS функции в PHP не видят внешних переменных.
Да, и это упрощает анализ кода функции, так как все входящие данные приходят только через аргументы и не надо искать по всему коду откуда тут эта переменная.
> if ($sum >= $payout) {
> $sum -= $payout;
Этот иф можно заменить на вызов функций min/max. Будет наверно короче код. А так, в общем, верно.
>>693309
> function inclineWord($declension, $latterFigure, $end) {
Давай посмотрим на эту функцию. Параметр $declension используется только с одной целью: взять подмассив из $end:
> $end[$declension][0];
> $end[$declension][1];
Раз так, может вместо этих 2 переменных сразу передавать подмассив с нужными 3 формами числа?
Также, ты не учел в этой функции что для чисел 11-19 используется другое окончание: 11 котов, а не 11 кот. Ты там где-то в другом месте это делаешь, но это вообще плохо. Алгоритм выбора формы слова должен быть целиком в одной функции, а не размазан по программе.
> return($text);
return это не функция, а оператор (команда), и скобки тут не нужны.
> return($text);
> break;
Ошибка: break можно использовать только внутри цикла. Также, return выходит из функции и идущие за ним команды никогда не выполнятся.
> function writeThousand($declension, $discharge, $text, $spelling) {
> $text = $text.' одна';
> return($text);
Тут не очень понятно зачем ты передаешь в функцию $text. Вместо того чтобы приклеивать число к строке, проще возвращать только его, а text не передавать вообще.
> $thousand = $number % 1000000 * 0.001;
тут вместо умножения наверно логчинее написать "поделить на 1000"
Собирать текст по словам удобнее, складывая слова в массив. Так будет проще чем возиться с правильной расстановкой пробелов.
Алгоритм в smallNumberToText сложноват. Я думаю, его проще переписать примерно так:
- если в числе есть сотни, добавить слово для них
- если в числе есть 11-19, добавить слово
- если в числе есть десятки, добавить слово
- если в числе есть единицы, ....
То есть записать как последовательные ифы - будет более простая структура кода.
> if ($number == 0) {
> $text = " ноль рублей";
Это логичнее в самое начало функции ставить, а не в конец.
> } elseif ($number % 1000 == 0) {
> $text = $text.' '.'рублей';
Это какой-то хак? Лучше бы без него
В общем. код требует доработки.
там же учебник яваскрипт и описывается клиентская часть, а не серверная. Серверную можно делать на любых технологиях, лишь бы она запросы правильно обрабатывала.
> Куда сохраняются сообщения? Допустим я хочу сделать серверную часть на пхп, мне ведь нужно вставлять записи в бд или хотябы в файл, чтобы другой юзер мог получить его гет запросом.
Не обязательно. Вообще, хранить сообщения в БД довольно неэффективно так как она сбросит их на диск, то есть создаст лишнюю нагрузку на сервер. Лучше хранилище в памяти.
Ну и такие штуки не очень эффективно писать на обычном PHP так как ты должен будешь держать в памяти большое число процессов, надо постоянно опрашивать хранилище на появление новых записей - это явно неправильно.
Тебе нужно написать асинхронный демон, который будет слушать TCP порт, принимать запросы, и пересылать сообщения аналогично тому как это сделано в примере на Node.JS. Для этого подойдет фреймворк ReactPHP, но учти что он сложный, и чтобы им пользоваться надо сначала изучить работу сетей (устройство интернета, протоколы IP, TCP), обычные сокеты Беркли и сетевое программирование, а только потом браться за асинхронщину.
У меня есть паста про архитектуры серверов: https://gist.github.com/codedokode/ffd520440a970c07c1c6
И вот такая довольно беспорядочная паста, собранная из нескольких постов: https://gist.github.com/codedokode/21a432321fe7bc435dab
> Тут это выглядит так, будто один пользователь отправляет сообщение напрямую другому, без сохранения куда-либо.
Там сообщения нигде не хранятся (разве что в переменной). При получении сообщения от клиента он пересылает его всем остальным. Там нет истории сообщений.
>> Также функция подсветки должна правильно делать htmlspecialchars, чтобы символы вроде & или < в HTML коде выводились корректно.
> Как сделать так чтобы htmlspecialchars не съел тег <mark>? Я пропускаю два значения через функцию paintFound заранее, а только потом его вставляю. Правильно?
В общем, это годится так как htmlspecialchars одинаково преобразует одинаковын слова. Но мне тм не нравится одна вещь: ты проходишься с заменой по HTML строке несколько раз. тут есть риск: что если мы ищем фразу "mark mar ark"? В этом случае во второй и третий раз ты заменишь название тега <mark>. Это надо исправить. Замену надо делать только один раз.
Плюс, мы можем получить вложенные теги mark, или даже неправильно закрытые, что тоже плохо.
думаю, надо делать замену 1 раз по выражению вроде /иванович|иванов|иван/ui
Другой вариант - разбивать строку на части, совпадающие с искомым словом и раположенные между ними (например preg_split), каждую часть обрабатывать htmlspecialchars, и склеивать с подстановкой тега mark, но это может быть сложнее.
> $searchArray
Лучше назвать searchWords
По поводу рабоыт с Бд, это в общем плохая идея:
> //Добавляем данные одним массивом
> $stmt->execute((array)$abiturient);
А что если кто-то добавит еще публичное или приватное поле? Тогда будет передан лишний элемент и все сломается. Не надо так, лучше сделать массив имен полей и извлечь данные из студента по нему.
Такой код который ломается от добавления поля - точно плохая идея.
> Обводится Иван Иван(конец обводки)ов.
Чтобы этого не было, надо сортировать поисковые слова по убыванию длины и сначала заменять длиннейшие.
> $path = __DIR__ . "\\src\\" . $name . ".php";
Беклеши не работают под линуксом. Используй прямые слеши которые работают везде.
Что это такое? Нельзя править сторонние библиотеки. Во-первых, теперь бутстрап невозможно обновить, не потеряв изменения, во-вторых, как я должен догадаться что ты что-то там поменял? Никогда так не делай.
Удали все измененные версии и добавь бутстрап как есть, полностью, в отдельную папку, не меняя и не переименовывая его файлы.
> https://github.com/greenTea242/Student-list/blob/64be58a7aadc56b7d9d4bf45d8dd55482c59ab21/public/css/style.css#L1
> body mark {
какой смысл имеет body в селекторе? Бывает mark не внутри body?
> .form-horizontal div {
> margin-bottom: 15px;
Очень плохо. Я захочу добавить в форму див и буду искать почему у него откуда-то взялся лишний маргин, а потом мне придется как-то переделвать код чтобы у твоих дивов он остался, а у моих нет. Так писать нельзя. Не применяй стили к дивам. Более того, тут скорее всего нужные возможности есть в бутстрапе, а ты их просто не нащел. Я думаю, там есть класс для того чтобы сделать строку в форме, а ты его просто не нашел.
Не применяй стили к дивам. Применяй их к классам.
Если плохо знаешь CSS, у нас есть задачки на него в ОП посте.
> Убираем расстояние между inline элементами как советуют
> в статье из оп учебника
лучше бы конечно другие методы использовать, а то ты сбросил шрифт для всех элементов, а восстановил только для инпутов, да еще и не тот который был. Посмотри лучше как эта проблема отступов решена в бутстрапе.
Более того, давай прочитаем что ты написал:
> .navbar-form {
> font-size: 0;
"в любых формах, добавленных на панель навигации, сбросить шрифт в 0". Я уверен что тебе надо не это. Тебе надо было убрать отступы только в одной конкретной форме, а не вообще в любых.
Файл htaccess надо переименовать (например перенести его в readme) так как Апач его прочитает и попытается выполнить и будет ошибка что virtualHost нельзя указать в htaccess
> https://github.com/greenTea242/Student-list/blob/master/src/ViewHelper.php#L7
> fixView
название конечно неудачное так как не говорит что он делает. Более того, судя по тексту, он предназначен для обработки строки запроса- но почему ты тогда применяешь его к куке в index.php? И к выводимым ссылкам - какое он имеет к ним отношение? Это как-то ненормально.
Также, тут явно есть уязвиимость XSS:
https://github.com/greenTea242/Student-list/blob/64be58a7aadc56b7d9d4bf45d8dd55482c59ab21/templates/register.html#L45
> value="<?=ViewHelper::FixView($abiturient->surname)?>"
ты выводишь данные не экранируя. Перечитай мой урок по XSS.
https://github.com/greenTea242/Student-list/blob/64be58a7aadc56b7d9d4bf45d8dd55482c59ab21/templates/register.html#L45
https://github.com/greenTea242/Student-list/blob/64be58a7aadc56b7d9d4bf45d8dd55482c59ab21/templates/index.html
Тут полностью скопипащен огромный кусок кода с шапкой и подвалом. Ты ведь не первый день в нашем треде, наверно слышал что копипаста самое плохое что может сделать программист.
https://github.com/greenTea242/Student-list/blob/master/src/Abiturient.php#L17
> const LOCAL = "yes";
Однотипные константы стоит оьъединять общим префиксом (началом названия), как с GENDER.
https://github.com/greenTea242/Student-list/blob/master/src/AbiturientValidator.php#L45
вар дамп не удалил. Надо смотреть git diff перед коммитом.
> Регулярки которые также используются в HTML5 паттернах
Тут есть риск из-за того что диалект регулярок в HTML5 и в PHP вроде как не совпадает. Соответственно легко при редактировании кода получить не работающую на клиенте регулрку. Возможно стоит сдеалать по 2 версии регулярки или еще что-то придумать.
https://github.com/greenTea242/Student-list/blob/master/src/AbiturientValidator.php#L62
> } elseif (mb_strlen($group) > 90) {
Там 5 символов ограничение
> $regexp = "/{$this->getRegExpForGroupNumber()}/u";
ты забыл про привязку к началу и концу строки
Также, в валидаторе нет проверки что указан пол и место жительства.
Также наверно лучше бы сделать чтобы одним валидатором можно было проверить несколько студентов, а не одного.
https://github.com/greenTea242/Student-list/blob/master/src/ini.php#L4
Конфиг нужно подключать без once
Насчет авторизации - почему бы не вынести ее в отдельный класс-сервис с методами вроде получитьСтудента/залогинитьСтудента/разлогинить. И соответственно всю работу с кукой скрыть в этом классе.
https://github.com/greenTea242/Student-list/blob/master/public/index.php#L12
> define('NOTIFY', $notify);
Что это? константа это не переменная которая может принимать лббые значения. Более того непонятно зачем дублировать переменную константой.
> $stmt->setFetchMode(PDO::FETCH_NUM);
> $counter = $stmt->fetchColumn();
В этом случае же setFetchMode не требуется вроде.
> if (!empty($searchQuery)) {
Это плохо что переменная может не существовать. Лучше тогда сделать массив вроде $values[':search'] = .... и передавать его в execute.
Также, при поиске хорошо бы обрабатывать поисковую строку - заменять в ней пробелы на знак % чтобы можно было набрать "ив нов" и найти Ивана Иванова. Также можно удалять левые символы вроде знаков препинания из поискового запроса. Подумай.
> getAbiturientsInPage($page,
Лучше передавать offset и не накладывать на функцию обязанность считать страницы.
> ORDER BY $sort DESC
Надо сортирвоать в обе стороны. Например повторным кликом по заголовку.
> оздаем уникальный идентификатор. если абитуриент впервые на сайте
Это не требуется - mysql умеет это делать, почему не исплоьзуешь auto_increment?
>> Также функция подсветки должна правильно делать htmlspecialchars, чтобы символы вроде & или < в HTML коде выводились корректно.
> Как сделать так чтобы htmlspecialchars не съел тег <mark>? Я пропускаю два значения через функцию paintFound заранее, а только потом его вставляю. Правильно?
В общем, это годится так как htmlspecialchars одинаково преобразует одинаковын слова. Но мне тм не нравится одна вещь: ты проходишься с заменой по HTML строке несколько раз. тут есть риск: что если мы ищем фразу "mark mar ark"? В этом случае во второй и третий раз ты заменишь название тега <mark>. Это надо исправить. Замену надо делать только один раз.
Плюс, мы можем получить вложенные теги mark, или даже неправильно закрытые, что тоже плохо.
думаю, надо делать замену 1 раз по выражению вроде /иванович|иванов|иван/ui
Другой вариант - разбивать строку на части, совпадающие с искомым словом и раположенные между ними (например preg_split), каждую часть обрабатывать htmlspecialchars, и склеивать с подстановкой тега mark, но это может быть сложнее.
> $searchArray
Лучше назвать searchWords
По поводу рабоыт с Бд, это в общем плохая идея:
> //Добавляем данные одним массивом
> $stmt->execute((array)$abiturient);
А что если кто-то добавит еще публичное или приватное поле? Тогда будет передан лишний элемент и все сломается. Не надо так, лучше сделать массив имен полей и извлечь данные из студента по нему.
Такой код который ломается от добавления поля - точно плохая идея.
> Обводится Иван Иван(конец обводки)ов.
Чтобы этого не было, надо сортировать поисковые слова по убыванию длины и сначала заменять длиннейшие.
> $path = __DIR__ . "\\src\\" . $name . ".php";
Беклеши не работают под линуксом. Используй прямые слеши которые работают везде.
Что это такое? Нельзя править сторонние библиотеки. Во-первых, теперь бутстрап невозможно обновить, не потеряв изменения, во-вторых, как я должен догадаться что ты что-то там поменял? Никогда так не делай.
Удали все измененные версии и добавь бутстрап как есть, полностью, в отдельную папку, не меняя и не переименовывая его файлы.
> https://github.com/greenTea242/Student-list/blob/64be58a7aadc56b7d9d4bf45d8dd55482c59ab21/public/css/style.css#L1
> body mark {
какой смысл имеет body в селекторе? Бывает mark не внутри body?
> .form-horizontal div {
> margin-bottom: 15px;
Очень плохо. Я захочу добавить в форму див и буду искать почему у него откуда-то взялся лишний маргин, а потом мне придется как-то переделвать код чтобы у твоих дивов он остался, а у моих нет. Так писать нельзя. Не применяй стили к дивам. Более того, тут скорее всего нужные возможности есть в бутстрапе, а ты их просто не нащел. Я думаю, там есть класс для того чтобы сделать строку в форме, а ты его просто не нашел.
Не применяй стили к дивам. Применяй их к классам.
Если плохо знаешь CSS, у нас есть задачки на него в ОП посте.
> Убираем расстояние между inline элементами как советуют
> в статье из оп учебника
лучше бы конечно другие методы использовать, а то ты сбросил шрифт для всех элементов, а восстановил только для инпутов, да еще и не тот который был. Посмотри лучше как эта проблема отступов решена в бутстрапе.
Более того, давай прочитаем что ты написал:
> .navbar-form {
> font-size: 0;
"в любых формах, добавленных на панель навигации, сбросить шрифт в 0". Я уверен что тебе надо не это. Тебе надо было убрать отступы только в одной конкретной форме, а не вообще в любых.
Файл htaccess надо переименовать (например перенести его в readme) так как Апач его прочитает и попытается выполнить и будет ошибка что virtualHost нельзя указать в htaccess
> https://github.com/greenTea242/Student-list/blob/master/src/ViewHelper.php#L7
> fixView
название конечно неудачное так как не говорит что он делает. Более того, судя по тексту, он предназначен для обработки строки запроса- но почему ты тогда применяешь его к куке в index.php? И к выводимым ссылкам - какое он имеет к ним отношение? Это как-то ненормально.
Также, тут явно есть уязвиимость XSS:
https://github.com/greenTea242/Student-list/blob/64be58a7aadc56b7d9d4bf45d8dd55482c59ab21/templates/register.html#L45
> value="<?=ViewHelper::FixView($abiturient->surname)?>"
ты выводишь данные не экранируя. Перечитай мой урок по XSS.
https://github.com/greenTea242/Student-list/blob/64be58a7aadc56b7d9d4bf45d8dd55482c59ab21/templates/register.html#L45
https://github.com/greenTea242/Student-list/blob/64be58a7aadc56b7d9d4bf45d8dd55482c59ab21/templates/index.html
Тут полностью скопипащен огромный кусок кода с шапкой и подвалом. Ты ведь не первый день в нашем треде, наверно слышал что копипаста самое плохое что может сделать программист.
https://github.com/greenTea242/Student-list/blob/master/src/Abiturient.php#L17
> const LOCAL = "yes";
Однотипные константы стоит оьъединять общим префиксом (началом названия), как с GENDER.
https://github.com/greenTea242/Student-list/blob/master/src/AbiturientValidator.php#L45
вар дамп не удалил. Надо смотреть git diff перед коммитом.
> Регулярки которые также используются в HTML5 паттернах
Тут есть риск из-за того что диалект регулярок в HTML5 и в PHP вроде как не совпадает. Соответственно легко при редактировании кода получить не работающую на клиенте регулрку. Возможно стоит сдеалать по 2 версии регулярки или еще что-то придумать.
https://github.com/greenTea242/Student-list/blob/master/src/AbiturientValidator.php#L62
> } elseif (mb_strlen($group) > 90) {
Там 5 символов ограничение
> $regexp = "/{$this->getRegExpForGroupNumber()}/u";
ты забыл про привязку к началу и концу строки
Также, в валидаторе нет проверки что указан пол и место жительства.
Также наверно лучше бы сделать чтобы одним валидатором можно было проверить несколько студентов, а не одного.
https://github.com/greenTea242/Student-list/blob/master/src/ini.php#L4
Конфиг нужно подключать без once
Насчет авторизации - почему бы не вынести ее в отдельный класс-сервис с методами вроде получитьСтудента/залогинитьСтудента/разлогинить. И соответственно всю работу с кукой скрыть в этом классе.
https://github.com/greenTea242/Student-list/blob/master/public/index.php#L12
> define('NOTIFY', $notify);
Что это? константа это не переменная которая может принимать лббые значения. Более того непонятно зачем дублировать переменную константой.
> $stmt->setFetchMode(PDO::FETCH_NUM);
> $counter = $stmt->fetchColumn();
В этом случае же setFetchMode не требуется вроде.
> if (!empty($searchQuery)) {
Это плохо что переменная может не существовать. Лучше тогда сделать массив вроде $values[':search'] = .... и передавать его в execute.
Также, при поиске хорошо бы обрабатывать поисковую строку - заменять в ней пробелы на знак % чтобы можно было набрать "ив нов" и найти Ивана Иванова. Также можно удалять левые символы вроде знаков препинания из поискового запроса. Подумай.
> getAbiturientsInPage($page,
Лучше передавать offset и не накладывать на функцию обязанность считать страницы.
> ORDER BY $sort DESC
Надо сортирвоать в обе стороны. Например повторным кликом по заголовку.
> оздаем уникальный идентификатор. если абитуриент впервые на сайте
Это не требуется - mysql умеет это делать, почему не исплоьзуешь auto_increment?
Тут, увы, быстро не рассказать - придется половину учебника яваскрипт пересказывать.
>>693911
Анон тут проверил: >>693999
>>694106
Да, под линуксом другие пути, там используется прямой слеш и нет букв дисков, но так сложно скзать - надо смотреть.
Попробуй в начале индекс.php поставить die('test') и проверь выполняется ли он вообще.
>>694117
А ты session-start делаешь ?
>>694182
Готовых ответов не будет (хотя ссылки легко найти в этом и предыдущем треде). Спрашивай. что именно непонятно, покажи код.
>>694210
return выходит из файла и программа завершается.
>>694218
теперь выглядит верно
>>694238
В комментариях к задаче написано - при регистрации генерируем длинный код, сохраняем в базу и в куки поьзователя. При редактивроании сверяем этот код с базой и находим по нему нужного студента.
Тут, увы, быстро не рассказать - придется половину учебника яваскрипт пересказывать.
>>693911
Анон тут проверил: >>693999
>>694106
Да, под линуксом другие пути, там используется прямой слеш и нет букв дисков, но так сложно скзать - надо смотреть.
Попробуй в начале индекс.php поставить die('test') и проверь выполняется ли он вообще.
>>694117
А ты session-start делаешь ?
>>694182
Готовых ответов не будет (хотя ссылки легко найти в этом и предыдущем треде). Спрашивай. что именно непонятно, покажи код.
>>694210
return выходит из файла и программа завершается.
>>694218
теперь выглядит верно
>>694238
В комментариях к задаче написано - при регистрации генерируем длинный код, сохраняем в базу и в куки поьзователя. При редактивроании сверяем этот код с базой и находим по нему нужного студента.
Хотелось бы по подробнее.
Например, как пхп определяет откуда тянуть файл если неймспейс не подробный?
Как влияет на производительность?
Большое спасибо тебе ОП, все косяки нашел и исправил.
Сам PHP никак не определяет откуда тянуть файл, это делает автозагрузчик.
>Плюс, ты читал PSR-3?
>A ninth method, log, accepts a log level as first argument.
По PSR-3 как раз общая функция log() тоже должна быть, и принимать уровень логгинга как параметр. Правда 8 остальных придется тоже дописать.
>Ну и у тебя какое-то странное наследвоание интерфейса только ради импорта констант - мне оно не нравится. Интерфейсы ведь не для этго.
Можно использовать класс LogLevels вместо интерфейса в клиентском коде, но это уже будет сильная связанность логгера с клиентом.
>И перед константой надо будет писать LogLeves::LOG_WARNING
В варианте с интерфейсом self::LOG_WARNING.
Ты полностью прочитал статью?
В самой функции автозагрузки нужно прописать, откуда "тянуть файл".
spl_autoload_register(function ($class) {
// Получаем путь к файлу из имени класса
$path = __DIR__ . $class . '.php';
if (file_exists($path)) {
require_once $path;
}
});
В примере выше все файлы классов лежат в той же папке что и основной скрипт.
Если у тебя неймспейсы и классы разложены по папочкам по psr стандартам, то и неймспейс соответствует путям в файловой системе. Бекслеши надо только заменить на прямые (этот разделитель пути понимает и виндофс, и линуксы).
Что-то типа $path = explode('\', 'MyApp\Model\User'); $path = implode('/', $path); require "$path.php";
Сделай это в качестве лабораторной работы, чтобы понимать как это работает, и забудь. Пользуйся композером, там этот автозагрузчик встроен. Можешь потом заглянуть в его код и посмотреть как там реализована автозагрузка.
>если неймспейс не подробный
Что? Неймспейс обязан соответствовать psr, иначе накой он вообще нужен.
>Как влияет на производительность?
Сделай тесты, если интересно.
В AJAX ответ обычно присылают в формате JSON. Соответсвенно можно прислать структуру вида
[
{
beforeId: ....,
html: ....
},
...
]
С новыми и изменившимися комментариями,а на клиенте вставить их в нужные места ДОМа.
Какие еще регулярки? HTML нельзя разбирать регулярками.
> если неймспейс не подробный?
Что это значит? PHP всегда передает полное имя класса, со всеми неймспейсами. При этом как по имени класса найти файл - это уже твоя проблема. Если следовать при выборе названия файла PSR-4 то проблемы нет.
Нет. Во время определения функции возникает ошибка.
Функция не должна знать что в неё передают элемент массива, ей должно быть все равно.
Объявление функции будет выглядеть как
>function func($arrayElement)
А передача в неё элемента массива
func($array[0]);
Черт! НИПАНИМАТ!!! Что тут не так? Выполняет код, но, как я понял, там бесконечный цикл. В чем беда?
Это зависит от логики. Если у тебя маргин зависит от ширины родителя то да, если не зависит то нет.
>>698847
В определении функции в скобках надо писать просто переменную.
>>698876
> for ($year; $deposit >= 1000000;
Там пишут условие продолжения цикла, а не условие остановки. Цикл не выполняется потому ни разу.
Также первое выражение не имеет смысла. Там надо написать либо $year = 0 либо ничего: for ( ; $deposit ....
Тут ошибка:
$deposit <= 1000000, $guyAge == 64;
Нельзя указать 2 условия через запятую. Условия можно объединить через && или ||, как это делается в if.
Также, я советую вынести часть кода из шапки, так как слишком она получилась длинная.
>>694295
Да, в общем верно.
>>694327
У тебя неправильное условие продолжения цикла:
$deposit == 1000000;
Тут надо писать условие выполнения цикла (пока меньше миллиона), а не условие завершения.
>>694445
не нужен массив, нужно просто в куке число заходов хранить
Не стоит смешивать в кучу код для вычисления результата и HTML код. Лучше разбить это на 2 файла, первый подготавливает данные, а второй выводит HTML-страницу, как описано тут: http://www.phpinfo.su/articles/practice/shablony_v_php.html
Код лучше постить на ideone, чтобы там же был виден результат запуска. Если конечно с ideone нет проблем и он работает.
> iconv_substr($this->firstName, 0, 2)
Есть же mb_substr, ей только в начале программы надо указать кодировку через mb_internal_encoding - в уроке про строки написано.
> public function getOverTimePay() {
> $needOverPay = 0;
> foreach($this->hours as $hoursPerWeek) {
> if($hoursPerWeek>40) {
> return $needOverPay;
Тут явно ошибка. return выйдет из цикла и ты посчитаешь только первую переработку, а остальные - нет. return ведь выходит из функции и соответственно из цикла тоже.
Аналогично в getOverTimeHours у тебя return внутри цикла и она посчитает только первую переработку, а не все в сумме.
> public function getOverTimePay() {
Эту функцию можно записать проще: взять число переработанных часов и умножить на ставку. А ты фактически копируешь здесь код из getOverTimeHours. Не надо так.
Также ты не учел что переработка там вроде как-то по повышенной ставке оплачена.
> class Control {
> public $totalSalary = 0;
Тут лучше не хранить это свойство, а сделать метод который вычисляет общую зарплату. Почему? Потому что если мы добавим нового работника или поменяем им какие-то свойства то метод посчитает новую, актуальную зарплату. А с твоим подходом в поле останутся старые, неактуальные данные.
> public function getInfo() {
Эта функция не должна быть в классе. зачем нам возвращать массив с информацией, которую и так можно получить, вызвав метод? Но ты можешь создавать массив где-то снаружи, если он тебе нужен.
> return array('totalSalary'=>$this->totalSalary,
> 'totalOverTime'=>$this->totalOverTime
Тут то же самое, надо просто сделать метод возвращающие отдельные знаечния, а массив в классе не создавать.
Не стоит смешивать в кучу код для вычисления результата и HTML код. Лучше разбить это на 2 файла, первый подготавливает данные, а второй выводит HTML-страницу, как описано тут: http://www.phpinfo.su/articles/practice/shablony_v_php.html
Код лучше постить на ideone, чтобы там же был виден результат запуска. Если конечно с ideone нет проблем и он работает.
> iconv_substr($this->firstName, 0, 2)
Есть же mb_substr, ей только в начале программы надо указать кодировку через mb_internal_encoding - в уроке про строки написано.
> public function getOverTimePay() {
> $needOverPay = 0;
> foreach($this->hours as $hoursPerWeek) {
> if($hoursPerWeek>40) {
> return $needOverPay;
Тут явно ошибка. return выйдет из цикла и ты посчитаешь только первую переработку, а остальные - нет. return ведь выходит из функции и соответственно из цикла тоже.
Аналогично в getOverTimeHours у тебя return внутри цикла и она посчитает только первую переработку, а не все в сумме.
> public function getOverTimePay() {
Эту функцию можно записать проще: взять число переработанных часов и умножить на ставку. А ты фактически копируешь здесь код из getOverTimeHours. Не надо так.
Также ты не учел что переработка там вроде как-то по повышенной ставке оплачена.
> class Control {
> public $totalSalary = 0;
Тут лучше не хранить это свойство, а сделать метод который вычисляет общую зарплату. Почему? Потому что если мы добавим нового работника или поменяем им какие-то свойства то метод посчитает новую, актуальную зарплату. А с твоим подходом в поле останутся старые, неактуальные данные.
> public function getInfo() {
Эта функция не должна быть в классе. зачем нам возвращать массив с информацией, которую и так можно получить, вызвав метод? Но ты можешь создавать массив где-то снаружи, если он тебе нужен.
> return array('totalSalary'=>$this->totalSalary,
> 'totalOverTime'=>$this->totalOverTime
Тут то же самое, надо просто сделать метод возвращающие отдельные знаечния, а массив в классе не создавать.
>ты session-start делаешь ?
В yii сессия стартует автоматически, я выше где-то расковырял эту тему
>>694604
Фреймворк автоматически подключает некоторые компоненты
https://github.com/yiisoft/yii/blob/8c9b5114db3ee524d23e985c637b52f329ca5bda/framework/web/CWebApplication.php#L149
в частности компонент session.
Подключение компонента осуществляется вызовом setComponent
https://github.com/yiisoft/yii/blob/083d36127de7298f03c0a701d88a5068dddb2a02/framework/base/CModule.php#L426
внутри которого вызывается метод init класса CHttpSession, внутри которого $this->open()
https://github.com/yiisoft/yii/blob/485c001e99ba1e60eabd496027e69eecdee5ed72/framework/web/CHttpSession.php#L88
внутри которого @session_start
https://github.com/yiisoft/yii/blob/485c001e99ba1e60eabd496027e69eecdee5ed72/framework/web/CHttpSession.php#L114
Видно они собакой подстраховываются от 'A session had already been started'.
Если нужно отключить автоматический старт сессии, можно в главном конфиге (main.php) прописать у компонента session значение autoStart => false.
http://www.emoji.esy.es/
(для тех, кто не понял — выбираем смайлики и пишем ими слова, код можно ставить в ВК)
Заполняю все поля, нажимаю нарисовать и получаю пикрелейтед. Так же можно заполнить не все поля, и тебе все равно покажет пустую форму.
Сделал бы хотя бы валидацию какую-нибудь.
>Заполняю все поля, нажимаю нарисовать и получаю пикрелейтед.
Все поля? И поле предложение тоже?
Валидацию сделаю, ага.
Работает через раз.
Первый раз вроде все правильно срабатывает, отображает код для вставки и картинку из смайлов.
Если после этого еще раз ввести то же самое предложение (или другое, неважно) и нажать нарисовать, выдает пустую форму
как на пике
>>698981
На самом деле форма не пустая, нужно обратить внимание на огромные полосы прокруток. В поле "код для вставки" получается куча переводов строк. Там где должна быть сформирована картинка, тоже туча <br>. Открой исходный код страницы (ctrl+u) и посмотри.
Лечится только нажатием на "сбросить", а потом на каком-нибудь фильтре, например "показать все".
Тогда можно по-новой заполнить форму.
Сделай чтобы нажатие на кнопке "сбросить" возвращало страницу к исходному виду. Пока эта кнопка только очищает "задний фон" и "букву".
>Если после этого еще раз ввести то же самое предложение (или другое, неважно) и нажать нарисовать, выдает пустую форму
как на пике
Да, есть такая проблема, подумаю.
Кнопку сбросить исправлю. Спасибо!
Не обрабатывать ненужные инпуты если не нажат нужный селект
Или еще четвертый вариант: добавлять на страницу лишь только что отправленный коммент, а от новых вообще отказаться. Хочешь посмотреть новые комментарии - обновляй страницу.
LAMP
Я понял свою ошибку. Было просто. ОП, есть замечания?
Собака скрывает ошибки. Возможно из-за какой-то из них сессия не создалась и потому код работает не так как ты думал. Он вроде в лог в этом случае что-то пишет.
Или например если запись в папку недоступна, сессия не сохраняется. Почему бы тебе не посмотреть какая это папка и какие в ней файлы, дату модификации, содержимое?
Но если ты используешь Юи ты не должен напрямую обращаться к SESSION, так как он преддоставляет класс, а то что напрямую будет работать - никто не обещал.
Также в PHP есть session handlers, которые отвечают за загрузку и сохранение сессий - может у тебя там с ними что-то не то.
Посмотреть настройки сессий можно в phpinfo.
Также проверь работают ли сессии без Юи.
Если это веб, то можно, достаточно будет освоить язык, на который будешь делать перекат (это может быть не так легко как кажется на первый взгляд). Если хочешь в другую область, то нужно будет учить больше вещей, например в десктопе MVC это не совсем то что в вебе, а в андроид разработке используют MVP (Model-View-Presenter).
>При чем тут вебмин? Вебмин если не ошибаюсь это аналог pma? Как он заменит веб-сервер, интерпретатор php и субд?
Webmin — это графический web интерфейс для управления сервером на базе Unix подобных операционных систем. То есть установив Webmin вы можете удалённо конфигурировать и управлять Linux сервер в удобном графическом интерфейсе на русском языке через браузер. >http://help.ubuntu.ru/wiki/webmin
Нужно вместе с новыми комментариями передавать их расположение относительно существующих. Как именно передавать - зависит от того какая у тебя структура дерева DOM. Определи минимальный и простейший способ указать расположение.
Ну например если комментарии в дереве идут плоским последовательным списком, то проще всего передать id предыдущего или следующего комментария. Можно также и пути как-то использовать наверно.
> Сравнивать каждый новый комментарий с путем каждого уже существующего
Ненужное усложнение. Браузер очень быстро ищет элементы по их id - логично это использовать.
Тут желательно выбрать самый простой способ (чем сложнее тем проще ошибиться) и не создающий проблем производительности (чтобы не надо было бегать по всему дереву ДОМ, или чтобы не надо на сервере было делать кучу запросов).
>>699200
Паттерны применимы к любым ООП-языкам, некоторые вообще независимы от языка.
> Сложно ли вообще перекатиться на другой ООП язык имея знания php на среднем уровне?
Нет, но по моим ощущениям под средним знанием ООП люди часто подразумевают незнание.
А когда что-то пойдет не так, что будет делать пользователь вебмина? Нет, не нужно. Начинающий должен все это делать из командной строки. Что за клоунада - администрировать линукс через графический интерфейс? для таких людей придумали виндоуз.
Да это не я оставлял начальный пост >>694117
У него там скорее всего дело в кешировании, у меня его код работает корректно.
Я мимопроходил, тоже сначала подумал про session_start, попробовал сам его прописать, юи выдает ошибку 'session had been already started'.
Покопался в исходниках и выяснил причины такого поведения фреймворка. Теперь сижу и горжусь.
>графический web интерфейс для управления сервером
>Поскольку Webmin это графический WEB интерфейс, то для его работы необходим web-сервер.
Что-то мне подсказывает, что сервера все-таки придется установить отдельно. Как веб-сервер, так и субд. Хотя я конечно могу ошибаться.
>>699189
консолю забыл
apt-get install mysql-client
>Что-то мне подсказывает, что сервера все-таки придется установить отдельно. Как веб-сервер, так и субд. Хотя я конечно могу ошибаться.
Да нет, я установил из под командной строки вебмин, и обновы или нужные библиотеки ставлю из под командной строки ( в вебмине есть доступ к ней сразу из под рута )
Страстно захотелось разобраться в консольке (там через неё устанавливается фреймворк, запускается Sublime и т.п.).
Посоветуйте хороших гайдов для работы с нею, пожалуйста.
Начни с этого: https://github.com/codedokode/pasta/blob/master/soft/cli.md
Алсо, если у кого-то есть годные ссылки про использование bash, основы линукса, на русском, скиньте пожалуйста.
http://rghost.ru/6MDG2wZds ну вот тут есть глава по командной строке на убунте. Я правда сам еще не читал, не знаю насколько полезно, но планирую.
Я учился по видеокурсу (не агрись пожалуйста), который записал некто Кирилл Семаев. Курс по плану lpic, автор вроде бы профессиональный айтишник и репетитор, так что вещь очень неплохая.
За неимением лучшего.
Канал на ютубе https://www.youtube.com/watch?v=rKCu-tfL730&list=PLmxB7JSpraiep6kr802UDqiAIU-76nGfc
Там правда записи разбросаны беспорядочно.
Есть на рутрекере.
if ($creditBalance <= $monthlyPayment) {
$monthlyPayment = $creditBalance;
break;
}
не получается.
Код вбрось на ideone.com, так непонятно ничего.
Мыслишь верно, но $creditBalance к моменту попадания в этот if должен уже быть с прибавленными процентами и комиссией. В этом всё дело.
>$creditBalance >= 0
Неправильный подход. Когда долг будет равен нулю, всё равно надо продолжать цикл?
>$creditBalance = ($creditBalance * $percent) + $servicePayment - $monthlyPayment;
Неверный подход. Тут от $creditBalance уже отнимается $monthlyPayment, после чего попадает в if. От этого будет считать всё неправильно (там может быть отрицательное число - Анончик становится должен банку, нонсенс).
На счет
>$creditBalance = ($creditBalance * $percent) + $servicePayment - $monthlyPayment;
я подозревал. Т.е. нужно вычитать платеж после if?
Сложно сказать.
Я обычно советую сделать отдельную переменную для расчёта только ($creditBalance * $percent) + $servicePayment, без вычета $monthlyPayment.
А дальше если эта переменная больше месячной выплаты - продолжаем цикл. А если она меньше - выплачиваем ровно столько и заканчиваем цикл (либо он сам закончится - зависит от условия для работы цикла).
Ты фреймворки называешь шаблонами?
Laravel и yii приблизительно одинаковые, оба имеют положительные и отрицательные стороны.
Если для себя, то без разницы, но в России больше Yii востребован, судя по вакансиям.
В штатах laravel.
Поскольку фреймворк штука немаленькая, есть смысл определиться в каком направлении будешь работать в дальнейшем (на россию или иностранных заказчиков) перед тем как выбирать какой из фреймворков учить.
Английский хотя бы на среднем уровне все равно понадобится.
Для второго юи тоже по-моему нет еще русской документации, а первый сильно устарел.
Что скажешь про Phalcon?
Хотя бы пару слов, бро.
Почему-то советуют для собственных проектов его из-за скорости.
Да фреймворки, я гуглил этот вопрос, мнения расходятся. Вот и я не могу решиться, а проект делать уже надо. Английский имеется, может немного не дотягивает до среднего.
Не знаю, не пробовал.
Почитай на хабре например.
https://habrahabr.ru/post/159217/
Судя по всему очередной хипсторский форс типа монгодб.
Фалькон компилируется из сишного кода. Это значит что если разработчики забьют на проект, поддерживать его дальше придется самостоятельно (для этого нужно знание си).
И зачем нужна скорость? У тебя планируется супер-мега-хайлод?
Короче фалькон для скучающих гиков, желающих экзотики.
http://ideone.com/AtdAXx
Спасибо.
Ты бы хоть писал номер задачи (хотя у опа они наверное и не пронумерованы) или цитировал условие.
Даже сам оп наверное их наизусть не помнит.
for ($i = 0; $i <= count($numbers);
Нужно $i < count, иначе получится на единицу больше, чем элементов в массиве.
Смотри, допустим у нас 10 номеров. count($numbers) даст 10.
А цикл будет выполняться для $i = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 11 раз.
$numbers[10] не существует, даст ошибку PHP Notice: Undefined offset: 10
"/^[8][0-9]{10}$/"
Восьмерку-то зачем в квадратные скобки? Квадратные скобки это группа символов, из которых должен быть выбран один. [abc] равносильно a|b|c (а или b или c). Какой смысл брать один символ в квадратные скобки?
if (preg_match($regexp,$hyphen,$match)) {
...
} if (preg_match($regexp2,$hyphen,$match)) {
Это равносильно
if () {} // одно условие
if () {} // второе условие, совершенно независимое от первого
То есть проверится сначала первый if, потом вне зависимости от результата второй if.
Номера у тебя сейчас по два раза проверяются.
Сначала первый иф говорит, что номер 84951234567 соответствует формату, а потом второй иф с элсом говорит об обратном.
Там наверное нужно if () {} elseif () {} else {}
К опу вопрос по поводу поддержки юникода функцией str_replace.
В оф.мануале об этом не сказано. Хотя может быть вот это место
>Замечание: Эта функция безопасна для обработки данных в двоичной форме.
Что такое двоичная форма? Может это упоминание о мультибайтовых кодировках?
Прокомментируй это
http://stackoverflow.com/questions/3786003/str-replace-on-multibyte-strings-dangerous
Я плохо понимаю басурманский, и там речь о каком-то 16-ричном коде, не понимаю о чем они там треплются короче.
Ты бы хоть писал номер задачи (хотя у опа они наверное и не пронумерованы) или цитировал условие.
Даже сам оп наверное их наизусть не помнит.
for ($i = 0; $i <= count($numbers);
Нужно $i < count, иначе получится на единицу больше, чем элементов в массиве.
Смотри, допустим у нас 10 номеров. count($numbers) даст 10.
А цикл будет выполняться для $i = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 11 раз.
$numbers[10] не существует, даст ошибку PHP Notice: Undefined offset: 10
"/^[8][0-9]{10}$/"
Восьмерку-то зачем в квадратные скобки? Квадратные скобки это группа символов, из которых должен быть выбран один. [abc] равносильно a|b|c (а или b или c). Какой смысл брать один символ в квадратные скобки?
if (preg_match($regexp,$hyphen,$match)) {
...
} if (preg_match($regexp2,$hyphen,$match)) {
Это равносильно
if () {} // одно условие
if () {} // второе условие, совершенно независимое от первого
То есть проверится сначала первый if, потом вне зависимости от результата второй if.
Номера у тебя сейчас по два раза проверяются.
Сначала первый иф говорит, что номер 84951234567 соответствует формату, а потом второй иф с элсом говорит об обратном.
Там наверное нужно if () {} elseif () {} else {}
К опу вопрос по поводу поддержки юникода функцией str_replace.
В оф.мануале об этом не сказано. Хотя может быть вот это место
>Замечание: Эта функция безопасна для обработки данных в двоичной форме.
Что такое двоичная форма? Может это упоминание о мультибайтовых кодировках?
Прокомментируй это
http://stackoverflow.com/questions/3786003/str-replace-on-multibyte-strings-dangerous
Я плохо понимаю басурманский, и там речь о каком-то 16-ричном коде, не понимаю о чем они там треплются короче.
Спасибо
> Что такое двоичная форма? Может это упоминание о мультибайтовых кодировках?
Это значит что функция способна обработать любые сочетания байтов в строке и не сломаться, но никак не гарантирует что на выходе получится что-то корректное.
Для utf-8 str_replace будет работать корректно (если представить как там символы кодируются, будет понятно почему). Для однобайтных кодировок тоже. А вот для 2- и 4-байтных вроде UCS-16 или UCS-32 - не будет.
>если представить как там символы кодируются, будет понятно почему
Как там символы кодируются?
Битрикс тем не менее с возложенными на него задачами справляется.
Поэтому с точки зрения клиента глубоко фиолетово, будет он написан на битриксе, симфони или маринованном огурце, лишь бы приносил доход.
Квалифицированный программист потребует за свою работу в десятки раз больше, чем быдлокодер, осиливший только синтаксис.
С точки зрения клиента конечный продукт от грамотного разработчика ничем не отличается от высера толпы австралопитеков. Так зачем платить больше?
Ну да, каждый месяц что-то протекает. Так посадим десяток-другой обезьян с з.п. 15.000 бананов, они подлатают до следующего месяца.
А что делать? Нанимать йоба-гроссмейстеров, требующих 4000 евро в месяц?
Статья выглядит как пронзительная мольба со стороны заебавшихся разработчиков к клиентам не покупать битриксы, но заказчик знает что ему выгодно.
Спасибо, ОП, какая значительная экономия вышла:
>echo "Ваш ответ на вопрос №$i ({$question->text}): \"{$answer}\" ({$question->answers[$answer]}). ";
>echo "Правильный ответ: \"{$question->correctAnswer}\" - {$question->answers[$question->correctAnswer]}.\n\n";
Ну и вот тот же код, исправленный в соответствии с твоими пожеланиями: http://ideone.com/u4LC5p
Нельзя в echo выводить метод (функции)?
Не сталкивался с таким прежде, но и функции тоже не пробовал выводить в echo.
привет оп, я вернулся. Ты вспомнишь меня по кириллическим переменным куче конкатенаций. Ну и я долго не мог решить задачу с кредитом, лол.
Тут я короче теперь с айпадом решаю. Подумал, что через объекты будет чуть-чуть проще да и мне так больше нравится.
Осталось доделать последний платеж, после айфона это легко, пока не до него, был свободный час.
Из того что мне в этом коде не нравится: $totalPayment переменные выдавали нотисы при инициализации, поэтому я сразу задал их вне циклов. Работает, но может как-то можно их сразу инициализировать и объявить?
А в целом вроде все как надо работает. Последний платеж и посчитать в каком банке выгоднее это пару строчек кода дописать.
ну и очевидно проверки на маленькие кредиты вроде тысячи рупиев, помню-помню, не напоминай
Наперед вопрос: взять финальные значения и прикрутить к ним сравнение для вывода более выгодного кредита, ага?
http://ideone.com/EQT3MF
Сделай хотя бы функцию для расчета, а лучше метод своему классу. У тебя 3 раза один и тот же код повторяется. Это плохо.
>260.89146680312<br>60000</br>-3731.2817891928<br>65000</br>
Дальше можно не смотреть.
Всё неправильно считает.
Ты на Айфон-то доделал решение, я что-то не помню?
><br>
></br>
Боже, что творится в этой голове...
В SEO-то хоть у тебя нормальные результаты?
Да, я работаю по seo.
Ну он пока уходит чутка в минус, по % я посчитал, он верно считает. А по платежу я написал что последний платеж он пока не считает, ну че ты начинаешь.
Я не пишу \n потому что у меня в xampp не работает он да и чистый пхп у меня нигде не юзается, везде ответ вываливается в хтмл либо аякс выводит массив, которые жсом разбираются на нужные мне дела.
Если ты к </br> <br> докопался - оба варианта работают, валидно со слешем, но и без работает.
Хотя я хтмл 5 спецификацию не очень освоил.
короче не нюфаг я. Когда у тебя 15-20 сайтов с правками то тупо нет времени вылизывать каждый код, особенно когда где-то жумла, на двух битрикс, на пяти модх и на еще 4 самописки от васянов. Работает и хуй с ним. Если бы мне платили за каждый сайт не 10-20тысяч а 200, то я бы нанял макак для вылизывания всех этих дел. Но увы.
прекращаю флуд //
Если там больше 65к, то какой ещё последний платёж?
Там должно быть 61270 всего - в этом банке.
Используй <br>, так правильнее
.
На какие стандартные грабли? Этих знаний вполне достаточно, если что-то непонятно ты всегда можешь спросить в треде. Тем более если ты сделал студентов и ОП их одобрил, то я не думаю что у тебя возникнут особые трудности с файлообменником.
Сейчас вроде все верно. Выводить результат вызова метода можно, видимо ты что-то напутал.
>>699914
Ты невнимательно читал урок про функции. Ты скопипастил один и тот же код 3 раза, а копипаста одна из самых плохих вещей которые может сделать программист. И ведь в уроке же написано, что надо использовать функции чтобы не копипастить код.
Значения по умолчанию для полей у тебя не указаны. Вот что если мы создадим Банк, но не зададим все параметры и сразу попробуем посчитать кредит? Надо либо ставить значения по умолчанию, либо (если ты изучил конструкторы) требовать передавать обязательные параметры кредита в конструктор.
Также, я думаю, сумма кредита это не свойство Банка. Ведь один и тот же банк может выдавать кредиты на разные суммы. Это могло бы быть свойство Кредита, но ты назвал свой класс Банк.
Так что нет, решение пока не подходит.
Ставь хотя бы \n после br чтобы на ideone тоже переносило.
### переносы строк и br
Чтобы переносы строк нормально работали и в браузере и в ideone (и в консоли), можно использовать для этого \n, а в начале программы поставить
header("Content-Type: text/plain; charset=utf-8");
Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать переносы строк в нем (так как в языке HTML перенос строки равносилен пробелу).
Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
> Если ты к </br> <br> докопался - оба варианта работают, валидно со слешем, но и без работает.
HTML прощает ошибки потому "работает" не значит "правильно". Ну и чтобы отличить закрывающий тег от открывающего спецификации не надо читать - это одна из первых вещей которые изучают в HTML.
>>699992
Оправдания-оправдания. Если ты хорошо знаешь предмет тебе и не требуется задумываться над каждой строчкой - оно само как надо пишется.
>>700141
Сделать задачу про студентов.
Главное отличие такое:
- при передаче по ссылке функция может изменять исходную переменную, так как она получает ссылку на нее
- при передаче по значению в функцию передается не исходная переменная, а ее копия. Если функция ее поменяет то она изменит только свою копию, а не исходную переменную.
Объекты в PHP всегда передаются "как будто" по ссылке, без создания копии. Массивы, строки, числа по умолчанию передаются по значению, то есть делается копия (на производительность это не влияет, там оптимизированный способ копирования).
Подробнее можно почитать мануал http://php.net/manual/ru/language.references.php
Использование ссылок усложняет код, если можно обойтись без них, лучше без них.
>>694628
> Стоп, но если сессия стартует всегда, то зачем в мануале (не в мануале а в апи) дается пример с явным началом сессии?
На тот случай если компонент используется отдельно или если автостарт отключен. ЧТо значит всегда? Эту настройку можно переопределить например наследованием или убрать компонент из автозапуска. Вообще, это плохая идея по моему всегда включать сессию так как часто она не нужна, а файлы создаются.
И компонент теоретически можно использовать и без фреймворка.
>>694644
>> $youGotDis = array_rand($answers,7);
> Вот эта строка значит, что я создал еще 1 массив в котором я рандомно перемешал всё элементы из массива $answers, я правильно понял ?
Нет, там не элементы, а там получились случайно выбранные 7 ключей.
Для перемешивания уже есть функция shuffle(). Чтобы выбрать один ответ, не надо перемешивать все, надо указывать единицу в аргументах, то есть выбрать один ключ.
> И еще, я не совсем понимаю, как работает следующая строчка
>> echo $answers[$youGotDis[0]]. "\n";
Почитай мануал по array_rand.
Главное отличие такое:
- при передаче по ссылке функция может изменять исходную переменную, так как она получает ссылку на нее
- при передаче по значению в функцию передается не исходная переменная, а ее копия. Если функция ее поменяет то она изменит только свою копию, а не исходную переменную.
Объекты в PHP всегда передаются "как будто" по ссылке, без создания копии. Массивы, строки, числа по умолчанию передаются по значению, то есть делается копия (на производительность это не влияет, там оптимизированный способ копирования).
Подробнее можно почитать мануал http://php.net/manual/ru/language.references.php
Использование ссылок усложняет код, если можно обойтись без них, лучше без них.
>>694628
> Стоп, но если сессия стартует всегда, то зачем в мануале (не в мануале а в апи) дается пример с явным началом сессии?
На тот случай если компонент используется отдельно или если автостарт отключен. ЧТо значит всегда? Эту настройку можно переопределить например наследованием или убрать компонент из автозапуска. Вообще, это плохая идея по моему всегда включать сессию так как часто она не нужна, а файлы создаются.
И компонент теоретически можно использовать и без фреймворка.
>>694644
>> $youGotDis = array_rand($answers,7);
> Вот эта строка значит, что я создал еще 1 массив в котором я рандомно перемешал всё элементы из массива $answers, я правильно понял ?
Нет, там не элементы, а там получились случайно выбранные 7 ключей.
Для перемешивания уже есть функция shuffle(). Чтобы выбрать один ответ, не надо перемешивать все, надо указывать единицу в аргументах, то есть выбрать один ключ.
> И еще, я не совсем понимаю, как работает следующая строчка
>> echo $answers[$youGotDis[0]]. "\n";
Почитай мануал по array_rand.
совет по коду:
-нехорошо 2 раза писать setookie когда мы можем вынести ее из ифа
- для кук желательно ставить путь и время жизни. Почитай про параметр path у кук: http://citforum.ru/internet/html/cookie.shtml
Также, поломай голову и попробуй ответить на мои вопросы выше. Нужно хорошо закрепить знание кук прежде чем переходить дальше.
>Пикрилейтед (проверь, пожалуйста, верно?)
Да, только разберись еще с параметрами path и expires у куки.
> Вопрос: правильно я понимаю, что там нужно генерировать каждому студенту куки-пароль и записывать его в БД. При каждом заходе проверяю куку - если совпадает с кукой-паролем от какого-либо студента, то позволяю править инфу, связанную с этим студентом?
Да
>>694710
На клиенте? На сервере? Если второе то http://php.net/manual/ru/faq.html.php#faq.html.arrays
>>694721
класс не требуется - в jquery можно искать по типу и имени.
>>694762
Не знаю, но думаю ты делаешь что-то не так. Код обычно пишет программист, зачем это тебе его править?
совет по коду:
-нехорошо 2 раза писать setookie когда мы можем вынести ее из ифа
- для кук желательно ставить путь и время жизни. Почитай про параметр path у кук: http://citforum.ru/internet/html/cookie.shtml
Также, поломай голову и попробуй ответить на мои вопросы выше. Нужно хорошо закрепить знание кук прежде чем переходить дальше.
>Пикрилейтед (проверь, пожалуйста, верно?)
Да, только разберись еще с параметрами path и expires у куки.
> Вопрос: правильно я понимаю, что там нужно генерировать каждому студенту куки-пароль и записывать его в БД. При каждом заходе проверяю куку - если совпадает с кукой-паролем от какого-либо студента, то позволяю править инфу, связанную с этим студентом?
Да
>>694710
На клиенте? На сервере? Если второе то http://php.net/manual/ru/faq.html.php#faq.html.arrays
>>694721
класс не требуется - в jquery можно искать по типу и имени.
>>694762
Не знаю, но думаю ты делаешь что-то не так. Код обычно пишет программист, зачем это тебе его править?
> $month = 20;
Нет, такие хаки не нужны. Надо все же использовать break, тем более у тебя он там есть ниже.
> $creditBalance = $creditBalance - $monthlyPayment;
Эту строчку можно вынести из цикла наружу
В остальном верно.
>>694925
Попробуй найти проблему отладчиком в dev tools.
>>694934
Как ты запросы к csv писать собрался?
>>694949
Картинка
>>694958
> $endDebt = $endDebt + $anonPay;
> $debtMain = $debtMain - $anonPay;
Это повторено 2 раза. Используя функции min/max, можно обойтись без повторения и упростить код.
А так, считает верно.
> $month = 20;
Нет, такие хаки не нужны. Надо все же использовать break, тем более у тебя он там есть ниже.
> $creditBalance = $creditBalance - $monthlyPayment;
Эту строчку можно вынести из цикла наружу
В остальном верно.
>>694925
Попробуй найти проблему отладчиком в dev tools.
>>694934
Как ты запросы к csv писать собрался?
>>694949
Картинка
>>694958
> $endDebt = $endDebt + $anonPay;
> $debtMain = $debtMain - $anonPay;
Это повторено 2 раза. Используя функции min/max, можно обойтись без повторения и упростить код.
А так, считает верно.
Тут что-то есть:
http://pco.iis.nsk.su/ICP/Practice/dd8-3/node6.html
http://algolist.manual.ru/ds/walk.php
http://learnc.info/adt/binary_tree_traversal.html
Там основные алгоритмы - обход в ширину и в глубину. Часто это делают через рекурсию.
Алсо там есть примеры кода, правда для графа, а не дерева: https://ru.wikibooks.org/wiki/Реализации_алгоритмов/Поиск_в_глубину
Насчет формул - может стоит почитать про язык на котором они пишутся? Вдруг пригодится. Там символы из теории множеств:
http://www.urtt.ru/bib/dataindex/dm/glava_2~.htm
https://ru.wikipedia.org/wiki/Множество
http://www.grandars.ru/student/vysshaya-matematika/mnozhestvo.html
ну например
> Процедура DFS (параметр — вершина u ∈ V)
u ∈ V значит "вершина u входит в множество V".
Если что, я могу еще подсказать. Освоив эти символы, ты может сможешь понимать математическую форму записи алгоритмов.
Хотя конечно алгоритм в статье википедии сложный и рассчитан на графы (они в отличие от деревьев могут иметь циклы).
>>695247
Можно через массив, создаешь пустой массив и на каждом шаге цикла добавляешь в него оин элемент.
> $name = array_fill(0, 4, $randomText);
Это не то, это ты на каждом шаге заново создаешь массив из 4 одинаковых элементов, затирая старый.
Тут что-то есть:
http://pco.iis.nsk.su/ICP/Practice/dd8-3/node6.html
http://algolist.manual.ru/ds/walk.php
http://learnc.info/adt/binary_tree_traversal.html
Там основные алгоритмы - обход в ширину и в глубину. Часто это делают через рекурсию.
Алсо там есть примеры кода, правда для графа, а не дерева: https://ru.wikibooks.org/wiki/Реализации_алгоритмов/Поиск_в_глубину
Насчет формул - может стоит почитать про язык на котором они пишутся? Вдруг пригодится. Там символы из теории множеств:
http://www.urtt.ru/bib/dataindex/dm/glava_2~.htm
https://ru.wikipedia.org/wiki/Множество
http://www.grandars.ru/student/vysshaya-matematika/mnozhestvo.html
ну например
> Процедура DFS (параметр — вершина u ∈ V)
u ∈ V значит "вершина u входит в множество V".
Если что, я могу еще подсказать. Освоив эти символы, ты может сможешь понимать математическую форму записи алгоритмов.
Хотя конечно алгоритм в статье википедии сложный и рассчитан на графы (они в отличие от деревьев могут иметь циклы).
>>695247
Можно через массив, создаешь пустой массив и на каждом шаге цикла добавляешь в него оин элемент.
> $name = array_fill(0, 4, $randomText);
Это не то, это ты на каждом шаге заново создаешь массив из 4 одинаковых элементов, затирая старый.
Поиск элемента в массиве по ключу.
>>695460
Отдавать без участия PHP, либо использовать readfile какой-нибудь.
>>695678
Копипаста много, и неохота разбираться в чужом коде.
Что там оптимизировать, в разборе строк из десятка символов?
>>695993
> https://ideone.com/fKYM51 - кредитный калькулятор с функциями
Ошибки же:
> PHP Notice: Undefined variable: totalPayment in /home/E4rxrX/prog.php on line 15
Обращаешься к несуществующей еще на тот момент переменной. Надо ее создать сначала, потом исопльзовать.
Также, можно было тут использовать min/max, упростив код. Считает верно.
> https://ideone.com/9wJors - проверка автомобильного номера
Все правильно.
> https://ideone.com/PXYHmh - проверка номеров
Тут тоже верно.
>>696040
Телефоны - varchar достаточной длины (погугли какой длины бывают номера)
координаты - float либо decimal (погугли в чем разница)
Булевых значений - в mysql есть bool, сининим tinyint. А так, inyint(1) NOT NULL
> Может, есть какие-то гайды, как рассчитать наиболее подходящее поле.
Прочитать список типов: http://phpclub.ru/mysql/doc/column-types.html
Поиск элемента в массиве по ключу.
>>695460
Отдавать без участия PHP, либо использовать readfile какой-нибудь.
>>695678
Копипаста много, и неохота разбираться в чужом коде.
Что там оптимизировать, в разборе строк из десятка символов?
>>695993
> https://ideone.com/fKYM51 - кредитный калькулятор с функциями
Ошибки же:
> PHP Notice: Undefined variable: totalPayment in /home/E4rxrX/prog.php on line 15
Обращаешься к несуществующей еще на тот момент переменной. Надо ее создать сначала, потом исопльзовать.
Также, можно было тут использовать min/max, упростив код. Считает верно.
> https://ideone.com/9wJors - проверка автомобильного номера
Все правильно.
> https://ideone.com/PXYHmh - проверка номеров
Тут тоже верно.
>>696040
Телефоны - varchar достаточной длины (погугли какой длины бывают номера)
координаты - float либо decimal (погугли в чем разница)
Булевых значений - в mysql есть bool, сининим tinyint. А так, inyint(1) NOT NULL
> Может, есть какие-то гайды, как рассчитать наиболее подходящее поле.
Прочитать список типов: http://phpclub.ru/mysql/doc/column-types.html
Отправлять можно с любого адреса, но можно и в спам попасть, плюс есть разные технологии вроде SPF. Настраивать сервер необходимо, на хабре полно статей.
>>696327
> Вот тут всё сложно. Или вот эта экзотика
Не надо это использовать, я помню там какие-то проблемы были.
>>696349
Ее более современным аналогом
>>696395
На битриксе код не повторно используемый, много копипасты и тд.
>>696561
Разумеется знание ORM подразумевает понимание как она устроена, а не просто копипасту кода из мануала.
>Сейчас вроде все верно. Выводить результат вызова метода можно, видимо ты что-то напутал.
Нет, там не ошибка и не notice, а только подсвечивание ошибки синтаксиса в Ideone. Нажми на fork - там заработает проверка синтаксиса незапущенного скрипта.
Раньше такого не встречал просто.
> Нет, не получает, только IP шлюза. Аналогично при ручной настройке указывается только IP. Подумай еще.
Отправляет широковещательный ARP-запрос в сеть с заголовком IP. Все узлы получают запрос, сверяют айпишник, и у кого совпадет - тот отправляет ответку со своим мак адресом. Теперь верно?
ОП, извини, что долго не отвечал. Я взял книжку Компьютерные сети. Учебник для вузов. Почти дочитал. И тогда дальше отвечу на твои вопросы. Подумал, что лучше уж прочитать одну книжку и все осмыслить, чем знать урывками информацию.
>извини, что долго не отвечал
Как ты мог? Он тут уже у всех спрашивал, куда ты делся, все ждал когда ты ответишь, а ты все не отвечал...
Шутник мамин, все в камеди клаб.
Я вот думал, что мне одному стыдно, когда ОП написал огромную стену текста с разбором мельчайших моих ошибок, а я даже не ответил на его ответ.
Но при этом я, разумеется, читаю все его ответы, пытаюсь принимать во внимание все его советы.
Просто часто переходим в новый тред, а ответы остаются в старом.
Стыдно от такого.
Суть такова: пользователь может либо загружать файлы с текстом (например электронную книгу xml/fb2 или plain text), либо указать ссылку на ресурс с текстом.
Этот текст разбирается на слова (на самом деле это неправильно, в английском например нужно переводить словосочетания-идиомы, а не отдельные слова, но для робота это уже непосильная задача), пользователю выводится табличка в формате 'слово англ.' => 'перевод на русский'. (А потом эти слова можно учить в стиле тестов memrise, но это уже другая история).
Перевод берется из базы данных (если он там есть, если нет, то нужно дернуть сторонний сервис типа google или yandex translate и добавить в свою базу-словарик).
Сразу встает вопрос, как будет выглядеть запрос? Вот я разбил текст на слова и удалил повторы array_unique, допустим получилось 1000 слов, а может и больше (особенно если юзер зафигачил целую книгу).
Таблица со словами общая для всех текстов и пользователей (язык-то общий).
Структура таблицы
id // только ради внешнего ключа, первичный ключ наверное лучше на самом слове, а может и нет
eng // тут точно как минимум уникальный индекс, а может даже первичный?
rus // варианты перевода, думаю в данном случае можно нарушить атомарность и хранить одной строкой, все равно выводиться это дело будет все вместе
Как извлечь из такой таблицы (или нужна другая структура?) перевод для тысячи слов? По колоночке eng идет поиск, что-то мне не нравится идея использовать where in (дофига значений).
Это первое затруднение.
А главное собственно в другом. Как хранить связь между текстами (которых один пользователь может загрузить несколько сот) и словами? Ну да, многие ко многим. В одном тексте много слов, и одно слово встречается во многих текстах.
Но как я уже говорил, в одном только тексте может встретиться сотни и тысячи слов, и текстов один пользователь может накидать весьма много. И пользователей может быть много тысяч.
Тут уже на миллиарды счет пойдет, если создать одну таблицу 'id_текста' : 'id_слова'.
>>700407
Я думаю у опа больше бомбит от кол-ва постов и скорости постинга, так что лучше стараться тоже писать одним постом и не поддерживать флуд и срач.
Вот например ты зачем-то как хомяк повелся на жирнющий вброс и кого-то покормил. Зачем? (это риторический вопрос) Подумаешь назвали аттеншнвхорой.
Суть такова: пользователь может либо загружать файлы с текстом (например электронную книгу xml/fb2 или plain text), либо указать ссылку на ресурс с текстом.
Этот текст разбирается на слова (на самом деле это неправильно, в английском например нужно переводить словосочетания-идиомы, а не отдельные слова, но для робота это уже непосильная задача), пользователю выводится табличка в формате 'слово англ.' => 'перевод на русский'. (А потом эти слова можно учить в стиле тестов memrise, но это уже другая история).
Перевод берется из базы данных (если он там есть, если нет, то нужно дернуть сторонний сервис типа google или yandex translate и добавить в свою базу-словарик).
Сразу встает вопрос, как будет выглядеть запрос? Вот я разбил текст на слова и удалил повторы array_unique, допустим получилось 1000 слов, а может и больше (особенно если юзер зафигачил целую книгу).
Таблица со словами общая для всех текстов и пользователей (язык-то общий).
Структура таблицы
id // только ради внешнего ключа, первичный ключ наверное лучше на самом слове, а может и нет
eng // тут точно как минимум уникальный индекс, а может даже первичный?
rus // варианты перевода, думаю в данном случае можно нарушить атомарность и хранить одной строкой, все равно выводиться это дело будет все вместе
Как извлечь из такой таблицы (или нужна другая структура?) перевод для тысячи слов? По колоночке eng идет поиск, что-то мне не нравится идея использовать where in (дофига значений).
Это первое затруднение.
А главное собственно в другом. Как хранить связь между текстами (которых один пользователь может загрузить несколько сот) и словами? Ну да, многие ко многим. В одном тексте много слов, и одно слово встречается во многих текстах.
Но как я уже говорил, в одном только тексте может встретиться сотни и тысячи слов, и текстов один пользователь может накидать весьма много. И пользователей может быть много тысяч.
Тут уже на миллиарды счет пойдет, если создать одну таблицу 'id_текста' : 'id_слова'.
>>700407
Я думаю у опа больше бомбит от кол-ва постов и скорости постинга, так что лучше стараться тоже писать одним постом и не поддерживать флуд и срач.
Вот например ты зачем-то как хомяк повелся на жирнющий вброс и кого-то покормил. Зачем? (это риторический вопрос) Подумаешь назвали аттеншнвхорой.
Вот тут:
public function getTotalHoursWorked()
{
$hours = array_sum($this->hours);
return $hours;
}
Как это достать из определения класса?..
Из класса ничего нельзя получить, класс это определение объекта какого-то типа, его описание.
Экземпляр объекта наверное нужно создать, после чего вызвать нужный метод.
Какую переменную ты хочешь получить? $hours? Ну так его возвращает метод getTotalHoursWorked, нужно только экземпляр класса создать.
$yourObject = new ClassName;
$hours = $yourObject->getTotalHoursWorked();
Кстати свойство $this->hours в твоем случае обязано содержать актуальный массив на момент вызова метода getTotalHoursWorked.
В конструкторе его можно заполнить например.
А вот реально ли сделать хороший переводчик, который мог бы и фразы понимать из контекста?
Значит проверяльщик ошибается. Видимо он не все правила синтаксиса знает.
>>700376
> и у кого совпадет - тот отправляет ответку со своим мак адресом.
Верно, только тм еще используют ARP кеш. В линуксе его можно по моему командой arp -a или arp -p посмотреть. Также, бывает "упреждающий ARP" - когда узел без запроса посылает широковещательное сообщение со своим маком и IP чтобы другие узлы его записали в кеш.
> Я взял книжку Компьютерные сети. Учебник для вузов.
Олифер? Знакомый учебник.
>>700454
> Как извлечь из такой таблицы (или нужна другая структура?) перевод для тысячи слов?
Можно через WHERE IN, но тут надо еще подумать: надо ли сразу все 1000 слов преводить? Может пользователю сразу столько и не нужно. Может можно как-то разбить текст на главы, страницы или абзацы.
> варианты перевода, думаю в данном случае можно нарушить атомарность и хранить одной строкой, все равно выводиться это дело будет все вместе
может боком вылезти.
Насчет производительности - тут гадать бесполезно. Сделай микробенчмарк и меряй разные варианты. Другого пути нет. Если что-то тормозит - надо изучать почему (для начала смотреть что загружено: CPU, память, диск и тд), анализировать запросы.
> Как хранить связь между текстами (которых один пользователь может загрузить несколько сот) и словами? Ну да, многие ко многим. В одном тексте много слов, и одно слово встречается во многих текстах.
Вообще для таких вещей могут пригодиться поисковые движки вроде sphinx - они хорош индексируют тексты и ищут в них по словам.
> Тут уже на миллиарды счет пойдет, если создать одну таблицу 'id_текста' : 'id_слова'.
Значит придется партицировать базу данных. Или рассматривать какие-нибудь NoSQL решения (но их тоже надо будет партицировать, не думай что они за тебя проблему решат). Вообще, если ты всерьез хочешь хранить сотни тысяч текстов то может тебе стоит рассмотреть вариант какого-то написанного на компилируемом языке демона, который будет держать все переводы всех слов в оперативной памяти, получать на вход страницу текста и выдавать ее с переводами.
Еще кстати интересный вариант - переводить на клиенте.
Ну и всегда есть варианты как-то по другому хранить данные. Например зачем делать связь между текстом и словами если слова можно и так извлечь из текста?
Но не забывай что все эти гипотезы надо проверять тестами.
Значит проверяльщик ошибается. Видимо он не все правила синтаксиса знает.
>>700376
> и у кого совпадет - тот отправляет ответку со своим мак адресом.
Верно, только тм еще используют ARP кеш. В линуксе его можно по моему командой arp -a или arp -p посмотреть. Также, бывает "упреждающий ARP" - когда узел без запроса посылает широковещательное сообщение со своим маком и IP чтобы другие узлы его записали в кеш.
> Я взял книжку Компьютерные сети. Учебник для вузов.
Олифер? Знакомый учебник.
>>700454
> Как извлечь из такой таблицы (или нужна другая структура?) перевод для тысячи слов?
Можно через WHERE IN, но тут надо еще подумать: надо ли сразу все 1000 слов преводить? Может пользователю сразу столько и не нужно. Может можно как-то разбить текст на главы, страницы или абзацы.
> варианты перевода, думаю в данном случае можно нарушить атомарность и хранить одной строкой, все равно выводиться это дело будет все вместе
может боком вылезти.
Насчет производительности - тут гадать бесполезно. Сделай микробенчмарк и меряй разные варианты. Другого пути нет. Если что-то тормозит - надо изучать почему (для начала смотреть что загружено: CPU, память, диск и тд), анализировать запросы.
> Как хранить связь между текстами (которых один пользователь может загрузить несколько сот) и словами? Ну да, многие ко многим. В одном тексте много слов, и одно слово встречается во многих текстах.
Вообще для таких вещей могут пригодиться поисковые движки вроде sphinx - они хорош индексируют тексты и ищут в них по словам.
> Тут уже на миллиарды счет пойдет, если создать одну таблицу 'id_текста' : 'id_слова'.
Значит придется партицировать базу данных. Или рассматривать какие-нибудь NoSQL решения (но их тоже надо будет партицировать, не думай что они за тебя проблему решат). Вообще, если ты всерьез хочешь хранить сотни тысяч текстов то может тебе стоит рассмотреть вариант какого-то написанного на компилируемом языке демона, который будет держать все переводы всех слов в оперативной памяти, получать на вход страницу текста и выдавать ее с переводами.
Еще кстати интересный вариант - переводить на клиенте.
Ну и всегда есть варианты как-то по другому хранить данные. Например зачем делать связь между текстом и словами если слова можно и так извлечь из текста?
Но не забывай что все эти гипотезы надо проверять тестами.
Нет
>Оправдания-оправдания. Если ты хорошо знаешь предмет тебе и не требуется задумываться...
не спорю, но на тестовых заданиях я не ставлю себе цель писать красивый и читабельный код, работает? работает. Ну да, не правильно. Но клиент на код не смотрит.
> на самом деле это неправильно, в английском например нужно переводить словосочетания-идиомы, а не отдельные слова, но для робота это уже непосильная задача
Посильная. Почитай про лексический и синтаксический анализ. Можно найти или написать библиотеки, которые определяют связи между словами. Ну например в фразе
put it on
синтаксический анализ выделит связь между put и on и это позволит искать в словаре сочетание put on, а не put.
Главная проблема - то что в языке нет строгого синтаксиса и много неоднозначностей. Ну например слово "белок" может быть формой слов "белок" или "белка". Каждое слово может иметь несколько интерпретаций, и выстраивая связи с другими словами, можно отсеять неверные.
http://aot.ru/technology.html
https://ru.wikipedia.org/wiki/Синтаксический_анализ
https://habrahabr.ru/post/137799/
https://tech.yandex.ru/mystem/
google: phpmorphy
https://habrahabr.ru/company/yandex/blog/219311/
> Верно, только тм еще используют ARP кеш.
Да-да, про кэш забыл.
> Олифер? Знакомый учебник.
Ага. Мне товарищ посоветовал, который как раз по нему учился в институте.
Если речь о тестовых заданиях для приема на работу то как раз на код там смотрят. Если речь об учебных задачниях то конечно качество кода тоже важно. Оно показывает хорошо ли ты понимаешь материал или нет. Знаешь ли как сделать перевод строки например.
А если мой компьютер отправляет широковещательный запрос, и другой компьютер в этой сети раньше роутера мне отправит свой mac-адрес? Теперь весь трафик будет проходить через его компьютер? Есть ли защиты от такого?
https://ru.wikipedia.org/wiki/ARP-spoofing
http://xgu.ru/wiki/ARP-spoofing
Увы, не сталкивался, потому могу посоветовать погуглить. Вообще, в протоколах интернета при желании можно найти много слабых мест.
КАк я понимаю, в случае общественной сети вроде провайдера, лучшее решение - засунуть каждого пользователя в отдельный VLAN. Правда, тогда они не смогут в игры играть по сети друг с другом. Может еще как-то можно фильтровать широковещательные запросы, не знаю. Можно мониторить ARP-ответы.
Если захочешь поэкспериментровать - сделай 2 вирт. машины с линуксом (+ хост-машина) и объедини виртуальной (host-only network) сетью.
>надо ли сразу все 1000 слов преводить?
Ну да, можно в цикле прокрутить по сотне. Обернуть в транзакцию само собой.
>Может пользователю сразу столько и не нужно.
Смотри, в чем идея. Есть ресурс memrise.com. Это тупая дрочильня, где тебе предлагают по 100 раз написать перевод слова, авось с сотого на автомате запомнится. А потом еще повторять каждый день, как зомби.
Результат некоторый дает, но недостаточно эффективно. Конечно же запоминается гораздо лучше благодаря ассоциациям и контексту. Например когда я слышу какое-то слово, то мне часто вспоминаются кадры из фильмов, где я его впервые услышал, или картинка из комикса, или фраза из книги и т.д.
Поэтому решил сам написать обертку над memrise, чтобы пользователь мог подгрузить текст (например книгу или статью), программа разбила бы его на слова, и уже эти слова повторять. Потом время от времени возвращаться к книге и пытаться читать ее. Снова наткнулся на непонятное слово? Повтори тесты, прикрепленные к этому тексту (тесты основаны на повторении слов, встречающихся именно в этом тексте).
>хранить одной строкой, все равно выводиться это дело будет все вместе
>может боком вылезти.
Охотно допускаю, но хочется конкретный пример. Мне нужно только получить перевод слова и показать его пользователю, а будет там один вариант перевода или десять, не очень важно, показаны они будут все паком.
Хотя допускаю, что когда понадобится расширить функционал, можно упереться в неправильную архитектуру. Не представляю пока практической ситуации, но верю что она может возникнуть. Надо подумать тогда как хранить множественные варианты перевода.
>придется партицировать базу данных
Страшное слово. Знать бы хоть как его гуглить. "Патрициация базы"? А, нашел, database partitioning.
>зачем делать связь между текстом и словами если слова можно и так извлечь из текста?
Каждый раз когда пользователь захочет пройти тест, разбивать этот текст на слова?
Хотя... а почему бы и нет? Это же не займет много времени. Текст только целиком хранить в базе в виде соотв.поля, точно не нужно извлекать его из файла или ресурса каждый раз.
Ну ок, спасибо, есть варианты и пища для размышления так сказать.
>>700486
Ой, опять какие-то алгоритмы, мат.анализ и прочая лабуда. Я не буду даже мараться об это.
Можно же ручками вбить в базу все возможные устойчивые словосочетания. Получится может быть несколько сот тысяч, но это же не так страшно.
Допустим, у меня в тексте есть фраза 'hang in the balance' (висеть на волоске).
Если переводить по одному слову, получится ахинея.
А что если в базе уже есть не только слова 'hang', 'in' и прочие? Что если там есть все (или многие) идиомы?
Тогда нужно всего лишь использовать LIKE 'hang%' вместо ='hang'.
Да, вернет больше вариантов. После чего проходим циклом по всем вариантам и сравниваем с исходной строкой. Если есть полное совпадение, то именно этот вариант выбираем в качестве правильного для всего словосочетания.
Но это потом, сначала нужно написать хотя бы простой сервис для перевода одиночных слов.
>надо ли сразу все 1000 слов преводить?
Ну да, можно в цикле прокрутить по сотне. Обернуть в транзакцию само собой.
>Может пользователю сразу столько и не нужно.
Смотри, в чем идея. Есть ресурс memrise.com. Это тупая дрочильня, где тебе предлагают по 100 раз написать перевод слова, авось с сотого на автомате запомнится. А потом еще повторять каждый день, как зомби.
Результат некоторый дает, но недостаточно эффективно. Конечно же запоминается гораздо лучше благодаря ассоциациям и контексту. Например когда я слышу какое-то слово, то мне часто вспоминаются кадры из фильмов, где я его впервые услышал, или картинка из комикса, или фраза из книги и т.д.
Поэтому решил сам написать обертку над memrise, чтобы пользователь мог подгрузить текст (например книгу или статью), программа разбила бы его на слова, и уже эти слова повторять. Потом время от времени возвращаться к книге и пытаться читать ее. Снова наткнулся на непонятное слово? Повтори тесты, прикрепленные к этому тексту (тесты основаны на повторении слов, встречающихся именно в этом тексте).
>хранить одной строкой, все равно выводиться это дело будет все вместе
>может боком вылезти.
Охотно допускаю, но хочется конкретный пример. Мне нужно только получить перевод слова и показать его пользователю, а будет там один вариант перевода или десять, не очень важно, показаны они будут все паком.
Хотя допускаю, что когда понадобится расширить функционал, можно упереться в неправильную архитектуру. Не представляю пока практической ситуации, но верю что она может возникнуть. Надо подумать тогда как хранить множественные варианты перевода.
>придется партицировать базу данных
Страшное слово. Знать бы хоть как его гуглить. "Патрициация базы"? А, нашел, database partitioning.
>зачем делать связь между текстом и словами если слова можно и так извлечь из текста?
Каждый раз когда пользователь захочет пройти тест, разбивать этот текст на слова?
Хотя... а почему бы и нет? Это же не займет много времени. Текст только целиком хранить в базе в виде соотв.поля, точно не нужно извлекать его из файла или ресурса каждый раз.
Ну ок, спасибо, есть варианты и пища для размышления так сказать.
>>700486
Ой, опять какие-то алгоритмы, мат.анализ и прочая лабуда. Я не буду даже мараться об это.
Можно же ручками вбить в базу все возможные устойчивые словосочетания. Получится может быть несколько сот тысяч, но это же не так страшно.
Допустим, у меня в тексте есть фраза 'hang in the balance' (висеть на волоске).
Если переводить по одному слову, получится ахинея.
А что если в базе уже есть не только слова 'hang', 'in' и прочие? Что если там есть все (или многие) идиомы?
Тогда нужно всего лишь использовать LIKE 'hang%' вместо ='hang'.
Да, вернет больше вариантов. После чего проходим циклом по всем вариантам и сравниваем с исходной строкой. Если есть полное совпадение, то именно этот вариант выбираем в качестве правильного для всего словосочетания.
Но это потом, сначала нужно написать хотя бы простой сервис для перевода одиночных слов.
А, и еще провайдеры обычно привязывают мак-адрес к порту коммутатора. Если ты поменяешь мак-адрес то никуда пакеты посылать не сможешь. Возможно это как-то исплоьзуется для защиты от спуфинга, не знаю. Возможно - нет.
Я бы не беспокоился о производительности пока. Тебе первое, что надо делать - это отрабатывать подачу информации, интерфейс и прочее. нагрузки в начале у тебя никакой не будет. А когда будет ясен механизм работы приложения, тогда и схему для хранения данных будет выбирать проще.
> Можно же ручками вбить в базу все возможные устойчивые словосочетания.
Не факт так как слова могут идти не подряд. И даже если идут подряд, это может быть не то сочетание.
А нет нельзя: http://xgu.ru/wiki/ARP-spoofing#.D0.9C.D0.B8.D1.84.D1.8B_.D0.B8_.D0.B7.D0.B0.D0.B1.D0.BB.D1.83.D0.B6.D0.B4.D0.B5.D0.BD.D0.B8.D1.8F.2C_.D0.BA.D0.B0.D1.81.D0.B0.D1.8E.D1.89.D0.B8.D0.B5.D1.81.D1.8F_ARP-spoofing
Антивирус Касперского говорят реагирует на изменение арп кеша. Вот и защита. Но а если под линуксом не знаю.
Мне надо просто воспользоваться функцией, которая внутри класса, и я не знал, как это делается.
>>700470
>Какую переменную ты хочешь получить? $hours? Ну так его возвращает метод getTotalHoursWorked, нужно только экземпляр класса создать.
Спасибо, вот это то, что нужно.
А можно ли как-то кратко посчитать все hours для любых экземпляров класса? Для всех имеющихся?
Или мне просто сложить $oneObject->hours + $twoObject->hours и так далее?
Ведь должен же быть какой-то способ автоматизации этого?
Помогите, братишки: http://ideone.com/aHTLbq
Дайте волшебного пендаля.
Наверное, надо как-то отдельно подсчитать нормальное время, отдельно переработанное и сложить? Как обычно, стоит спросить совета.
Но ведь это как-то должно в цикле выдаваться, а у меня там $ivan->getSalary() + $peter->getSalary()...
Без вас не разобраться.
https://github.com/someApprentice/Students/blob/6471191b2bd63bb5aa3205369cfb26adb5a0067d/app/Controller/RegisterAction.php#L50-L52
>Что такое MVC? Модель хранит и изменяет данные, контроллер обрабатывает запрос от пользователя. Контроллер должен быть тонким и все, что можно обобщить и абстрагировать, надо из него выносить.
>Вот например это:
>> $salt = $this->reghelper->generateSalt(); //getRegHelper() будет лучше?
>> $hash = $this->reghelper->hashPassword($password, $salt);
>> $token = $this->reghelper->generateToken();
>что оно делает в контроллере? Должен быть метод в модели, который реализует процесс регистрации нового студента, а ты почему-то написал стену текста прямо в контроллере. Подумай, как можно изолироать все, что не привязано к форме и вынести из конроллера.
А контроллер разве не реализует процесс регистрации нового студента? Я не могу понять в какой модели иначе это должно реализоваться. На данный момент у меня есть RegisterForm, Student, RegistrationHelper, StudentGateway, и не к одному из них я не могу отнести эти методы. За исключением разве что модели студента, но там встает такая проблема - поле с хэшом может браться из ДБ а не генерироваться при регистрации, и соответственно становиться проще сгенерировать хэш где-то снаружи и потом его просто передать.
>зачем делать связь между текстом и словами если слова можно и так извлечь из текста?
Можно было бы действительно разбивать каждый раз текст на слова, но меня это не устраивает, потому что пользователь должен иметь возможность "почистить" словарик, относящийся к данному тексту. Убрать стоп-слова типа артиклей и местоимений, удалить уже известные ему слова, которые не хочется повторять.
Программа должна разбить текст на слова и предоставить пользователю причесать полученный список (как минимум удалить все лишнее, оставив только новые полезные слова, а может быть даже предложить свой вариант перевода вместо гугловского), короче что-то типа круда.
Тогда я попытался рассмотреть вариант, а не хранить ли словарик вместе с текстом в базе? Таблица текстов будет содержать два больших текстовых поля, одно с исходным текстом, а второе сериализованный словарик. Проблемка все та же: как это потом редактировать? Я себе уже представил страницу, где есть таблица 'слово - перевод', рядом с каждой строкой галочка на удаление. Внизу кнопка "удалить выбранные". А как мне галочки связать-то с записями? Вот незадача.
Можно аяксом конечно, но я исхожу из позиции, что нужно сделать чтобы сайт был полностью рабочим без единой строки js. А потом уже обмазывать джаваскриптами.
Может сделать кучу скрытых инпутов, по два на слово? Или даже не скрытых. Пара инпутов name="updateVocab[eng]" и name="updateVocab[rus]", галочка дисейблит пару инпутов напротив которой стоит. На сервере уже разгрести полученную из формы кашу и слепить массив, сериализовать и сохарнить в поле для словаря.
Допустим у текста словарь из ста слов. Двести инпутов в одной форме все-таки перебор.
Надо поспать, крыша едет куда-то.
>>700737
Регистрация это обычный сейв новой записи в базе. Так что класс отвечающий за взаимодействие с базой должен заниматься сохранением их в базе, data mapper или tdg.
https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md#table-data-gateway
addNews из примера замени на registerStudent
>зачем делать связь между текстом и словами если слова можно и так извлечь из текста?
Можно было бы действительно разбивать каждый раз текст на слова, но меня это не устраивает, потому что пользователь должен иметь возможность "почистить" словарик, относящийся к данному тексту. Убрать стоп-слова типа артиклей и местоимений, удалить уже известные ему слова, которые не хочется повторять.
Программа должна разбить текст на слова и предоставить пользователю причесать полученный список (как минимум удалить все лишнее, оставив только новые полезные слова, а может быть даже предложить свой вариант перевода вместо гугловского), короче что-то типа круда.
Тогда я попытался рассмотреть вариант, а не хранить ли словарик вместе с текстом в базе? Таблица текстов будет содержать два больших текстовых поля, одно с исходным текстом, а второе сериализованный словарик. Проблемка все та же: как это потом редактировать? Я себе уже представил страницу, где есть таблица 'слово - перевод', рядом с каждой строкой галочка на удаление. Внизу кнопка "удалить выбранные". А как мне галочки связать-то с записями? Вот незадача.
Можно аяксом конечно, но я исхожу из позиции, что нужно сделать чтобы сайт был полностью рабочим без единой строки js. А потом уже обмазывать джаваскриптами.
Может сделать кучу скрытых инпутов, по два на слово? Или даже не скрытых. Пара инпутов name="updateVocab[eng]" и name="updateVocab[rus]", галочка дисейблит пару инпутов напротив которой стоит. На сервере уже разгрести полученную из формы кашу и слепить массив, сериализовать и сохарнить в поле для словаря.
Допустим у текста словарь из ста слов. Двести инпутов в одной форме все-таки перебор.
Надо поспать, крыша едет куда-то.
>>700737
Регистрация это обычный сейв новой записи в базе. Так что класс отвечающий за взаимодействие с базой должен заниматься сохранением их в базе, data mapper или tdg.
https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md#table-data-gateway
addNews из примера замени на registerStudent
Один скрытый инпут конечно. Джаваскриптом менять ему значение, реагируя на галочки.
Но как без js обойтись, непонятно.
Без яваскрипта можно обойтись если у тебя там что-то статичное (например текст, где над каждым словом написан перевод) или несложная форма. Если пользователь может взаимодействовать с текстом и что-то там менять, например щелкать по словам и что-то выбирать, то наверно без яваскрипта это будет делать неоправданно сложно. Да и перезагружать страницу на каждый клик не лучшая идея.
Без яваскрипта делаются сайты на которых нет особой интерактивности - блог, например. они хорошо программируются чистым HTML, простые формы.
Если же сайт больше выглядит как приложение, с которым пользователь активно взаимодействует, то его и надо программировать как приложение - в том числе с явакриптом, может даже придется что-то вроде MVC там делать. А вывод первоначального состояния страницы можно сделать на сервере. А уже после добавляются скрипты для интерактивности.
Если конечно делать именно таблицу с формой, то тут можно и без JS обойтись.
> рядом с каждой строкой галочка на удаление. Внизу кнопка "удалить выбранные"
Последние тренды - удалять сразу когда ты галочку ставишь, но предусмотреть возможность отменить удаление. Эти кнопки сохранения - это из предыдущей эпохи, сейчас их нигде нет, ни в веб-приложениях ни на мобильных платформах. Ну и защищает от случая когда ты что-то отредактировал и случайно вкладку закрыл.
Насчет базы - определись сначала с тем как будет выглядеть интерфейс, а исходя из него уже проектируй базу.
> а не хранить ли словарик вместе с текстом в базе?
Есть ли смысл многократно дублировать данные? Вряд ли. Выбрать 1000 записей по id можно достаточно быстро.
>галочка дисейблит пару инпутов напротив которой стоит.
Удалять слова надо явной передачей признака удаления - чтобы при ошибке ничего не удалилось, а не вообще все слова.
Без яваскрипта элементарно делается - редактирование слова через инпут, удаление галочкой (причем с помощью ксс можно даже например слово перечеркивать при включении галочки).
Плохо что непонятно.
>Регистрация это обычный сейв новой записи в базе. Так что класс отвечающий за взаимодействие с базой должен заниматься сохранением их в базе, data mapper или tdg.
>https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md#table-data-gateway
>addNews из примера замени на registerStudent
Но какой тогда хэш передавать в модель студента? Пароль из поста? Где тогда получатся соль и токен, если такие поля заполнять требуется? Учитывая что при получение объекта из ДБ эти свойства должны быть.
Класс сохранения в базу должен наверно получать уже готового студента с заполненными полями. То есть проставляться токен или хеш пароля должен где-то снаружи.
Стоит наверно сделать метод вроде "задать пароль" который все это и прописвает в модель студента.
if( $city===('Москва' OR 'Санкт-Петербург') )
всегда будет false, если $city==='Москва'?
Доселе проблема не была решена.
Прошу помощи!
>>700833
Насколько мне известно, это неправильный синтаксис (либо я где-то тоже ошибался). Во всяком случае, всегда делал вот так: http://ideone.com/LrjpVk - и всё работало.
Так писать нельзя. or это логическая операция, которая возврращает true или false. Соответственно у тебя получится либо
$city === true
либо
$city === false
И в обоих случахя условие не сработает.
http://php.net/manual/ru/language.operators.logical.php
С помощью or можно объяединять толкьо условия, а не значения. Надо писать вроде такого:
if ($a == 1 || $b == 2)
>То есть проставляться токен или хеш пароля должен где-то снаружи.
В этом и вопрос что где "снаружи". У меня он прописан в контроллере, и в чем я ошибка я не могу понять. Если всё оставить как есть, то никаких проблем не остается.
Нет, я все же вижу проблему. Генерация всех этих токенов - это явно отдельное действие, и его можно вынести в отдельный метод. Метод задания студенту пароля.
Далее, еще советы по этому коду
https://github.com/someApprentice/Students/blob/master/app/Controller/RegisterAction.php
https://github.com/someApprentice/Students/blob/master/app/Controller/RegisterAction.php#L27
Что если тебе надо будет проверять студента в другом месте - ты туда скопипастишь эту стену кода? Надо сделать одинметод который принимает студента и возвращает например массив ошибок.
Вместо стены кода лучше сделать цикл.
> getRegHelper() будет лучше?
думаю это не требуется, тут же все в одном классе небольшом
https://github.com/someApprentice/Students/blob/master/app/Controller/RegisterAction.php#L61
Эту стену кода надо заменить циклом.
> new Student($name, $surname, $gender, $grupnumber, $email, $satscores, $yearofbirth, $location,
нельзя делать больше 3 .. 5 аргументов. Тут ведь ошибку не увидеть. У тебя нет ощущения что тут что-то не в порядке?
Аналогично с функцией Signup.
И вот что еще. Ты хранишь пришедшие из формы данные в 10 переменых. В таких случаях надо использовать массив. Но тут у тебя есть объект Студент, в котором хранить эти данные даже еще удобнее. Исопльзуй-ка его.
>>700862
В PHP можно не только перезаписывать переменные но и дописывать: $var = 'My name';
$var .= ' is';
в результате в $var будет находиться текст "name is".
.= это короткая запись такого типа: $var = $var . ' is'; (такое же есть и для арифметический операций).
Огромное спасибо, анон!
Сорян за набор слов в вопросе - температура и я на работе ещё:
суть проблему - xdebug при прослушивании порта подхватывает и phpmyadmin если его запустить. Надо как-нибудь запретить ему это делать.
> ServiceLocator - это создаем класс и в нем складываем все хелперы, а в классе, имеющем зависимости, обращаемся к сл и берем у него что нужно.
> Dependency Injection - это то же самое, только попадает в зависимый класс через конструктор.
> Я правильно разницу понял?
Да. И смотри, какая интересная тут есть особенность. При использовании DI ты не обязан использовать контейнер - ты можешь создавать зависимости вручную или как-то еще. а вот при использовании подхода с передачей в конструктор SL твои классы все становятся зависимыми от конкретного класса SL и независимо их использовать нельзя. Это плохо, так как из-за этого трудно их вынести в отдельную библиотеку например.
>>696965
Да
>>697093
Норма. Соотношение - не знаю, наверно практики чуть больше. Часто. Хорошо относятся. Нет.
>>697111
Есть такое
http://www.mediafire.com/download/5o7mmd25bvn2o9d/архив-тредов-с-марта-2015.zip
http://www.mediafire.com/download/kgzl1f9366gc6ed/threads-archive-11..20.zip
http://www.mediafire.com/download/gza5360wdzqd743/threads-archive-pr-1..17.zip
http://www.mediafire.com/download/s12ktalf8r8rl48/pr-threads-69-70.zip
Хорошо, только я бы тут не создавал новые переменные а использовал ту же самую:
> $textLower = mb_strtolower ($text);
> $textNoSpace ....
Так, верно решено.
>>697237
Чтобы при гуглении не выдавало Моцарта и Баха наверно. Ну и чтобы понятно было что речь не о музыке.
Тут написано https://en.wikipedia.org/wiki/Symfony#Sponsors раньше префиксы у классов были sf, возможно в этом еще дело.
>>697292
Тут ведь не один курс нужен, а по каждой технологии. Если решишь все задания в ОП посте, может что-то и получится.
>>697655
max-width наверно поставить
> 1 задача: https://jsfiddle.net/te5t987m/
> div {
Стоит сразу приучаться не вешать стили на див, так как на реальной странице вседа много дивов и все может сломаться. А так, верно.
> 2 задача: https://jsfiddle.net/13Lkpwtc/
Ок, верно.
> 3 задача: https://jsfiddle.net/8gcbwyc5/
правильно
> 4 задача: https://jsfiddle.net/5qotwgrr/
> margin-left: 7px;
А почему не 10? Этот способ имеет тот недостаток что зависит от размера шрифта и особенностей регдеринга на разных платформах. Почитай еще про другие способы, это вроде в комментариях к задаче описано.
Копипасту в стилях надо победить с помощью записи селекторов через запятую или дополнительного класса.
> 5 задача: https://jsfiddle.net/skemuf9g/
Паддинг забыл, а так - верно.
> 6 задача: https://jsfiddle.net/as3yrj0y/
- заголовок должен быть не жирным шрифтом
- san-serif - опечатался
- в меню надо убрать точки и увеличить расстояние между пунктами
- br используется только для разрыва строки в текстах программ, стихах, адресах. Тут надо использовать абзацы.
> .sidebar {
> min-width: 200px;
что если мы удлиним пункт меню? https://jsfiddle.net/92p4avx7/3/ - твоя верстка явно не стабильна. Надо чтобы пункт меню просто переносился на новую строку.
для статьи можно использовать тег article. Также может тут можно исопльзовать nav, может нет.
> 7 задача: https://jsfiddle.net/t7d5x54r/
между элементами не 10px, а больше, почитай комментарии к задаче
> height: 30px;
> height: 31px;
Не совпадает же. Ты паддинги учел? Посмотри в developeer tools в чем дело.
> 8 задача: https://jsfiddle.net/74398gsy/
> width: auto;
> height: auto;
Это писать не надо так как по умолчанию там такие значения и стоят.
Вот я ее баг нашел - примечанию могут накладываться друг на друга: https://jsfiddle.net/zftm0x1y/1/ - подумай над решением проблемы
> p {
> margin: 0;
Плохо - абзацы склеиваются. Так делать не надо. Подумай над более точечным указанием селектора.
> 9 задача: https://jsfiddle.net/bmsof3d1/
Неудачно выбраны способы позиционирования. Во-первых, серый блок не растягивается на 100% родителя по ширине. Во-вторых, если сделать маленькие абзацы, они могут выстроиться горизонтально: https://jsfiddle.net/eb16Ljdh/1/ (попробуй поставить ширину окошка побольше).
Ну и это тоже плохо
> p {
> margin: 0 10px 0px 180px;
А, еще, ты применил флоат к абзацам, а что если добавить другие теги в текст? Заголовки, картинки, списки? Не работает: https://jsfiddle.net/eb16Ljdh/2/
Боюсь твой подход не работает.
> 10 задача: https://jsfiddle.net/sfybve16/
> position: absolute;
> right: 90%;
Неудачный способ так как нет гарантий что при любой ширине поля слева будут больше 10%. Впрочем можно сделать right 100% + вытянуть с помощью margin-right, также возможно рассмотреть флоат для этой цели.
> img {
Надо бы стили применять не ко всем картинкам а только к нужной тебе.
Для картинки нет ограничения по размеру, то есть она увеличивается на большой щирине, а увеличивать растровые картинки больше 100% нельзя.
Пока картинка не загрузилась, черная плашка наезжает на текст - нехорошо.
Надпись in the picture надо сделать бледнее.
> 11 задача: https://jsfiddle.net/3uhzjytk/
Что-то совсем не похоже на картинку. для верстальщика важно уметь верстать близко к макету, а не заменяя круглые блоки на квадратные.
Между кнопками сдвоенная граница, а на макете - одинарной ширины.
> .buttons label {
> width: 70px;
не годится. Что если надпись будет длинее? Всегда когда можно надо не указывать конкретные размеры, а сделать чтобы они считались автоматически.
Плохо вписывается в текст: https://jsfiddle.net/77vw5u4o/2/ (должен быть перевод строки после блока с кнопками так как он засунут в див)
> top: -100px;
Ненадежно так как у родителя может быть position relative и тогда отсуп будет считаться от него.
Что насчет клавиатурной навигации?
> 1 задача: https://jsfiddle.net/te5t987m/
> div {
Стоит сразу приучаться не вешать стили на див, так как на реальной странице вседа много дивов и все может сломаться. А так, верно.
> 2 задача: https://jsfiddle.net/13Lkpwtc/
Ок, верно.
> 3 задача: https://jsfiddle.net/8gcbwyc5/
правильно
> 4 задача: https://jsfiddle.net/5qotwgrr/
> margin-left: 7px;
А почему не 10? Этот способ имеет тот недостаток что зависит от размера шрифта и особенностей регдеринга на разных платформах. Почитай еще про другие способы, это вроде в комментариях к задаче описано.
Копипасту в стилях надо победить с помощью записи селекторов через запятую или дополнительного класса.
> 5 задача: https://jsfiddle.net/skemuf9g/
Паддинг забыл, а так - верно.
> 6 задача: https://jsfiddle.net/as3yrj0y/
- заголовок должен быть не жирным шрифтом
- san-serif - опечатался
- в меню надо убрать точки и увеличить расстояние между пунктами
- br используется только для разрыва строки в текстах программ, стихах, адресах. Тут надо использовать абзацы.
> .sidebar {
> min-width: 200px;
что если мы удлиним пункт меню? https://jsfiddle.net/92p4avx7/3/ - твоя верстка явно не стабильна. Надо чтобы пункт меню просто переносился на новую строку.
для статьи можно использовать тег article. Также может тут можно исопльзовать nav, может нет.
> 7 задача: https://jsfiddle.net/t7d5x54r/
между элементами не 10px, а больше, почитай комментарии к задаче
> height: 30px;
> height: 31px;
Не совпадает же. Ты паддинги учел? Посмотри в developeer tools в чем дело.
> 8 задача: https://jsfiddle.net/74398gsy/
> width: auto;
> height: auto;
Это писать не надо так как по умолчанию там такие значения и стоят.
Вот я ее баг нашел - примечанию могут накладываться друг на друга: https://jsfiddle.net/zftm0x1y/1/ - подумай над решением проблемы
> p {
> margin: 0;
Плохо - абзацы склеиваются. Так делать не надо. Подумай над более точечным указанием селектора.
> 9 задача: https://jsfiddle.net/bmsof3d1/
Неудачно выбраны способы позиционирования. Во-первых, серый блок не растягивается на 100% родителя по ширине. Во-вторых, если сделать маленькие абзацы, они могут выстроиться горизонтально: https://jsfiddle.net/eb16Ljdh/1/ (попробуй поставить ширину окошка побольше).
Ну и это тоже плохо
> p {
> margin: 0 10px 0px 180px;
А, еще, ты применил флоат к абзацам, а что если добавить другие теги в текст? Заголовки, картинки, списки? Не работает: https://jsfiddle.net/eb16Ljdh/2/
Боюсь твой подход не работает.
> 10 задача: https://jsfiddle.net/sfybve16/
> position: absolute;
> right: 90%;
Неудачный способ так как нет гарантий что при любой ширине поля слева будут больше 10%. Впрочем можно сделать right 100% + вытянуть с помощью margin-right, также возможно рассмотреть флоат для этой цели.
> img {
Надо бы стили применять не ко всем картинкам а только к нужной тебе.
Для картинки нет ограничения по размеру, то есть она увеличивается на большой щирине, а увеличивать растровые картинки больше 100% нельзя.
Пока картинка не загрузилась, черная плашка наезжает на текст - нехорошо.
Надпись in the picture надо сделать бледнее.
> 11 задача: https://jsfiddle.net/3uhzjytk/
Что-то совсем не похоже на картинку. для верстальщика важно уметь верстать близко к макету, а не заменяя круглые блоки на квадратные.
Между кнопками сдвоенная граница, а на макете - одинарной ширины.
> .buttons label {
> width: 70px;
не годится. Что если надпись будет длинее? Всегда когда можно надо не указывать конкретные размеры, а сделать чтобы они считались автоматически.
Плохо вписывается в текст: https://jsfiddle.net/77vw5u4o/2/ (должен быть перевод строки после блока с кнопками так как он засунут в див)
> top: -100px;
Ненадежно так как у родителя может быть position relative и тогда отсуп будет считаться от него.
Что насчет клавиатурной навигации?
> http://ideone.com/kr3ibA - имейлы в тексте
Ок, верно
> http://ideone.com/TujCVy - автозамена
> [о|o]
В квадратных скобках вертикальная черта не имеет особого значения и обозначает саму себя. Тут она не нужна.
> http://ideone.com/bEr5sE - проверка номеров и приведение их к одной форме
> ([/\s()-/]*)
Что за странное выражние? Почему скобки использованы как оганичители? Почему внутри квадратных скобко слеши? Ощущение что ты наугад символы ставил.
>>698150
Значит надо больше верстать для закрепления знаний.
>>698276
property_exists, но тут надо бы исопьзовать еще белый список разрешенных полей
$attempts = Yii::app()->session['attempts'];
потом идёт валидация, etc и если валидация фейлится, то записываем в сессию обратно
Yii::app()->session['attempts'] = $attempts;
и тут всплывает одно НО: строка
$attempts = Yii::app()->session['attempts'];
всегда возвращает null, независимо от того, что я туда раньше клал. Всё хранится только в пределах одного обращения.
я уже проверял параметры через
Yii::app()->session['attempts'];
что показало session lifetime равным 0 и когда я явно задавал lifetimve, то всё равно при следующем обращении было снова 0. В конфиге Yii ничего про сессию не написано. При попытке прописать session lifetime напрямую в php.ini всё равно снова получал 0.
ЧЯДНТ?
этот кусок кода не кешируется, если что
Ну так дай ссылку плиз.
Господа, я сделал задачу на рекурсивное вычисление факториала - получилось. Сделал на линейно-итеративное и не получилось. Что у меня здесь не так?
Должно выдать 120, а не выдает ничего, помогите разобраться, пожалуйста.
https://ideone.com/Ahneci
Проверь, что нет ошибки при первоначальной инициализации этого значения (может ты забыл туда положить стартовое значение, естественно при попытке его получить каждый раз будет возвращаться null).
Проверь настройки yii. В main.php это секция components => session.
Проверь работают ли сессии без юи.
У меня подобный код корректно работает на голом свежеустановленном бандле
public function actionTest()
{
if (!isset(Yii::app()->session['attempts'])) {
Yii::app()->session['attempts'] = 0;
}
$attempts = Yii::app()->session['attempts'];
echo $attempts;
Yii::app()->session['attempts'] = ++$attempts;
}
Есть сайт, который на аналоге modx, в нем нет готового модуля магазина. Я собсна затем и стал на нем писать магазин, чтобы попрактиковаться.
У одного товара может быть куча рубрик (7 && 8 && 9)
Теперь два стула - один запрос на все рубрики, в котором эти id динамически меняются в зависимости от рубрики, либо
на каждой странице свой запрос, а всего их будет где-то 40. Что приводит меня к тупому мартышкиному труду.
Вопрос: по каким параметрам определять рубрику и скармливать нужные значения в запрос?
Урл у всех уникален, в родительских категориях будут выводиться дети, в детях родители не выводятся.
Как я это представляю - написать массив, который цепляется по id (либо URL) страницы и по значению онной подставлять данные в post.
Либо тоже самое, но аяксом.
Самый хуевый метод - 40 запросов на каждую страницу. Я так уже делал, метод работает, но пора расти ж бля.
Как я не хочу делать - меню формой, при клике на категорию будет уходить пост запрос с данными.
Как бы сделал ты?
А как оно может выдать, если ты в блоке else ничего не возвращаешь. Он выполняется и программа завершается.
Достаточно очистить куки и число попыток сбрасывается? Не лучшая идея.
Вообще, почему все так любят эти сессии? прежде чем их испоьзовать изучите хотя бы что это такое и как работает.
>>700940
Я ничего не понял. Что значит "есть запрос к рубрике"? Что значит "каждый запрос на отдельной странице"? Там скопипащен один файл много раз? Тогда это непраивльно. Копипасты быть не должно.
И не понимаю при чем тут POST. Это массив, хранящий пришедшие из формы данные, зачем в него что-то подставлять?
Есть рубрика "Смесители".
В ней есть документы,
Они привязаны к ней по айди.
Есть страница "Смесители".
На ней запрос из бд вываливает документы, которые привязаны к смесителям.
Т.е. банальное "многие-ко-многим".
В значении id стоит число, его можно передавать через пост/гет и тем самым динамизировать запрос. Вот этот момент и я спросил - как это сделать лучше, чтобы избавиться от копипасты со сменой чисел для каждой категории.
бля не умею мысли четко излагать, сорян
ОП, спасибо, когда ты только всё успеваешь?..
>А почему не 10?
Я делал эти задачи прямо на JSfiddle, там не сразу разобрался с тем, как правильно сохранять, там непонятно, в какой-то момент, наверное, сохранил такой промежуточный вариант.
Делал целый месяц по чуть-чуть.
Ох щи, сколько у меня ошибок...
Стыдоба-то какая...
Всё сохраняю, все твои ответы, стараюсь следовать советам. Не всегда получается исправлять какие-то решения - хочется уже дойти до своего проекта, но буду заставлять себя.
Спасибо!
>Без яваскрипта делаются сайты на которых нет особой интерактивности
Разумно, принимаю.
>Эти кнопки сохранения - это из предыдущей эпохи, сейчас их нигде нет
Да ладно. Заверенный скриншот прилагаю.
>Удалять слова надо явной передачей признака удаления
Я же об этом первоначально и спросил, как связать галку с той или иной парой слов.
Можно по индексу в имени чекбокса, который будет совпадать с индексом в имени инпутов.
Хотя меня смущает кол-во элементов формы (по три на каждую пару слов, который в свою очередь может быть около сотни).
>>700760
Галочку то как связать с парой слов?
>Плохо что непонятно.
Довольно обидны ваши слова.
Ладно, я вижу ты не в настроении, видимо из-за необходимости разгребать старый тред и пилить новый.
Щас тогда сделаю хоть как-то, потом будем думать как поправить, все же лучше чем топтаться на пустом месте.
Вообще я уже вижу что идея с этим сайтом не очень хорошая, но других нет.
Очень хочется тренироваться, но нет идей что делать.
Рубрике "Смесители" и странице "Смесители" соответсвует один Id. Делаешь SELECT запрос, который запрашивает по этому Id все привязанные к нему товары. Если в урл нет Id, то пишешь роутер, который делает маппинг url-id, таблица соответствий берется из бд, управление ей делаешь где-нибудь в админке. POST тебе тут вообще не нужен. В select функцию подставляется каждый раз значение id, полученное от роутера.
>('Москва' OR 'Санкт-Петербург')
Что в скобках всегда возвращает true. Ты сравниваешь $city c true, а в $city значение 'Москва'. true !== 'Москва', поэтому всегда будет false.
Все так, но это работает только пока сайт небольшой и малопосещаемый. Как только организация расширится, сайт начнет обрастать фичами, багфиксами и допилами, и через год-другой эти поделки от десятка обезъян превратятся в чудовищную запутанность кода. Придется постоянно держать толпу программистов, любые новые мелкие фичи будут занимать тучу времени, и вообще IT начнет сжирать весь бюджет. Реальный случай, сейчас в одной конторе уже 3й год разрулить такие высеры предыдущих лет пытаемся, идет тяжело и туго.
Еще как пишет. Причем от фреймворков в пользу чистого PHP еще отказываются, ибо быстрее работает и проще все контролировать, нет зависимости от внешних разрабов. Для хайлоад сайтов чистый PHP тем более маст хэв. При этом местами бывает через композер вставлены куски из других библиотек или фреймворков в некритичных местах, которые самим долго писать было бы. Ну и естественно все SOLID и с нормальной архитектурой, без SOLID писать на чистом PHP вообще смысла нет.
Начинают любой проект с архитектуры. Составь список требований и ТЗ, попытайся выделить проблемные места, нарисуй схемы роутеров, взаимодействий модулей и взаимодействие с БД или файловой системой, внешними API, разметь примерную схему таблиц и форматы данных внутри системы. Потом рисуй схему классов, фабрики, локаторы, используемые паттерны, иерархию наследования, взаимодействие с фронтендом по аяксу и прочее. Тут у тебя уже схема сайта будет примерно ясна, под это дело можно выбирать фреймворк (или решаешь на чистом Php писать) и библиотеки для фронтенда/бэкенда. Дальше дополняешь схему на основе выбранного инструментария. Пишешь бэкенд без фронтенда (вместо фронтенда просто echo получаемых данных везде, можно примитивные формы), пишешь юнит тесты, потом интеграционные тесты, в последнюю очередь в view модулях пишешь фронтенд, к нему каспер тесты.
Логика примерно ясна, тоже думал начать с ТЗ и списка требований. спасибо!
Все верно?
Ток вот у меня как-то не сошлось с ответом.
У меня создается локальная ветка (no branch), и я не могу никак зашуить ее, ни объединить. Мне не нужно много веток, я считаю, что ограничусь основной веткой, так как я единственный разработчик (в рамках этого проекта), но если я пытаюсь создать локальную ветку, то все равно ничего не пушится и висит (no branch)! Почему?
Может я что-то не то делаю? Посмотрел вот этот мануал: https://netbeans.org/kb/docs/ide/git_ru.html
но там нет ничего о том, как в идеале должна происходить работа с гитом.
Есть ли у Вас какие либо предпочтения по выбору Framework'а?
А меня?
Вот это повторяется в двух местах:
>$creditBalance = $thatMouthPay - $monthlyPayment;
>$paymentTotal = $paymentTotal + $monthlyPayment;
Это копипаст, необходимо от него избавиться.
И за первые месяцы тоже желательно вне if.
Вот то, что я показывал, - это должно быть вне условий в этой ситуации.
Так, от прямого складывания часов одного работника и часов другого избавился вот так:
$allHours[] = $ivan->hours;
$allHours[] = $peter->hours;
for ($i = 0; $i < count($allHours); $i++) {
$hours += array_sum($allHours[$i]);
}
Далее просто подставляем $hours в нужную ячейку таблицы.
Теперь остаётся считать с помощью функций и с помощью всё того же массива $allHours нормальные рабочие часы и переработку (овертайм).
На том ли я пути?
Сейчас не вижу ничего более подходящего для решения этой задачи.
Вот так решил:
for ($i = 0; $i < count($allHours); $i++) {
$hours += array_sum($allHours[$i]);
$salary += $employees[$i]->getSalary();
$normalHours += $employees[$i]->getNormalHours();
$overtimeHours += $employees[$i]->getOvertimeHours();
}
И чисто технический момент остался - по разным ставкам посчитать оплату.
Но терзают некоторые сомнения благодаря привитому ОПом подходу: а на том ли я пути вообще?
В принципе, удалось автоматизировать, но не является ли добавление часов в массив "костылём"?
Нет, я не прав: так считает общие часы, а нужно у каждого экземпляра считать отдельно, потому что ставки у всех разные.
Тупик, короче.
Надо для каждого объекта отдельно считать, буду думать, как.
Постараюсь держать вас в курсе, это очень важно!
Делаешь git branch -b твояветка
Потом git checkout твояветка
git merge master
Работаешь в этой ветке, коммиты делаешь, пушишь:
git push origin твояветка
можешь замержить в мастер
git checkout master
git merge твояветка
Самый простой автолоадер есть в документации к функции spl_autoload_register.
http://php.net/manual/en/function.spl-autoload-register.php
Но этот способ as is может загружать файлы только из одной папки. Конечно, можно написать костыль для загрузки из нескольких папок, но гораздо лушче будет освоить неймспейсы и рекомендацию PSR-4, тогда ты сможешь взять любой автозагрузчик, который работает с PSR-4 неймспейсами.
Что почитать по неймспейсам:
https://github.com/codedokode/pasta/blob/master/php/autoload.md Урок ОПа
http://www.php-fig.org/psr/psr-4/ Сама рекомендация PSR-4
Так же, ты можешь взять автозагрузчик из менеджера пакетов composer
https://getcomposer.org/
Он довольно простой и отлично подойдет для твоего случая. В уроке ОПа описано как он работает и как его настроить.
А на выходе
array(2) { [0]=> object(PDORow)#4 (4) { ["queryString"]=> string(22) "SELECT FROM projects" ["id"]=> NULL ["name"]=> NULL ["chpu"]=> NULL } [1]=> object(PDORow)#4 (4) { ["queryString"]=> string(22) "SELECT FROM projects" ["id"]=> NULL ["name"]=> NULL ["chpu"]=> NULL } }
Почему? База не пуста. Если в while выводить то там есть значения.
Другие яп учил, в частности : жаба и си.
<-----
Смотрите: Петров работал 140 часов, из которых 10 - овертайм.
130 часов рассчитываются по ставке 8:1, а 10 переработанных - по ставке 12:1.
130 х 8 = 1040 тугриков.
10 х 12 = 120 тугриков.
Итого: 1160 тугриков у Петрова.
А у Иванова 160 нормальных часов по ставке 10:1, то есть 1600.
Всего: 1160 + 1600 = 2760.
Вопрос: откуда у ОПа взялось 2800 тугриков в итоге?
Ещё вопрос: какого чёрта я сразу не посчитал это всё и вожусь с задачей второй день?
Я тормоз, там по двойной, а не по полуторной ставке, ёлки-палки...
$array = ['var1' = 'text1']
extract($array);
//$var1 = 'text1';
а,
some_func($array);
// $data['var1'] = 'text1';
?закомментировано то, что должно получиться после выполнения функции
>file_put_contents(/home/user/.composer/cache/repo/https---packagist.org/provider-nikic$fast-route.json): failed to open stream: Permission denied
http://packagist.org could not be fully loaded, package information was loaded from the local cache and may be out of date
>Failed to download container-interop/container-interop from dist: Could not delete /home/user/.composer/cache/files/container-interop/container-interop/fc08354828f8fd3245f77a66b9e23a6bca48297e.zip
>Failed to download nikic/fast-route from dist: Could not delete /home/user/.composer/cache/files/nikic/fast-route/31fa86924556b80735f98b294a7ffdfb26789f22.zip
Я конечно догадываюсь, что дело в правах (я такой умный), но кому и какие права я должен вручить, чтобы все стало правильно?
Исполняемый файл композера (/usr/local/bin/composer) принадлежит руту.
Папка .composer принадлежит пользователю.
В cache/files много директорий с пакетиками, все принадлежат пользователю. Однако некоторые руту.
До этого все работало без ошибок, подгружало из кеша, теперь вот пытался поставить слим3, его зависимости почему-то поставились из-под рута ("nikic" и "container-interop").
Не надо было запускать композер из-под рута.
Самое простое решение проблемы - удалить целиком папку ~/.composer
> его зависимости почему-то поставились из-под рута ("nikic" и "container-interop").
Потому что ты от имени рута запустил композер. Никогда не логинься под рутом и не используй su - только sudo и только там где нужно.
>>702035
Мамой клянусь, не запускал от рута. Оно само.
Если серьезно, то наверное какую-то другую команду запускал от рута, может быть self-update.
Удалил папку .composer из домашней директории, помогло.
Дважды установил слим ради эксперимента. Первый раз естественно произошла установка из сорцев, а во второй раз "loading from cache". Однако папка .composer не реинкарнировалась в директории пользователя, она наверное теперь живет по другому адресу.
Так что тут дело не в запуске от рута, там в самом композере шото поменяли.
А, кеш композера теперь переехал в общую папку ~/.cache/composer
Конфиг ~/.config/composer
Однако в нем теперь только .htaccess. А где глобальные настройки, composer.json?
Вечно что-то меняют, все им неймется.
>On nix systems that follow the XDG Base Directory Specifications, it points to $XDG_CONFIG_HOME/composer. On other nix systems, it points to /home/<user>/.composer.
Это наверное моя ебунта обновилась так, что теперь следует этим xdg спецификациям.
Ну ладно, проехали.
Для удобного хранения файлов я решил создавать новую папку на каждые 100 id файлов. Таким образом в папку с именем 100 пойдут все файлы с id от 1 до 100, в папку 200 пойдут все файлы с id от 101 до 200 и т.д.
Проблема в том, что я не придумал как нормально посчитать в какую папку должен идти файл, поэтому сейчас там вот такой костыль
https://github.com/foobar1643/filehosting/blob/master/app/Model/File.php#L88
Я понимаю что это вроде как легкая задача, но решения придумать не могу, прошу помощи.
Перед тем как выбрать id файлов в поиске, я считаю общее кол-во найденых результатов через
>SELECT COUNT() FROM index_files, rt_files
Проблема в том, что этим способом он считает удаленные файлы. Я частично исправил это, сделав удаление записей из rt-индекса при удалении файла, но если файл уже в основном индексе, то его оттуда никак не удалить, только ждать переиндексации. А это значит что из основных индексов он будет считать удаленные файлы как обычные. Из этого вытекает баг с постраничной навигацией, потому что я использую общее кол-во записей для расчета оффсета выборки. Ну и очевидным фиксом будет выбрать все результаты через SELECT FROM, потом проверить существуют ли все id, и только после этого посчитать их количество. Но не будет ли это одновременно копипастой (я по сути делаю ту же самую выборку еще раз, только с оффсетом для постраничной навигации) и усложнением?
Мне очень не хотелось наступать на те же грабли с разделением кода, но тут получилось так же. Сейчас код очень плохо разделен и у меня появилась идея вынести все действия над файлами в хелперы, а из контроллеров потом вызывать их. Примером приведу удаление файла:
В хелпере создаю функцию deleteFile(), которая принимает на вход объект File, и проводит все необходимые действия для его удаления с диска, из базы и поисковых индексов. А контроллер будет проверять на правильность данные от пользователя (существует ли файл с таким id, имеет ли пользователь право его удалять), и если все проверки выполнились успешно - вызывать функцию deleteFile() из хелпера. Таким образом можно будет все манипуляции с файлами вынести в хелпер и использовать их повторно, если нужно будет добавить другую фору загрузки, а в контроллере оставить только проверку юзер-инпута. Что-то мне подсказывает что в нормальном MVC как-то так и должно быть, но в то же время это все мне кажется усложнением хелперов. Хотя хелпер это же сервис вроде как, поэтому он может работать с несколькими объектами, как писал ОП.
>Сервис это объект который обычно есть в одном числе и выполняет какие-то действия над другими объектами или чем-то еще, а тут обычный объект не-сервис. Его надо просто создавать через new.
>По идее концепция такая, что сервисы не хранят состояние, зависящее от текущего запроса. То есть один и тот же объект-сервис можно использовать для обработки нескольких запросов от разных пользователей.
Тут не знаю как сделать, поэтому пока оставил все в контроллерах.
Про древовидные структуры. Читал этот урок https://github.com/codedokode/pasta/blob/master/db/trees.md и не понял зачем в Materialized Path нужна колонка number. Так же, во время поиска теории, я наткнулся на интересный пост на Stack Overflow, в котором объяснялось почему такой Materialized Path как в уроке - неправильный. Ссылка вот http://stackoverflow.com/a/2797732
У себя я сделал так же, в конец колонки path для каждого файла добавляю id файла. Конечно, в таком случае на добавление комментария я делаю два запроса, но и в способе ОПа я тоже не вижу как посчитать колонку number и добавить комментарий одним запросом.
Обработка ошибок формы через исключения.
При загрузке файла у меня выбрасываются исключения, если что-то пошло не так (файл слишком большой, поля формы не заполнили и т.д.). Потом обработчик исключений ловит его, и выводит обычную страницу поиска, только с ошибкой. Правильно ли так делать? Или лучше поменять на обычный редирект с гет параметром вроде "?error=filesize"?
Для удобного хранения файлов я решил создавать новую папку на каждые 100 id файлов. Таким образом в папку с именем 100 пойдут все файлы с id от 1 до 100, в папку 200 пойдут все файлы с id от 101 до 200 и т.д.
Проблема в том, что я не придумал как нормально посчитать в какую папку должен идти файл, поэтому сейчас там вот такой костыль
https://github.com/foobar1643/filehosting/blob/master/app/Model/File.php#L88
Я понимаю что это вроде как легкая задача, но решения придумать не могу, прошу помощи.
Перед тем как выбрать id файлов в поиске, я считаю общее кол-во найденых результатов через
>SELECT COUNT() FROM index_files, rt_files
Проблема в том, что этим способом он считает удаленные файлы. Я частично исправил это, сделав удаление записей из rt-индекса при удалении файла, но если файл уже в основном индексе, то его оттуда никак не удалить, только ждать переиндексации. А это значит что из основных индексов он будет считать удаленные файлы как обычные. Из этого вытекает баг с постраничной навигацией, потому что я использую общее кол-во записей для расчета оффсета выборки. Ну и очевидным фиксом будет выбрать все результаты через SELECT FROM, потом проверить существуют ли все id, и только после этого посчитать их количество. Но не будет ли это одновременно копипастой (я по сути делаю ту же самую выборку еще раз, только с оффсетом для постраничной навигации) и усложнением?
Мне очень не хотелось наступать на те же грабли с разделением кода, но тут получилось так же. Сейчас код очень плохо разделен и у меня появилась идея вынести все действия над файлами в хелперы, а из контроллеров потом вызывать их. Примером приведу удаление файла:
В хелпере создаю функцию deleteFile(), которая принимает на вход объект File, и проводит все необходимые действия для его удаления с диска, из базы и поисковых индексов. А контроллер будет проверять на правильность данные от пользователя (существует ли файл с таким id, имеет ли пользователь право его удалять), и если все проверки выполнились успешно - вызывать функцию deleteFile() из хелпера. Таким образом можно будет все манипуляции с файлами вынести в хелпер и использовать их повторно, если нужно будет добавить другую фору загрузки, а в контроллере оставить только проверку юзер-инпута. Что-то мне подсказывает что в нормальном MVC как-то так и должно быть, но в то же время это все мне кажется усложнением хелперов. Хотя хелпер это же сервис вроде как, поэтому он может работать с несколькими объектами, как писал ОП.
>Сервис это объект который обычно есть в одном числе и выполняет какие-то действия над другими объектами или чем-то еще, а тут обычный объект не-сервис. Его надо просто создавать через new.
>По идее концепция такая, что сервисы не хранят состояние, зависящее от текущего запроса. То есть один и тот же объект-сервис можно использовать для обработки нескольких запросов от разных пользователей.
Тут не знаю как сделать, поэтому пока оставил все в контроллерах.
Про древовидные структуры. Читал этот урок https://github.com/codedokode/pasta/blob/master/db/trees.md и не понял зачем в Materialized Path нужна колонка number. Так же, во время поиска теории, я наткнулся на интересный пост на Stack Overflow, в котором объяснялось почему такой Materialized Path как в уроке - неправильный. Ссылка вот http://stackoverflow.com/a/2797732
У себя я сделал так же, в конец колонки path для каждого файла добавляю id файла. Конечно, в таком случае на добавление комментария я делаю два запроса, но и в способе ОПа я тоже не вижу как посчитать колонку number и добавить комментарий одним запросом.
Обработка ошибок формы через исключения.
При загрузке файла у меня выбрасываются исключения, если что-то пошло не так (файл слишком большой, поля формы не заполнили и т.д.). Потом обработчик исключений ловит его, и выводит обычную страницу поиска, только с ошибкой. Правильно ли так делать? Или лучше поменять на обычный редирект с гет параметром вроде "?error=filesize"?
Как оценить проект такой сложности ? ориентируюсь на цифру в 100к рублей. реальная цена или сильно занижена ?
Вот в гайдах к третьему слиму пару моментов успел заметить.
1. Разный стиль именования переменных. В одном месте кемелкейс, в другом сишные подчеркивания. Допускаю, что у автора кода были какие-то скрытые мотивы, но я лично не знаю какие.
https://github.com/slimphp/Slim-Website/blob/gh-pages/docs/tutorial/first-app.md#use-monolog-in-your-application
$file_handler = new \Monolog\Handler\StreamHandler("../logs/app.log");
$logger->pushHandler($file_handler);
Чего файл_хендлер написали?
2. В третьем слиме в отличие от второго в каждый роут(ер?), ну то есть в колбек-функцию обработчик теперь нужно передавать два параметра: $request и $response. В некоторых примерах указывают тайпхинт, в других нет.
https://github.com/slimphp/Slim-Website/blob/gh-pages/docs/index.md#how-does-it-work
Встает вопрос, обязательно ли? Знаю что с точки зрения интерпретатора необязательно, а с человеческой?
Может это важно для каких-нибудь тестов? (никак не дойду до тестирования)
Ты эти "сайты" видел?
https://jenniferdewalt.com/node/hello_world
Я сначала повелся, думаю респект бабенке, надо глянуть может какую идею спизжу, а там такой трешак.
Ну и? Можно сказать полноценное задание из учебника ОПа по жсу, даже посложнее, она сделала 180 таких.
Двачую, мне похожее тестовое давали на собеседовании. Взяли сразу синьором.
http://ideone.com/8HkLTf
Ты обращаешься к неизвестной функции mb_ucfirst. Видимо ты откуда-то неправильно скопипастил этот код.
Логично. А что это за индексы в переменных?
$explodedText[1]=trim($explodedText[1]);
$explodedText[$i]=mb_ucfirst($explodedText[$i]);
Всё вроде работает, но почему русские слова не переводит в верхний регистр? Кодировку же написал.
Оп все правильно делает. Попробуй устройся на работу со своими смешанными стилями и отсутствием тайпхинтов, тебя там через день уже про это заебут, QA ни один тикет не пройдет.
>Встает вопрос, обязательно ли?
Если это твой личный проект, который ты только своей кошке показывать собрался, то не важно. В любой нормальной фирме все эти стандарты - жизненно важное требование, иначе код через год-другой становится очень трудно поддерживать и расширять. Оп кстати еще мало с вас требует, в фирмах помимо тайпхинтинга еще докблоки для каждого теста и каждой функции, соблюдение всяческих PSR, определенные договоренности по именованию классов, размещению файлов, структуре тестов и еще много всяких условностей соблюдают. Code Guidelines только 3 страницы текста занимает, каждого нового программиста в него регулярно тыкают.
>Может это важно для каких-нибудь тестов? (никак не дойду до тестирования)
Да, при написании тестов в том числе.
>Если это твой личный проект
Нет, это не мой личный проект.
Я против стандартизации и строгости ничего не говорил, наоборот сетовал на то что этому никто не учит к сожалению. Вон даже в официальном гайде к известному фреймворку не соблюдают этих правил и не объясняют их необходимости.
Ок, то что в крупных конторах (которых не так много) важны стандарты, это понятно.
Ты лучше смени менторский тон и расскажи о командной работе. Я где-то выше спрашивал. >>690750
Как проходит рабочий день и что подразумевается под "умением работать в команде". Как можно не уметь работать в команде?
Судя по твоим вопросам ты не очень хорошо понимаешь что такое функции и как они работают. Учебник ОПа читал, задачи делал?
Функция ucfirst вроде бы не работает с кириллицей: http://ideone.com/s2uYIE
Попробуй mb_substr.
>>702513
В переменную, которой ты и присваиваешь работу этой функции.
>>702520
Человек решил сэкономить на своих решениях и воспользовался чужими. Проходили такое сто раз.
Переделал под substr. Нашёл такой способ:
$explodedText[$i]=mb_strtoupper(mb_substr($explodedText[$i], 0, 1)). mb_substr($explodedText[$i], 1);
Можешь пояснить как через точку ещё функцию сделали?
>не знать про конкатенацию
>браться за сложные почти бонусные задачи
У Вас телега впереди лошади, сударь.
Не помню такого в уроках ОПа. Ладно, пойду перечитаю заново.
Переписал половину скрипта и запилил меры. Посчитал и потестил - вроде норм все, но у меня такое чувство, что этот код как земля.
В первом задании не ясно: нужно считать с босса, если он инженер и увольнять вместо него рабочего или нет я слегка тупой, но я посчитал.
http://ideone.com/7TpNMo
>Как проходит рабочий день и что подразумевается под "умением работать в команде".
День обычно с распределения тикетов начинается, потом рефайнмент будущих тикетов часа на 2 всем тимом, это заседание такое, где обсуждают толпой какие архитектурные решения будут в решении каждого тикета применять, какие вопросы надо решить, чтобы тикет стал однозначным (например позвонить провайдеру API и задать определенные вопросы), какие технологии использовать и прочее такое. В случае готового тикета проводится голосование и все решают, насколько высока его сложность и какие трудозатраты будут. В заседаниях активно участвуют представители бизнеса, которые оценивают business value каждого тикета, и нужно ли его вообще делать по результатам оценки.
>Как можно не уметь работать в команде?
Очень просто, весь код пишется не одним тобой, а маленькими кусками, раскиданными между людьми в команде. Постоянно нужно согласовывать, как что будет написано, потому что если это не делать, можно написать дублированный код или код, который друг к другу не подходит, несовпадающие форматы, разные архитектуры. Потому здоровая часть времени уходит на выяснение отношений с членами команды. Естественно тут нужны социальные навыки, каждый стремится всунуть свое видение, люди забывают сообщить нужную информацию, делают что-то на свое усмотрение, у кого-то плосто фигово с коммуникацией, кто-то вообще придерживается идеологии - весь проект сам напишу, постоянно нужны компромиссы. Плюс кроме программеров есть другие отделы, всякие маркетинги, продукт менеджменты, SEO, спецы по безопасности, бухгалтеры и прочий цирк, с ними тоже надо регулярно коммуницировать. Эти часто вообще не могут внятно объяснить чего они хотят, и не понимают, почему что-то представляет сложности или занимает много времени. Все это вместе требует развитых коммуникативных навыков, нужно доносить свое видение и аргументировать свои решения. Бывает, что напишешь что-то правильно и хорошо, но поскольку другие не поняли, то твое решение потом выпилят и заменят на фиговое. Не сумел аргументировать значит и презентовать. Это фэйл командной работы. Алсо в конце любой крупной фичи нужно презентовать свой проект уже перед представителями бизнеса на большом экране и им аргументировать те или иные решения, при чем у них своя логика, и они в программерские аргументы часто не врубаются. Вот это все и есть командная работа.
>Как проходит рабочий день и что подразумевается под "умением работать в команде".
День обычно с распределения тикетов начинается, потом рефайнмент будущих тикетов часа на 2 всем тимом, это заседание такое, где обсуждают толпой какие архитектурные решения будут в решении каждого тикета применять, какие вопросы надо решить, чтобы тикет стал однозначным (например позвонить провайдеру API и задать определенные вопросы), какие технологии использовать и прочее такое. В случае готового тикета проводится голосование и все решают, насколько высока его сложность и какие трудозатраты будут. В заседаниях активно участвуют представители бизнеса, которые оценивают business value каждого тикета, и нужно ли его вообще делать по результатам оценки.
>Как можно не уметь работать в команде?
Очень просто, весь код пишется не одним тобой, а маленькими кусками, раскиданными между людьми в команде. Постоянно нужно согласовывать, как что будет написано, потому что если это не делать, можно написать дублированный код или код, который друг к другу не подходит, несовпадающие форматы, разные архитектуры. Потому здоровая часть времени уходит на выяснение отношений с членами команды. Естественно тут нужны социальные навыки, каждый стремится всунуть свое видение, люди забывают сообщить нужную информацию, делают что-то на свое усмотрение, у кого-то плосто фигово с коммуникацией, кто-то вообще придерживается идеологии - весь проект сам напишу, постоянно нужны компромиссы. Плюс кроме программеров есть другие отделы, всякие маркетинги, продукт менеджменты, SEO, спецы по безопасности, бухгалтеры и прочий цирк, с ними тоже надо регулярно коммуницировать. Эти часто вообще не могут внятно объяснить чего они хотят, и не понимают, почему что-то представляет сложности или занимает много времени. Все это вместе требует развитых коммуникативных навыков, нужно доносить свое видение и аргументировать свои решения. Бывает, что напишешь что-то правильно и хорошо, но поскольку другие не поняли, то твое решение потом выпилят и заменят на фиговое. Не сумел аргументировать значит и презентовать. Это фэйл командной работы. Алсо в конце любой крупной фичи нужно презентовать свой проект уже перед представителями бизнеса на большом экране и им аргументировать те или иные решения, при чем у них своя логика, и они в программерские аргументы часто не врубаются. Вот это все и есть командная работа.
>Есть ли разделение труда, типа отдел верстальщиков-фронтендеров, бекенд-программисты, системные администраторы, или везде фулстаки (которые на словах умеют "все", но делают это все плохо)?
Есть, все разделено. Когда фронтенды не справляются из-за огромного объема тикетов, подключают фуллстаков клепать фронтенд. Админы админят, и до них достучаться только админскими тикетами можно. Бэкенды и фуллстаки большую часть времени заняты бэкендом, но фронтенда тоже хватает.
>Проводят ли старшие программисты код-ревью, то есть проверку кода джунов?
Да, все есть. Любой твой написанный код проходит через 3 стадии - сначала идет в QA, где его по очереди проверяют 3 программиста, пишут заметки по коду, и отправляют назад в статус Reopened, если все плохо. Когда код тобой доведен до нужного качества и он прошел проверку на QA, его отправляют на деплоймент. Деплоишь либо ты, либо другие программисты. Деплоймент идет сначала на внутренний сервер, где на него набрасываются отделы контроля качества, это еще ХХ человек, оттуда бывает тоже тикеты возвращаются. Когда проверку на внутреннем сервере прошел, деплоится уже на live, там тоже его грызут отделы качества, ну и программисты разок смотрят для порядка. Если на live глюки, то делается глобальный откат, и все сдеплоенное улетает обратно. Закрывается тикет окончательно только после проверки всеми на live.
>Есть ли семинары или что-то подобное для повышения квалификации?
Есть, раз в 2-3 месяца организуют всяческие воркшопы. Также можно ездить на конференции за счет фирмы.
>Как проходит именно рабочий процесс? Тимлид бегает и раздает всем мелкие задания, следит за выполнением и подсказывает (инбифо: размечтался), или все более бюрократично, типа вон список задач, бери шо хочешь, делай как хочешь, сдавай как хочешь.
Это не задача тимлида, организацией распределения тикетов заниматься. Тимлид обсуждает решения с другими отделами и командами, участвует в заседаниях тимлидов и начальства, доносит важную информацию до тима.
>Только если будет жалоба, тебя выпизднут.
Жалобы на тебя не может быть, поскольку качество кода - ответственность тима, а не отдельного человека, для этого многоступенчатая проверка. Жалоба может быть только на тебя от тима, если ты хреново в командную работу умеешь.
>Есть ли разделение труда, типа отдел верстальщиков-фронтендеров, бекенд-программисты, системные администраторы, или везде фулстаки (которые на словах умеют "все", но делают это все плохо)?
Есть, все разделено. Когда фронтенды не справляются из-за огромного объема тикетов, подключают фуллстаков клепать фронтенд. Админы админят, и до них достучаться только админскими тикетами можно. Бэкенды и фуллстаки большую часть времени заняты бэкендом, но фронтенда тоже хватает.
>Проводят ли старшие программисты код-ревью, то есть проверку кода джунов?
Да, все есть. Любой твой написанный код проходит через 3 стадии - сначала идет в QA, где его по очереди проверяют 3 программиста, пишут заметки по коду, и отправляют назад в статус Reopened, если все плохо. Когда код тобой доведен до нужного качества и он прошел проверку на QA, его отправляют на деплоймент. Деплоишь либо ты, либо другие программисты. Деплоймент идет сначала на внутренний сервер, где на него набрасываются отделы контроля качества, это еще ХХ человек, оттуда бывает тоже тикеты возвращаются. Когда проверку на внутреннем сервере прошел, деплоится уже на live, там тоже его грызут отделы качества, ну и программисты разок смотрят для порядка. Если на live глюки, то делается глобальный откат, и все сдеплоенное улетает обратно. Закрывается тикет окончательно только после проверки всеми на live.
>Есть ли семинары или что-то подобное для повышения квалификации?
Есть, раз в 2-3 месяца организуют всяческие воркшопы. Также можно ездить на конференции за счет фирмы.
>Как проходит именно рабочий процесс? Тимлид бегает и раздает всем мелкие задания, следит за выполнением и подсказывает (инбифо: размечтался), или все более бюрократично, типа вон список задач, бери шо хочешь, делай как хочешь, сдавай как хочешь.
Это не задача тимлида, организацией распределения тикетов заниматься. Тимлид обсуждает решения с другими отделами и командами, участвует в заседаниях тимлидов и начальства, доносит важную информацию до тима.
>Только если будет жалоба, тебя выпизднут.
Жалобы на тебя не может быть, поскольку качество кода - ответственность тима, а не отдельного человека, для этого многоступенчатая проверка. Жалоба может быть только на тебя от тима, если ты хреново в командную работу умеешь.
>Проводят ли старшие программисты код-ревью
Ах да, про это забыл. Код ревью проводят не старшие программисты, а архитекторы - это должность специальная такая, на каждый тим 1-2 архитектора приходится. На код ревью обычно приглашаются все программисты, запускается экран во всю стену и на него выводят код. Архитектор критикует каждое решение, тим отбивается, пытается отстоять свои решения. В итоге находят компромиссный вариант, делают список изменений в новом тикете, раскидывают по тиму и меняют код. Через пару недель повторный код ревью.
Можно ли было вот так добавить ещё одно поле в класс для сохранения переработанных часов? Можно вместо этого сохранить в новый массив, а потом достать значения в цикле, но вроде бы так удобнее.
Вообще очень удобно в ООП доставать значения из определения класса, удобно применять функции.
Но правильно ли я вообще сделал, что некоторые функции определил вне класса? По ООП ли это?
Просто многое требовало подстановки изменённых значений, а не тех, которые были даны изначально.
>Как проходит именно рабочий процесс? Тимлид бегает и раздает всем мелкие задания, следит за выполнением и подсказывает (инбифо: размечтался), или все более бюрократично, типа вон список задач, бери шо хочешь, делай как хочешь, сдавай как хочешь.
Еще дополню по процессу - вся работа делится на спринты, это периоды в 2 недели. Перед началом каждого спринта специальная программа высчитывает среднее количество сложности, сделанной в предыдущие спринты. Потом вводятся данные по праздничным дням с спринте, отпускам сотрудников, больничным и прочие, число сложности корректируется. На основании этого числа в спринт забивают определенное количество тикетов, у каждого тикета своя подсчитанная сложность (для этого голосовали на рефайнменте), общая сложность всех тикетов должна совпадать с подсчитанным программой числом. Дальше все тикеты в спринте, и можно выбирать только из них. Каждый член команды сам выбирает себе подходящий тикет из свободных. К середине спринта начинается приближение к красной линии, и включается сигнал тревоги, если количество невыполненных тикетов велико. Тут тим собирается на кризисное собрание и решают, как распределить тикеты лучше, на какие тикеты кинуть больше народу, какие делать через парное программирование для ускорение процесса и прочее такое. Если после собрания спринт все еще находится под угрозой, срочно звонят в другие тимы и подтягивают свободных людей оттуда. Общими усилиями одолевают спринт, но не всегда. Если к концу спринта тикеты не выполнены и спринт завален, то это катастрофа похуже конца света, начинается беготня начальства, разносы и поиск виноватых. После разбора полетов тим лиды и менеджмент лишаются премий, делаются Action Improvements - это такие правила новые для тимов и вносятся в свод правил, до всех членов тима доносится информация, что нужно изменить в работе. Заваленных спринтов никто не любит, поэтому обычно такого не бывает.
В Jira и Confluence. Slack не используется, вместо него внутренний Jabber сервер с кучей чатов для разных тимов. Код через Atlassian Stash и Bamboo.
Я не понял, на чем ты хочешь писать? Если на PHP то учебники и мануалы есть в сети, если на Яве - тоже книги есть, но конкретные я посоветовать не могу. Чтобы писать на Яве, надо изучить синтаксис, стандартную библиотеку, коллекции там всякие, потом ООП и тд. Довольно много, на PHP может и проще было бы.
>>698337
Если ты не знаешь какого типа данные приходят в функцию, это усложняет работу с ними, надо писать ифы, преобразования. Легко где-то ошибиться. Стоит всегда четко определяться какой тип имеет каждый аргумент.
stdClass плох тем что это как массив, только функций для работы с ним нету.
>>698404
Не. это всегда неудобно когда неизвестен тип, надо писать дополнительные условия, легко что-то перепутать. Лучше всегда знать тип каждой переменной и не передавать/хранить данные разных типов в одной и той же переменной.
На автоматическое преобразование полагаться нельзя.
>>698847
Когда ты определяешь (создаешь) функцию, ты пишешь в скобках не то что передается, а переменные которые принимают аргументы. И им не важно, передается в них элеиент массива или еще что-то
>>699194
> $deposit <=1000000;
Вот условие прождолжения странно выглядит. Если мы набрали ровно миллион - все равно продолжать цикл? Я думаю, не надо.
> if($deposit>=1000000) {
Это лучше поставить после цикла. Ведь в цикле мы обычно пишем повторяющиеся действия, а это действие выполняется уже после заверщения цикла (а он завершится когда сумма дойдет до млллиона и потому дополнительная проверка в виде ифа тут будет не нужна).
То есть считает программа верно, но код можно организовать чуть логичнее. И если нетрудно, пости лучше на ideone, там сразу и результат виден.
Я не понял, на чем ты хочешь писать? Если на PHP то учебники и мануалы есть в сети, если на Яве - тоже книги есть, но конкретные я посоветовать не могу. Чтобы писать на Яве, надо изучить синтаксис, стандартную библиотеку, коллекции там всякие, потом ООП и тд. Довольно много, на PHP может и проще было бы.
>>698337
Если ты не знаешь какого типа данные приходят в функцию, это усложняет работу с ними, надо писать ифы, преобразования. Легко где-то ошибиться. Стоит всегда четко определяться какой тип имеет каждый аргумент.
stdClass плох тем что это как массив, только функций для работы с ним нету.
>>698404
Не. это всегда неудобно когда неизвестен тип, надо писать дополнительные условия, легко что-то перепутать. Лучше всегда знать тип каждой переменной и не передавать/хранить данные разных типов в одной и той же переменной.
На автоматическое преобразование полагаться нельзя.
>>698847
Когда ты определяешь (создаешь) функцию, ты пишешь в скобках не то что передается, а переменные которые принимают аргументы. И им не важно, передается в них элеиент массива или еще что-то
>>699194
> $deposit <=1000000;
Вот условие прождолжения странно выглядит. Если мы набрали ровно миллион - все равно продолжать цикл? Я думаю, не надо.
> if($deposit>=1000000) {
Это лучше поставить после цикла. Ведь в цикле мы обычно пишем повторяющиеся действия, а это действие выполняется уже после заверщения цикла (а он завершится когда сумма дойдет до млллиона и потому дополнительная проверка в виде ифа тут будет не нужна).
То есть считает программа верно, но код можно организовать чуть логичнее. И если нетрудно, пости лучше на ideone, там сразу и результат виден.
Вебмин - это может и неплохо, но он для тех кто уже умеет администрировать через командную строку. Он не годится как способ избежать изучение команднйо строки, так как если что-то пойдет не так, он тебе проблему не покажет.
>>699297
перед тем как платить смотреть чему равен остаток, если маленький то платить не 5000, а сколько осталось.
>>699314
>>699325
Тут в статье laravel критикуют:
http://amdy.su/недостатки-laravel/
Я сам с ним не работал, мне в общем нравятся компоненты из Симфони и микрофреймворки вроде Слима/silex. Хотя для простых вещей компоненты от Симфони может и перебор.
>>699361
Код на Си - значит что ты не можешь так просто в нем найти ошибку, если не знаешь Си, не можешь отлаживать итд. Может для хайлоад-проектов и имеет смысл. Вообще, по моему опыту, хайлоад проекты на php обычно самописиные (хотя например тот же гитхаб написан на фреймворке на Руби).
>>699396
Вроде исправил уже ошибку? Тогда по коду советы:
- вместо for для обхода массива лучше использовать foreach
- не надо для хранения номера создавать каждый раз новую переменную ($space $bracketStart $bracketClose $hyphen) - используй одну и ту же, а то от большого количества переменных путаешься
- 2 регулярки тут можно объединить в одну
- многочисленные замены можно сделать одной командой, например с помощью strtr с массивом или preg_replace
Ну и конечно это задача на регулярки, было бы хорошо написать регулярку, которая бы без замен проверяла номер.
Код определенно стоит доработать, пока слабенько.
Вебмин - это может и неплохо, но он для тех кто уже умеет администрировать через командную строку. Он не годится как способ избежать изучение команднйо строки, так как если что-то пойдет не так, он тебе проблему не покажет.
>>699297
перед тем как платить смотреть чему равен остаток, если маленький то платить не 5000, а сколько осталось.
>>699314
>>699325
Тут в статье laravel критикуют:
http://amdy.su/недостатки-laravel/
Я сам с ним не работал, мне в общем нравятся компоненты из Симфони и микрофреймворки вроде Слима/silex. Хотя для простых вещей компоненты от Симфони может и перебор.
>>699361
Код на Си - значит что ты не можешь так просто в нем найти ошибку, если не знаешь Си, не можешь отлаживать итд. Может для хайлоад-проектов и имеет смысл. Вообще, по моему опыту, хайлоад проекты на php обычно самописиные (хотя например тот же гитхаб написан на фреймворке на Руби).
>>699396
Вроде исправил уже ошибку? Тогда по коду советы:
- вместо for для обхода массива лучше использовать foreach
- не надо для хранения номера создавать каждый раз новую переменную ($space $bracketStart $bracketClose $hyphen) - используй одну и ту же, а то от большого количества переменных путаешься
- 2 регулярки тут можно объединить в одну
- многочисленные замены можно сделать одной командой, например с помощью strtr с массивом или preg_replace
Ну и конечно это задача на регулярки, было бы хорошо написать регулярку, которая бы без замен проверяла номер.
Код определенно стоит доработать, пока слабенько.
> Квалифицированный программист потребует за свою работу в десятки раз больше, чем быдлокодер, осиливший только синтаксис. С точки зрения клиента конечный продукт от грамотного разработчика ничем не отличается от высера толпы австралопитеков.
Не всегда. Если проект сложный, то низкоквалифицированные кодеры сделают хуже и потратят намного больше времени чем профессионал - экономии не будет, будет много потраченных нервов. Я такое видел не раз.
Самый экономный и выгодный вариант как я понимаю - сильный старший разработчик + несколько недорогих, но мотивированных падаванов.
> гроссмейстеров, требующих 4000 евро в месяц?
Ну ты загибаешь. Насколко я знаю, в той же Европе программисты часто меньше этой суммы зарабатывают, а в нашей стране ее платить нет экномического смысла.
> как пронзительная мольба со стороны заебавшихся разработчиков к клиентам не покупать битриксы
Ситуации бывают разные. Низкоквалифицированные разработчики на битриксе ограничивают уровень, на котором можно сделать проект.
>>699723
> $i++;
> echo "Ваш ответ на вопрос №$i ({$question->text}): \"{$answer}\" ({$question->answers[$answer]}). ";
> $i--;
Можно просто сделать $number = $i + 1; - ниже так и сделано. Не стоит лишний раз менять переменную-счетчик.
>>700141
Сделал задачу про студентов? Тогда не бойся, файлообменник это не самое сложное задание.
Если ответ причитали, значит он писался не зря. Ну и может кто мимопроходящий тоже прочел и что-то для себя узнал новое.
>>700616
Методы вызываются так. Снаружи - с указанием объекта:
$x = $ivan->getTotalHours();
изнутри класса - через $this:
class A
{
public function x()
{
$y = $this->getTotalHours();
}
}
> А можно ли как-то кратко посчитать все hours для любых экземпляров класса? Для всех имеющихся?
Сложить их в массив и пройтись по нему foreach. Также есть array_sum.
>>700697
> public function getSalary()
Не учитывает повышенную оплату овертайма
> __construct
Конструктор лучше ставить первым из методов, так как он отвечает за инициализацию объекта.
> public function getNormalHours() {
Она не учитывает часы в неделях с овертаймом
getNormalHours, getOvertimeHours - кстати одно из этих значений можно получить вычтя другое из общего числа часов.
> $i = preg_split('//u', $x);
Что за нахвания переменных? Непонятно же, используй нормальные слова.
> function padRight($x, $y){
Ты там что-то переусложнил. С помощью mb-strlen найди длину строки и с помощью str_repeat добавь не хватающее число пробелов.
> if ($employee->getOvertimeHours() > 0) {
> $overtime += $employee->getOvertimeHours();
тут иф не нужен - от прибавления нуля ничего не меняется
> как именно надо подсчитать разницу в оплате переработанного времени.
зарплата = обычное время x обычная ставка + овертайм x ставка овертайма
Если ответ причитали, значит он писался не зря. Ну и может кто мимопроходящий тоже прочел и что-то для себя узнал новое.
>>700616
Методы вызываются так. Снаружи - с указанием объекта:
$x = $ivan->getTotalHours();
изнутри класса - через $this:
class A
{
public function x()
{
$y = $this->getTotalHours();
}
}
> А можно ли как-то кратко посчитать все hours для любых экземпляров класса? Для всех имеющихся?
Сложить их в массив и пройтись по нему foreach. Также есть array_sum.
>>700697
> public function getSalary()
Не учитывает повышенную оплату овертайма
> __construct
Конструктор лучше ставить первым из методов, так как он отвечает за инициализацию объекта.
> public function getNormalHours() {
Она не учитывает часы в неделях с овертаймом
getNormalHours, getOvertimeHours - кстати одно из этих значений можно получить вычтя другое из общего числа часов.
> $i = preg_split('//u', $x);
Что за нахвания переменных? Непонятно же, используй нормальные слова.
> function padRight($x, $y){
Ты там что-то переусложнил. С помощью mb-strlen найди длину строки и с помощью str_repeat добавь не хватающее число пробелов.
> if ($employee->getOvertimeHours() > 0) {
> $overtime += $employee->getOvertimeHours();
тут иф не нужен - от прибавления нуля ничего не меняется
> как именно надо подсчитать разницу в оплате переработанного времени.
зарплата = обычное время x обычная ставка + овертайм x ставка овертайма
> А контроллер разве не реализует процесс регистрации нового студента? Я не могу понять в какой модели иначе это должно реализоваться.
Погугли "тонкие контроллеры". Код в контроллере не повторно используемый, потому не стоит его там много писать. Мы должны выделять из этого кода отдельные, не зависмые от контроллер функции и выносить наружу. Ну например, регистрацию можно делать и без контроллера - что если нам надо программно сгенерировать 100 студентов и вбить в базу? Ты будешь копипастить код контроллера?
Давай-ка сделаем так. Чтобы ты лучше это понял, сделай скрипт для командной строки, который генерирует заданное число студентов и вставляет в базу. Вызывается он например так:
php generate-students.php 100
Паста про командную строку есть в ОП посте, для генерации имен и прочего можно использовать библиотеку faker или же написать свой код (библиотека конечно удобнее). Если тебе надо добавлять какие-то опции в командную строку, для их разбора есть функция getopt().
Файл для командной строки храни вне веб-папки, например в папке cli или command. Этот файл по сути будет альтернативным контроллером.
> На данный момент у меня есть RegisterForm, Student, RegistrationHelper, StudentGateway, и не к одному из них я не могу отнести эти методы
RegistrationHelper по названию подходит для всего связанного с регистрацией.
>>700839
Я там выше написал советы вроде.
>>700869
Обычно отладка включается добавлением параметра в URL, вроде XDEBUG_ENABLE или как-то так. Если ты используешь куки для этого, то удали их и исползуй параметрв УРЛ - тогда отлаживаться будут только скрипты где ты дописал в УРЛ параметр.
>суть проблему - xdebug при прослушивании порта подхватывает и phpmyadmin
Он по моему ничего не прослушивает. Это отладчик или иде слушает порт, а xdebug к нему коннектится.
> А контроллер разве не реализует процесс регистрации нового студента? Я не могу понять в какой модели иначе это должно реализоваться.
Погугли "тонкие контроллеры". Код в контроллере не повторно используемый, потому не стоит его там много писать. Мы должны выделять из этого кода отдельные, не зависмые от контроллер функции и выносить наружу. Ну например, регистрацию можно делать и без контроллера - что если нам надо программно сгенерировать 100 студентов и вбить в базу? Ты будешь копипастить код контроллера?
Давай-ка сделаем так. Чтобы ты лучше это понял, сделай скрипт для командной строки, который генерирует заданное число студентов и вставляет в базу. Вызывается он например так:
php generate-students.php 100
Паста про командную строку есть в ОП посте, для генерации имен и прочего можно использовать библиотеку faker или же написать свой код (библиотека конечно удобнее). Если тебе надо добавлять какие-то опции в командную строку, для их разбора есть функция getopt().
Файл для командной строки храни вне веб-папки, например в папке cli или command. Этот файл по сути будет альтернативным контроллером.
> На данный момент у меня есть RegisterForm, Student, RegistrationHelper, StudentGateway, и не к одному из них я не могу отнести эти методы
RegistrationHelper по названию подходит для всего связанного с регистрацией.
>>700839
Я там выше написал советы вроде.
>>700869
Обычно отладка включается добавлением параметра в URL, вроде XDEBUG_ENABLE или как-то так. Если ты используешь куки для этого, то удали их и исползуй параметрв УРЛ - тогда отлаживаться будут только скрипты где ты дописал в УРЛ параметр.
>суть проблему - xdebug при прослушивании порта подхватывает и phpmyadmin
Он по моему ничего не прослушивает. Это отладчик или иде слушает порт, а xdebug к нему коннектится.
> Сделал на линейно-итеративное и не получилось.
Цикл забыл. Надо ведь чтобы после выполнения кода он выполнялся пока мы не дойдем до нужного числа. Потому нужна либо рекурсия либо цикл чтобы многократно выполнять код.
>>700966
Норм.
>>700972
Такие штуки обычно делают с помощью роутера. Никто не создает кучу php-файлов для каждой рубрики. Просто с помощью роутера перенаправляют все однотипные УРЛ чтобы их обьрабатывал один и то же контроллер. Ты слышал про MVC и фреймворки вроде Slim, Silex, Yii 2? Погугли.
> Есть страница "Смесители".
> На ней запрос из бд вываливает документы, которые привязаны к смесителям.
Никто не делает страницу на каждую категорию разве что кроме поехавших любтелей битрикса. Нужен один код который работает с любой категорией.
>>700999
Плохо успеваю. Спасибо всем анонам, кто помогает новичкам и облегчает мою работу.
> Не всегда получается исправлять какие-то решения - хочется уже дойти до своего проекта, но буду заставлять себя.
Тут надо бы разрбраться, так как это пока все же основы и без крепкого понимания основ крепко на ногах стоять не сможешь.
>>Плохо что непонятно.
> Довольно обидны ваши слова.
ну я специально не хотел обижать, я же не знаю твой уровень и прошел ты это или нет. Если нет - то почитай про формы, элементы которые в них можно использовать. как делать массивы чекбоксов итд.
> Я же об этом первоначально и спросил, как связать галку с той или иной парой слов.
> Можно по индексу в имени чекбокса, который будет совпадать с индексом в имени инпутов.
Погугли "php POST формы массивы". Ты можешь сделать имена у чекбоксов вроде delete[100] или delete[hello] то есть указать в них первичный ключ записи для удаления. Принцип работы чекбокса такой: если в нем стоит галочка то при отправке формы на сервер передается строка name=value, если не стоит то ничего не передается.
Почитай про формы, про метод POST в протоколе HTTP, про кодирование данных формы (enctype, multipart/form-data, application/x-www-form-urlencoded) при отправке.
http://htmlbook.ru/samhtml5/formy/otpravka-dannykh-formy
Тут есть что-то: http://citforum.ru/internet/html40/interact/forms.html - не немнго замудрено написано, поймешь ли? Прочти в любом случае.
Тут что-то есть http://www.intuit.ru/studies/courses/1036/239/lecture/6170?page=7
> Хотя меня смущает кол-во элементов формы (по три на каждую пару слов, который в свою очередь может быть около сотни).
Ну с этим ничего не поделать.
> Вообще я уже вижу что идея с этим сайтом не очень хорошая,
Почему не хорошая? Если тебе она нравится то это самое важное. Для обучения такой сайт вполне годится, хотя я бы советовал и наше задание на студентов посмотреть, хотя бы римечания почитать - там много полезного напсиано. Может что-то можно применить к твоей задаче.
>>701083
У нас в последние несколько лет меняли правила зимнего времени - проще всего перевести время вручную. Или поставить зону вроде Дубаев. По идее под линуксом там надо как-то обновлять какую-то библиотеку (tzdata). гугли.
>>Плохо что непонятно.
> Довольно обидны ваши слова.
ну я специально не хотел обижать, я же не знаю твой уровень и прошел ты это или нет. Если нет - то почитай про формы, элементы которые в них можно использовать. как делать массивы чекбоксов итд.
> Я же об этом первоначально и спросил, как связать галку с той или иной парой слов.
> Можно по индексу в имени чекбокса, который будет совпадать с индексом в имени инпутов.
Погугли "php POST формы массивы". Ты можешь сделать имена у чекбоксов вроде delete[100] или delete[hello] то есть указать в них первичный ключ записи для удаления. Принцип работы чекбокса такой: если в нем стоит галочка то при отправке формы на сервер передается строка name=value, если не стоит то ничего не передается.
Почитай про формы, про метод POST в протоколе HTTP, про кодирование данных формы (enctype, multipart/form-data, application/x-www-form-urlencoded) при отправке.
http://htmlbook.ru/samhtml5/formy/otpravka-dannykh-formy
Тут есть что-то: http://citforum.ru/internet/html40/interact/forms.html - не немнго замудрено написано, поймешь ли? Прочти в любом случае.
Тут что-то есть http://www.intuit.ru/studies/courses/1036/239/lecture/6170?page=7
> Хотя меня смущает кол-во элементов формы (по три на каждую пару слов, который в свою очередь может быть около сотни).
Ну с этим ничего не поделать.
> Вообще я уже вижу что идея с этим сайтом не очень хорошая,
Почему не хорошая? Если тебе она нравится то это самое важное. Для обучения такой сайт вполне годится, хотя я бы советовал и наше задание на студентов посмотреть, хотя бы римечания почитать - там много полезного напсиано. Может что-то можно применить к твоей задаче.
>>701083
У нас в последние несколько лет меняли правила зимнего времени - проще всего перевести время вручную. Или поставить зону вроде Дубаев. По идее под линуксом там надо как-то обновлять какую-то библиотеку (tzdata). гугли.
> Еще как пишет. Причем от фреймворков в пользу чистого PHP еще отказываются, ибо быстрее работает и проще все контролировать, нет зависимости от внешних разрабов.
Ты пробовал форму с валидацией делать на числом PHP в сравнении с теми же симфони формс? Не проще и не быстрее, а больше рутины и копипасты. Как это ускоряет разработку, неоьходимость все писать руками каждый раз? Те кто так говорят наверно просто боятся что не осилят фреймворк.
Да и не все проекты такие уж высоконагруженные, и можно использовать микрофреймворки например, какие-то отдельные компоненты и тд. Я видел переходы в обе стороны - на самопис и с самописа на фреймворк.
>>701093
В чем смысл делать что-то вторичное? Так ты не победишь.
>>701160
> 13 месяц спустя: долг = -3729.8132554793 руб,
Тут явно ошибка. В последний месяц надо платить не 5000, а остаток долга, 1270 р.
>>701164
Гит это не часть нетбинс, а независимая программа, то что там есть это обертка над гитом. Освой гит в командной строке и только потом переходи награфический интерфейс к нему. Гугли git book - она простая и есть на русском.
Помощь по командной строке - в ОП посте.
> но там нет ничего о том, как в идеале должна происходить работа с гитом.
Он рассчитан на тех кто уже освоил сам гит, отдельно от нетбинс.
>>701207
> 13 месяц спустя: долг = -3729.8132554793 руб,
С этим разберись еще
> Еще как пишет. Причем от фреймворков в пользу чистого PHP еще отказываются, ибо быстрее работает и проще все контролировать, нет зависимости от внешних разрабов.
Ты пробовал форму с валидацией делать на числом PHP в сравнении с теми же симфони формс? Не проще и не быстрее, а больше рутины и копипасты. Как это ускоряет разработку, неоьходимость все писать руками каждый раз? Те кто так говорят наверно просто боятся что не осилят фреймворк.
Да и не все проекты такие уж высоконагруженные, и можно использовать микрофреймворки например, какие-то отдельные компоненты и тд. Я видел переходы в обе стороны - на самопис и с самописа на фреймворк.
>>701093
В чем смысл делать что-то вторичное? Так ты не победишь.
>>701160
> 13 месяц спустя: долг = -3729.8132554793 руб,
Тут явно ошибка. В последний месяц надо платить не 5000, а остаток долга, 1270 р.
>>701164
Гит это не часть нетбинс, а независимая программа, то что там есть это обертка над гитом. Освой гит в командной строке и только потом переходи награфический интерфейс к нему. Гугли git book - она простая и есть на русском.
Помощь по командной строке - в ОП посте.
> но там нет ничего о том, как в идеале должна происходить работа с гитом.
Он рассчитан на тех кто уже освоил сам гит, отдельно от нетбинс.
>>701207
> 13 месяц спустя: долг = -3729.8132554793 руб,
С этим разберись еще
Проще сложить самих работников в массив, а не их часы. Обойти этот массив циклом и просуммировать.
> for ($i = 0; $i < count($allHours); $i++) {
> $hours += array_sum($allHours[$i]);
Это не очень правльно так как суммировать часы за неделю должен сам работник.
>>701307
У работника должен быть метод который считает его зарплату. Суть ООП в том что мы в классе объединяем данные и методы для их обработки. И за расчет своей зарплаты отвечает сам работник.
А вот за сумму по всем работникам- уже внешний код.
> по разным ставкам посчитать оплату.
Умножь и сложи, что тут думать.
>>701416
Прочитай вот это:
----
Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:
— какие есть сущности, для которых мы сделаем классы? (Сотрудник)
— какие у них есть свойства. Зарплата не является свойством так как она вычисляются из других свойств и хранить ее не надо.
— что мы хотим от них получить (какие у них должны быть методы). Например мы хотим узнать сколько сотрудник заработал.
— как сущности связаны? Тут всего один класс и работники никак не связаны.
----
Нужно сделать метод расчета зарплаты в сотруднике.
>>701439
>>701453
Ему над изучить сам гит сначала.
Проще сложить самих работников в массив, а не их часы. Обойти этот массив циклом и просуммировать.
> for ($i = 0; $i < count($allHours); $i++) {
> $hours += array_sum($allHours[$i]);
Это не очень правльно так как суммировать часы за неделю должен сам работник.
>>701307
У работника должен быть метод который считает его зарплату. Суть ООП в том что мы в классе объединяем данные и методы для их обработки. И за расчет своей зарплаты отвечает сам работник.
А вот за сумму по всем работникам- уже внешний код.
> по разным ставкам посчитать оплату.
Умножь и сложи, что тут думать.
>>701416
Прочитай вот это:
----
Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:
— какие есть сущности, для которых мы сделаем классы? (Сотрудник)
— какие у них есть свойства. Зарплата не является свойством так как она вычисляются из других свойств и хранить ее не надо.
— что мы хотим от них получить (какие у них должны быть методы). Например мы хотим узнать сколько сотрудник заработал.
— как сущности связаны? Тут всего один класс и работники никак не связаны.
----
Нужно сделать метод расчета зарплаты в сотруднике.
>>701439
>>701453
Ему над изучить сам гит сначала.
Была статья на хабре. Также, мануал.
>>701812
> Почему? База не пуста. Если в while выводить то там есть значения.
Открой мануал и прочитай в нем про все использованные методы и константы, чтобы ты понимал что значит каждое слово. Если в мануале что-то непонятно, задавай вопросы.
>>701859
Официальнй мануал, php the right way, ООП, MVC, фреймворки, задачи из ОП поста.
>>701882
Овертайм по двойной ставке.
>>701951
Функции возвращают значения через return.
>>701955
> foreach ($arr as $k => $v) {
> $data[$k] = $v;
$data = $arr;
Была статья на хабре. Также, мануал.
>>701812
> Почему? База не пуста. Если в while выводить то там есть значения.
Открой мануал и прочитай в нем про все использованные методы и константы, чтобы ты понимал что значит каждое слово. Если в мануале что-то непонятно, задавай вопросы.
>>701859
Официальнй мануал, php the right way, ООП, MVC, фреймворки, задачи из ОП поста.
>>701882
Овертайм по двойной ставке.
>>701951
Функции возвращают значения через return.
>>701955
> foreach ($arr as $k => $v) {
> $data[$k] = $v;
$data = $arr;
Не пишите тут больше. Я тут проверил все до 29 марта, остальное проверю тут же чуть позже. зайдите вечером или завтра, проверьте не появился ли ответ.
> Проблема в том, что я не придумал как нормально посчитать в какую папку должен идти файл, поэтому сейчас там вот такой костыль
> for($i = 100; $i < 100000000; $i += 100) {
> if(($this->id / $i) <= 1) return $i;
Деление используй без цикла.
Также, вставку надо завернуть в транзакцию. В базе не при каких условиях не должно быть записи, для которой еще или уже нет файла на диске. Сначала сохраняешь файл и в случае успеха коммитиш транзакцию.
https://github.com/foobar1643/filehosting/blob/master/app/Controller/FileController.php#L46
> >analyze("storage/{$file->getFolder()}/{$fileHelper->getDiskName($file)}");
Получение пути у файлу должно быть в одной функции, а не размазано по всему коду.
https://github.com/foobar1643/filehosting/blob/master/app/Controller/FileController.php#L28
> if($file != null) {
Этот огромный иф надо перевернуть, поменяв условие на обратное
https://github.com/foobar1643/filehosting/blob/master/app/Controller/DownloadController.php#L32
> attachment; filename={$file->getName()}")
Это работает только если имя в кодировке ASCII, с русскими буквами не будет работать во всех браузерах.И вообще в заголовках можно только ASCII использовать.
https://github.com/foobar1643/filehosting/blob/master/app/Controller/DownloadController.php#L33
> ->withHeader('Expires', "0")
Зачем?
Для скачивания надо сделать поддержку отдачи файлов через Xsendfile если он установлен на сервере. Это эффективнее чем через PHP.
> https://github.com/foobar1643/filehosting/blob/master/app/Controller/UploadController.php#L28
> if($_FILES['filename']['error'] == "UPLOAD_ERR_OK") {
Гигансткий иф надо перевернуть. Неправильно когда у тебя 95% функции вложено в одном огромном ифе.
------
Форматирование IF
Помещайте более короткую ветвь IF первой. Это позволит видеть сразу обе ветви, что повысит читаемость кода. Если ветка ELSE содержит одну-две строки, а ветка IF гораздо больше, то поменяйте их местами, не забыв инвертировать условие.
------
> Перед тем как выбрать id файлов в поиске, я считаю общее кол-во найденых результатов через
>>SELECT COUNT() FROM index_files, rt_files
Вообще, это по моему неправильно. Сфинкс при поиске умеет возвращать сразу и число результатов. Там в АПИ есть функция и в SQL наверно есть ее аналог. Погугли (SHOW META).
Также, не лучше ли превьюшку делать до коммита транзакции? Вообще, подумай, в каком порядке безопаснее всего выполнять действия.
> Проблема в том, что этим способом он считает удаленные файлы.
Это следствие того что вместо одного хранилища данных они у нас хранятся в 2 местах и рассинхронизируются. Решения такие:
- игнорировать и надеяться что никто не заметит
- при выводе писать "этот файл был удален" - тогда количество не нарушится (вполне нормальный вариант)
- не писать точное число записей. Посомтри, гугл например не пишет точное число результатов и ограничивает число страниц.
Кстати, сфинкс по моему тоже имеет какое-то ограничение на максимально допустимый оффсет - изучи этот вопрос, опция max_matches по моему.
> Ну и очевидным фиксом будет выбрать все результаты через SELECT FROM, потом проверить существуют ли все id, и только после этого посчитать их количество.
Нет, это будет неэффективно так как ты должен выбрать из сфинкса кучу данных. потом из базы и потому 99% их выбросить так как они не влезают на страницу. Это нехорошо.
> Из этого вытекает баг с постраничной навигацией, потому что я использую общее кол-во записей для расчета оффсета выборки
Это как? Обычно считают по принципу ($page - 1) x $perPage
> Сейчас код очень плохо разделен и у меня появилась идея вынести все действия над файлами в хелперы, а из контроллеров потом вызывать их.
ПРавильная мысль
В качестве доказательства что твой код разделен, сделай простой клиент для командной строки. Он должен позволять добавлять файл с диска в приложение, удалять файл по id и например показывать список файлов с указанием оффсета и лимита. Представь что это такой инструмент для администратора. Для парсинга аргументов командной строки можно использовать getopt или компонент Симфони для командной строки.
> Тут не знаю как сделать, поэтому пока оставил все в контроллерах.
Контроллеры надо делать тонкими.
> и не понял зачем в Materialized Path нужна колонка number.
Я тоже не помню.
> Так же, во время поиска теории, я наткнулся на интересный пост на Stack Overflow, в котором объяснялось почему такой Materialized Path как в уроке - неправильный.
По моему там то же самое что и у меня - тоже написано про выравнивание нулями. Кстати, раз мы заговорили про Mpath, сделай такие штуки:
- проверку ограничений на максимальную глубину и число комментов в ветке чтобы не сломать дерево
- подумай над такой ситуацией: 2 потока одлновременно хотят добавить коммент в одну и ту же ветку. Не получится ли у них одинаковый mpath? Как можно с этим бороться? Погугли про блокировки в БД.
- посмотри, можно ли отделить код реализации Mpath чтобы например можно было легко добавить этот функционал к другим таблицам. Особо сложного делать не надо ничего, просто посмотри реально ли это.
> в конец колонки path для каждого файла добавляю id файла.
Зачем? Не понимаю. path там содержит номера комментариев по порядку в каждой из веток в которые он вложен.
> Правильно ли так делать? Или лучше поменять на обычный редирект с гет параметром вроде "?error=filesize"?
Неправльно. Надо обрабатывать ошибки загрузки в контроллере без редиректов. Как описано в уроке по работе с формами.
Насчет переиндексации - а правильно ли что ты сначала очищаешь rt индекс, а только потом пополняешь основной индекс? Не вызовет ли это перебоев в работе поиска? Изучи это вопрос.
>Установите права исполняемого файла для cron/reindex.sh используя команду chmod a+x reindex.sh
Это можно сделать через гит - он сохраняет флаг исполняемости, изучи этот вопрос.
Кстати, а почему storage в публичной папке? Зачем?
https://github.com/foobar1643/filehosting/blob/master/filehosting.sql#L4
> uploader character varying(35) DEFAULT 'Anonymous',
Не советую так делать. Лучше подменять имя при выводе. Как ты например сделаешь многоязычность в этом случае?
В таблицу комментариев возможно стоит добавить parent_id. Это позволит связать комментарии внешним ключом и восстановить parent_path в случае повреждений. Подумай над этим.
Далее, я вижу ты взял файлы из video.js и перемешал их со своими. Это неправильно. Стороннюю библиотеку надо положить в отдельную папку.
Далее, почему этот video.js такой гигантский? 681 Кб? Выясни. что там такого напихано и можно ли получить версию только с тем что нам нужно.
https://github.com/foobar1643/filehosting/blob/master/app/Helper/FileHelper.php#L9
> const FORBIDDEN_EXTENSIONS = ["php", "phtml", "js", "html", "htm"];
Это ненадежно, черные списки. на хостинге может например быть расширение вроед php5 или phtml, привязанное к PHP.
Надо вынести файлы из публичной папки, перименовывать все кроме белого списка, запретить выполнение кода в папке с файлами через htaccess если используется апач.
... продолжение ниже ...
> Проблема в том, что я не придумал как нормально посчитать в какую папку должен идти файл, поэтому сейчас там вот такой костыль
> for($i = 100; $i < 100000000; $i += 100) {
> if(($this->id / $i) <= 1) return $i;
Деление используй без цикла.
Также, вставку надо завернуть в транзакцию. В базе не при каких условиях не должно быть записи, для которой еще или уже нет файла на диске. Сначала сохраняешь файл и в случае успеха коммитиш транзакцию.
https://github.com/foobar1643/filehosting/blob/master/app/Controller/FileController.php#L46
> >analyze("storage/{$file->getFolder()}/{$fileHelper->getDiskName($file)}");
Получение пути у файлу должно быть в одной функции, а не размазано по всему коду.
https://github.com/foobar1643/filehosting/blob/master/app/Controller/FileController.php#L28
> if($file != null) {
Этот огромный иф надо перевернуть, поменяв условие на обратное
https://github.com/foobar1643/filehosting/blob/master/app/Controller/DownloadController.php#L32
> attachment; filename={$file->getName()}")
Это работает только если имя в кодировке ASCII, с русскими буквами не будет работать во всех браузерах.И вообще в заголовках можно только ASCII использовать.
https://github.com/foobar1643/filehosting/blob/master/app/Controller/DownloadController.php#L33
> ->withHeader('Expires', "0")
Зачем?
Для скачивания надо сделать поддержку отдачи файлов через Xsendfile если он установлен на сервере. Это эффективнее чем через PHP.
> https://github.com/foobar1643/filehosting/blob/master/app/Controller/UploadController.php#L28
> if($_FILES['filename']['error'] == "UPLOAD_ERR_OK") {
Гигансткий иф надо перевернуть. Неправильно когда у тебя 95% функции вложено в одном огромном ифе.
------
Форматирование IF
Помещайте более короткую ветвь IF первой. Это позволит видеть сразу обе ветви, что повысит читаемость кода. Если ветка ELSE содержит одну-две строки, а ветка IF гораздо больше, то поменяйте их местами, не забыв инвертировать условие.
------
> Перед тем как выбрать id файлов в поиске, я считаю общее кол-во найденых результатов через
>>SELECT COUNT() FROM index_files, rt_files
Вообще, это по моему неправильно. Сфинкс при поиске умеет возвращать сразу и число результатов. Там в АПИ есть функция и в SQL наверно есть ее аналог. Погугли (SHOW META).
Также, не лучше ли превьюшку делать до коммита транзакции? Вообще, подумай, в каком порядке безопаснее всего выполнять действия.
> Проблема в том, что этим способом он считает удаленные файлы.
Это следствие того что вместо одного хранилища данных они у нас хранятся в 2 местах и рассинхронизируются. Решения такие:
- игнорировать и надеяться что никто не заметит
- при выводе писать "этот файл был удален" - тогда количество не нарушится (вполне нормальный вариант)
- не писать точное число записей. Посомтри, гугл например не пишет точное число результатов и ограничивает число страниц.
Кстати, сфинкс по моему тоже имеет какое-то ограничение на максимально допустимый оффсет - изучи этот вопрос, опция max_matches по моему.
> Ну и очевидным фиксом будет выбрать все результаты через SELECT FROM, потом проверить существуют ли все id, и только после этого посчитать их количество.
Нет, это будет неэффективно так как ты должен выбрать из сфинкса кучу данных. потом из базы и потому 99% их выбросить так как они не влезают на страницу. Это нехорошо.
> Из этого вытекает баг с постраничной навигацией, потому что я использую общее кол-во записей для расчета оффсета выборки
Это как? Обычно считают по принципу ($page - 1) x $perPage
> Сейчас код очень плохо разделен и у меня появилась идея вынести все действия над файлами в хелперы, а из контроллеров потом вызывать их.
ПРавильная мысль
В качестве доказательства что твой код разделен, сделай простой клиент для командной строки. Он должен позволять добавлять файл с диска в приложение, удалять файл по id и например показывать список файлов с указанием оффсета и лимита. Представь что это такой инструмент для администратора. Для парсинга аргументов командной строки можно использовать getopt или компонент Симфони для командной строки.
> Тут не знаю как сделать, поэтому пока оставил все в контроллерах.
Контроллеры надо делать тонкими.
> и не понял зачем в Materialized Path нужна колонка number.
Я тоже не помню.
> Так же, во время поиска теории, я наткнулся на интересный пост на Stack Overflow, в котором объяснялось почему такой Materialized Path как в уроке - неправильный.
По моему там то же самое что и у меня - тоже написано про выравнивание нулями. Кстати, раз мы заговорили про Mpath, сделай такие штуки:
- проверку ограничений на максимальную глубину и число комментов в ветке чтобы не сломать дерево
- подумай над такой ситуацией: 2 потока одлновременно хотят добавить коммент в одну и ту же ветку. Не получится ли у них одинаковый mpath? Как можно с этим бороться? Погугли про блокировки в БД.
- посмотри, можно ли отделить код реализации Mpath чтобы например можно было легко добавить этот функционал к другим таблицам. Особо сложного делать не надо ничего, просто посмотри реально ли это.
> в конец колонки path для каждого файла добавляю id файла.
Зачем? Не понимаю. path там содержит номера комментариев по порядку в каждой из веток в которые он вложен.
> Правильно ли так делать? Или лучше поменять на обычный редирект с гет параметром вроде "?error=filesize"?
Неправльно. Надо обрабатывать ошибки загрузки в контроллере без редиректов. Как описано в уроке по работе с формами.
Насчет переиндексации - а правильно ли что ты сначала очищаешь rt индекс, а только потом пополняешь основной индекс? Не вызовет ли это перебоев в работе поиска? Изучи это вопрос.
>Установите права исполняемого файла для cron/reindex.sh используя команду chmod a+x reindex.sh
Это можно сделать через гит - он сохраняет флаг исполняемости, изучи этот вопрос.
Кстати, а почему storage в публичной папке? Зачем?
https://github.com/foobar1643/filehosting/blob/master/filehosting.sql#L4
> uploader character varying(35) DEFAULT 'Anonymous',
Не советую так делать. Лучше подменять имя при выводе. Как ты например сделаешь многоязычность в этом случае?
В таблицу комментариев возможно стоит добавить parent_id. Это позволит связать комментарии внешним ключом и восстановить parent_path в случае повреждений. Подумай над этим.
Далее, я вижу ты взял файлы из video.js и перемешал их со своими. Это неправильно. Стороннюю библиотеку надо положить в отдельную папку.
Далее, почему этот video.js такой гигантский? 681 Кб? Выясни. что там такого напихано и можно ли получить версию только с тем что нам нужно.
https://github.com/foobar1643/filehosting/blob/master/app/Helper/FileHelper.php#L9
> const FORBIDDEN_EXTENSIONS = ["php", "phtml", "js", "html", "htm"];
Это ненадежно, черные списки. на хостинге может например быть расширение вроед php5 или phtml, привязанное к PHP.
Надо вынести файлы из публичной папки, перименовывать все кроме белого списка, запретить выполнение кода в папке с файлами через htaccess если используется апач.
... продолжение ниже ...
https://github.com/foobar1643/filehosting/blob/master/app/Helper/PaginationHelper.php#L40
> return $this->link . "&"
Откуда у тебя уверенность что в ссылке содержится знак вопроса?
https://github.com/foobar1643/filehosting/blob/master/app/Helper/PaginationHelper.php#L47
используй деление
https://github.com/foobar1643/filehosting/blob/master/app/Helper/PreviewHelper.php
насчет этого класса - не лучше ли его сделать как сервис с возможностью обработрать несколько файлов подряд? FileHelper внедрить через DI?
https://github.com/foobar1643/filehosting/blob/master/app/Helper/SearchHelper.php#L20
делать запросы в цикле непарвильно и неэффективно. Обойдись одним запросом.
В хелперах стоит перед классом писать хотя бы пару строчек, для чего этот класс нужен.
https://github.com/foobar1643/filehosting/blob/master/public/index.php#L85
Это выглядит ненормально - почему ты в обработчике исключений выводишь форму загрузки? Ты читал мой урок про обработку форм? Один и тот же контроллер и выводит форму и обрабатывает ее.
https://github.com/foobar1643/filehosting/blob/master/templates/index.twig#L9
br исплоьзуется только для разрыва строки в программах, стихах, почтовых адресах. тут надо использовать список или таблицу.
https://github.com/foobar1643/filehosting/blob/master/templates/upload.twig
Что-то тут дивов подозрительно много для формы загрузки.
https://github.com/foobar1643/filehosting/blob/master/templates/error.twig#L3
Тег link 2 раза повторен
https://github.com/foobar1643/filehosting/blob/master/templates/search.twig#L31
> {% for i in range(0, files|length - 1) %}
Нумерация же не учитывает номер страницы тут?
https://github.com/foobar1643/filehosting/blob/master/templates/search.twig#L34
пагинацию надо вынести в макрос. Задача - сделать универсальную пагинацию которую можно прикрутить куда угодно с минимумом усилий.
https://github.com/foobar1643/filehosting/blob/master/templates/file.twig#L24
> {% if 'image' in fileInfo['mime_type'] %}
Что если майм-тип имеет вид text/x-image-description? Надо сделать метод в классе хранящем информацию от id3 вроде isImage или isPreviewable.
> <img src="/storage/previews/thumb_{{fileHelper.getDiskName(file)}}" alt=
нарушение принципов DRY и единой ответственности. пути должна генерировать предназначенная для этого функция.
> https://github.com/foobar1643/filehosting/blob/master/templates/file.twig#L34
> type='audio/mpeg
Ты проверяешь что там такой тип данных?
Еще меня немного беспокоит отсутсвие системы именования классов. Где гарантия что твое имя не пересечется с используемым в бутстрапе? То же самое по поводу имен JS функций. Подумай, что можно сделать.
Давай пока с этим разберемся, а потмо еще код посмотрим - я там вижу другие сомнительные места.
Так, в общем, в коде там немало и хороших моментов, но на них мы останавливаться не будем.
https://github.com/foobar1643/filehosting/blob/master/app/Helper/PaginationHelper.php#L40
> return $this->link . "&"
Откуда у тебя уверенность что в ссылке содержится знак вопроса?
https://github.com/foobar1643/filehosting/blob/master/app/Helper/PaginationHelper.php#L47
используй деление
https://github.com/foobar1643/filehosting/blob/master/app/Helper/PreviewHelper.php
насчет этого класса - не лучше ли его сделать как сервис с возможностью обработрать несколько файлов подряд? FileHelper внедрить через DI?
https://github.com/foobar1643/filehosting/blob/master/app/Helper/SearchHelper.php#L20
делать запросы в цикле непарвильно и неэффективно. Обойдись одним запросом.
В хелперах стоит перед классом писать хотя бы пару строчек, для чего этот класс нужен.
https://github.com/foobar1643/filehosting/blob/master/public/index.php#L85
Это выглядит ненормально - почему ты в обработчике исключений выводишь форму загрузки? Ты читал мой урок про обработку форм? Один и тот же контроллер и выводит форму и обрабатывает ее.
https://github.com/foobar1643/filehosting/blob/master/templates/index.twig#L9
br исплоьзуется только для разрыва строки в программах, стихах, почтовых адресах. тут надо использовать список или таблицу.
https://github.com/foobar1643/filehosting/blob/master/templates/upload.twig
Что-то тут дивов подозрительно много для формы загрузки.
https://github.com/foobar1643/filehosting/blob/master/templates/error.twig#L3
Тег link 2 раза повторен
https://github.com/foobar1643/filehosting/blob/master/templates/search.twig#L31
> {% for i in range(0, files|length - 1) %}
Нумерация же не учитывает номер страницы тут?
https://github.com/foobar1643/filehosting/blob/master/templates/search.twig#L34
пагинацию надо вынести в макрос. Задача - сделать универсальную пагинацию которую можно прикрутить куда угодно с минимумом усилий.
https://github.com/foobar1643/filehosting/blob/master/templates/file.twig#L24
> {% if 'image' in fileInfo['mime_type'] %}
Что если майм-тип имеет вид text/x-image-description? Надо сделать метод в классе хранящем информацию от id3 вроде isImage или isPreviewable.
> <img src="/storage/previews/thumb_{{fileHelper.getDiskName(file)}}" alt=
нарушение принципов DRY и единой ответственности. пути должна генерировать предназначенная для этого функция.
> https://github.com/foobar1643/filehosting/blob/master/templates/file.twig#L34
> type='audio/mpeg
Ты проверяешь что там такой тип данных?
Еще меня немного беспокоит отсутсвие системы именования классов. Где гарантия что твое имя не пересечется с используемым в бутстрапе? То же самое по поводу имен JS функций. Подумай, что можно сделать.
Давай пока с этим разберемся, а потмо еще код посмотрим - я там вижу другие сомнительные места.
Так, в общем, в коде там немало и хороших моментов, но на них мы останавливаться не будем.
> Разный стиль именования переменных.
Это конечно нехорошо.
> Встает вопрос, обязательно ли? Знаю что с точки зрения интерпретатора необязательно, а с человеческой?
Я думаю, они не ставят их так как эту функцию все равно только Слим может вызвать и ничего левого он в нее не передаст. Но от того что поставишь тайп хинт хуже точно не станет.
>>702447
Это обращение к элементу массива. Код надо бы отформатировать. Также, лучше писать самому а не копировать не понимая, как код работает.
>>702455
Зависит от схему URL твоего сайта. есть правило, одна страница = один URL. Вряд ли тебе нужна страница с адресом index.php.
>>702513
Почитай урок про функции и про return.
Ой-ой, это совсем не ООП. Массивы на массивах и массивами погоняют. Вот тебе паста:
--------
Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:
— какие есть сущности, для которых мы сделаем классы? (Сотрудник и Департамент, может быть еще Компания?)
— какие у них есть свойства (у Сотрудника есть ранг, базовая ставка, профессия, является ли боссом). Потребление кофе или зарплата не являются свойствами так как они вычисляются из других свойств и хранить их не надо.
— что мы хотим от них получить (какие у них должны быть методы). Например мы хотим узнать сколько сотрудник заработал или сколько он пьет кофе. От департамента мы наверно хотим получить сколько всего выпито кофе и заплачено денег.
— как сущности связаны? Очевидно, Сотрудник работает в каком-то Департаменте.
Также, сразу скажу еще один совет: гораздо удобнее сделать не один класс Сотрудник, а 4 класса: Инженер, Менеджер, и т.д. Тогда мы можем легко менять например правила расчет зарплаты или кофе для каждой профессии. Естественно, копипастить одинаковый код в 4 класса не надо — создай базовый абстрактный класс Сотрудник и унаследуй от него 4 класса-профессии. Правда в этом случае мы не можем поменять профессию сотрудника.
Наследование позволяет создавать класс не с нуля. а расширяя сущетсвующий класс: http://php.net/manual/ru/language.oop5.inheritance.php
«Абстрактный» — это класс, объект которого нельзя создать. Он предназначен для наследования от него других классов: http://php.net/manual/ru/language.oop5.abstract.php
Также, ты должен для всех полей и методов расставить модификаторы доступа (pubic, private, protected - они определяют, откуда можно обращаться к полю или методу). Ты должен подумать логически и для каждого поля/метода определить: это часть кода, которая относится к внутренней логике класса и не должна быть доступна снаружи, или же это часть кода, которая должна быть доступна. Ну к примеру, в Департаменте метод посчитатьОбщиеЗатратыНаЗарплату() должен быть публичным - для этого мы и пишем класс, чтобы считать затраты.
В общем, чем меньше публичных свойств и методов, тем лучше. Ведь когда другой разработчик или ты сам захочет использовать класс, он будет смотреть только на публичные элементы, и чем их меньше, тем проще разобраться как класс работает. Но не стоит закрывать вообще все: надо думать, является ли метод частью вунтренней логики класса или он предназначен для выдачи полезной информации.
Когда ты проектируешь класс, ты можешь представить себе что ты делаешь некую коробочку, из которой торчат переключатели и провода. Публичные свойства и методы - это то, что ты разрешаешь использовать другим программистам. Приватное - это то, что скрыто внутри коробки и что они трогать не должны.
--------
Теперь пройдемся по коду.
Во-первых, код надо пропускать через форматтер, читай второй пост в треде. Ну это же невозможно читать, я даже не понимаю где заканчивается и начинается цикл.
Вот у тебя класс Employees. Он видимо представляет группу однотипных работников. Первый недостаток виден сразу: а что если нам надо наградить или повысить зарплату части группы? Как ты это будешь делать? А если нам надо уволить пару человек и добавить пару новых?
Очевидно лучше сделать для каждого работника свой индивидуальный экземпляр объекта.
Далее, непонятно зачем ты в каждого работника передаешь название департамента. Достаточно того факта что работник находится внутри департамента. Более того, было бы удобнее создавать работника вне департамента и позже добавлять его туда:
$employee = new Employee(...);
$marketing->addEmployee($employee);
А у тебя работник рождается уже приписанным к департаменту. Я думаю, это лишнее усложнение, не дающее никакой выгоды.
Далее, у тебя там функции-простыни по 50 строчек. Это слишком много, невозможно читать и поддерживать, разбивай их на более мелкие.
> 'Me'=>500,
Для обозначения вещей вроде профессий надо использовать константы классов, а не текстовые строки. А то опечатаешься и никто не заметит.
> $this->boss['position'] = $position;
> $this->boss['rank'] = $rank;
Непонятно зачем тут массив. Что тебе мешает напрямую значения в полях объекта хранить, а не усложнять все?
Более того, у тебя там куча аргументов в конструкторе и даже непонятно какого они типа и что хранят. Например что такое rates? Это понять невозможно.
Далее, класс EmployeeOrder. Посмотрим на его конструктор:
construct($workers, $coffe)
Абсолютно непонятная логика. почему мы кофе передаем отдельно, а зарплату например нет?
Далее, ты зачем-то копируешь данные:
> $this->employees[] = $worker->employee;
Это плохая идея. Когда у тебя 2 копии данных, непонятно как их обновлять и какая из них правильная.
Более того, мы тут имеем сложный 2-мерный массив непонятной структуры. Мы изучаем ООП и данные необходимо хранить в виде объектов. В отличие от массива, в объекте всегда понятно какие у него есть поля и что в каждом хранится.
Далее,
> $this->department = $worker->department;
Эта строчка стоит в цикле и получается у нас сохранится толбко последнее значение. Зачем это?
> $this->rates = $worker->rates;
А это строчка после цикла и опять же непонятно почему мы копируем rates только из последнего объекта.
> function crysis()
Имена функций начинаются с глагола.
> if (!function_exists('multisort')) {
> function multisort($array, $index)
Что это за ерунда? Почему ты внутри класса создаешь динамически новые функции? Как такой код отлаживать когда функции в нем появляютяс когда хотят? И вообще, разве это задача класса EmployeeOrder создавать функции сортировки? Уверен он не для этого делался.
Далее, тут видна ошибка:
> new Department((new EmployeeOrder($workers1, $coffe)), $documentation),
Почему мы в конструткто Департамента передаем АнтикризисныйКомитет? А в Комитет передаем работников и какое-то кофе? Это же странно.
АнтикризисныйКомитет это отдельная сторонняя сущность. Ты даешь ему Компанию (или Департамент) и он выполянет над ней антикризисные действия:
$comittee = new AntiCrisisComittee;
$comittee->applyPlan1($company);
Вот и все. Не надо усложнять. Заметь что в моем варианте Комитет способен обработать аж несколько компаний по очереди.
Не надо 3 раза создавать все департемаенты. Изучи оператор clone и сделай чтобы компанию можно было клонировать со всеми департаментами и работниками:
$company2 = clone $company;
В общем, давай для начала сделаем нормальные классы для Сотрудника, Департамента и Компании, добьемся чтобы каждый из них умел бы делать что-то полезное, а потом уже будем делать антикризисный менеджемент. Сделай первую версию программы без антикризиса для начала.
Более того, если ты не очень уверен что правильно пишешь, ты можешь создавать по одному классу. То есть создай например Работника и проверь что он хранит всю нужную информацю, что он что-то умеет считать, свою зарплату например. Или даже ты можешь перед тем как писать код, попробовать просто написать какие поля и методы будут в классе.
Я может не очень внятно тут написал, так что задавай вопросы, я или анонимные эксперты тебе что-нибудь подскажут. ООП важная штука и надо в нем разбираться.
Я вижу ты там еще одну задачу на ООП запостил - сначала надо ее сделать идеально тогда.
Ой-ой, это совсем не ООП. Массивы на массивах и массивами погоняют. Вот тебе паста:
--------
Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:
— какие есть сущности, для которых мы сделаем классы? (Сотрудник и Департамент, может быть еще Компания?)
— какие у них есть свойства (у Сотрудника есть ранг, базовая ставка, профессия, является ли боссом). Потребление кофе или зарплата не являются свойствами так как они вычисляются из других свойств и хранить их не надо.
— что мы хотим от них получить (какие у них должны быть методы). Например мы хотим узнать сколько сотрудник заработал или сколько он пьет кофе. От департамента мы наверно хотим получить сколько всего выпито кофе и заплачено денег.
— как сущности связаны? Очевидно, Сотрудник работает в каком-то Департаменте.
Также, сразу скажу еще один совет: гораздо удобнее сделать не один класс Сотрудник, а 4 класса: Инженер, Менеджер, и т.д. Тогда мы можем легко менять например правила расчет зарплаты или кофе для каждой профессии. Естественно, копипастить одинаковый код в 4 класса не надо — создай базовый абстрактный класс Сотрудник и унаследуй от него 4 класса-профессии. Правда в этом случае мы не можем поменять профессию сотрудника.
Наследование позволяет создавать класс не с нуля. а расширяя сущетсвующий класс: http://php.net/manual/ru/language.oop5.inheritance.php
«Абстрактный» — это класс, объект которого нельзя создать. Он предназначен для наследования от него других классов: http://php.net/manual/ru/language.oop5.abstract.php
Также, ты должен для всех полей и методов расставить модификаторы доступа (pubic, private, protected - они определяют, откуда можно обращаться к полю или методу). Ты должен подумать логически и для каждого поля/метода определить: это часть кода, которая относится к внутренней логике класса и не должна быть доступна снаружи, или же это часть кода, которая должна быть доступна. Ну к примеру, в Департаменте метод посчитатьОбщиеЗатратыНаЗарплату() должен быть публичным - для этого мы и пишем класс, чтобы считать затраты.
В общем, чем меньше публичных свойств и методов, тем лучше. Ведь когда другой разработчик или ты сам захочет использовать класс, он будет смотреть только на публичные элементы, и чем их меньше, тем проще разобраться как класс работает. Но не стоит закрывать вообще все: надо думать, является ли метод частью вунтренней логики класса или он предназначен для выдачи полезной информации.
Когда ты проектируешь класс, ты можешь представить себе что ты делаешь некую коробочку, из которой торчат переключатели и провода. Публичные свойства и методы - это то, что ты разрешаешь использовать другим программистам. Приватное - это то, что скрыто внутри коробки и что они трогать не должны.
--------
Теперь пройдемся по коду.
Во-первых, код надо пропускать через форматтер, читай второй пост в треде. Ну это же невозможно читать, я даже не понимаю где заканчивается и начинается цикл.
Вот у тебя класс Employees. Он видимо представляет группу однотипных работников. Первый недостаток виден сразу: а что если нам надо наградить или повысить зарплату части группы? Как ты это будешь делать? А если нам надо уволить пару человек и добавить пару новых?
Очевидно лучше сделать для каждого работника свой индивидуальный экземпляр объекта.
Далее, непонятно зачем ты в каждого работника передаешь название департамента. Достаточно того факта что работник находится внутри департамента. Более того, было бы удобнее создавать работника вне департамента и позже добавлять его туда:
$employee = new Employee(...);
$marketing->addEmployee($employee);
А у тебя работник рождается уже приписанным к департаменту. Я думаю, это лишнее усложнение, не дающее никакой выгоды.
Далее, у тебя там функции-простыни по 50 строчек. Это слишком много, невозможно читать и поддерживать, разбивай их на более мелкие.
> 'Me'=>500,
Для обозначения вещей вроде профессий надо использовать константы классов, а не текстовые строки. А то опечатаешься и никто не заметит.
> $this->boss['position'] = $position;
> $this->boss['rank'] = $rank;
Непонятно зачем тут массив. Что тебе мешает напрямую значения в полях объекта хранить, а не усложнять все?
Более того, у тебя там куча аргументов в конструкторе и даже непонятно какого они типа и что хранят. Например что такое rates? Это понять невозможно.
Далее, класс EmployeeOrder. Посмотрим на его конструктор:
construct($workers, $coffe)
Абсолютно непонятная логика. почему мы кофе передаем отдельно, а зарплату например нет?
Далее, ты зачем-то копируешь данные:
> $this->employees[] = $worker->employee;
Это плохая идея. Когда у тебя 2 копии данных, непонятно как их обновлять и какая из них правильная.
Более того, мы тут имеем сложный 2-мерный массив непонятной структуры. Мы изучаем ООП и данные необходимо хранить в виде объектов. В отличие от массива, в объекте всегда понятно какие у него есть поля и что в каждом хранится.
Далее,
> $this->department = $worker->department;
Эта строчка стоит в цикле и получается у нас сохранится толбко последнее значение. Зачем это?
> $this->rates = $worker->rates;
А это строчка после цикла и опять же непонятно почему мы копируем rates только из последнего объекта.
> function crysis()
Имена функций начинаются с глагола.
> if (!function_exists('multisort')) {
> function multisort($array, $index)
Что это за ерунда? Почему ты внутри класса создаешь динамически новые функции? Как такой код отлаживать когда функции в нем появляютяс когда хотят? И вообще, разве это задача класса EmployeeOrder создавать функции сортировки? Уверен он не для этого делался.
Далее, тут видна ошибка:
> new Department((new EmployeeOrder($workers1, $coffe)), $documentation),
Почему мы в конструткто Департамента передаем АнтикризисныйКомитет? А в Комитет передаем работников и какое-то кофе? Это же странно.
АнтикризисныйКомитет это отдельная сторонняя сущность. Ты даешь ему Компанию (или Департамент) и он выполянет над ней антикризисные действия:
$comittee = new AntiCrisisComittee;
$comittee->applyPlan1($company);
Вот и все. Не надо усложнять. Заметь что в моем варианте Комитет способен обработать аж несколько компаний по очереди.
Не надо 3 раза создавать все департемаенты. Изучи оператор clone и сделай чтобы компанию можно было клонировать со всеми департаментами и работниками:
$company2 = clone $company;
В общем, давай для начала сделаем нормальные классы для Сотрудника, Департамента и Компании, добьемся чтобы каждый из них умел бы делать что-то полезное, а потом уже будем делать антикризисный менеджемент. Сделай первую версию программы без антикризиса для начала.
Более того, если ты не очень уверен что правильно пишешь, ты можешь создавать по одному классу. То есть создай например Работника и проверь что он хранит всю нужную информацю, что он что-то умеет считать, свою зарплату например. Или даже ты можешь перед тем как писать код, попробовать просто написать какие поля и методы будут в классе.
Я может не очень внятно тут написал, так что задавай вопросы, я или анонимные эксперты тебе что-нибудь подскажут. ООП важная штука и надо в нем разбираться.
Я вижу ты там еще одну задачу на ООП запостил - сначала надо ее сделать идеально тогда.
> public function getSalary()
не учитывается повышенная оплата овертайма
> construct($name, $rate)
Он обычно пишется первым среди методов
> if ($hoursAWeek <= 40) {
> $normalHours += $hoursAWeek;
Используй min/max
Число 40 там повторяется много раз, вынеси его в константу класса.
> function getNormalSalary($normalHours, $rate)
Это должно быть методом класса. Идея ООП в том что мы в классе заключаем, инкапсулируем данные и методы для работы с ними. Объект это такая самостоятельная часть программы, которая умеет что-то делать сама по себе. Нет причин выносить этот метод из класса.
> function padRight($x, $y){
Слишком сложно, тут хватит mb_strlen и str_repeat.
> // Цикл для удаления части имени работника
Это должно быть сделано методом в классе
> $employee->name = preg_replace('/( )([А-ЯЁ])([а-яё]+)/u', ' $2.', $employee->name);
Ты безвозвратно перезаписываешь полное имя. Как его достать обратно? Менять поле name можно только в случае если работник поменял свое имя.
> for ($i = 0; $i < count($allHours); $i++) {
тут нужен foreach
> Но правильно ли я вообще сделал, что некоторые функции определил вне класса? По ООП ли это?
В данном случае нет так как функции явно должны быть внутри класса, они работают только с хранящимися в нем данными.
> public function getSalary()
не учитывается повышенная оплата овертайма
> construct($name, $rate)
Он обычно пишется первым среди методов
> if ($hoursAWeek <= 40) {
> $normalHours += $hoursAWeek;
Используй min/max
Число 40 там повторяется много раз, вынеси его в константу класса.
> function getNormalSalary($normalHours, $rate)
Это должно быть методом класса. Идея ООП в том что мы в классе заключаем, инкапсулируем данные и методы для работы с ними. Объект это такая самостоятельная часть программы, которая умеет что-то делать сама по себе. Нет причин выносить этот метод из класса.
> function padRight($x, $y){
Слишком сложно, тут хватит mb_strlen и str_repeat.
> // Цикл для удаления части имени работника
Это должно быть сделано методом в классе
> $employee->name = preg_replace('/( )([А-ЯЁ])([а-яё]+)/u', ' $2.', $employee->name);
Ты безвозвратно перезаписываешь полное имя. Как его достать обратно? Менять поле name можно только в случае если работник поменял свое имя.
> for ($i = 0; $i < count($allHours); $i++) {
тут нужен foreach
> Но правильно ли я вообще сделал, что некоторые функции определил вне класса? По ООП ли это?
В данном случае нет так как функции явно должны быть внутри класса, они работают только с хранящимися в нем данными.
Вы видите копию треда, сохраненную 2 апреля 2016 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.