24 декабря Архивач восстановлен после серьёзной аварии. К сожалению, значительная часть сохранённых изображений и видео была потеряна. Подробности случившегося. Мы призываем всех неравнодушных помочь нам с восстановлением утраченного контента!
Добро пожаловать в наш уютный тред. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет научиться программировать, кто-то - делать сайты, кто-то - просто размять мозги и заняться чем-то полезным.
Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме. ОПу ведь все это читать придется.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост, прежде чем писать код).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
У ОПа нет аккаунтов и групп вконтакте, в фейсбуке, в твиттере, все "пхп-треды" там поддельные.
Платиновые вопросы
- Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко. - Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета) - Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery - Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/. - Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев - Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm - Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию. - Что самое главное для программиста? Умение аккуратно оформлять код. - ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет. - Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.
Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода.
Вообще, в 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 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Давай удочку, а не рыбу
Лучше не давать готовое решение проблемы, а рассказать как его искать. Может дать ключевые слова для гугла или ссылку. Но помогай, а не пытайся показать превосходство. Если даешь ссылки на нерусскоязычные статьи, упомяни об этом.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?» Не годится: «В гугле забанили?» Не годится: «Твой код плохой» Хорошо: «Вот, как можно улучшить этот код: ...» Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского или русского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде» Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)» Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
>>919076 ОПчик, почему тут цикл состоит только из 1 значения? http://ideone.com/lcS8qQ Дело в continue? Мысль была такова, что при положительном итоге проверки на наличие купюр, он их просто пропускает и переходит к следующему номиналу.
Я уже начал делать MVC сапера отсюда https://github.com/codedokode/pasta/blob/master/js/minesweeper-mvc.md , смысл делать позер-MVC, когда можно полноценное. Вопрос такой, ты помогал советами анонам писать event dispatcher для паттерна observer? Или они брали готовый код (глянул на гитхабе енота, вроде свой). Можешь ли ты подробней расписать про этот паттерн, а то я пока что не понял как работают его методы и как будет устроен класс, понял только что он будет следить за изменением модели за счет addEventListener. Там вроде есть ссылки на эти классы, но мне кажется если я их посмотрю, это будет как подглядывание.
Класс очень простой, он по сути позволяет сделать 2 вещи:
- добавить обработчик для какого-то события (addEventListener) - вызвать все зарегистрированные обработчики и может быть передать им параметры события (triggerEvent)
Примерно так:
var ed = new EventDispatcher; ed.addEventListener(SOME_EVENT, function (event) { ... }); ed.addEventListener(SOME_EVENT, function (event) { ... });
ev.triggerEvent(SOME_EVENT, { data: ... });
Есть еще альтернативный подход, когда класс представляет диспетчер только для одного события (то есть на каждое событие создается отдельный объект):
var someEvent = new EventDispatcher; someEvent.subscribe(function (event) { ... }); someEvent.trigger({ data: ... });
https://arhivach.org/thread/216627/#899868 >> .header h1 { >> font-family: ReklameScriptRegularDEMO, Cambria >В конце списка шрифтов надо указывать бы стандартный (serif и подобный). Cambria есть только на windows. Вы кидали сайт где указывались шрифты и статистика использования на разных платформах. Выбрал Кабмрию потому что там было 90%+ и для Эпл и красивенько выглядел.
>> .services .content .box .consectetur::before { >> background-position: 0px 0px; >> width: 47px; >> height: 54px; >Вот тут проще было для 4 блоков указать одинаковый размер картинки, а не различающиеся на 2-3 пикселя. В фш так вырезалось что все картинки разных размеров...
>> .services .content .box .fermentum::before { >я бы убрал тут .content, он выглядит лишним Как понять 'выглядит'? Разве не нужно соблюдать иерархию дерева? Знаю что не обязательно, но моё субъективное восприятие подсказывает что так выглядит лучше.
Есть массив в котором содержатся хлебные крошки, в формате [id]=>[title]. Необходимо сделать так, чтобы последняя ссылка в хлебных крошках не была ссылкой. Могу реализовать двумя вариантами, либо подчистить довольно сложным регулярным выражением, либо же ввести счётчик ($i) и если это будет последняя итерация, то есть условие переменная счетчика равна количеству элементов в массиве просто не записывать html код, то есть не делать ссылку. Как правильнее и быстрее? $i=1; foreach($breadcrumbs_array as $id => $title) { $string ="<a href='?category=$id'>$title</a> / "; if($i==count($breadcrumbs_array)) { $string = $title; } $breadcrumbs.= $string; $i++; }
>>919800 Во-первых, когда ты используешь unset, то ключи в массиве не сдвигаются. Допустим, у тебя есть массив $a = [1, 2, 3] и ты используешь unset($a[1]). Массив примет такую структуру: [0] => 1 [2] => 3 Обходится хаком с array_values: http://stackoverflow.com/a/5217738
Во-вторых, в коде бесконечный цикл, т.к total всегда будет больше либо равно 5. Как-то так: http://ideone.com/gRDsbR Учти, что условий твоей задачи я не знаю и за правильность не ручаюсь.
Изучаю сейчас все подробности создания сайтов каталогов, и хочу уже использовать всё это в каком-нибудь реальном сайте. Подскажите, каталог чего можно создать? Только не товаров с возможностью покупки, как в интернет-магазине, а чего-нибудь другого, например каталог сайтов или что-то такое.
Получаю с Select формы массив данных со значениями полей. В нём может быть разное количество элементов, от 1 до 8. Далее мне нужно внести эти данные в таблицу, в котором есть условно два столбца id и text, где текст это значение каждого элемента массива. То есть, если в массиве 6 элементов, я должен записать 6 строк в таблицу. Можно ли это как-то сделать, но без использования запроса к базе данных внутри цикла?
Все, пиздец, не могу решить задачу Опа "Считалочка". http://archive-ipq-co.narod.ru/i/l1/l1-bonus-survivor.png Логика моего решения примерно такова: создаем пустой массив длиной в 30 символов пока длина этого массива больше чем количество слогов: начинаем считать сначала, находим первый элемент который делится на 5 без остатка ( элемент % 5 == 0) как только находим его, делаем новый массив в который добавляем все числа которые идут после него и до конца. затем к этому новому массиву добавляем те элементы которые шли сначала и до этого элемента в итоге получаем массив начинающийся с числа 6 до 30, а далее 1,2,3,4. Это для того чтобы считать дальше начиная со следующего элемента. скопировать значения из этого нового массива в финальный, чтобы пройтись по нему таким же алгоритмом снова как только в массиве остается 4 числа, выводим их в ответ
У меня нихуя не получается переназначить первоначальный массив, он всегда остается таким же как был.
>>920199 Судя по примерному коду ОПа из этой задачи, у него решение четкое логичное и аккуратное, у меня же как говно. Скорее всего сам алгоритм неверен.
>>920199 > пока длина этого массива больше чем количество слогов: А количество слогов здесь причём? Тебе нужно оставить какое-то определённое количество девочек с чаем (по условию - 4), эта цифра к количеству слогов в считалке никак не относится. И как мне кажется, проще манипулировать индексами, а не копировать массивы из одного в другой. У меня как-то так вышло: http://ideone.com/CEZH6d А за хак с array_values извиняюсь, есть же array_splice.
Я хочу, чтобы this._field (он представлен в виде массива [{x:1, y:1}, {x:2, y:1} ...etc] остался в таком виде по возрастанию. Если я сделаю на него shuffle, то он пересортируется случайно. Поэтому я делаю неглубокию копию массив и воздействую на элементы массива - объекты, которые соответственно будут меняться и в оригинальном массиве. Вот такой неочевидный абуз. Я получаю, то что мне нужно (минирую поле) и массив по прежнему в порядке возрастания. Наверное надо делать метод setMine и передавать в него элемент скопированного массива, чтобы good code? А этот метод будет минировать поле field.
И еще я думаю как хранить мины, флажки и открытые клетки. Два варианта. Либо это boolean свойства объекта Cell, либо они хранятся в свойствах-массивах this._flags, this._mines, this._openCells. В последнем случае будет еще существовать мета-массив field, в котором будут все клеточки. Получится так, что элементы этих массивов будут ссылаться на одни и те же объекты Cell. Это нормально или делать глубокое копирование?
Есть файл, в котором находится скрипт обрабатывающий данные приходящие из формы. Как только происходит их обработка, он автоматически перенаправляет пользователя на другой файл. Как закрыть доступ со стороны браузера к этому файлу? Пока что только приходит, сделать так, что если обязательные данные не заполнены, то есть их нет в массиве ПОСТ вызывать exit; Со стороны формы, которая находится в другом файле пустую строку не будет пропускать яваскрипт. Какие есть лучшие варианты?
Так же вопрос, можно ли данный метод http://ideone.com/8v7B0B вставить в ConsoleController ? Или в модель это пойдет. Суть его в том, чтобы команды вроде 'a2' из консоли переводить в объекты Cell, ведь наверное нельзя передавать аргументы в контроллер вот так game.setFlag(new Cell(1,5), верно?
анончики, расскажите, сложно ли вкатиться в фриланс на похапе? я знаю жс(+jquery+react+react-native+ember),html,css на уровне 3-4 месяцев практики, сделал тройку сайтов для себя + игру на андроид, и сейчас выбираю между пхп и питоном. На жс+верстке не въехть из за обилия макак, которые имеют сотни отзывов и опыт на сайте, а мой профиль без рейтинга никому не нужен, поэтому хочу попробовать что-то еще. Ну и типа фуллстак же буду.
>>921275 Пока ты не начнешь выгрызать и находить себе заказы, ты так и будешь выбирать между пхп и питоном, потом еще из какой нить дрочи и везде будут "обилие макак".
> Лучше было бы просто переупорядочить правила. > "если ни одна из предыдущих скидок не применена, и пользователь выбрал 3 или более продуктов, то применить одну из этих 3 скидок в зависимости от количества" - вот это с моей точки зрения самое логичное. Это конечно же многое облегчает. Да, в задаче чётко написано, что каждый товар должен использоваться лишь один раз.
Если вы что-то писали в старом треде, и я не ответил, не проверил, напомните о себе тут.
Также, напомню, что в старом треде опубликованы ответы:
>>919067 - про задачу про ООП и скидки >>919065 про JS задачу на DOM номер 4 >>919061 клавиша шифт, йода, сумма прописью >>919060 про сумму прописью >>919059 про калькулятор >>919058 про preg_match
Старые ответыАноним29/01/17 Вск 08:48:25#32№921310
>>Ты по моему не очень понимаешь, что такое AR. AR это когда класс/объект представляет и строку из базы данных, и содержит методы для ее загрузки/сохранения в БД. Ты уверен, что ничего не перепутал? > Просто я видел такую фишку, когда делали абстрактный класс model в котором просто были сделаны операции типа insert и delete, а под конкретную типа student от него наследовались, называли это актив рекорд. Нет, наследование тут не при чем. Главная особенность Active Record - то, что класс-модель сам умеет себя сохранять в базу:
$student = new Student; $student->name = 'Ivan'; $student->save();
В других паттернах обычно 2 класса: класс-модель, редставляющий сущность и класс-сохранятель этой сущности в базу.
>>Лучше иметь сервис, в котором есть методы для проверки и сохранения файла. Чтобы мы всегда могли бы программно сохранить файл (даже если мы не собираемся это делать, просто чтобы код был логически разделен на част). > О, отлично. Только это же все равно логически относится к моделям, правда?
Да, в MVC это модель.
>>безопасность, чтобы нельзя было сохранить файл с расширением php или именем htaccess > Такие файлы стоит просто запрещать загружать или же менять им расширение? Удобнее разрешать загружать, но при сохранении менять расширение на безопасное вроде .txt
Старые ответыАноним29/01/17 Вск 08:48:49#33№921311
> Начал писать свой пикчехостинг на ларавеле. Вопрос следующий: у меня есть возможность загружать картинку не только с компа, но и по урл. Написал свой формреквест, форма валидируется нормально, но пропускает одновременно оба заполненных инпута, с файлом и урлом (нужен xor). Вопрос: как лучше организовать проверку на xor, писать свой Rule или делать это на стороне контроллера?
Я не особо разбираюсь в этом фреймворке. Я думаю, что стоит сделать оба поля необязательными, а затем написать правило, проверяющее, что хотя бы одно заполнено. Лучше конечно делать это в форме, а не в контроллере.
> Можете подсказать, почему конечный результат отличается? Ты в последний месяц, когда там остается выплатить около 4000, выплачиваешь их сразу ( else {$paymentTotal = $paymentTotal + $creditBalance; ), а ведь на них сначала должны начислиться проценты и комиссия. И выйдет больше.
> Где phpMyAdmin хранит комментарии к ячейкам таблицы? phpMyAdmin сам их не хранит, а передает на сервер MySQL для хранения. Эти же комментарии можно добавить и без phpMyADmin, через SQL запрос вида:
CREATE TABLE x ( y INT COMMENT 'Примечание' ) COMMENT 'Примечание';
> Участвуют ли они в запросах? > Есть ли разница в производительности запросов с ними / без? Думаю, нет. Но разбираться в таблицах с комментариями гораздо удобнее.
> Какой движок (MyIsam, InnoDb, другой?) подойдет лучше для ситуации: Почитай про различия между движками, гугли "отличия innodb и myisam"
> Не будут ли тормозить запросы в конце года? 100 000 не так и много, думаю, при правильно поставленных индексах все будет хорошо. Но конечно, если ты выбираешь все 100 000 записей, очень быстро сделать это не получится просто из-за большого объема передаваемых данных.
Вообще, тебе лучше бы просто сделать таблицу, скрипт выборки и померять время.
Старые ответыАноним29/01/17 Вск 08:50:18#34№921312
>>Конечно, копирует ссылку на функцию. > Но функция находиться же в объекте obj! В чём подвох?
var o = {}; o.fn = function() {};
Функция o.fn сама по себе никак к этому объекту не привязана. Объект хранит в себе ссылку на функцию, а функция на объект - нет. Потому если мы копируем ее в отдельную переменную, и вызываем, то она про исходный объект ничего уже не знает и this указывает на window:
var f = o.fn; f();
А вот если мы пишем
o.fn();
То интерпретатор JS видит, что функция вызвыается на объекте, и подсовывает его в качестве this.
Чтобы она "запомнила" свой объект, мы должны использовать bind:
var f = o.fn.bind(o); f();
>>Задача 1: написать функцию bindContext(fn, that). Она создает новую функцию, которая при вызове вызывает fn с указанным this и переданным аргументами. То по сути есть привязывает произвольное значение this к функции. > https://jsfiddle.net/Luubgokx/ Все верно.
>>Задача 2: сделать функцию addProperty(object, name, initialValue) для создания приватных свойств с геттерами и сеттерами на объекте или прототипе объекта. > https://jsfiddle.net/sh21j4p1/ Тут опечатка в коде:
> addProperty(obj, 'test', 10); > console.log(obj.getName()); Свойство test, а вызывается getName вместо getTest().
По коду: в общем, верный подход, мы прячем переменную в замыкании, но вот не очень понял, зачем использовать defineProperty. Функции get/set можно просто добавить через obj[funcName] = function ...
> name[0].toUpperCase() + name.slice(1) Это конечно лучше было вынести в вспомогательную функцию.
Задача про фастфуд
> Почему-то не получается https://jsfiddle.net/y28h2o2b/3/ Там надо открыть отладчик (Ctrl + SHift + I) и включить режим "останавливаться на исключении". И там будет видно, что this.menu не определено, отсюда и ошибка.
Аналогичный отладчик есть и в Фаерфоксе, и в Сафари.
На jsfiddle отладка может и не заработать (хотя у меня работало), в этом случае надо просто сделать свой HTML файл, открыть в браузере и отлаживать его.
Электросеть
> ...только мне теперь кажется логичным что у каждого элемента сети должен быть один параметр, это мощность, и этот элемент должен сам определять дальнейшие условия определения этого параметра в соответствии\зависимости со средой (определение дневного\ночного времени).
Тут есть разные варианты, надо просто выбрать такой, какой удобнее:
- можно вообще не делать свойств в базовом классе, и в каждом наследнике написать свой метод getPower() со своей логикой. Соответственно, наследник определяет, какие будут свойства (вроде числа квартир) и как из них вычисляется потребление. - можно сделать в базовом классе свойства dayPower/nightPower и метод getPower, который их возвращает. А логику вычисления этих свойств писать в конструкторах наследников. И не делать свойств вроде числа квартир.
Первый подход наверно гибче.
> //Нужен ли тут гетер, если к свойству можно обратиться через точку? мы можем договориться, что свойство приватное, чтобы в него напрямую не лезли, и тогда геттер будет нужен.
> Лучше исключить её из перебора потому, что ЛЭП тоже может вернуть какое-то количество мощности. Мне кажется, надежнее прописать там ноль, так как мы не знаем, какая у нее мощность. Ну или вообще не делать в ней метода getPower(), чтобы его не пытались даже вызывать.
> С другой стороны электросеть не знает о ценах и о внутреннем устройстве ЛЭП. Моя идея в том, баланс можно просто передать в условный счетчик. Ведь это для ЛЭП свойственно иметь и считать цену. Электросеть не знает цены и пропускной способности, но она всегда может ее у ЛЭП спросить. ЛЭП сама не может ничего посчитать, так как не знает баланс энергии во всей сети, и не может решить, сколько надо закупать. Потому расчет, сколько энергии купить, должен быть в электросети.
> this.elements.sort(function (a, b) { > if (a.price > b.price) { Вот тут я вижу неточность: в коде предполагается, что у всех элементов сети есть свойство "цена". Но оно есть только у ЛЭП. Потому мы должны отобрать ЛЭП и сортировать только их.
Также, sort меняет порядок следования элементов в this.elements, что может где-то быть нежелательно. Ведь получается что метод с названием get Something фактически изменяет внутреннее состояние объекта, что неожиданно. Лучше получить отдельный массив ЛЭП и сортировать его.
> if (this.elements instanceof PowerLine) { > price += this.elements.countPrice(balance); > balance = this.elements.countPower(balance); Тут нет расчета, сколько именно нужно купить. Нужно покупать не всю доступную энергию, а только ту, что не удалось произвести.
> function Electrostation(power) { > if (power >= 1 Math.pow(10, 6) && power <= 100 Math.pow(10, 6)) { > this.power = power; > this.nightpower = power; Тут лучше не задавать свойства вручную, а вызывать конструктор предка. Может потом туда допишут еще какой-то код, и тут он не сработает. Принято всегда вызвать конструктор предка, так как именно он отвечает за инициализацию предка. И если его не вызвать, то что-то из задуманного может не выполниться.
> function PowerLine(power, price) { > this.power = power; > this.price = price; > } Мне кажется, тут неправильно используется свойство power, так как у ЛЭП это не фактически переданная мощность, а пропускная способность (сколько максимум можно купить/продать), и логично для нее использовать другое название, чтобы не было путаницы.
> PowerLine.prototype.countPower = function(power) { > var thispower = this.power;
> for (var i = 0; i < thispower; thispower--) { > if (power == 0) { > break; > }
> power += power / -Math.abs(power); что-то я не могу толком понять, что тут происходит. Зачем мы power делим саму на себя? Получится ведь либо 1, либо -1. Тут явно ошибка.
Определение типа переменной
> Что подрузумевается здесь под словом 'хеш'? Хеш, он же словарь, он же ассоциативный массив, он же объект - это вот это:
var x = { 1: 2, 'x': 'y' };
Я просто написал что вместо switch можно было сделать объект, в ключах которого хранятся значения вроде '[object Function]'. И искать тип в этом объекте.
>>Недостаточно, надо бы проверить что там есть свойства от 0 до length - 1. >>от 0 до length - 1 > А как это выразить в условии Написать цикл, проверяющий наличие свойств с помощью оператора in.
15. Напиши функцию неглубокого копирования объектов и массивов
> Опять же, не могу понять что с этим не так: Если это клон объекта, то этот клон должен иметь тот же прототип что и "донор"(?). Не, до такой степени скопировать объект мы вряд ли сможем. Достаточно копировать только свойства самого объекта, копировать прототип не требуется.
Вообще, в JS не все можно скопировать полностью. Некоторые встроенные объекты, например, массив, функцию-замыкание с захваченными переменными, или исключение, идеально скопировать может не получиться (насчет массива: он ведь мог быть создан в другом ифрейме, тогда копирование через var copy = [] не даст точную копию). Потому в задаче и не требуется все копировать полностью, а только то, что описано в условии.
> Лучше использовать for ... object.length вместо for in? У объектов нету object.length, length есть только у массивов. Лучше использовать либо for .. of из ES5, либо проверку через hasOwnProperty() из ES3.
> https://jsfiddle.net/uyey3at1/1/ Тут в коде, я вижу, есть поддержка копирования объектов Date и обычных объектов, а что с массивами? Для них ведь надо изначально создавать пустой массив и копировать элементы. Иначе тест вроде Array.isArray() не пройдет на копии.
Глубокое копирование
> https://jsfiddle.net/j8pydqsg/2/ > var clone = new object.constructor; Неприавльно вызывать конструктор. Мы ведь не знаем, какие аргументы у него есть и что в них надо передать. Надо делать так:
- если источник - это Date, то создать новый Date, можно сразу передать правильное значение даты - если источник - массив, создать новый массив и скопировать элементы - если источник - другой объект создать пустой объект и скопировать все его свойства, не относящиеся к прототипам - иначе, если источник - не объект (а число, строка, null и тд), можно просто вернуть его
Тут из-за кучи цитат становится уже трудно понимать некоторые ответы, если что-то непонятно, можно просто задать вопрос отдельно.
Старые ответыАноним29/01/17 Вск 08:50:37#35№921313
> Спасибо. Будет интересно для практики сделать статус-бар загрузки контента не НА сервер, а С сервера. В этом нет особого смысла, так как данных там немного и фактически большую часть времени там идет ожидание ответа сервера. А его длительность угадать нельзя и сделать правильный прогресс-бар не получится. Потому лучше просто крутящийся индикатор, что идет загрузка.
> А ещё интересно было бы узнать, как по уму реализовывать хранение конфига системы в базе данных (как у всех популярных cms). Сделать таблицу вида key | value, то есть 1 строка = 1 настройка. Если данные разных типов, то можно сделать key | int_value | string_value и тд.
Тут важно понимать, какие нам нужны настройки? Если они для менеджеров и меняются через админку - то в таблице, если для сисадмина или разработчика и меняются редко - может, удобнее в файл поместить.
> отдельная модель UserConfig с отдельной таблицей в БД, сохраняющая при каждом изменении данные в кэш. Ты усложняешь раньше времени. Кеш можно добавить, но тогда надо решать, как именно его делать: 1 ключ для всех настроек или для каждой настройки свой ключ. И на малонагруженном сайте скорее всего с кешем будет примерно такая же скорость, что и с БД.
Насчет кода - да, хорошо бы реализацию спрятать в классе, чтобы код только вызывал нужный метод и не знал, как именно там все реализовано.
> Всё это дело выполняет отдельный миддлвэр для всех запросов к серверу. middleware - это в смысле что-то аналогичное middleware в Слиме? Оно явно не для настроек и конфигов предназначно.
> для всех запросов к серверу. Вообще, логичнее читать конфиг, только если он нужен.
> while (($amount >= $value) and ($count > 0)) { > $amount -= $value; > $countBills += 1; Цикл с вычитанием нужно заменить на деление. Учесть ограничение на число имеющихся банкнот можно с помощью min/max.
А чем создание каталогов отличается от каких-то других сайтов? Ну не знаю даже что, сделай каталог уроков по программированию например, если своих идей нет.
Можно сделать мультиинсертом, если надо вставить несколько записей за раз, но обновить несколько записей можно только циклом. Желательно обернуть цикл в транзакцию, чтобы запросы могли выполниться только целиком.
Тут надо правильно выбрать формат массива. Например, можно сделать так:
- ключ обозначает текущий порядковый номер девочки от 0 до N (и ключи пересчитываются заново при удалении с помощью array_values/array_splice), а значение - исходный номер (когда еще все были в круге). На определенном шаге мы имеем такой массив:
[0] => [2] [1] => [3] [2] => [5] [3] => [7] ...
Тогда нам достаточно иметь просто счетчик, который мы увеличиваем на X с переполнением, и удаляем девочку с таким индексом (например, через unset или array_splice). Переполнение счетчика делается через взятие остатка от деления на текущий размер массива.
- можно сделать массив, где в значении хранится исходный номер, и ключи не пересчитываются (они тут вообще не важны). Вместо этого мы просто делаем цикл foreach по массиву и увеличиваем счетчик на каждом шаге на 1, когда он дойдет до определенного значения - удаляем текущий элемент (через unset, не пересчитывая ключи) и сбрасываем счетчик
И изучи функцию array_splice, она может быть полезна.
> Поэтому я делаю неглубокию копию массив и воздействую на элементы массива - объекты, которые соответственно будут меняться и в оригинальном массиве Можно так сделать.
И в коде конечно ошибки, например:
> if (typeof x != "number" || y != "number") { Должно быть typeof y
Также, не уверен, что нужно свойство nearMines у Cell. Зачем оно там?
Также, в твоем массиве не очень удобно искать ячейку по координатам.
Ну тут надо думать, какой подход будет удобнее. Оба подхода имеют право на жизнь. Главное отличие, что в случае массивов this._mines, this._flags информация хранится в классе Field, а не в объектах Cell.
Тут надо сравнивать такие вещи:
- удобно ли найти информацию о клеточке - удобно ли отслеживать изменения и генерировать события? - есть ли возможность менять свойства в обход класса, не генерируя события? Это может вести к багам
Вообще, в сложных моделях данные не получится все хранить в одном объекте и придется их разносить по отдельным объектам, которые образуют дерево или граф. Ну представь, например, текстовый редактор, где модель документа содержит объекты-заголовки, -картинки, -абзацы, -таблицы, и какие-то из них внутри еще содержат другие объекты. Все это может меняться, и все изменения надо как-то отслеживать.
Можно в контроллер, можно в вспомогательный utility класс.
> var regex = new RegExp("^\\w(\\d){1," + Util.getNumberLength(this._minesweeperGame.MAX_HEIGHT) + "}$", "i"); Это уже переулсожнение, проще просто потом проверить значение числа.
> ведь наверное нельзя передавать аргументы в контроллер вот так game.setFlag(new Cell(1,5), верно? Да, в условиях задачи требуется передавать человекопонятные обозначения.
> PageObject Пока гуглил, заметил, что многие понимают PageObject по-разному: кто-то предлагает просто выносить селекторы в объекты со статическими свойствами, кто-то считает, что PageObject должен предоставлять интерфейс страницы, пользователи которого не знают ничего о селекторах и взаимном расположении DOM-элементов. Мне второй вариант понравился больше.
Насчёт теста функции экранирования: > - передаем строку с тегом и проверяем, что на выходе тега нет > - вызываем html_entity_decode на результате и проверяем, что получилась исходная строка > - аналогично можно проверить кавычки, а также отдельные угловые скобки, что их нет в результирующей строке Если правильно понимаю, то второй пункт работает, только если искомая строка не будет найдена. В противном случае результат будет содержать тег b или mark, и исходную строку от такого результата не получим. В общем, сам тест: https://github.com/kubk/students/blob/master/tests/StudentTwigExtensionTest.php#L71
> Насчет авторизации по паролю - лучше в куке (и в БД) хранить не пароль, а его соленый хеш. Чуть безопасней, а так у тебя пароль в открытом виде на каждый запрос шлется. И в базе лежит. Украли базу/куки - и можно идти проверять, подойдет ли этот пароль к почте, к соцсетям итд. В базе был только хеш, а насчёт кук - да, сглупил.
> я бы назвал класс не UniqueEmail, а StudentEmailUnique, так как это ограничение работает только для одного класса - студента. Насчёт универсального решения понятно, но вряд ли оно мне где-либо ещё пригодится, раз доктрина в симфони почти что стандарт и там уже есть UniqueEntity.
Хероку без подтверждения кредитки даёт только постгрес (а ещё на нём почему-то тесты прогоняются раза в 2-3 быстрее, чем на MySQL). Впредь постараюсь быть внимательнее и лучше тестировать то, что отдаю на проверку.
Нужно ли проверять переданные параметры в js функциях? В некоторых проектах этого не делают, а пишут перед методами/функциями комментарий для jsdoc с текстом вроде @param {number} [value]. Разве он что-то сделает если туда передать допустим строку?
Нашел неплохую книгу по PHP Написана может не очень хорошо, но неплохие практики, перед прочтением пройдите туториал от ОПа. >Бретт Маклафлин - PHP & MySQL. The Missing Manual, 2nd Edition / PHP и MySQL. Исчерпывающее руководство, 2-е издание
>>921309 >>это ведь на проверку? Возможно. Кажется, я как-то неправильно использую кастомные ограничители в валидаторе. Получается гораздо запутанней, чем если бы я написал свой класс валидатор. Стандартные ассерты, определенные аннотациями не работают, возможно из-за кастомного constraint validator. Я так понимаю, что нужно использовать для создания формы entity класс, но в форме всего 2-3 поля, а в классе их больше, к тому-же хочется проверять сразу класс, а не поля отдельно друг от друга. Я создал отдельные классы форм, это выглядит как костыль. По какой-то причине ошибки, выдаваемые валидатором при использовании метода getMessage() не имеют ключей и просто выдают месседжи об ошибке без привязки к полю объекта формы. Если тянуть ошибки из формы, то там их вообще нет. Я где-то накосячил и не пойму где. В общем нужны советы и мб какието пояснения по коду. Про то, что нужно сделать бутстрап файл, я уже догадался. И возникла странная проблема: если поместить сонфиг подключения к бд в ини файл и сделать parse_ini_file, вставив значения в DoctrineServiceProvider(), то консоль не может подключиться к базе данных, хотя приложение ее видит и сайт работает.
>>922237 kek. Если бы я нашел что-то лучше... Просто того же Робина читал, у него вперемешку представление и код, тут хотя бы разделение, обрезание пробелов, что-то еще, что довольно неплохо. Нет ООП, да, это плохо, но хотя бы учат писать код правильно (до того места, где я дочитал).
Есть еще книга украинского программиста, но такое ощущение, что она писалась в разное время разными людьми, он более-менее кода, до вырвиглазного. Из нормального мне понравилась только книга с рецептами, но там же не учат с нуля. Да и вообще актуальных книг не могу найти.
> Разве он что-то сделает если туда передать допустим строку? Это ведь просто комментарий. Многих людей не устраивает такая расхлябанность и они берут TypeScript/Flow. Первый похож на C#, второй подойдёт если просто хочешь добавить тайп-хинты. Интересный доклад о важности типизации: https://www.youtube.com/watch?v=Ui8YfxzjaTY
>>922390 И тогда в функцию будет прилетать непонятно что и тебе самому сложнее будет с таким кодом работать. И вопрос, что у тебя в ифах? Если проверка через typeof, то учитывай, что он выдаёт "object" для null и "number" для NaN. Такой уж язык, что даже для проверки типов нужно извращаться с toString. Мне проще поставить Flow.
Дорогой ОП, сделал калькулятор - http://ideone.com/PBnVRM Это первая задача (не считая самые базовые), которую сделал полностью сам, не подсматривая код вообще нигде. Приятное чувство )
как же уничтожает мозг $ в имени переменных и отсутствие объявления. раньше писал на жс все задачки переделываю раза по два, потому что по привычке ебашу var/let и без $, особенно в цикле фор.
>>922738 > и отсутствие объявления Это реально пиздец. Даже в древнем бейсике (Visual Basic 6 1998-го года) можно было включить режим обязательного объявления. А вот в PHP 2017-го года - нет. Воистину СЛАДКИЙ ХЛЕБУШЕК
и да, если ты подразумеваешь, что все жс-юзеры дрочат $$$$$$ в жквери, то ты ошибаешься. У нас там уже реакт, нода, и куча всего, чем успешный говнокодер может лепить говносайты и взламывать глаза и логику хороших кодеров.
for (let i = 0; i < array.length; i++) {} for ($i = 0; $i < $length; $i++) {} 1. читабельно без $$$$, переменная i создается на время действие цикла и выгружается из памяти после его конца, есть отдельный метод, читающий длинну строки, массива, аллаха. 2. я очень люблю доллары, но тут они не настоящие, чтоб читать длинну массива, надо ее записать в переменную, либо делать огромное условие.
Объявление переменных просто логичнее и приятнее. Мы создаем меременную, потом присваиваем ей значение, меняем, уничтожаем. В пхп все не так гладко.
и да, foreach применяется не везде, так что .length - важная фича.
>>922770 > читабельно без $$$$ Исключительно вкусовщина.
>for ($i = 0; $i < count($array); $i++) {// переменная доступна только в теле цикла, после его завершения память освобождается.}
Проблемы?
> foreach применяется не везде В php 99% это foreach.
>>922771 >еще в пхп ругается интерпретатор, если я задаю переменную внутри чего-то, того же цикла. Надо как дебилу сначала до него написать $x = 0 или "". Шо? Это как?.
ну, типа я пишу тот де форич иии { $буква = значение... }, и потом смотрю, что это надо было вынести и поставить до начала функции. В общем, забей, это просто мои барибухи с непривычки, вот и все.
>>922779 Это не баг, а фитча. Область видимости переменной не может выходить за рамки контекста в котором она определена.( локальные переменные ) Можно конечно продлить жизнь временным данным, но это уже другая история
Есть что почитать клевое по паттернам и ооп? Пробовал Зандстру и дропнул как раз на той главе где начинаются шаблоны, тупо льет воду, не могу читать такое.
Мне надо не рассусоливать о том как круты паттерны проектирования, а что: вот есть у нас проблема, и вот смотри какой есть элегантный способ её решить, го расскажу!
>У нас тут не принято манкипатчить Дык я не собирался. Пришлось в коде конвертировать объект в массив, вспомнил о том, как когда-то давно с этим экспериментировал и как обнаружил эту странность. Решил спросить.
>сall_user_func Ну так оно, по сути, работает уже с переданной лямбдой. Так не интересно.
Короче, как я понял, эта дрянь формируется где-то на уровне транслятора, а потом можно только "вызвать метод strClass::show в контексте объекта obj", но не "получить свойство show объекта obj и вызвать его". Видимо, я мыслю слишком "по-JSному". Охуевал когда узнал, что, по сути, в PHP нет большой разницы между статичными методами и обычными.
>>923286 Я об этом-же. PHP позволяет >"вызвать метод strClass::show в контексте объекта obj" вместо >"получить свойство show объекта obj и вызвать его" . Хрен знает почему, но так, видимо, нужней. Ну и хуй с ним.
При запуске скрипт показывает процесс импорта – номер позиции и количество использованной PHP-памяти. Когда количество памяти приближается к 350 Мб – импорт замедляется. Первые 11000 позиций обновляются приблизительно минут за 10-15. Затем доходит до 1 позиции за 3 секунды.
Анончик там лимит на оперативку и свопится начинает? Оперативки на сервере 8 гигов
Анон, все мое программирование закончилось на первом курсе универа на паскале. В школе в блокноте писал какие то одностраничный примитивные сайты. И венец творения калькулятор, возводящий в степень и производящий выделения корня, написаный в паскале. И тут в 25 решил вкатиться в программирование. Собственно прочитал гайд и понял, что нужно пошагово как в гайде учиться.верно? И сильно я сосну с маком? Надо ли накатывать винду на него?
>>923336 >Собственно прочитал гайд и понял, что нужно пошагово как в гайде учиться.верно? Да. >И сильно я сосну с маком? Надо ли накатывать винду на него? С ним даже удобнее будет.
>>923499 Нет, это про биты. Почитай об этом лучше в учебнике по JS: learn.javascript.ru/bitwise-operators - там намного лучше описано что это и где применяется, нежели в документации PHP.
>>923333 Похоже здесь какие-то циклы разрастаются, в результате этот единственный процесс как было 90% процессорного времени занимал, так и сейчас занимает, но скорость обновления товара все сильнее падает. Анончик помоги это выше моего уровня
В общем методом дедукции и расставлением микротаймов было выяснено, что скрипт в основном тратит время чтобы пройти участок кода return $controllers[$entity_type];
$entity_type - это commerce_product $controllers[$entity_type]; - не содержит ничего count ($controllers[$entity_type];) - не содержит ничего
Не знаю почему участок тормозит. Вот вся цепочка которую я раскручивал: ---------------
function import_product($item){ $product = commerce_product_load_by_sku($item[14]);
----------------
function commerce_product_load_by_sku($sku) { $start = microtime(true); //начало измерения print "^^^^ 0 $start "; $products = commerce_product_load_multiple(array(), array('sku' => $sku));
$end3 = microtime(true); //конец измерения print "3 $end3 !!!";
API обычно это либо набор функций в библиотеке, либо (в случае веб-сервисов) набор URL, к которым можно обратиться. Яваскрипт тут вообще не при чем. Это можно делать на любом языке программирования.
>>923835 >Я точнее хотел спросить -API можно предоставить только посредством JS или есть ещё какие-то другие варианты? Твое API что должно делать? Ты знаешь различия между front end и back end? Твоему API нужны какие данные, которые необходимо формировать на стороне сервера?
>>923336 Я маки терпеть не могу, но стоит признать, что как ОС она в чем-то намного более прямая и правильная. Возможно, будут проблемы с выбором инструментария разного рода - на винде арсенал шире в разы.
>>923894 Сам себя запутал. Я видел пример как подключают js файл в шапке html документа по ссылке, и подумал что уже этот js файл взаимодействует с сервером где находиться этот файл.
Значит подключение API зависит от среды в которой его нужно подключить и каждая API это каждый отдельный случай?
Всё равно не понятно каким образом API взаимодействует с отдельным сервером.
Допустим я хочу воспользоваться API от сайта example.com на своем сайте mysite.org Что должен предоставить сайт example.com чтобы предоставить свой функционал для моего сайта?
>(в случае веб-сервисов) набор URL, к которым можно обратиться Этим пользуются с помощью html-тэга iframe? Есть ещё какие-нибудь варианты?
>>923921 У меня не какой-то конкретный случай. Пытаюсь разобраться как работает любое API.
Реализовать доступ к API можно по-разному. Кто-то подключает js-файл на веб-страницу и скрипты на странице вызывают функции в том файле. А кто-то обращается к API со своего сервера или из мобильного приложения, и там они могут использовать любой язык программирования.
Если ты хочешь выполнять код в браузере пользователя то да, нужен яваскрипт (API тут не при чем, просто большинство браузеров поддерживают только JS). Если ты не ограничен браузером, то можно использовать любые языки.
>>924097 >>924104 типа считать теги на странице, которую ему дадут. Вроде реализуемо и даже прогресс есть, но я ебал такие тестовые делать для каждой вакансии, блядь (это не единственный вопрос, как вы, наверное, уже догадались)
>>924112 >типа считать теги на странице, которую ему дадут. Просто получить количество тегов на страничке? А какие-то требования были дополнительные? Ну потому что вроде тут из сложнго только подумать в каком виде представить базу данных с тегами. Я конечно не делал, но так вроде с помощью парочки регулярок и циклов можно сделать.
>>924077 >А кто-то обращается к API Но как можно обратиться к нему, если оно находиться на стороннем сервере? Как, например, посредством php получить доступ к функции, например, getAllPost(...) из этого API, которое находиться на другом сервере? Или как это делается. Я это понять не могу.
>>924117 Это я как раз уже сделал, но из требований: оформить всё в правильный ООП, чтобы решение было расширяемым, мать его. Ну и всякие по мелочи отдать в виде xml и html (не понимаю, как можно отдать результаты поиска тегов в виде хтмл?) короче, не имея опыта с этой хуйнёй чувствую, что написал полное дерьмо
Продолжаю изучать книгу >Кевин Янк - PHP и MySQL. От новичка к профессионалу - 2013
Что хорошо: пхп код отделен от HTML; Рассказывают о том, данные от пользователя не безопасны; Для полдключения к бд используется PDO, как им пользоваться, основные команды. Например по книге делаем сборник анекдотов: создаем таблицы с шутками, авторами, у шуток есть категории. Все это вместе соединяем, создаем, редактируем и тому подобное.
В книге не разъясняется синтаксис html и css, азовые вещи скорее всего тоже пропущены, но я сам начал смотреть книгу где-то с 3 главы.
По беглому взгляду не нашел MVC, паттерны, продвинутое ООП и так далее. Книга подойдет начинающим, если вы до этого что-то читали.
>>924128 >оформить всё в правильный ООП Ну тут хз конечно, но видимо они хотят что бы ты сделал так, что бы например каждый класс выполнял только одну роль и все такое. >чтобы решение было расширяемым, мать его. Это о том, что твой код должен быть простым и очевидным настолько, насколько это возможно без ущерба функциональности и стандартам. >не понимаю, как можно отдать результаты поиска тегов в виде хтмл? В смысле? Тебе список тегов надо вернуть в итоге? Ну так почитай как сохранять инфу в виде хмл.
>>924133 Ну я правильно понимаю, что если мне надо вернуть список "тег" - "колво" в HTML формате, то я внутри php скрипта генерю html страницу в виду гигансткого string'a и в него в <table> загоняю свои значения? Или это не так делается?
>>919074 (OP) Привет, аноны. Какой лучше всего способ использовать для подключения к дб? <?php require_once 'login.php'; $conn = new mysqli($hn, $un, $pw, $db); if ($conn->connect_error) die($conn->connect_error); ?>
Или $connect = mysqli_connect('localhost', 'root', '12345', 'mydb'); Вообще будет ли это юзаться где или же сразу надо копать какой-нибудь нетбим ОРМ?
>>924170 Причем тут ORM? ORM это уже архитектурные изыски. Ты явно путаешь это с драйвером БД. PDO это просто самая удобная на данный момент обвязка драйвера БД.
>>924188 Ты все таки хуиты где-то нахватался. Тот же mysqli это просто расширение для работы с бд в пхп, это еще не ORM в полном виде. ORM в целом это уже нечто посложнее, погугли что такое active record, data mapper и т.п, освоишь это а там уже до доктрины какой-нибудь дорастешь. Если же тебе интересно какое расширение лучше - сейчас почти все юзают пдо.
Анончики, особенно кто делал задачу про файлообменник, возникла у меня проблемка, а именно - про сохранении файлов на сервер с кирилическими названиями вместо оных появляются кракозябры, т.е. понятное дело проблемы с кодировкой. public function upload(\Slim\Http\UploadedFile $file) { $params = $this->getFileParams($file); $file->moveTo($params['link']); } В парамсе у меня хранятся данные о файле, но не суть. Что интересно, кириличные имена файлов с помощью mb_detect_encoding() определяются как ютф-8, а латинца - асц2. Как решить проблему? В гугле все советуют не париться и латинизировать названия, но мне бы хотелось все таки сохранять в кирилице. Алсо в БД имена сохраняются как положено.
Сап. Изучаю Symfony 3, хочу сделать магазин на нем для закрепления знаний. Но так как мне немного лениво и от крудов тошнит, да и с php я хорошо знаком, писал уже на Yii, то реквестирую более-менее готовый каркас для создания магазинов или crm на симфони. Есть же, наверное, какой-то открытый компонент такой на гитхабе с базовым функционалом магазина? Чтобы можно было доделать его, добавить какую-то фичу по желанию, управление акциями, например.
Я только что вкотился, поясните как сделать в нетбинсе, чтоб результат сразу показывало в браузере? В настройках выбираю пикрел, когда пытаюсь запустить, в браузере нихуя. Надо похапе установить или что? Если что я на убунте.
А как по-твоему браузер загружает страницы? И как яваскрипт обращается к API на удаленном сервере?
Две программы, расположенные на разных компьютерах, могут установить сетевое соединение через Интернет и обмениваться данными. Обычно для соединения используют протокол TCP, поверх которого работает какой-нибудь высокоуровневый протокол вроде HTTP.
Очевидно, они хотят посмотреть, как ты справишься с этой задачей и какой подход выберешь. Знаешь ли ты про шаблоны или нет. Видимо не знаешь, судя по твоему вопросу.
Уточняющие вопросы по задаче логичнее задавать тому, кто ее дал.
Оператор обращения к полю объекта или вызова метода объекта. Если ты не знаешь, что такое классы и объекты, тебе надо их сначала изучить, например в учебнике в ОП посте есть глава про ООП, и в других учебниках наверно тоже есть.
> Что интересно, кириличные имена файлов с помощью mb_detect_encoding() определяются как ютф-8, а латинца - асц2. Эта функция не работает и возвращает случайные значения. Почитай например мой урок про кодировки и сам поймешь, почему в принципе невозможно 100% точно определить кодировку (можно только угадывать с какой-то вероятностью): https://github.com/codedokode/pasta/blob/master/cs/strings.md
Насчет имен файлов - тут такая ситуация:
Имена файлов скорее всего приходят в $_FILES в той кодировке, которая исользовалась на HTML-странице. Насколько я знаю, браузер вообще все данные форм ($_POST, $_FILES) кодирует кодировкой страницы, где эта форма расположена. Данные в _GET - не уверен, то ли кодировкой страницы, то ли всегда utf-8
Функции работы с файлами вроде fopen, file_put_contents, move_uploaded_file принимают имена в той кодировке, которая определяется ОС и ее настройками:
- в Windows они принимают имена в 8-битной кодировке, зависящей от языка системы. Для русского языка это Windows-1251 - в Mac они принимают имена в utf-8 - в Linux имена файлов не имеют определенной кодировки. Но отображение имен файлов использует заданную в системе кодировку, как правило, это utf-8. То есть в linux скорее всего надо передавать имена в utf-8
Теперь у тебя есть понимание, как решить проблему?
Нетбинс спрашивает, как у тебя организовано обновление и просмотр сайта. Выбранный тобой вариант подразумевает, что у тебя на компьютере запущен веб-сервер, URL которого предлагается указать в настройках. Также есть опция при деплое копировать файлы в другую папку, которую использует этот веб-сервер.
Вообще, если ты совсем начинающий, то ты можешь пока решить проблему без нетбинз - например, поднять Апач и руками копировать файлы в папку Апача или запустить встроенный в PHP-веб-сервер. Или даже запускать скрипты в командной строке.
А позже, когда поймешь, что у тебя как работает, уже настроить нетбинз. Тут важно понимать, за что отвечает какая настройка и что происходит, а не тыкать настройки наугад.
Ты вообще знаешь, что такое веб-сервер и как запустить PHP скрипт в командной строке? Если нет, то надо разобраться, если да, то хорошо, прочитай документацию нетбинза, и если что-то осталось непонятно, я могу пояснить.
Вообще, в PHP уже есть готовые расширения для парсинга HTML, так что не думаю, что это сложно. Или тут именно свой код нужен? Тогда чуть сложнее, конечно.
Ну не знаю, я использовал когда-то хакинтош и у меня осталось ощущение, что он тормозной. Конечно, может это из-за того, что это хакинтош, но у меня ощущение, что оно рассчитано на мощное железо и например на стареньком Core 2 duo с медленным HDD быстро не заработает. А Windows XP - заработает.
И там вроде до сих пор не научились раскрывать окна на весь экран?
Ну может ты просто взял учебник не для совсем начинающих? Там в начале не написано, что надо знать? Или чего-то не знаешь? Или просто надо сбавить темп изучения и повторить тему еще раз?
В любом случае, надо полностью разобраться в том, что ты изучаешь.
Видимо, ты что-то считаешь неправильно. Также, надо учесть что под виндой точность функции microtime(true) составляет около 15 мс, то есть время может получиться либо 0 либо 15 мс, но не 1 или 2 мс например. И если ты попадешь на границу между 2 интервалами то вернется 15 мс даже если в реальности там было намного меньше.
Лучше бы использовать профайлинг в xdebug.
> return $controllers[$entity_type]; Если $controllers - это массив, то это мнговенно выполнится, но если это объект с магическими методами или ArrayAccess, то конечно возможны варианты.
У тебя в коде ошибка. Переменная $size создается внутри блока if, но используется снаружи, и возможно, что она в некоторых случаях даже не создается (или выводится старое значение). То есть тебе стоило бы язык PHP подучить для начала.
Битовые операторы работают с представление числа в двоичном виде (из нулей и единиц). Сдвигается именно число в двоичном представлении. Начни с изучения двоичной системы счисления:
На первый взгляд тебе может это показаться запутанным (зачем преобразовывать число в двоичный вид, делать что-то с ним, преобразовывать обратно), но тут важно помнить, что внутри компьютера числа как раз хранятся и обрабатываются в двоичном виде, и для процессора это как раз простые операции.
На практике они редко нужны, если только тебе не надо работать с отдельными битами в числах.
Когда-то их еще использовали для оптимизации (сдвиг влево на 1 разряд равносилен умножению на 2, только выполнялся быстрее), но это неактуально для высокоуровневых языков вроде PHP/JS и не дает никакой выгоды.
- командами top, htop, free посмотреть сколько памяти используется в свопе, сколько свободно - посмотреть процент использования CPU процессом - при своппинге он падает и становится намного меньше 100% (хотя это может быть вызвано и другими причинами: чтение файлов, ожидание данных из сети).
JS тут плохая аналогия, так как в нем полноценных классов и ООП вообще нет. Это скорее проблема в JS, что для него метод и записанная в поле анонимная функция - одно и то же.
> по сути, в PHP нет большой разницы между статичными методами и обычными. Разница есть, они работают как и принято в ООП.
Для паттернов надо взять код, где они используются, например, компоненты Symfony Forms, Symfony Validation, Doctrine, и изучать их параллельно с паттернами. Так, просто в теории их изучать смысла нет.
Ты к ерунде придираешься, а реальных проблем не видишь. Ну и в JS их не меньше, кстати. Чего стоит только отсутствие нормального ООП.
> выгружается из памяти после его конца Сомневаюсь. Это конечно зависит от реализации, но в реальности, думаю, ничего никуда не выгружается, чтобы не тратить время.
> я очень люблю доллары, но тут они не настоящие, чтоб читать длинну массива, надо ее записать в переменную, либо делать огромное условие.
> Объявление переменных просто логичнее и приятнее. Мы создаем меременную, потом присваиваем ей значение, меняем, уничтожаем. В пхп все не так гладко. Так в PHP даже короче получается.
Можно проверять, хуже не будет, наоборот, поможет найти ошибку. Но может тебе будет удобнее использовать языки поверх JS с проверкой типов на этапе компиляции.
> Стандартные ассерты, определенные аннотациями не работают, возможно из-за кастомного constraint validator. Чтобы аннотации работали, надо их прочитать. Возможно, что это делается в Симфони, а при использовании отдельного компонента - не делается. В таком случае тебе надо найти код для чтения этих валидаций и вызвать его самому.
Так как в больших приложениях много форм, и неинтересно под каждую писать однотипный класс валидации. Проще описать только правила проверки.
При написании своего валидатора тебе ведь придется многое повторять, те же проверки на не-пустоту, длину строки и тд. То есть ты можешь написать свой класс-валидатор, но даже в этом случае, возможно, стоит как-то поддерживать и стандартные ограничения.
Вообще, есть альтернативы. Я вижу, ты создаешь форму прямо в контроллере. Но возможно, удобнее было бы сделать отдельный класс формы LoginType (не модели данных для формы) и настраивать список полей и ограничения в нем. Там же можно прописать кастомную валидацию.
Либо же разобраться с аннотациями и как-то брать описание формы из класса модели формы.
Также, ты вызываешь валидацию вручную через $this->validate(). Но формы интегрируются с валидатором и умеют сами его вызывать.
Что касается регистрации - регистрация это создание пользователя, и наверно, там в качестве модели для формы выгоднее использовать сразу модель пользователя, нет?
> Я так понимаю, что нужно использовать для создания формы entity класс, но в форме всего 2-3 поля, а в классе их больше, к тому-же хочется проверять сразу класс, а не поля отдельно друг от друга Не обязательно. В самой Симфони форма может использовать в качестве модели массив, а не Entity. Или просто обычный класс, не связанный с доктриной. То есть там как раз все максимально гибко сделано. И ты можешь привязать и форму симфони, и валидацию к обычному классу или даже массиву.
Не очень понял, а зачем тут провайдер? Почему нельзя записать что-то в контейнер $app напрямую? Провайдеры обычно используют для каких-то библиотек, чтобы достаточно было добавить в прилоежние один провайдер и не надо было описывать инициализацию библиотеки, и каждый сервис из библиотеки прописывать в DI контейнер вручную. Но у тебя там всего один сервис и объявляется (validator.login), и он не универсальный, его нельзя использовать в другом приложении.
То есть как я понял, провайдер используется как этакий "мост" для простого подключения сторонней библиотеки в Silex.
Я все же думаю, что это уже не задача формы - проверять логин. Задача формы:
- принять данные от пользователя - проверить их на соответствие заданному формату и ограничениям
Но проверять логин и пароль - это уже задача какого-то другого кода, например, сервиса проверки авторизации или еще чего-нибудь. У тебя форма берет на себя слишком много и занимается не своим делом.
Должно быть примерно так:
if ($form->validate()) { $email = $form->email; $password = $form->password;
if (!validateEmail($email, $password)) { $form->addViolation('неправильный логин или пароль'); } }
Я думаю, тут должно быть 2 класса-ограничения: одно для проверки логина, другое для email. А может какое-то более уникальное ограничение для проверки уникальности любого поля. Так как по задумке Constraint - это одно ограничение, а не много.
Ты используешь constraint неправильно, это именно объект, представляющий одно ограничение, а не валидатор формы. Если тебе нужен валидатор формы - сделай класс и там работай с формой (или ее моделью) напрямую:
if ($form->password == ...) { $form->addViolation(..); }
if ($model->email == ....) { return new ValidationError(....); }
Ну и представь, что ты сделаешь форму восстановления пароля. Там тебе надо будет проверять, что введенный email есть в таблице пользователей. Там можно было бы переиспользовать ограничение для проверки существования email.
Обрати внимание, что для произвольных ограничений есть такие варианты:
Еще у тебя я вижу в коде стремление писать все в контроллерах и не использовать сервисы. Ну например, регистрация/авторизация/получение текущего пользователя - для этого нет готовых методов. Нет сервиса для работы с комментариями. То есть ты вместо MVC пишешь толстые контроллеры.
Я предлагаю для начала разобраться с формами, моделями и валидацией, а дальше посмотрим остальные проблемы в коде. Я тут написал много текста, так что уточняй, если что-то неясно.
Я предлагал это как один из возможных вариантов. Если подумать, то логично как-то оптимизировать поиск объекта Cell по координатам, и тут есть варианты:
- хранить их в словаре вроде cells[y][x] - хранить их в массиве в определенном порядке, чтобы их можно было найти по формуле вроде cells[y * columns + x]
Я не настаиваю на какой-то конкретной реализации. Просто подумай, удобно ли будет в том или ином случае искать нужную клеточку, отслеживать изменения состояния клеточки, простой ли получится код. Тут нет какого-то одного правильного ответа.
Ну вот смотри, сколько тут опций:
- можно хранить все клетки в виде объектов Cell, а можно хранить отдельно список мин, список открытых клеток, список флажков - можно использовать массив, а можно словарь для поиска по координатам - в случае объекта Cell, можно хранить информацию об открытых клетках и флажках в нем, а можно не в нем - можно хранить объекты Cell внутри другого класса и не выдавать их наружу, а можно выдавать
Ты должен как-то взвесить все эти варианты и выбрать наиболее подходящий. Если совсем не уверен, что взять, выбери какой-то вариант, набросай несколько функций для работы с клеточками, и покажи, а я напишу, какие получаются недостатки.
Это вряд ли реально. Проще подстроить приложение и для винды перекодировать имена в нужную ей кодировку. Для этого можно сделать слой совместимости, который скрывает эти особенности внутри.
Вообще, конечно, это большая проблема. Ведь в русской версии винды используется одна 8-битная кодировка, а в американской - другая. Почему разработчики PHP не хотят использовать юникодные функции или хотя бы сделать дополнительные функции для юникода (в идеале для utf-8)? PHP формально кроссплатформенный, но от решения этой проблемы он самоустранился.
>>924446 >А что с этим делать и как решать эту проблему, рассказывают?
Ну да, вроде. Предлагают функцию с магическими кавычками, рассказывают, что если будет множество инклюдов и кавычек, то можно проблемы какие-нибудь получить.
На странице данные выводятся через htmlspecialchars, с константами (потом пишется обертка для нее). В mysql данные передаются через псевдо-переменные PDO
>>924523 >Проще подстроить приложение и для винды перекодировать имена в нужную ей кодировку. Для этого можно сделать слой совместимости, который скрывает эти особенности внутри. Я нихуя не понял. И вообще, это в пхп работа с кодировками адов труд, или я слишком неофит?
Вместо того, чтобы вызывать функцию вроде file_put_contents напрямую, сделай свою функцию, которая проверяет ОС и если надо, перекодировывает имя файла.
>>924424 Я догадывался что это выполняется посредством http-запроса, но мне не понятно как отправить его посредством, к примеру, php. Я видел как обрабатываются http запросы, но не разу не видел чтобы они отправлялись.
>>924484 >>Возможно, он рассчитан на использование совместно с аннотациями, тогда ведь получается проще? Или с каким-то конфигом, где описаны ограничения. Да, в официальной документации приводятся примеры использования yaml конфига, как альтернатива аннотациям, но проблема в том, что я использую силекс, а не симфони и тут все не так, как в симфони. В сети не так уж много инфы по использованию некоторых модулей симфони с силексом. И хотя я не искал варианты использования yaml конфигов с силексом, в надежде на кастомные констранты, я пока не могу представить как это все будет выглядеть. Чем больше модулей симфони прикручивается к силексу, тем больше мне кажется, что он изначально не предназначался для этого.
>>Что касается регистрации - регистрация это создание пользователя, и наверно, там в качестве модели для формы выгоднее использовать сразу модель пользователя, нет? Я об этом и хотел написать с самого начала. Если мы используем модель пользователя для регистрации, то зачем создавать отдельную модель для логина, ведь можно использовать ту же модель пользователя. И тут можно использовать уже используемый доктриной entity класс, ведь нам всеравно нужно при логине получить данные из бд о пользователе, которого логиним.
>>То есть как я понял, провайдер используется как этакий "мост" для простого подключения сторонней библиотеки в Silex. Да, это так. Я много гуглил этот вопрос и нагуглил то, что если я собираюсь использовать констранты с кастомным валидатором, ведь мне нужно впихнуть в валидатор entity manager, то мне придется зарегистрировать эти валидаторы как отдельный сервис.
>>Я все же думаю, что это уже не задача формы - проверять логин. Но это же не форма. Это валидатор, в который я передаю форму с констрантой. Ну и если это все-таки форма, то я тогда ничего не понимаю. Этот класс создан специально для того, чтобы проверить есть ли такая связка логин+пароль в базе, и если этот класс не может этого сделать, то зачем он тогда нужен?
>>Еще у тебя я вижу в коде стремление писать все в контроллерах и не использовать сервисы. Ну например, регистрация/авторизация/получение текущего пользователя - для этого нет готовых методов. Нет сервиса для работы с комментариями. То есть ты вместо MVC пишешь толстые контроллеры. Что значит использовать сервисы? У тебя есть уроки использования или примеры таких сервисов?
>>919074 (OP) Привет аноны. Решил учить PHP, пока для себя, потом как получится. Несмотря на ококолоайтишную вышку, последний раз пытался погромировать в школе, на делфи. Ну да ладно, делаю сейчас по вот этой ссылке - http://archive-ipq-co.narod.ru/, и такое чувство возникает странное, я вроде не совсем идиот, но в этих задачках больше сижу и думаю как как это реализовать в коде, а как хотя бы понять что вообще требуется и как бы я делал это допустим вручную. (например считал каждый месяц на калькуляторе в задачке про школьника). Я совсем конченый или еще нет? Что это? Проблема с воображением или что? С этим можно жить? вот и задачка, мож кто посмотрит http://ideone.com/TKF4VQ
за день пролистал весь сайт ОПа на народе, вроде все более-менее разжевали и в рот положили, хотя некоторые задачки можно укоротить, если не читать начало решения. Постарался еще сделать красивый вариант калькулятора. :З http://ideone.com/q71hdO интересная штука, оказалось, планирую прикрутить еще скобочки туда, а потом последовательность действий человеческую
Я зеленый нуб, пошел качать php для Windows для обучения и увидел вот такое:
Thread Safe и Non Thread Safe. Начал искать информацию о разницы, на русском ничего не нашел. На англ не понял, ибо база знань информатики желает быть лучше.
Может кто знает нормальный проект(репозиторий) на ларавел для ознакомления с фреймворком, чтобы поковырять и приступить к реальной работе на бирже? Буду благодарен
>>925115 1. Там старый софт. 2. Помогать тебе если что то не будет там работать не будут. Т.к. Что там авторы намутили всем лень разбираться.
Если ты почитаешь ссыли из шапки, то там есть гайд от ОПа по установке PHP и прочее в Windows. Вообще, там есть все что нужно человеку для начала изучения. + Мы всегда поможем. Только учти, что тред медленный.
Для использования вместе с Апачом под виндой нужен ThreadSafe. Для использования без Апача или под линуксом можно и Non-Thread-Safe. Это поддержка многопоточности.
>>925125 Да, я видел шапку и внимательно ее прочитал, но все равно туго доходило. В общем, я пока прохожу: 1. на этом сайте php https://www.codecademy.com/ - немного сложновато в понимании информации и поэтому сижу со словарем. Но, главный минус - это примитивные задания. 2. ну и скачал книжку PHPTheRightWay. 3. сервер скачал отсюда http://www.wampserver.com (вроде уже не старые технологии), или это плохая идея и мне таки лучше всего уже самому учиться ставить апачи, пхп, mysql?
есть ли хороший и приятный гайд, где тебе разжевывают создание вебсервиса на похапе с нуля? типа рейлс фор зомбиз. Там тебе и про руби, и про рейлс, и про архитектуру, а пока рассказывают, ты делаешь свой твиттер. Большую часть книг и сайтов что я нашел можно выкинуть, т.к они втирают про сам язык и программирование, а я хочу про его применение в вебе - написать сайт с формами етц, опыт набивать короче. Заранее спасибо большое. :3
Извините, что беспокою. Помогите, пожалуйста, понять этот эльфийский: preg_match('/^['.$Line['text'][0].']{3,}[ ]([\w-]+)?[ ]$/', $Line['text'], $matches)
Я вот почитал статью: http://archive-ipq-co.narod.ru/l1/regexp.html и расшифровал фразу как-то так: Ищется точное совпадение шаблона в строке $Line['text'] (символы ^ в начале и $ в конце строки). В начале ищется повторение три и больше раз строки, которая находится в $Line['text'][0]. Потом идет много пробелов. Потом идет строка из одного или нескольких буквенных символов, которые могут встретиться или не встретиться. Потом идет один или несколько пробелов
Сапер MVC. Оп, я правильно работаю со словарями? http://ideone.com/petHF7 Решил отказаться от объектов Cell. Теперь везде появился вложенный цикл, там где раньше был простой перебор массива с объектами, что меня смущает.
И еще, стоит ли писать вот такую обертку вокруг метода реализации чтобы не кидать каждый раз свойства объекта ему в аргументы http://ideone.com/Bom4oP ?
>>925165 Ну а применить знания из "рейлс фор зомбиз" в PHP нельзя? Там наверное рассказывают про HTTP, ну и в рельсах есть MVC, ActiveRecord, ServiceObjects. Всё это используется в PHP, просто открываешь доку по заинтересовавшему тебя фреймворку и пишешь приложение.
>>925387 Ты описал более-менее верно, только строка "пробел-звёздочка" значит не "один или несколько пробелов", а "произвольное количество пробелов, в том числе и отсутствие". Ну и сама регулярка написана странно, квадратные скобки означают "один из символов", потому в части "[ ]✱" эти скобки бессмысленны.
>>925132 Тебе уже посоветовали ставить руками. Не хочешь - жди когда проблема дырявых абстракций доберётся и до тебя. Тогда ты опять полезешь в тред вместо того, чтобы легко и просто решить проблему самому.
это сайт, который включает похапе, например. А я в похапе умею только задачки решать, а не в похапе морской бой могу написать на крестах, лол.
>>925572 > Ну а применить знания из "рейлс фор зомбиз" в PHP нельзя? Там наверное рассказывают про HTTP, ну и в рельсах есть MVC, ActiveRecord, ServiceObjects. Всё это используется в PHP, просто открываешь доку по заинтересовавшему тебя фреймворку и пишешь приложение.
проблема в том, что я их не проходил, просто знаю, что там вот так, а не иначе. В серверном программировании я ноль полный.
> Тут есть 2 варианта, как это хранить: в виде 2-мерного массива, например this.openCells[y][x] = true помечает клеточку открытой ...
...ты имел ввиду действительно двумерный массив ([ [true, false], [false, false], [false, true], [true, false]) или словарь ( {1: {1: true, 2:false}, 2: {1: false, 2: false}, 3: {1:false, 2: true})? Мне кажется, ты имел ввиду первое, а я делаю через второе и в некоторых местах трудности (например мучаюсь как создать мины при такой структуре чтобы не было вечного рандома. Когда у меня был массив объектов Cell я просто делал на него shuffle и превращал в мины n-ое количество равное числу мин).
не хочу смущать тут всех своим вариантом, потому что я либо подскажу новичкам развернутое и полное решение, либо задурю им мозги. Напиши мне в телеграмм? Да и учить вместе веселее будет.@Kyooni
Блин ребят , может кто ссылку кинуть на урок или гайд ? Я просто вообще не вдупляю как пэхапэ в общем связывается в коде с html и как его туда вставлять
>>919074 (OP) Посоветуйте пожалуйста книжку почитать, желательно современную, но на русише. В программировании не новичок, с php уже дело имел, сейчас нужно все это вспомнить.
>https://github.com/someApprentice/Students/blob/master/app/init.php#L10 >> use App\Model\Helper\LoginHelper; >> use App\Model\Helper\LoginHelper as Authorizer; >Тут зачем-то класс 2 раза импортирован Хотел задать пространство имен для ЛогинХелпера. Ведь это же и Авторайзер в то же время.
>https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php >Вот тут конечно методы вроде getPageQuery или getSortQuery явно не очень правильно смотрятся. Ведь это базовый контроллер, и в него надо класть только то, что может пригодиться в любом контроллере, а это явно функции для вывода таблицы постранично. Возможно, стоило их поместить в унаследованный класс BaseTableController, возможно - вынести в Helper. В принципе, это исправлять не надо, но в дальнейшем надо задумываться, куда лучше поместить метод. А я спрашивал насчет этих методов. Конечно, сейчас мне очевидно, что по-хорошему нужно сделать какой-нибудь дочерний контроллер для этих методов. Переносить их в Хелпер - плохая идея потому, что хелпер это модель, и заниматься GET-запросами должны контроллеры.
>Действия Search и просто вывод таблицы стоило бы объединить. Это ведь почти одно и то же, и там и там есть и сортировка, и пагинация, проще использовать один код и в нужных местах просто поставить пару if. Не совсем понимаю как это сделать - согласен, и там и там есть общий код, но он минимален, и ведет себя как свойственно контроллеру: 1. получаем запросы\конфигурацию. 2. создаем паджер, обращаемся к БД. 3. выводим шаблон
Общие в этом только получение конфигураций и создание паджера. Конечно, я мог бы объеденить ещё объеденить метод обращения к БД, отправляя пустой запрос в метод поиска чтобы получить все записи, но помимого этого для шаблона нужен и паджер и записи, к тому же ему могут понадобиться и запросы. Получается замкнутый круг. Или стоит как-то исхитриться? Ради чего?
>https://github.com/someApprentice/Students/blob/master/app/Controller/SearchAction.php#L19 >> if ($_GET) { >Я бы не советовал так проверять, так как в теории в GET могут быть какие-то неотносящиеся к поиску параметры (их могут добавить позже). Лучше проверять, например, что $_GET['query'] не пуст. А если пользователю захочется найти всех пользователей, т.е. сделать пустой запрос? Или, например, я хочу объеденить способ получения всех записей и поиска, передавая в метод тот же пустой запрос? Или, например, я хочу объеденить методы получения всех записей и поиска, опять же отправляя пустой запрос? Обязательно ли вообще делать проверку на гет-запрос?
>> $this->render('templates/search.phtml', compact('query', 'pager')); >> } else { >> $this->render('templates/search.phtml'); >Вот это тоже странно. Один и тот же шаблон может вызываться как с переменными, так и без. Как писать надежный код, если ты даже не знаешь, передана такая переменная или нет? Да и неудобно, перед любым использованием переменной надо писать if (isset()). Не стоит так делать, тут стоит оставить единственный вызов render, в который передаются все нужные переменные. А как выводить один и тот же шаблон если к странице могут обратиться и без запроса? Этих переменных просто может не быть, потому что в них нету пока надобности.
>Теперь посмотрим на использование класса Pager. Это класс, в котором много неудачных решений: > >Во-вторых, почему-то для передачи аргументов в конструктор используется массив. Причем вместе идут как параметры, которые не зависят от номера страницы (query, sort), так и номер текущей страницы. Тоже нелогично, мне кажется, что номер страницы должен идти отдельно. >Опять же, если мы хотим использовать класс, то неочевидно, что за массив надо ему передать, и что в нем должно быть. Это не просто массив а массив запросов - $queries. По моему, по названии перемной должно быть понятно что это запросы. Я использовал такой подход в попытке сразу передать этот массив в метод http_build_query($queries) на практике ничего не получилось и, к тому же, не всегда известно какие запросы понадобиться передать ещё для формирования ссылок.
>>916132 >https://github.com/someApprentice/Students/blob/master/templates/index.phtml#L10 >> <a href="logout.php?token=<?= $token ?>&go=/public/index.php">logout?</a> >LogOut лучше бы делать отправкой POST-запроса (например, пустой формы с одной кнопкой). Это ведь изменяет состояние залогиненности, а GET запросы обычно не меняют состояние сервера. А я спрашивал почему в популярных соц.сетях разлогинивание сделано через форму.
Нужно делать сущность LogoutForm со всеми вытекающими для этого?
Есть какой-нибудь css хинт чтобы форма с кнопкой выглядела как ссылка или как любой другой элемент?
>Это ведь изменяет состояние залогиненности, а GET запросы обычно не меняют состояние сервера. А можно по подробней на этот моменте? Чем POST-запросы лучше GET-запросов? Ведь по сути они оба просто массивы. И как разлогинивание меняет сосотяние сервера? Мы же не используем локальные кукисы и не добавляем ничего нового например в БД.
>use Symfony\Component\HttpFoundation\{ParameterBag, Cookie, ResponseHeaderBag}; Что означает тут синтаксис в литералах? Это перечисление разных классов в одной и той же директории?
>public function registerStudent(Student $student): Student И тут, что означает : Student в объявлении функции?
Мне нравиться такой код. Я тоже научусь пользоваться фреймворками.
>К нему даже написан тест, который проверяет например, что если вызват метод залогинивания, получить куки и скормить их этому классу, то мы получим нужного пользователя: У меня тоже можно написать такой тест, у меня есть функция которая возвращает пользователя по кукисам: https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L16
>Далее, тут https://github.com/someApprentice/Students/blob/master/app/Controller/RegisterAction.php#L58 мы не завершаем контроллер после редиректа. Про это я тоже спрашивал. Мне сразу показалось не естественно делать ридерект по серди класса, к тому же, как вы тогда ответили, нет смысла что-то делать после ридеректа. Нужно выполнить exit()\die() после него? Не совсем понимаю как правильно завершить работу контроллера.
>https://github.com/someApprentice/Students/blob/master/app/Model/Validators/StudentValidations.php >Константы вроде const GENDER_MALE = "Man"; логичнее поместить в студента. Это ведь его свойства, а не свойства валидатора. В валидатор можно поместить константы вроде VALIDATE_MIN_LENGTH, относящиеся к валидации. Представь, что нам не нужна валидация и мы удалим этот класс. И вместе с ним удалятся константы, обозначающие пол, хотя они-то нам еще нужны. А класс валидации не присваивает эти значения. Присваивает форма. Класс валидации только проверяет что значения правильные, и это его задача знать внутреннее устройство или механику проверки.
>Хотя, конечно, не очень понятно, как тогда там вставить код, меняющий правила проверки пароля: Мне вообще кажется, что смена пароля должна осуществляться отдельно.
>Ну и дальше стоит начинать изучать фреймворки, хотя бы микрофреймворки для начала, так как тут мы писали все с нуля, и на практике конечно эффективнее учиться использовать готовый код. Также потом стоит глянуть шаблонизатор twig и, может быть, библиотеку-data mapper для работы с БД под названием Doctrine. Не терпиться уже начать!
>Doctrine Даже после прочтения сложных определений в гугле не до конца понимают что это такое. Оно заменяет Mysql или любую другу БД?
....
Это нормально отвлекаться на постороние вещи во время изучения? Хоть я и настроен на продуктивную работу, всё равно, сложно сконцентрироваться на каком-то сложном вопросе. Я подумал, что мозг может работать в пассивном режиме, например, как ты когда что-то пытаешься вспомнить, и это потом сомо, через какое-то время, вспыхивает у тебя в голове. Ведь, в конце концов я самостоятельно решаю этот вопрос. С этим всё нормально? Я хорошо справляюсь?
Аноны, помогите правильно вкатится в PHP и стать junior. 21 с лишним хромолет. Есть высокий интерес к этому, но даже школьного курса информатики не помню, могу только шиндовс переустановить и по интернету полазить. С чего начать и через какой срок уже можно начать парится макакой. Мамка гонит, тем не менее время есть и желание тоже. Сильно не обоссывайте. В шапке хорошая инфа, но мне хочется, чтобы аноны поделились со своим опытом, с чего начинать
>>926220 >>use Symfony\Component\HttpFoundation\{ParameterBag, Cookie, ResponseHeaderBag}; > Что означает тут синтаксис в литералах? Это перечисление разных классов в одной и той же директории? В одном и том же пространстве имён. Так чуть точнее, потому что в PHP классы с разными пространствами имён могут находиться не то, что в одной директории, но и в одном файле: https://secure.php.net/manual/en/language.namespaces.php#118554
>>public function registerStudent(Student $student): Student > И тут, что означает : Student в объявлении функции? Тайп-хинт для возвращаемого значения метода. Обо всём этом написано тут: https://secure.php.net/manual/en/migration70.new-features.php
пытаюсь начать программировать на похапе так, как это задумывалось, а не только решать задачки. Научился выводить скрипт на страницу и отправлять запросы в бд(MySQL) + немного работы через PhpMyAdmin. Стоит ли мне сразу вскочить на фреймворк и набегать на создание сайтов, обмазываясь гайдами, т.е поступать в стиле руби он рейлс или надо сначала осознать как это все делать на чистом пхп, итд? посмотрел тут решение задачки про студентов, охуел от количества файлов. Без фреймворков можно с ума сойти же.
>>926597 Когда перейдешь к фреймворкам после задач, то понимаешь, что все твои решения задач это корявые велосипеды и в реальной разработке не нужны. Но они учат понимать язык и его возможности.
>>926604 Ради фана или развития может быть, а по факту обычному разработчику этого знать не надо. Тебе совершенно не надо знать как работает мешалка массива, когда тебе его тупо надо перемешать. Или тебе должно быть похер как отправляются данные в БД, твоя задача лишь знать куда и что отправляешь, а как уже оно там будет работать тебе должно быть чхать, если оно правильно работает.
но ведь создавая с десяток MVC компонентов самостоятельно я убью неделю на то, что требует часа с фреймворком. Плюс, я могу просто посмотреть что создает именяет то или иное мое действие, и точно так же разобраться. Ну и я не имею ввиду, что я просто научился писать if else и сразу ВБОЙ ЕБАНА. Я почитаю самые основы этой ебони, а дальше фреймворки.
>>926603 но зачем язык и возможности, если я буду знать возможности фреймворка? в смысле, если я знаю максимум того, что выжму из фреймворка, мне не нужно знать то, что я могу выжать из пхп вне фреймворка, потому что это будет какой нибудь лютый велосипед для нестандартного случая.
мрт - тот же фреймворк, который показывает что у тебя в голове, например. Врачу не нужно знать молекулярной биологии и прочих ужасов, чтоб посмотреть на снимок и сказать, что у тебя мозг рака. батя врач, ты сказал чистую истину касательно 99% врачей
В общем, вы меня вдохновили на почитать основы, как минимум. Подскажите еще, пожалуйста, какой фреймворк актуален в сфере зарабатывания денег при выполнении работы рабодниками на работе? я так понимаю, что йии2 и симфони2 сейчас топовые, но который из них?
то, что на MVC это логически проще, что ли. Ну или это потому что я уже почитал про мвц, а про то, как это сделать на чистом пхп я не могу сообразить, потому что в сети мало толковой информации про такое. Ну и потому что это будет некрасивым, медленным велосипедом. Так то, я могу тебе и на реакте сейчас написать сайт со всем этим и уместить в одном index.js, но это будте жутко уродливо.
Вопросы все еще по MVC саперу. А вот в какой-то момент я буду тестировать несколько domView, а там на html странице будут повторяющиеся id. От id в шаблонах наверное вообще отказаться тогда и заменить на классы?
>>926669 >про то, как это сделать на чистом пхп я не могу сообразить 1) У тебя не должно быть глобальных переменных; 2) Только функции, принимающие данные на вход и бросающие в ответ изменённые данные; 3) Функции эти надо собрать в пространства имён, в виде дерева, а данные — в классы; 4) На вход им передавать другие функции, создавая таким образом композицiю их; 5) Логи и сообщения не должны оставаться всю ночь до утра; 6) Интерфейсы программ твоих приноси в дом господа, бога твоего; 7) Не еби TCP-сокет в контексте окружения его.
>>926669 хоспаде, туториал погугли (мвц на пхп), просто берешь и повторяешь. вообще умение хуярить мвц на чистом пхп - оно и не нужно по сути. Возьми фреймворк. А можешь даже попробовать взять цмску и поправить ее мвц код под свои нужды, у тебя сразу будет рабочий вариант с красивой админкой - такие задачи чаще всего и встречаются в рабоче пхпшника. Но перед этим лучше ООП поучить, про паттерны занстра, pdo почитать, а то с ходу в коде цмски не разберешься.
>>926730 Что за хуйню ты ему втираешь? Что значит "чистое пхп"? Как правило имеется ввиду отсутствие фремфорка. ООП вообще часть языка блять. А вот мвц это всего лишь патер, пусть пользует, хорошо и полезно.
>>926651 В фреймворках бывают недостатки и неудачные решения. Например, в команде Yii есть какой то любитель пользовать указатели, что в пхп имхо не нужно вообще, и из за этого была большая ошибка в их RBAC модуле.
Возможности фремворка это расширение возможностей ПХП и не зная толком ПХП можно просто не понять или упустить многие возможности фреймворка. >велосипед для нестандартного случая Не для всех общих случае есть готовые хорошие решения, что говорить про нестандартные. Вот хорошая статья на тему http://www.habrahabr.net/thread/1716
>мрт - тот же фреймворк Плохой пример. Мрт и врач это, как программист и монитор.
>Подскажите еще, пожалуйста, какой фреймворк актуален в сфере Yii проще и популярнее в СНГ, Symfony сложнее, но вроде как более грамотно сделан. Там еще кажется Symfony3 вышел, но я его не смотрел.
Аноны, как сделать так, чтобы после обновления страницы сбрасывались значения передаваемые через гет? А то вот так вот выходит всё. И почему echo $_SERVER['HTTP_USER_AGENT']; Показывает почему-то не мой браузер, а несколько штук?
>>926842 > and the user agent string was a complete mess, and near useless, and everyone pretended to be everyone else, and confusion abounded. Именно так и вижу этот список. Мельком прочитал эту новеллу, но все-таки как быстро узнавать какой браузер?
Так как js тред умер напишу тут. Есть у меня в общем фронтэнд сторона, где есть форма и в ней генерятся разные поля, и это все потом отправляется php скрипту для обработки. Есть там поле с загрузкой нескольких изображений, надо что бы после загрузки юзер мог видеть то, что загрузил и менять порядок картинок, есть ли какая либа готовая под это дело? И в каком формате отправлять лучше на серв, если у меня там и картинки и текстовые поля в одной форме?
Поигрался я с ideone, установил phpstorm, в общем когда он открывает браузер там error502, как в таком случае поступают настоящие гуру пхп? Нужно установить веб сервер? А какой? Денвер?
>>927169 > Это нормально что он по 3 раза подряд одно и то же "случайно" выбирает? Или мой косяк? разве array rand не возвращает случайное значение? Попробуй выводить $рандом, а не массив[рандом]
public function __construct($first_name, $last_name) { $this->first_name = $first_name; $this->last_name = $last_name; } Аноны, почему они не пишут сразу $this->$first_name? Зачем писать first_name? какого значение этой хуйни? Она ведь нигде не употребляется больше, это не переменная, ничто
>>927223 И далее public function say_name() { echo "My name is " . $this->first_name . " " . $this->last_name . ".\n"; } Почему нельзя написать вместо $this->first_name просто $first_name?
>>927240 Усложнено настолько, что это просто охерено упрощает остальные 100500 ситуаций. Давай представим, что у тебя класс 40 свойств. И наизусть ты их не помнишь. Предположим, что ты добавляешь в класс новый метод, в котором ты создаешь новые переменные и работаешь с ними. Создал метод, все вроде работает, нормально вызывается, но иногда почему этот класс начинает работать непонятно как и в нем совершенно другие значения свойств, а не те, которые ты ожидаешь. Лезешь в код и видишь, что переменная $item, которую ты создал в методе оказывается перезаписала свойство $item у этого же класса, а ты не знал, что в классе такое свойство есть. И таким образом, взглянув на код ты не можешь сразу визуально определить в каком случае работа происходит с локальной переменной метода, а когда затрагивается свойство класса.
Ты понимаешь, что обозначает $this->first_name? Это не то же самое, что переменная $first_name, это другая вещь. Это поле объекта. Соответственно, слева от стрелки указывается объект, а справа - название поля в нем.
Если что, в учебнике в ОП посте есть глава про ООП. Там это вроде объясняется.
>>927219 >Не было ничего нихрена о ней сказано Там же написано: "необходимо изучить куки, переменную $_COOKIE и функцию setcookie()". При запуске скрипта проверяешь, прислал ли тебя пользователь куку с именем, скажем, "hui". Если прислал, то выводишь сообщение с текущим значением, увеличиваешь ее значение на единицу и ставишь пользователю, если не прислал - то ставишь ему эту куку со значением 1. Все, блядь, больше вообще ничего не надо.
>>926256 > информатика > интерес > PHP Ты СОВЕРШЕННО не понимаешь в чем суть PHP. PHP это не SICP "о, привет чуваки, зацените решение задачки на скиме, писал два месяца". PHP это не псевдоинтеллектуальные обсуждаения алгоритмов и структур данных. PHP это не сложные вычисления, нейроночки или динамические интерфейсы. PHP это язык, где люди могут побыть говнокодерами — ужасными, тупыми, безразличными ко всему рабами галер, которыми они на самом деле и являются. json_decode возвращает null, а мы смеемся. Кусок стэйта рендерится на сервере в глобальной области видимости, а мы смеемся и обмазываемся миддлварями на ноде. Три сеньор разработчика спрыгнули с крыши, пытаясь отрефакторить движок корпоративной CMS на 4-й пыхе, а мы смеемся и просим еще. Лапшекод, регулярочки, критические уязвимости — мы смеемся. Мы бездушно подпишемся на любой проект, где нам заплатят дошираком, наши предпочтения не основаны на логике программирования, бесцельное внедрение сторонник библиотек — наша стихия, мы — истинное лицо вебдевелопмента.
>>927324 Не буду кидать, ибо оффтоп. А вообще - ОП-няша. Добра ему, всех благ и в нелегком деле обучения ньюфагов. Именно благодаря ему сей тред не тонет. Домо, PHP-ОП-сан!
начал делать 1 упражнение из основ ООП http://ideone.com/xHIidQ не могу понять в чем ошибка, нужно передавать во 2 foreach массив из ответов на вопросы, для которого писать отдельную функцию?
Пацаны у меня трабл. Нужно сделать на старом сервисе одном подобие апи, что бы отдавать расписание.
Написано всё на modx, в котором нет человекочасов разбираться. Прикручивать отдельно фреймворк для апи тоже не буду отдельным костылем.
Поэтому буду делать просто php файлом в корне проекта.
Суть проблемы в следующем:
Например есть много эвентов, и сторонний сервис, который будет моё "апи" опрашивать, требует под каждый эвент отдельный урл.
Под каждый эвент я не хочу хуярить отдельный файл вот так: site.ru/event1_scheduale.php site.ru/event2_scheduale.php site.ru/event3_scheduale.php site.ru/event3_scheduale.php
На фреймворке с нормальным роутингом я бы наебенил очень просто через 1 метод в 1 классе всё и урлы бы были вида: site.ru/api/sceduale/event1 site.ru/api/sceduale/event2 site.ru/api/sceduale/event3
Но как так изебнуться что бы сделать в 1 пхп файле так? Что бы не копипастить всё это дело?
Ебаться с htaccess?
Я бы очень хотел сделать 1 файл, что бы пусть даже был некрасивый урл типа такого:
Я сейчас конечно попробую протолкнуть им id квеста не в самом урле, а в гет части, но что-то мне кажется это мимо. Особенно в той части в которой они будут делать бронь.
>>927404 >AcceptPathInfo Это ты про то, что бы никто не мог лазить по папкам и запускать скрипты которые не в корне лежат или другие файлы скачивать/смотреть вообще? Спасибо за совет.
Ребят, пытался пару раз вкатиться в пхп, пытался начать с заданий с сайта, но вообще не вдупляю как делать задание, хотя до этого прочитал фак, это я про http://archive-ipq-co.narod.ru/, может какую то литературу прочитать до того как начать знакомство с переменными и тд
В свое время(годик назад) когда вообще ничего не понимал да и сейчас ничего не понимаю, дало неплохой старт, теперь могу спокойной пилить какие нибудь проектики для себя
>>927491 А я не хвалю. Там первые несколько глав конечно хорошо подают основы ООП, а вот дальше начинается вода, так что я даже дропнул не дойдя до собственно паттернов, ну не смог я читать то, что тупо срет тебе в мозг без конкретики.
Он хоть и примитивный, но выдает довольно случайные значения. И как видно из статьи, применяется много где. Главные преимущества- очень простой и очень быстрый.
Он выдает более "случайные" числа. Но как и предыдущий метод, этот метод генерирует не по-настоящему случайные числа, а лишь математически вычисляемую последовательность.
Для критографии нужно использовать специальные особо надежные функции, вроде
Они используют функции ОС, на Линукс например это /dev/urandom, который собирает случайные значения из окружающей среды (время нажатия кнопок, прихода сетевых пакетов и тд). Надо понимать, что тут скорость генерации ограничена.
И если уж на то пошло, почему бы тебе не написать самому простой линейный ГСЧ и посмотреть на числа, которые он генерирует, чтобы проверить, насколько они получаются случайными? В статье википедии выше есть формулы и константы, если что. Знаний PHP особых не нужно, достаточно знать циклы.
Аноны, такая хуйня. Есть у меня такое СПА, которое формы слать должно на сервер. Но роутинг осуществляется через якоря в урле. Все формы аяксом отправляются. Серв на пхп. Как он воспримет гет запрос с якорем внутри. Или все постом делать, что бы урл не трогать?
Значит с формами и валидатором я разобрался. Хотел использовать entity класс для создания формы регистрации, но отказался и вот почему: 1 - я не храню пароль в базе, а в форме он должен быть 2 - для проверки полей на UniqueValue() нужно установить doctrine bridge и doctrine bundle и как-то это прикручивать к силексу и здесь смысл использования entity класса исчезает. Поэтому проще сделать отдельную форму и написать для нее свой unique constraint.
Все еще не ясно, что ты имеешь ввиду под использованием сервисов. В 83 треде ты писал, что: > $app['validator'] = function() use($app){return new App\Helper\Validator($app);}; >Это по моему нарушение принципа DI, получается не DI, а Service Locator Нужно регистрировать сервис провайдеры или что?
>>927305 >Три сеньор разработчика спрыгнули с крыши, пытаясь отрефакторить движок корпоративной CMS на 4-й пыхе, а мы смеемся и просим еще Проиграл бы если бы сам с таким не сталкивался.
Поясните за ORM. Нахуй он нужен? Я работал с Yii-шным ActiveRecord и Doctrine 2, а также с чистым PDO в других проектах. Для простых крудов да, ООП, вся фигня, код с объектвми выглядит сладко. Но описывать более сложные SQL-запросы (с подзапросами, джойнами..) через квери-билдеры в ORM - Я ЕБАЛ!!1 Это ж ебаный бойлерплейт! ->select('kokoko') ->from('yoba') ->where('1=1') Куча ебаных геттеров-сеттеров! Структура базы, связи между таблицами описывается внутри doc-комментов! Это я про доктрину. В Yii вообще пиздец без identity map, апдейты по всем полям, даже если ты изменил одно поле. Ну что за пиздец?
>>927837 Что тебе мешает использовать DQL той-же доктрины? Как по мне, доктрина очень годная ORM. Анотации, консоль, DQL, query builder, интеграция в симфони и дохуя чего еще. Но можно просто обмазываться PDO. Никто не запрещает.
анон, пробегись по моему коду, пожалуйста. Я почти доделал по одному гайду недосайт и ЖЕЛАЮВСЕМТЕЛОМ советов по улучшению читабельности/качества кода ну и, если есть, ошибки какие. С учетом того, что я js-джун и с бакэндом столкнулся три дня назад.4 дня до этого еще подучил синтаксис похапе
>>927998 Схуяли там инъекция? Там intval, защищает от хуйни.
Схуяли sql в контроллере это не mvc? Обмажутся своими active record и ябут друг друга в жеппу! В идеале выделить работу с sql в прослойку - маппер, чтобы она не была в model. Но если нет, то где ей больше место - в model или controller?
Господа, как убрать пробелы из значений элементов двумерного массива? Вроде как сделал через foreach и сомневаюсь, что так "правильно" - для одномерных массивов можно сделать array_map('trim', $array)
Я ознакомился со статьёй о безопасной авторизации на хабре: https://habrahabr.ru/post/13726/ -Безопасный метод авторизации на PHP И имею вопрос. Вот пользователь. Он ввёл свои данные, скрипт поискал юзера, нашёл, сравнил пароли, при совпадении создал ему новый хеш, записал куки и перенаправил работу скрипту проверки. Скрипт проверки сравнивает то, что записано в куках с тем, что записано в базе (как я понял) и в случае совпадения, возвращает "ок".
А теперь дурацкий вопрос. Как этим пользоваться? Сами скрипты я повторил у себя на хостинге, они работают. Допустим, у меня есть ещё пара php файликов, которые хочу доверить только авторизованным пользователям. Как это сделать?
И сразу ещё один вопрос. Там используется конструкция header("Location: check.php"); exit(); Я погуглил на тему header(), и везде пишут, что так отправляются заголовки html страницы. А в коде это используется для передачи управления другому скрипту. Как так-то?
Помните например такой проект как спрашивай.ру, который существует и сейчас. Проект с довольно большой аудиторией, на чём надо писать подобные сайты чтобы они нормально работали? Обыкновенного ПХП ООП и обычной базы данных хватит? Или нужно что-то сложнее?
>>928097 Там смысл в том, что на страницах, которые ты хочешь отдавать только авторизованным пользователям, проверяются куки. Соответственно на любой такой странице тебе надо выполнять код скрипта проверки, если куки пользователя проходят проверку - отдавать содержимое, если нет - посылать нахуй или на страницу регистрации. >>928103 Это не передача управления, а редирект на любую страницу, все правильно пишут. В статье просто демонстрируется проверка сразу после регистрации.
>>928139 То есть, весь код из check.php должен выполняться перед любым кодом со страницы, (допустим, index.php), а вместо print "Привет, ".$userdata['user_login'].". Всё работает!"; писать тело страницы со всеми хидерами и футерами?
А допустимо ли делать скачивание файла в задачке про файлообменник(и вообще) вот так вот: <a href="/{{file.link}}" download>Скачать бесплатно и без смс</a> Или надо как-то сложнее изворачиваться?
>>928325 Два массива со значениями от 1 до 10. Если "введённое в поле" равно $arr1[$i] + $arr2[$o], то echo ссылка. При обновлении страницы $i++, а $o+2 либо - array_rand. Ну и вывод значений на странице соответствующий.
>>928331 >Два массива со значениями от 1 до 10. >Если "введённое в поле" равно $arr1[$i] + $arr2[$o], то echo ссылка. >При обновлении страницы $i++, а $o+2 либо - array_rand. >Ну и вывод значений на странице соответствующий. Сложна. Это что, делать отдельный шаблон и перенаправлять на него для этой хуиты? >>928336 >>928338 Это сложно? Я вот погуглил, вроде гугл капчу нельзя прикрутить на локалхост, не?
>>928343 > Это что, делать отдельный шаблон и перенаправлять на него для этой хуиты? Вроде того. >Это сложно? Я вот погуглил, вроде гугл капчу нельзя прикрутить на локалхост, не? Это сложнее. Прикрутить можно, если сервер на твоем локалхосте имеет доступ в Интернет.
>>928356 >Вроде того. Да не, это какой-то изъеб. Вот был же ex.ua, там можно было качать без капчи и регистраций, как они это делали не боясь что им завалят сервера? >Это сложнее. Прикрутить можно, если сервер на твоем локалхосте имеет доступ в Интернет. Ладно, только гугл подсказывает только сраные плагины на вордпресс.
>>928358 Ну я хз, вот тут как-то сделано на жабаскрипте: http://biotualet1.ru/otzyvy.html То, что я имел в виду. Но там после ввода ответа и нажатия срабатывает POST, а ты бы просто ссылку выдавал.
>>928358 Тебе не нужно геморроиться. Только желающие повалить будут писать скрипты под тебя. Ты можешь действия там менять рандомно (минус, плюс, деление, умножение) и т.п.
>>928361 >Но там после ввода ответа и нажатия срабатывает POST, а ты бы просто ссылку выдавал. В то то вот и дело, что я не знаю как это сделать. >>928362 Ну как такое сделать я понимаю, но хотелось бы именно не "лишь бы работало", а правильно сделать.
>>928358 >ex.ua Там, где нет капчи, пользуются другими методами - типа блокировки известных прокси и ограничениями на количество запросов/одновременных подключений для остальных. Но это, вроде, уже к настройкам сервера ближе, а не PHP.
>>928367 > POST > не знаю Прочитай первые главы учебника по пыхе "PHP 5 в подлиннике". Его принято поливать говном и считать за днище, однако это единственный учебник, где прежде, чем перейти к профессиональному программированию, освещается необходимый для этого дела минимум по запросам и формам.
>>928377 >Ну напиши простейший скрипт на JS, который AJAX запрос отправляет и получает ссылку на скачивание ответом. Я так и думал. Проблема в том, что я толком то JS не знаю, не то что бы аякс. Ну да ладно, будет как раз повод его освоить.
Посоны, есть куча PHP классов от вебсервиса, сгенерированных из XSD. Там собственно только поля, сеттеры и геттеры. Данные получаются на вебсервис и разгоняются по этим классам автоматом. Вопрос - как загнать эти классы в БД автоматом? При том, что там поля не соответствуют полям в БД? Есть какие-то готовые решения? Или все вручную катать?
>>928462 Вручную не нравится - классов полно, методов на вебсервисе тоже. Что хотелось бы - какую-то маппилку, которая просто берет готовые классы, маппит по какому-нибудь правилу или списку на классы из БД и все сама пишет в БД.
>>928496 Измени условие на ошибочное и запусти. Это ведь Codeacademy? Днище, на самом деле, не всегда ясно, чего от тебя хотят, сам с этого охуевал. В данном случае, очевидно, хотят, чтобы ты сначала проверил верное утверждение ("3<7"), а потом изменил его на неверное ("3>7") и опять проверил.
Допустим пишу я сеттер для свойства класса и в нём делаю проверку. Например для $id я делаю проверку на то, что это число и оно больше либо равно нулю. Если всё хорошо, то присваиваю значение. Что лучше делать если условие не проходит? Выкинуть исключение и в нём написать в чём проблема или тупо вернуть false (или null) и ничего не делать?
>>928514 я ничего не делаю, так как у меня простые пути. Тупо если запросили несуществующее id с базы например, то и хуй с ним. Будет тупо редирект на уровне контроллера если модель ничего не вернула на 404 или вообще нахуй в личный кабинет, ибо нехуй лазить по чужим заявкам/страницам/платежам и пр.
>>928529 А записывать ты туда всякий мусор разрешаешь? Меня в данном случае сеттер волнует. Да конечно на сайте может быть валидация на стороне пользователя, но разве можно быть на 100% быть уверенным в том, что мы получили валидные данные от пользователя?
Прохожу от нехуй делать курсы битрикса (на самом деле, работодатель попросил). В принципе, там много неоднозначных ответов (в одном тесте например правильный ответ - может работать на любом вебсервере умеющем в похапе, в другом - бэкэнд это строго апач с похапе). Дурдом, короче. Зато теперь я трижды сертифицированный говноед. Четвертый курс (Huiload) сдавать буду на следующей неделе у них в офисе.
>>928531 Не разрешаю, тоже анально игнорирую если у меня попытались хуйню протолкнуть. А вообще я даже логирую пользовательские действия, и если кто-то попытался отключить фронт-энд проверки и споткнулся на бек-энд проверках, то так и заношу в базу, что вот дескать этот хуй пытался МАМ,ХАКЕРИТЬ)))
>>928514 Исключение конечно. Причем проверку не в сеттере лучше делать, а отдельный метод написать, который из сеттера вызывается. Вот метод этот уже true/false возвращает. А сам сеттер выглядит вроде этого: if ($this->parameterIsValid($parameter)) { $this->parameter = $parameter } throw new \UnexpectedValueException('Parameter is not valid');
Я тут немного костылей нагородил, теперь вот не знаю, правильно или нет.
В общем, есть на странице селект, содержимое которого берётся при генерации страницы из бд с помощью функции: <div id="div_change"> <?php list_selector($table, $column, 'list_id', 'list_name'); ?> </div> Содержимое селекта - список предметов. И этот список можно менять, добавляя или удаляя предметы. Сделал это через аякс: нажимаем кнопку, срабатывает js-крипт, запускает через ajax php-код, а тот прописывает добавление/удаление предмета в БД.
И тут мне восхотелось сделать так, чтобы список на странице тоже обновлялся без перезагрузки страницы. И сделал это так: как только у аякса срабатывает success, тут же запускает через ещё один аякс ещё один пхп-файл, который принимает через _POST данные для генерации list_selector и запускает его с этими данными. Функция возвращает собранный html-код в тот файл, который вызван через второй аякс, оттуда код возвращается в js-скрипт и селектор обновляется.
Кривость какая-то, но проще способа не нашёл. Это так и должно быть, или я уже шизею?
Привет котаны. Дело в том, что я уже достаточно долго пилю свой бложек на php, теоретически я хотел бы показать его своему потенциальному работодателю. Стоит ли мне это делать, либо у меня пиздец какое позорище получилось? Буду благодарен за любое мнение. https://github.com/honeydev/s-blog Пример для понажимать - http://honeytype_0ayl98.radius-host.net/
>>928730 Нет, не покрывал не умею в функциональное тестирование. >>928713 Просто у меня классы контроллеров не вынесены в отдельные файлы, но сами классы разделяются. Короче буду все переделывать, спасибо. Все же нужно было изучать паттерны сначала, а не писать лижбы написать.
>>928793 Вообще, да. Можно. Но тогда через аякс нужно будет передавать все данные и для апдейта таблицы и для апдейта селектора. Надо будет подумать на свежую голову завтра.
>>928914 >Дело в том что я прохожу по видеокурсам Какие-то хуевые видеокурсы. Чисто на первый взгляд >include_once 'c:\openserver что-то там дальше Во-первых, там и правда учат так пути прописывать? Во-вторых, инклюдить что-то в скрипте с объявлением класса это тихий ужас, это говнокодище за которое руки отрывать надо. Учи что такое неймспейсы и автозагрузка классов. В третьих, там какая-то дикая мешанина из статики и динамики. Короче исправь первые два пункта и потом попробуй написать тоже самое, только без статики.
>>928911 Алсо нихуя не понял зачем ты там еще и тру возвращаешь. Это же пхп, тебе не надо париться по поводу того что ты там возвращаешь в методе/функции.
>>928920 Ну теперь все встало на свои места. Хохол-быдлокодер хуже индуса. Мой тебе совет: Не надо проходить мутные курсы в стиле 'Магазин дилдаков за 24 наносекунды'. В ОП посте есть учебник. Лучше порешай задачи из него и попробуй сделать студентов.
>>928964 >>928999 Для начала стоит написать индексный файл и заинклюдить туда шаблон главной страницы, прикрутив к нему бутстрап. Потом можно уже добавлять функционал. Можете посмотреть гитхабы анонов уже сделавших студентов.
Поясните, почему хранить разметку в бд зашквар? Например, у сайта сложный дизайн, не хранить же каждый блок текста в отдельной таблице и не выводить его потом??
>>929059 Но тогда получается, что одна страница будет лежать в нескольких колонках базы данных. А это множение колонок в таблице. ведь под каждый кусок шаблона должен выводиться определенный кусок из одной статьи.
например я же не буду писать <ul><?php foreach($result as $item){ <li><?=$item?></li> <?php } ?> </ull> <?php foreach($result2 as $text) {?> <p class="hueta"><?=$text?></p> <?php }?> И подумайте сколько запросов к бд делать придется под такую жесть. И не рациональное использование таблиц получится (много таблиц с кусками одной страницы)
>>929070 я тебе про сложную верстку поясняю маня.>>929072 А не одностраничники на яндекс.народе Или мне весь текст прямо в шаблоне хранить ежели верстка сложная?
в оп посте нет ни одного гайда про веб-дев. Хохол-быдлокодер внятно объясняет азы, а в оп-посте просто блять задача в стиле "я научил тебя пользоваться палкой, иди строй ткацкий станок". Критикуешь этот курс - покажи хороший. другой анон
Анон, помоги, пожалуйста! Прохожу ООП по учебнику из ОП поста. Вроде не дурак, все разминочные задания сделал без особых проблем, а вот с последним (которое про компанию ВЕКТОР) впал в ступор. Расписал абстрактные классы компания, департамент и сотрудник. Че дальше то делать ? Нужно создавать класс для каждой профессии, или сделать профессию свойством сотрудника ? Почему потребление кофе - не является свойством сотрудника ? Является ли свойством количество производимых страниц ? Если нет - почему ? Где должны создаваться и добавляться в департамент сотрудники ? Это нужно делать в отдельном классе или прямо в классе департамент ?
Вопросов гораздо больше, но даже сформулировать их пока очень трудно. Помогите, прошу.
>>929078 >Почему потребление кофе - не является свойством сотрудника ? Потому что я блять хуй знает. Я ебал этой задачи рот. Вообще обосрался на этой задаче, хотя что-то до этого получалось. Слава богу кто-то подсказал, что так заморачиваться не надо - это нигде на хуй не нужно будет.
Это все потому, что ОП - няшка. Ты слишком буквально пытаешься следовать тексту, а текст, к сожалению (а может и нет?), далек от академичности и однозначной трактовки.
> Почему потребление кофе - не является свойством сотрудника ? Потому что потребление кофе вычисляется методом на основании профессии и ранга. То же самое с зарплатой и листами.
>>929076 Текст храни в базе, разметку страницы в шаблонах. Научись правильно оформлять запросы к БД. Сделал запрос данных из таблицы, перевел полученное в массив, вывел массив на странице. Все.
>>929078 Компания и департамент-то с чего абстрактные? Они обычные классы.
>Че дальше то делать ? Компанию заполняешь департаментами, департаменты сотрудниками. Пишешь методы подсчета для компании - они опрашивают департаменты. Потом для департаментов - они опрашивают сотрудников.
>Нужно создавать класс для каждой профессии, или сделать профессию свойством сотрудника ? Нужно, там базовые ставки разные. Причем все эти классы должны наследовать от общего, у тебя же есть общие признаки для всех сотрудников.
>Почему потребление кофе - не является свойством сотрудника ? Потому что оно из базового абстрактного класса считается. Свойство сотрудника - это его вид - руководитель, профессия, ранг.
>Является ли свойством количество производимых страниц ? Если нет - почему ? Оно тоже считается из класса, основываясь на виде сотрудника. Ты не задаешь каждому сотруднику напрямую его страницы.
>Где должны создаваться и добавляться в департамент сотрудники ? В контроллере. Для департамента пишешь сеттер сотрудников, контроллер добавляет их туда через сеттер. Можно без сеттера сразу при создании департамента через Dependency Injection, тогда тебе придется сначала создать сотрудников.
> Это нужно делать в отдельном классе или прямо в классе департамент ? Это делается извне, в контроллере. В департаменте никакие сотрудники не создаются, они сами туда приходят (в нашем случае контроллер их туда добавляет).
> Расписал абстрактные классы компания, департамент и сотрудник. А почему они абстрактные? Абстрактный класс - это класс, объект которого нельзя создать и который обычно предназначен как основа для наследования.
> Нужно создавать класс для каждой профессии, или сделать профессию свойством сотрудника ? Можно и так, и так. Обычно отдельные классы делают, если у разных профессий разное поведение, разные методы расчета чего-нибудь.
> Почему потребление кофе - не является свойством сотрудника ? Потому, что это производная величина, которая зависит от: профессии, ранга, статуса босса. Хранить надо исходные данные, а производные величины просто вычислять из них (если это не требует больших затрат процессорного времени конечно). Иначе ты замучаешься их обновлять при изменении исходных данных (например, ранга).
Ты случайно не путаешь базовое потребление кофе, одинаковое для всей профессии, и итоговое потребление, которое зависит от разных факторов?
> Является ли свойством количество производимых страниц ? Если нет - почему ? Как я понимаю, это производная величина, вычисляющаяся через другие.
> Где должны создаваться и добавляться в департамент сотрудники ? Это нужно делать в отдельном классе или прямо в классе департамент ? Тут есть 2 подхода:
- если сотрудники не могут существовать вне департамента, то может быть логично их в нем и создавать и использовать. - если сотрудники могут существовать вне департамента, их можно добавлять в него и убирать, то очевидно, что это уже не задача департамента их создавать.
Что еще непонятно?
Решение задачи с помощью ООП по сути и сводится к тому, что надо понять, какие у тебя будут классы, что в них будет свойствами, как они взаимодействуют и тд. И надо искать решение, которое быстро пишется, делает код более понятным другим людям, в котором проще разобраться, которое легко изменять, в котором трудно сделать ошибку.
Если ты из тех, кто критикует ООП, считает что он переусложнен и не нужен, то можешь попробовать решить задачу без ООП для сравнения. И посмотреть, насколько более простым будет решение.
Есть много объектов, заполненных данными. Можно как-то их на поля таблицы разметить, чтобы сохранялись туда автоматом? Поля не соответствуют полям таблицы, имена классов тоже. Доступа к классам нет, так что в самих классах ничего не напишешь. К классу, от которого они все унаследованы, доступ есть.
Если ты написал все классы, то дальше надо использовать их для решения задачи. А именно:
- создать объект компании - создать и добавить в нее все департаменты - создать всех работников и рассовать по департаментам - сделать цикл по всем департаментам, для каждого департамента получить данные по зарплате, кофе, вывести их в виде таблицы
С гайдами, да, не очень, но у нас есть задача про студентов и в ней очень много комментариев. Со ссылками на статьи про паттерны работы с БД, внедрение зависимостей, MVC и прочие умные вещи.
Ну например там есть папка components, а что такое "компоненты", ты можешь сформулировать?
Или например есть класс Cart, который судя по названию, представляет одну корзину, но почему у него все методы статические? Как создать например 2 корзины? На самом деле у него неправильное навание и правильно его называть SessionCartManager или как-то так.
То есть у меня ощущение, что там в коде использованы классы, но автор толком не понимает ООП. Зачем он тогда их использует? Чтобы были? Чтобы было что показать на собеседовании проверяющему, который тоже не знает ООП и не видит ошибок? Пусть пишет на функциях тогда.
Или вот класс DB. Можно подумать, это класс для работы с БД, но у него почему-то всего один метод getConnection. Может правильнее его было назвать ConnectionFactory? и опять же, везде статические методы.
ООП значит "объектно-ориентированное программирование". Но объектов-то в коде нет. Классы используются только для группировки функций.
Класс Product опять же назван неправильно, его объект не представляет собой один товар.
И так далее.
У нас в задаче про студентов изучаются примерно те же вещи, построение приложения. Только без злоупотребления статическими методами.
>>929134 >Потому, что это производная величина, которая зависит от: профессии, ранга, статуса босса. Хранить надо исходные данные, а производные величины просто вычислять из них (если это не требует больших затрат процессорного времени конечно). Иначе ты замучаешься их обновлять при изменении исходных данных (например, ранга). > >Ты случайно не путаешь базовое потребление кофе, одинаковое для всей профессии, и итоговое потребление, которое зависит от разных факторов?
Проиграл с задроченного ноулайфера, который не видит людей и строит абстрактные модели их предпочтений.
Можно сделать внешние классы-мапперы. Например, UserMapper умеет сохранять и загружать объекты User из таблицы users. В мапперах прописать название таблицы и соответствие между колонками таблицы и полями объектов, может даже правила преобразования (например поле DATETIME в PHP объект DateTime).
В динамических сайтах в БД хранятся исходные данные (в нормализованном виде), а шаблон страницы хранится в виде файла. Соответственно, при генерации страницы данные берутся из БД и подставляются в шаблон.
Что значит "сколько запросов"? А сколько у тебя данных выводится на странице? Может ты просто запросы делаешь неэффективные, и все тормозит? Или используешь бесплатный хотинг? Ты обязан хорошо знать SQL, чтобы писать динамические сайты с базой данных.
Бывает, делают кеширование, то есть сохраняют на будущее сгенерированный кусок HTML, но у этого подхода очень много недостатков (пример: мы можем кешировать список комментариев, но как только нам надо подсвечивать комментарии текущего пользователя, а также показыать автору пока не одобренные комментарии, этот кеш становится бесполезен).
Но даже в случае кеширования, кеш хранится отдельно от исходных данных.
Поясните, пожалуйста за сессии. Есть некий php-класс. В одном методе я открываю сессию с помощью session_start(), пишу в $_SESSION, потом пишу header("Location: ".$desiredLocationURL) и в следующей строке записываю exit
Как можно в другом методе класса, который вызывается позже, получать доступ к $_SESSION? Почему-то к нему нету доступа, пишет >Undefined variable: _SESSION Нужно писать session_start()? Сессия будет работать, если открыть браузер в анонимном режиме?
О какой разметке речь? Если ты хочешь сохранить набранный в HTML редакторе код статьи с форматированием - пожалуйста, сохраняй. Если ты хочешь сохранить верстку/дизайн сайта в БД, то это плохая идея. Ну хотя бы потому, что верстальщику неудобно будет с ней работать. Ведь все редакторы кода работают с файлами на диске, а не с данными в базе.
Файлы легко поместить в систему контроля версий вроде git, а данные в базе - нет.
Бывают CMS, где верстка хранится в БД, но это очень неудобно.
Шаблоны дизайна все же должны лежать в виде файлов на диске.
> Например, у сайта сложный дизайн, не хранить же каждый блок текста в отдельной таблице и не выводить его потом?? кто сказал, что весь текст должен быть в базе? Если этот текст никогда не меняется, его проще просто прописать в сам шаблон. Если же его должен править редактор через админку то да, надо поместить его в базу.
> Но тогда получается, что одна страница будет лежать в нескольких колонках базы данных И пусть.
> ведь под каждый кусок шаблона должен выводиться определенный кусок из одной статьи. Ты что-то путаешь. Статья должна храниться в БД как одна сущность, целиком.
>>929152 >Паттерн так и называется Data Mapper, подробнее у Фаулера и у меня в уроке
О, как раз что искал. Буду писать мапперы. Про доктрину почитал, но все пишут тормознутая, а мне надо что-то побыстрее. К тому же там как я понял надо в самих классах комментарии писать, чтобы доктрина их понимала. Свой маппер не должен сильно затормозить, это же всего +1 класс к каждому объекту, либо можно вообще общий для всех написать.
- данные могут браться только из 2 колонок таблицы - нельзя отфильровать данные перед выводом в список - нельзя преобразовать данные - нельзя брать данные не из таблицы
Гораздо удобнее сделать отдельно функцию получения данных, и отдельно функцию генерации списка.
По поводу аякса, тут есть варианты:
- можно возвращать в ответе новый список, и явакриптом перегенерировать список опций - можно возвращать кусок HTML и заменять его - можно просто добавлять/удалять одну опцию из списка (изучи DOM, такая возможность есть). Это наверно самый оптимальный вариант.
То есть тебе надо подучить DOM, и DOM-объекты соответствующие тегам SELECT и OPTION.
Уголовный кодекс изучи, школьник. А так, вирусы мало кто пишет, их либо покупают, либо берут выложенные в паблик. Но вот например если ты интересуешься этой темой, ты должен знать историю ботнета Mirai, Citadel и тд.
Могу посоветовать интересный блог с свежей и актуальной информацией про ботнеты и прочий скам: https://krebsonsecurity.com/ Правда он на английском, но без английского в сфере кибербезопасности делать нечего.
Антивирусы (ядро) обычно пишут на Си++ ради производительности, но чтобы их писать, нужны очень широкие знания - начиная с машинных кодов и работы процессора, продолжая WinAPI, заканчивая форматами файлов и виртуальными машинами. То есть надо очень много изучать разных вещей, и низкоуровневых, и высооуровыневых, и этому на сомнительных форумах вряд ли научат. Там тебя только научат как скачать готовую программу, взломать кривой непатченный годами магазин на PHP и попасть в отдел К.
>>929183 >>929078 я тут обосрался изза того что в глаза долблюсь, потом просто наговнокодил и не стал переделывать, чтобы хоть как то соответствовать требованиям задачи, можешь посмотреть может поможет
Как правильно прятать файл, который обрабатывает форму? Допустим мы используем аякс или просто js, что позволяет нам не писать допустим action="save.php", но на странице всёравно же будет виден код ajax или js, и по ним можно будет понять какой файл обрабатывает форму. Как правильно прятать?
Это потому что у тебя либо много совбодного времени, либо очень маленький проект. На практике такие логи читать будет некому, и там много будет ложных срабатываний (вроде всяких ботов, заполняющих все формы подряд и тд). Проще просто не пропускать плохие запросы и все.
- как в сеттере могут оказаться неправильные данные? - что мы хотим в этом случае делать?
Вот первое, что мне приходит в голову, что левые данные там могут оказаться из-за кривых рук программиста. Раз так. надо выбрасывать исключение с пояснением причин ошибки, и пусть оно завершит скрипт.
Но может быть, у нас класс специально сделан так, чтобы в него можно было пихать любые данные, а он возьмет что ему нужно. Если так, то может быть стоит сделать как-то по-другому.
А может у нас куча кривого кода, и надо срочно что-то сделать, и разбирать его некогда, сделаем его еще кривее, и пусть он игнорирует все ошибки, а разгребать это потом будет кто-то другой.
Валидация и пользователь тут вообще не при чем. Класс должен заниматься только своим делом, если валидация не его задача, то он не обязан искать и исправлять чужие ошибки. А может сразу выбросить исключение и отказаться работать.
Логично капчу выводить до попытки скачивания. Логика может быть такая:
На странице просмотра файла:
- если пользователь не прошел капчу, показать ему капчу - иначе не показать
Обработчик формы с кодом капчи можно сделать обычный (POST-форма), можно аяксовый, на выбор. В случае обычной формы, можно после успшного решения капчи редиректить на скаичвание файла.
В обработчике скачивания файла:
- если пользователь прошел капчу. отдать файл - иначе, перенаправить его на страницу просмотра файла
Хранить информацию о решении капчи можно в куках или сессии.
То есть тебе бы стоило начать с понимания, как работает HTTP, что такое GET/POST запросы.
>>929186 Зачем прятать? Если save.php нормально написан, то ничего прятать не требуется, он любые параметры принимает, валидирует и выдает сообщения об ошибке в случае левых данных. Надо не прятать, а нормально инпуты проверять.
>>929186 В коде аякса секретный ключ + текущее время. В htaccess редирект например /save/ на save.php. Потом из аякса делаем запрос на /save?secretkey, где secretkey md5 от секретного ключа + текущее время. Сервак сравнивает и показывает 404 not found со всеми заголовками, если не совпало.
>>929186 НИКАК С помощью WEB-консоли браузера ЭКСПЕРИМЕНТАТОР может отследить параметры запроса и по какому адресу отправлены данные, а потом на питончике набросать скрипт, который отправляет тот же запрос, представляется браузером и сохраняет печеньки.
Можно настроить роутинг с помощью Alto Router или mod_rewrite, и тогда прописывать не action="save.php", а action="/backend/"; некоторые фреймворки позволяют повесить обработчики серверных событий, типа onRequestURL, например Wordpress мне кажется. Это не остановит заинтересованных лиц от попыток обхода механизмов. Так что для особо критических мест решает все более детальная проверка данных.
Ну, не буду спорить, конечно, но названия классов и переменных - это уже нутакое, не влияющее на функционал. А так да, у хохла много лишнего, типа папки КОНФИХ и компоненцс. С другой стороны, такой подход удобен, чтоб скинуть клиенту готовый архив с сайтом и послать нахуй, а он сам сможет разобраться уже в коде на базовом уровне. Я вот сейчас тот же тутор хохла прохожу, но многое переделываю под себя и свою логику. убрал дб_конфих и внес в database.php, где к базе подключается и ведется всякое нехорошее
да, кстати, а зачем корзине быть нестатической? Ну, то есть, зачем создавать еще корзин богу корзин? Мне в любом шопе одной хватало, когда чот покупал, лол. >>929077-кун
вообще приятно, что в пхп-тредике ответят и пояснят, а не обоссут за любой вопрос, как в жс-треде, раковнике кстати, можешь что нибудь сказать о ноде? У меня лежат две книги по ней и чешуться руки, но я только начал осваивать пхп, а еще в инетах пишут, что нода нинужна хотел бы работать фуллстек жс макакой, в идеале еще и на удаленке
- ссылку не надо формировать в шаблоне, а праивльно сделать метод, который ее генериурет - нельзя давать прямую ссылку на файл, так как он может быть сохранен не под исходным именем или расширением
Почитай комментарии к задаче про файлообменнник, там же это расписано вроде.
Защиту от роботов делать не требуется, но если очень хочется, то можешь добавить.
- проверить введенный логин и пароль - залогинить пользователя с данным id
Первое я разбирать не будут, а второе обычно реализуется через куки (либо через сесиии, которые используют те же куки).
Чтобы понять, кто перед нами, мы должны выдать куку с каким-то идентификатором. Например, id пользователя, email, логин.
Но этого мало. Ведь злоумышленник может поставить себе любую куку и выдать себя за легитимного пользователя. Потому дополнительно мы должны выдать какой-то код, ключ, токен, который знает только пользователь и не знает посторонний. Например: случайны длинный код, хеш пароля.
Вместо 2 кук можно использовать и одну. Например, длинный код может и идентифицировать пользователя, и подтверждать его личность.
Авторизация на основе сессий устроена примерно так же, только там нет риска подделки и достаточно хранить только идентификатор. Но сессия - вещь временная и быстро умирает.
Я тебе советую вместо чтения статьи просто понять, как работает авторизация и написать функции залогинивания/разлогинивания/проверки самому.
SQL в контроллере это большой толстый контроллер, а не MVC. Код в контроллере не повторно используемый, его неудобно тестировать, и лучше его писать там поменьше.
> В идеале выделить работу с sql в прослойку - маппер, чтобы она не была в model. Но если нет, то где ей больше место - в model или controller? Ты по моему не понимаешь, что такое модель и как работает MVC. У меня есть урок https://github.com/codedokode/pasta/blob/master/arch/mvc.md
> Но описывать более сложные SQL-запросы (с подзапросами, джойнами..) через квери-билдеры в ORM Query Builder перпендикулярен ORM. Можно делать ORM без Query Bulder, можно использовать Query Builder без ORM. Как следует из названия, он предназначен для сборки запросов по частям, например, когда вид запроса зависит от каких-то условий. В моем уроке это упомянуто.
То есть ты не разобрался, используешь QB не там, где надо, и жалуешься, что это неудобно.
> Структура базы, связи между таблицами описывается внутри doc-комментов! А как ты бы хотел их описывать? В доктрине есть другие варианты + можно написать свой парсер.
Есть дата в формате 02/14/2017, как перевести её в количество секунд прошедших с 1970 года. Только без математических расчётов, есть функция которая преобразует дату в обычном формате в unix формат, я что-то не могу найти
Удобнее наверно сделать хороший редактор, где все вопросы на одной странице. Сам подумай, в тесте может быть 10-50 вопросов. И может потребоваться их переставлять как-то.
У меня там есть наброски интерфейса (на mockinbird), и там вроде показано, как это может выглядеть.
С другой стороны, если ты можешь сделать удобный многостраничный редактор (например страница со списком вопросов и страница редактирования), это приемлемо. Но ты тогда не научишься работать со сложными динамическими формами, что плохо.
Удобнее всего отправлять как обычную форму с приложенными файлами наверно. Ну либо каждую картинку отдельным запросом, если соединение плохое и надо переотправлять запросы.
Библиотек не знаю, но наверно можно нагуглить при желании.
Ответь сначала на такие вопросы (если знаешь ответ, если нет, так и пиши):
- что такое сессия? - где хранятся помещенные в нее данные? - если сессий на сервере много, как понять, какая из них соответствует какому пользователю? Ну то есть пришел HTTP-запрос от браузера, как понять. какая сессия соответствует этому пользователю? - что делает sesion_start()? - кто и когда заполняет массив $_SESSION? Что происходит с ним после завершения скрипта? - как удаляются данные сессий, если они долго не используются?
Можешь также погуглить перед тем, как писать, что не знаешь.
А если этот "экспериментатор" освоит браузерные расширения, то его вообще будет крайне тяжело отличить от человека. Можно показать капчу, но есть сервисы по ее распознаванию, хотя говорят, гугловскую трудно пройти.
Проще наверно вводить какие-то лимиты и искать подозрительных пользователей которые методично загружают страницу за страницей.
В данном случае названия классов показывают непонимание их назначения и вообще непонимание ООП. Ну или может это такой альтернативный взгляд на вещи. Только вот будут ли рады ему например на собеседовании?
> да, кстати, а зачем корзине быть нестатической? Ну например, надо зачем-нибудь сравнить корзины 2 пользователей. Или еще что-нибудь с ними сделать. Или в тесте мы создаем корзину, делаем что-нибудь с ней и выкидываем.
Ну или например мы хотим поработать с корзиной в CLI-скрипте. Этот класс ведь без сессии вообще работать не будет. Потому что это не корзина. А редактор данных в сессии, хранящих информацию о корзине.
В коде в принципе нет объекта, представляющего корзину. Есть только массив данных в сессии, описывающий ее содержимое.
По ноде я не могу сказать. Мне кажется, она нужна только в определенных нишах.
Если ты хочешь писать сложные JS приложения, тебе все равно надо понимать ООП. У нас кстати есть задачи по JS самого разного уровня в ОП посте. В том числе и на сложное приложение.
Я всегда стараюсь объяснить, почему кто-то не прав, чтобы из этого была польза и люди учились сами мыслить аналогично. А не заучивали догмы, не понимая, почему так, а не иначе.
>>929219 >Это тестовое задание? Можно через циклы, можно через array-walk_recursive или рекурсивные итераторы по массиву. Не тестовое, аутирую с вордпрессом. Мне требовалось убрать пробелы у значений перед отправкой в бд. Сделал через вложенный foreach, но думаю, что сделал какое-то говно и так никто не пишет.
>>929178 >list_selector($table, $column, 'list_id', 'list_name'); Там как раз и есть две функции. Одна работает с таблицей, а list_selector только формирует список, используя столбец $column в таблице $table и формируя div с параметрами id и name, list_id и list_name, в который его и помещает.
>>929349 С тех пор ничего не изменилось же. Новые фичи в php7 и фреймворки появились, но основы от этого не меняются. Что в шапке, вполне актуально, а для новых фич качни любую книгу, где php7 разбирается.
>>929448 Я бы очень рад тебе помочь, но я не понял самого вопроса, в чем у тебя проблема то? Это тестовая/учебная задача, или у тебя траблы с реальным проектом?
Тебе нужно селект написать? В котором будет посчитано сколько книг в каждом жанре? Наверное как-то так SELECT genres, COUNT(*) FROM books GROUP BY genres;
Привет анончики. Хочу запилить мультиязычность наYii. Пробема в том что не знаю как организовать проверку кук и запись в сессии на всех страницах. Сперва нужно по дефолту (при заходе на любую страницу сайта) повесить куку с дефолтным языком и записать дефолтную сессию, а при выборе другого языка - поменять. Очевидно, мне не хочется проверять существование кук и сессий в каждом экшене, как это сделать в одном месте? Может есть варик через конфигурацию компонентов?
>>929470 по сути мультиязычность нужна только на стороне клиента. так что на основном контроллере в папку frontend. Там сейчас 10 страниц, очень не хочется вешать на каждую проверку Отвечая конкретно на вопрос, при вызове контроллера SiteController (я и не парился его переназывать ) проводить проверку сессий и кук
да, нужен селект. Списки жанров и книг в разных таблицах. Они связаны между собой проходной таблицей. То есть вместо того, чтобы в одну ячейку писать id жанров, я сделал табличку.
>>929474 Прости бро, но я в глаза ниразу не видел yii, просто основываясь на опыте пытаюсь тебе дать совет. > Там сейчас 10 страниц, очень не хочется вешать на каждую проверку Что такое страницы? Страница собой представляет контроллер? Или ты методы одного контроллера имеешь ввиду?
Если у тебя все "страницы" в пределах одного контроллера, то напиши ему конструктор, в котором это будет проверяться.
>>929566 Можно, но ты ниже используешь эхо на переменной, которая не существует в этой зоне видимости. И вообще это пиздарики. Куча каких-то эхо, наркоманские названия переменных, $bd++ вместо $db++.
>>929560 это тяжелый случай, у тебя функция ничего не ретернит, нигде не вызывается и ты к внутренним переменным функции обращаешься в глобальном коде.
>>929569 >>929570 Я вас понял, поскольку функция это отдельный мир кода, так сказать, измерение, и все переменные внутри функции внешний мир не видит, для него они не существуют. Следовательно, что-бы вызвать результат функции, нужно echo название_функции написать?
>>929574 Нет, ты можешь и внутри функции эхо написать, но ты ВЫЗОВИ СУКА ЕЁ ГДЕ-НИБУДЬ В КОДЕ то что у тебя там написано function hueta($huitka) { ....hueta code } - это только ОПИСАНИЕ ФУНКЦИИ, понимаешь? Ты тут лишь показываешь языку как она должна работать.
Потом ты в своём коде где тебе нужно пишешь hueta($var); и она выполняется
>>929596 Ну и зачем ты все разжевал? А? А? А? А? А? А? А? А? Давай удочку, а не рыбу, еба. Когда сам роешь инфу по проблеме, то в конце ты чувствуешь, что заебись ваще чотко все порешал. А если тебя тычут носом в решение, то это хуйня.
Я все равно не могу понять ситуацию с кофе и страницами. В моем нынешнем решении я копирую несколько раз код функции getDrunkCofee, меняя только одно значение. Этого ведь можно избежать, сделав кофе и страницы свойствами сотрудника, разве не так ? Может я не правильно понял условия, ведь потребление кофе и количество страниц зависит только от того, является ли сотрудник боссом ? Или при повышении ранка повышается потребление кофе и производство страниц ?
>>929612 >>>929134 >>>929132 И еще, кто-то может подсказать, в какую сторону читать: >>929612 В голове возникла мысль ! А может быть в общем классе "сотрудник" полностью описать функцию просчета, с использованием instanceOf, и выдавать результаты в зависимости от профессии(типа, класса) ?
Функцию еще иногда называют "подпрограмма". То есть это как бы отдельная маленькая программа. Мы вызываем ее, даем ей аргументы, и она что-то с ними делает и возвращает результат.
Конструкция такого вида
function somehing($x) { ..... return $y; }
создает новую функцию (но код в ней не выполняется, просто PHP теперь знает, что такая функция есть). В данном случае создается функция с названием something, которая принимает один аргумент, обозначенный переменной $x и возвращает что-то в конце своего выполнения с помощью return. return это специальная команда, которая выходит из функции, и возвращает указанное после нее значение.
Чтобы вызвать функцию (после того, как мы ее создали конечно), мы пишем ее имя и скобки, в скобках указываем значения аргументов:
something(10);
Вот эта строчка вызвает функцию и выолняет записанный в ней код. При этом в функции будет доступна переменная $x, равная 10. Если мы хотим сохранить результат, который вернет функция с помощью return, мы должны использовать переменную:
$result = something(10);
Вот конкретный пример. Напишем функцию, принимающую на вход 2 числа и возвращающую сумму их квадратов:
Видно, что это функция, которая принимает 2 значения, возводит их в квадрат, складывает и возвращает сумму с помощью return.
Теперь посчитаем с ее помощью сумму квадратов чисел 3 и 4:
$sum = getSquareSum(3, 4); echo $sum; // 25
Можно обойтись без промежуточной переменной:
echo getSquareSum(5, 6); // 61
Функция может быть без аргументов (ничего не принимать на вход) и может ничего не возвращать (то есть в ней нет команды return).
И да, функция не видит внешние переменные. Все, что ей нужно, ты должен явно передать через аргументы. Это делает код более логичным, сразу по заголовку видно, что нужно передать функции для ее работы.
Копировать код функции 4 раза - плохая идея. Это затрудняет изменение программы и говорит о неправильном подходе.
Более того, тот, кто будет добавлять новые професссии, должен будет копипастить этот код.
Давай подумаем: в 4 классах-профессиях логика расчета потребления кофе - разная или одинаковая? Она одинаковая, единственное различие - это один коэффициент.
Следовательно, нам нужно не 4, а одна функция. Мы объявляем ее в базовом классе, и она потому будет доступна во всех потомках.
Но как прописать, что в каждом классе свой коэффициент? Логично сделать поле либо функцию, которая его возвращает. Вот такого вида:
protected function getBasicCoffeeConsumption() { return 10; }
Но тут встает другая проблема:
- во-первых, мы не можем из базового класса вызвать функцию, которая есть только в его потомках. Базовый класс не должен ничего знать о своих потомках, так как они могут добавляться в будущем - во-вторых, как объяснить людям, которые будут делать новые профессии, что они обязаны сделать такую функцию?
Обе этих проблемы решают абстрактные методы. В базовом классе мы делаем абстрактный метод:
abstract protected function getBasicCoffeeConsumption();
Так как мы его объявили, то теперь мы можем его вызывать. А тот, кто наследует наш класс, обязан будет этот метод реализовать, иначе произойдет ошибка и класс не создастся.
То есть абстрактный метод - это метод, который не описан в базовом классе, но который обязаны реализовать все его потомки.
Иногда используют другой подход: делают метод по умолчанию в базовом классе, а часть потомков его переопределяет, если хочет. Но у нас не та ситуация, у нас нет коэффициента по умолчанию, у каждой профессии он свой.
Есть ли в моем подходе недостаток: да, есть. Он предполагает, что во всех профессиях будет использоваться один и тот же метод, формула расчета кофе. Если это не так, то этот мой подход будет плохо работать (попробуй подумать, почему).
> А может быть в общем классе "сотрудник" полностью описать функцию просчета, с использованием instanceOf, и выдавать результаты в зависимости от профессии(типа, класса) ? Это полная противоположность ООП-подходу. В ООП, если какая-то информация или логика относится только к одному классу, то она должна быть в нем.
В таком случае мы можем добавлять новые профессии, не трогая старый код (не всегда конечно, но иногда это получается).
Ты предлагаешь вынести знание о том, как считать потребление, из класса профессии наружу.
В твоем случае для добавления профессии придется менять код в нескольких местах. Это как миниумм неудобно. Если ты используешь сторонний код, который править нельзя, то получается ты вообще не можешь расширять.
То есть код вида:
если класс == Менеджер то... если класс == Инженер то...
противоречит идеям ООП о разделении кода на классы. Ты выносишь код, относящийся к классу, из класса наружу.
> public function getDrunkCofee() > { > return 'nothing'; //заглушка Это неправильно. Таких "заглушек" быть не должно. Так как кто-то может вызвать функцию, и эти данные куда-то дальше пойдут. Тут надо использовать абстрактный метод без реализации.
Твоя ошибка в том, что ты сделал бесполезный класс Employee (зачем он сделан? за что он отвечает? за общий для профессий функционал? для этого у нас уже есть AbstractEmployee), в то время как надо было наследовать профессии напрямую от AbstractEmployee.
> abstract class AbstractEmployee > private $baseRate; Перечитай в чем разница между protected и private.
> protected $baseRate = 500; Нет гарантии, что все потомки укажут значения поля. Тут надо использовать абстрактный метод для получения этого числа.
Аноны, тупые вопросы за 300. У меня есть приложуха которая шлет гет запрос на получение списка, еще есть пост запрос на добавление данных и редактирование и есть еще удаление(как его слать кстати). Так вот на сервере эти запросы обрабатывает один файл, но разные функции? И получается для разных пост запросов надо разные пхп файлы?
Извиняюсь что немного не по теме. - Есть один сайт на php, который возможно мне придется админить/переписывать и тд. - в php ноль, но знаю питон, не слишком хорошо, но 99% проблем могу решить сам, не умоляя слезно на всех форумах сразу. Вопрос в том как мне поступить, учить php и дербанить существующий сайт или писать на питоне с нуля? И сколько нужно просить за такую работу (сайт на питоне), учитывая что я живу мухсранске, нищеброд без гроша и фирма мелкая. Извиняюсь за сумбурность
Спасибо ОПу за задачки и обучение программирование на пыхе, а также анонам из версткотредов. Я переехал в ДС и нашел работу. Как я вас могу отблагодарить? Могу подарить тортик :3
Прятать стили в тэге стайл прямо в середину хтмл страницы - ведь совсем зашквар? Не первый раз такое встречаю, прямо у меня на работе есть такой говнокодер.
>>929753 Можно просто в style у элементов же прописывать. <div style="background-image: url(../images/vasya.gif);background-repeat:no-repeat; background-position:50% 50%;"> background-position:50% 50% </div>
>>929775 Я знаю, но они именно ебашут <style> в середине html и это меня ужас как бесит. Оправдывается разраб тем, что ну стили же легче будет найти потом)) т.е. ему легче искать стили к странице, в которой он их прям в середине заебашил. ппц
>>929793 Я так и сделал. Даже пастбин с моей базой сделал. Жанры и книги связаны между собой через промежуточную таблицу. Нужно придумать, как оформить Селект, чтобы было Жанр - количество книг в жанре.
Есть несколько кнопок radiobutton, как среагировать в jQuery на клик по любой из них. Класс и id не могу поставить каждой кнопке свой, так как они выводятся динамически.
Возможно тупой вопрос, но всё же. Представим ситуацию: у меня есть сделанный мной сайт, который активно работает с моей же базой данных. Сайт лежит в папочке, к которой прописаны пути в настройках апача. Так же есть база данных и конкретно phpmyadmin для неё, который допустим висит на локалхосте. Теперь я хочу чтобы всё это моё дело вышло в свет. Беру хостинг, заливаю туда папочку своего сайта и... Что делать с базой? Где она должна быть? Она отдельно хостится? Я ни разу не выкидывал в продакшн проекты.
PHPч, ПАМАГИ! Помогите оценить время и стоимость следующей работы: Нужен сайт - обменник криптовалюты Предполагается: 1. Сверстать сайт под популярные браузеры из небольшого количества страниц без излишеств, никаких WebGL, Unity и прочих монстросити, но при этом не совсем голый html, допустим используется какой нибудь bootstrap 2. Настроить взаимодействие с некоторыми банками для транзакций (у некоторых, вполне возможно, есть API для php, у некоторых может и нет) 3. Настроить взаимодействие кошельков с криптовалютой для транзакций. 4. Настройка БД для логгирования различных действий (транзакции-шманзакции) 5. Смазать всё это дело защищенным соединением (HTTPS все дела)
При условии: Разрабатывается в одно ебало, нет возможности работать в фул-тайм, где то половина-3/5 рабочего дня.
Хочу услышать большое количество времени, сколько при таких условиях ушло бы времени на разработку именно у ТЕБЯ и сколько бы денег в качестве оплаты запросил именно ТЫ.
>>930105 Ну что у тебя за хостинг. Например обычные веб-хостинги предоставляют панель управления. Такой же phpmyadmin. Делаешь бекап своей базы, заливаешь его на хостинг. Прописываешь пути подключения и все.
>>930164 А какого ты ответа ждешь? Чтобы я тебе сказал сколько ты должен брать за джобу? Ну пиздец, чо. Требуй с него 1 дошик, если долго будешь делать, а есть быстро, то два.
>>930166 >Чтобы я тебе сказал сколько ты должен брать за джобу? Я попросил просто примерную стоимость описанной работы. Я же не прошу тут бухгалтерские расчёты вести и проводить серьёзную аналитику. Просто примерная цена или диапазон ну без фантазий конечно, типа 300 мильёновтыщ в секунду/доширак и свистнуть в хуй исходя из вышеописанных условий.
>>930167 Пиздос, ты знаешь всю ситуацию, представляешь себе заказчика и не выкладывая никакой инфы по своим скилам, платежеспособности заказчика и примерном времени выполнения тобой джобы, спрашиваешь у анона сколько тебе заломить с заказчика. Если ты считаешь, что заказчик может соскочить, и он из страны, где о рублях не слыхали, то стартуй из расчета 15 баксов в час. Но это совет в стиле: 'Секс переоценен, я на дваче читал'. Только ты владеешь инфой и ты можешь трезво оценить всю хуйню. Короче я заебался писать, проси у него 3 дошика.
>>926220 >>Doctrine >Даже после прочтения сложных определений в гугле не до конца понимают что это такое. Оно заменяет Mysql или любую другу БД? На этот вопрос отвечать не нужно - ознакомился чуть подробней.
Товарисчи, до сих пор ебусь с задачкой про компанию Вектор. Вроде бы основную логику сделал, сейчас с выводом информации на экран мучаюсь http://ideone.com/3uQv9G - вот код Вопросы: 1) Какого хера мне выдает ошибку "PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen() in /home/z65BF4/prog.php:200" ??? Делал ведь предыдущую задачу про эту компанию, с этими же функциями и всё работало...
2) Как бы так красиво, в ООП стиле оформить вывод информации на экран и сам экшон (заполнение компании департаментами, тех сотрудниками и подсчет всего, что необходимо по условиям задачи) ?
>>930220 >>930234 Сорян, не сразу понял второй вопрос. Можно создать отдельный класс для заполнения сотрудниками. А выводить на экран лучше, создав функцию по типу той, что я описал выше.
http://ideone.com/oZw7mB - Айфон в кредит. Доброго времени суток, я тут ебусь с задачей про айфон в кредит и не могу понять какого хуя оно что-то плюсует к долгу, вместо того, чтобы отнимать от него месячную стоимость. Это происходит с разными данными. Например, с оригинальными данными 40к кредит, 5% процент и 1к комиссия, 5к месячная плата считает как надо, пробовал числа по-меньше - считает то нормально, то опять плюсует неизвестные числа. Сейчас в ней поставлены другие значения, а не оригинальные, дабы было понятно что за хуйня. Может кто знает в чём ошибка и где я обосрался, помогите.
for (months=0;credit>0;months++) { credit = credit*percent+service-payment; if (credit<payment) { spent += credit; months++; break } else { spent+= payment} так же проще. если я не проебался нигде, еду с универа только
>>930134 Я б сделал примерно за 2-3 месяца, может меньше. Но я не начинающий. Если хуефрилансера с сайта нанять, то может и на год растянуться и забаговано все будет. Самая сложная часть криптовалюты и как с ними взаимодействовать, остальное достаточно просто и стандартно. Запросил бы 10к баксов.
Правильно ли понимаю, что по принципу Лисков, если наследник переопределяет не абстрактный метод, то он обязан вызвать родительский? Понял принцип так: "Вместо родителя всегда можно подставить наследника и код должен работать как и прежде". Заодно напомню о скидках: https://ideone.com/IscxDU
>>930547 >Windows: C:\Users\{LoginName} - Открываем контектное меню и выбираем пункт Git Bash Что за LoginName?можешь дать почту или линк вк?то я тупой
>>930554 По принципу Лискова ты не можешь менять методы в классах-детях, которые были определены в родителе. Иначе ребенок уже не соответствует родителю, и ты не можешь заменить им родителя. Весь смысл наследования теряется. Конструктор к примеру если определен в родителе с параметрами, то он такой же и в детях, нельзя его переопределять под другие параметры.
>>930593 К тому же это фукнциональности касается, да. Если к примеру был метод turnPage($number), который менял страницу, то если в ребенке у тебя turnPage не меняет страницу, а делает что-то другое, то это нарушение по Лискову.
>>930593 > Иначе ребенок уже не соответствует родителю, и ты не можешь заменить им родителя. Весь смысл наследования теряется. И правда.
> Конструктор к примеру если определен в родителе с параметрами, то он такой же и в детях, нельзя его переопределять под другие параметры. Выходит, что parent::__construct() это плохо? Набросал простой пример, когда, вроде бы, принцип Лисков не нарушается, даже невзирая на то, что конструктор в наследнике переопределён: https://ideone.com/JBf2VC
>>930609 Нет, почему? Если у тебя __construct в ребенке принимает все те же параметры, что и parent::construct, то можно расширять. Это соответствует open-closed principle - ты не меняешь parent, а расширяешь его функциональность в ребенке. При этом функциональность parent остается нетронутой, ведь его __construct работает так же как и прежде.
Не обязан. Разве что в конструкторе почти всегда приходится это делать (например, потому что он инициализирует private поля, которые по-другому не инициализировать).
Методы можно менять, но изменения должны быть совместимыми. Например, можно добавить новый аргумент, но у него должно быть значение по умолчанию. А убирать, или менять тайп-хинт на более узкий, естественно, нельзя.
К конструктору это не относится, конструктор можно менять как угодно. На него правило Лисков не распространяется, так как оно относится к уже созданным объектам, а конструктор мы вызываем когда объект еще не создан.
Раз уж ты интересуешься наследованием, то почитай заодно про проблему прямоугольника и квадрата:
К конструктору требование совместимости не относится. Так как конструктор никто не вызывает на уже созданных объектах. Принцип Лисков говорит о совместимости созданных объектов, а не классов.
>>930609 В твоем примере лисков как раз нарушен - ты в ребенке принимаешь другое число параметров чем в родителе. Теперь ситуация - ты где-то юзаешь ребенка, а понадобилось заменить родителем. Ты этого сделать больше не сможешь - вызовет ошибку из-за несоответствия количества параметров.
> ..если для каждого объекта o1 типа S существует объект o2 типа T такой, что для всех программ P, определенных в терминах T, поведение P не изменяется при замене o2 на o1, то S является подтипом (subtype) для T.
> Говорят, что экземпляр наследника также ЯВЛЯЕТСЯ экземпляром базового класса, что выражается в возможности использования экземпляров наследника везде, где ожидается использование базового класса.
Видите, речь идет об объектах. Условно говоря, если у вас есть функция
function doSmth(A $a) { ... }
Что это значит? Значит, что эта функция должна обращаться только к полям и методам, которые есть в классе A.
Но вы в нее можете передать объект класса B, наследующегося от A, и все должно работать. То, что у него другой конструктор - это не проблема, так как вызываете вы его за пределами функции. Сама функция констурктор у $a не вызовет, так как это уже созданный объект.
>>930627 >К конструктору требование совместимости не относится. Так как конструктор никто не вызывает на уже созданных объектах. Принцип Лисков говорит о совместимости созданных объектов, а не классов.
Если создаешь объекты в цикле, и попал родитель и ребенок - будет ошибка. Тебе в каждом цикле придется смотреть, чтобы не создавался объект с 3 параметрами, а это уже кривой код. Код должен быть защищен от ошибок на уровне интерфейса.
Ты не так понял. "Можно использовать вместо родительского класса" не значит, что ты можешь пойти и в коды программы поменять имена классов. Смысл замены в том, что ты можешь в функцию передать объект наследник вместо предка, как тут >>930633
Пожалуйста перечитай внимательно определения. Речь о том, что можно использовать объект наследника вместо предка, а не менять имена классов в тексте программы.
>>930638 >Саттер и Александреску в своём руководстве по использованию C++ для выражения этого принципа также используют фразу «подкласс не должен требовать от вызывающего кода больше, чем базовый класс, и не должен предоставлять вызывающему коду меньше, чем базовый класс».
В случае конструктора с расширеными параметрами подкласс как раз требует больше, чем базовый класс. Прямое нарушение.
Если ты имеешь в виду код вида $x = new $class, то это уже твоя проблема, что ты используешь такую конструкцию. Надо использовать if/else или switch ($class) ... и проблемы не будет. Или делать еще и конструкторы совместимыми.
>>930643 >Принцип Лисков не распространяется на конструкторы. В исходном определении речь идет о types и subtypes, которые по сути и есть классы и подклассы. >We add to a type’s specification a constraint clause that captures exactly those history properties of a type that must be preserved by any of its subtypes, and we prove that each of the type’s methods preserves the constraint.
>>930638 >http://sergeyteplyakov.blogspot.ru/2014/09/liskov-substitution-principle.html На этой странице тоже пишут: >Если посмотреть на исходное описание принципа подстановки в трудах Барбары Лисков, то можно с удивлением обнаружить, что оно полностью основано таких понятиях, как предусловия, постусловия и инварианты. Другими словами, описание этого принципа полностью основано на принципах проектирования по контракту:
>Производные классы не должны усиливать предусловия (не должны требовать большего от своих клиентов). >Производные классы не должны ослаблять постусловия (должны гарантировать, как минимум тоже, что и базовый класс). >Производные классы не должны нарушать инварианты базового класса (инварианты базового класса и наследников суммируются) >Производные классы не должны генерировать исключения, не описанные базовым классом.
Изменения конструктора нарушает эти правила, в частности первое.
> $matchedProducts = $discountResult->getMatchedProducts(); > $matchedPrice = $matchedProducts->reduce($pricesSum, 0); > $totalPrice += $matchedPrice - $matchedPrice $discountResult->getPercent(); Вот тут ты накладываешь много ограничений на расчет скидки, вместо того, чтобы отдать это объекту скидки. Ну например, ты требуешь, чтобы все скидки были в процентах, и не даешь возможности написать произвольный алгоритм расчета скидки. Мне кажется, если бы вместо этого мы могли передать набор товаров в скидку и получить абсолютную скидку либо итоговую сумму, было бы гибче.
С точки зрения задачи твой подход верный, но интуиция говорит мне, что на практике его может быть, придется потом менять.
Метод getDiscountResult я бы переименовал в calculateDiscount/applyDiscount, так точнее получается.
> class CombinationDiscount implements DiscountInterface > public function getDiscountResult(ProductCollection $notUsedProducts) { ... > $notUsedProducts->removeProduct($matchedProduct); Вот это неожиданно. Я думал, что функция getDiscountResult не изменяет исходные данные, а она изменяет, причем это нигде никак не написано. Это может привести к ошибкам, например, если мы вызовем ее 2 раза с одними и теми же данными (например чтобы сделать вывод отладочной информации), то второй раз она вернет другие значения.
Тем более название начинается с get...
Тут наверно лучше было спроектировать функцию так, чтобы она не меняла исходные данные. Это ведь не сильно усложнит программу, а от ошибок защитит.
А, и еще. А что, если в цикле тут название первого товара есть в списке, а второго нет?
> foreach ($this->names as $name) { ... > if ($matchedProduct) { > $notUsedProducts->removeProduct($matchedProduct);
Тогда получается, скидка не будет применена, но товар будет удален из исходного списка. Это же ошибка. И допустил ее ты именно из-за того, что модифицируешь исходные данные. Ну и причина, почему я ее заметил, в этой строке:
> return new DiscountResult(new ProductCollection(), $this->percent);
Подозрительно, что ты не используешь тут переменную $productsUsedInThisDiscount, я решил выяснить, почему так, и нашел ошибку.
----
Я хочу еще немного отвлечься и рассказать про такую вещь, как exception safety, или "безопасность" исключений (корректность работы программы в случае выброса и перехвата исключения в любом месте кода). Эта тема важна только в программах, которые часто перехватывают и обрабатывают исключения (имеются в виду исключения, не говорящие об ошибке в коде, а например, об ошибке соединения с удаленным сервером), что редко встречается на практике, но тем не менее интересна.
Предположим, что у тебя строка $productsUsedInThisDiscount->addProduct($matchedProduct); может выбросить исключение и выполнение методы getDiscountResult прервется. При этом переданный список будет уже изменен, и удаленные продукты при повторном вызове метода не будут участвовать в расчете скидок. То есть безопасность программы при возникновении исключения нарушена.
В случае выброса исключения, код, который не меняет переданные данные, работает обычно корректнее, так как он не оставит исходные данные в наполовину измененном виде.
В этой статье https://habrahabr.ru/post/126374/ упоминается "строгая гарантия". Если бы метод не менял исходные данные, он бы реализовал "строгую" гарантию безопасности исключений.
Особо конечно с этим заморачиваться не нужно, но знать про такие вещи полезно.
----
> return new DiscountResult(new ProductCollection(), 0); Если это часто встречается, стоило добавить конструктор DiscountResult::makeEmpty();
Насчет связи скидок через интерфейсы - думаю, это правильное решение, так как тут у скидок нет общего кода и особого смысла в наследовании нет, хотя допустимо сделать связь и через абстрактный класс.
> $answer = (200 - 200 0.1) + (200 - 200 0.05) + (200 - 200 0.05) + (400 - 400 * 0.01) + 100; > assert($answer == $c->calculateTotalPrice($discountCollection, $productCollection)); Вот тут есть момент, на который стоит обратить внимание. Дело в том, что в PHP дробные числа (float) хранятся приближенно (да еще и в двоичном виде, что требует преобразований в/из десятичной системы счисления), и операции с ними неточные. Ну например:
Дело в том, что в двоичной форме число 0.3 - это бесконечная дробь. Там на самом деле 0.1 + 0.2 дают что-то вроде 0.29999999, просто при выводе оно округляется до красивого числа. А вот при сравнении видимо где-то в последнем разряде получается разница.
Потому дробные числа нельзя сравнивать через ===. Надо проверять, что их разница меньше некоторого значения. Подробнее
В случае гита в консоли ты напрямую отдаешь команды на получение или изменение данных. В случае ГУИ клиента это от тебя спрятано и ты хуже понимаешь, что происходит. Потому изучать лучше в консоли, а потом можешь пользоваться чем удобнее. Ну и ГУИ клиенты могут в каких-то сложных ситуациях работать не так и сбивать тебя с толку.
> Subtype Requirement: Let \phi (x) be a property provable about objects x of type T. Then \phi (y) should be true for objects y of type S where S is a subtype of T.
> function collectionToArray(collection) { > return Array.prototype.slice.call(collection); Кстати, если хочется извернуться с функциональным программированием, то можно написать так:
var collectionToArray = Array.prototype.slice... (дальше подумай сам)
> function getElemByIdWithContext(selector, context) { > return getElementsByProperty("id", selector, context); Тут неточность, при поиске по id надо сравнивать строку целиком, а не искать в ней частичное совпадение. Решить проблему можно функциональным программированием (которое тебе уже возможно успело надоесть в первых задачах) и отделением функции обхода дерева от функции проверки элемента:
var id = 'lalala'; findElementsRecursively(context, function (el) { return el.id == id; });
Второй вариант кажется неудобнее. Используя функцию partialAny, мы можем принести больше функционального программирования богу функционального программирования:
var findById = partialAny(findElementsRecursively, undefined, 'id', undefined, function (prop, value) ...);
>>930680 http://ideone.com/U1QFQk >Fatal error: Uncaught ArgumentCountError: Too few arguments to function ChildClass::__construct(), 0 passed in /home/lpoSIT/prog.php on line 28 and exactly 2 expected in /home/lpoSIT/prog.php:20
Суть задачи тут все же в определении классов, как ты сделаешь вывод - не так принципиально. Можно просто функцию сделать, класс, или так написать.
Если тебе хочется ООП подход, то обычно это делается через классы для построения отчетов. Я бы сделал класс например StatReporter такого вида:
$reporter = new StatReporter; $reporter->printReport($company);
Создание сотрудников можно просто сделать кодом, можно сделать отдельный класс, если хочется, который например получает на вход массив данных о сотрудниках, на выходе дает объекты.
> PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen() На сайте не включено расширение mb_string. Видимо что-то сломали. Попробуй другой сайт.
ну, не знаю. Я пробовал и с консолью пол года, и на ГУИ. Гуи удобнее и нагляднее, а с консолью иногда казусы. Мне кажется, гуи дает полный необходимый для работы функционал, потому что большей частью фич гита никто не юзает, да и мало там прям таких извращенных штук.
>>930686 Ага, я вчера тоже заметил такую хрень, когда просто менял саму сумму долга, а не долго+проценты и комиссия. Если меня только её - всё норм считает, так что можно считать что оно вроде бы правильно работает, хех. Но спасибо таки за ответ.
А так, это определяется рынком. Заказчик хочет заплатить как можно меньше и точно не больше, чем он получит прибыли от проекта. Исполнитель хочет получить как можно больше (те самые 300 к в секунду), но чтобы выиграть, он должен попросить меньше других. Но при этом нет смысла брать меньше, чем можно получить за другую работу.
Ну то есть если условно тебе надо неделю, и ты можешь вместо написания программы разгружать коробки в ближайшей пятерочке за 5000 р, то меньше просить наверно смысла нет.
А если например ты по какой-то причине не можешь разгружать коробки, других заказов нет, и живешь ты за бесплатно, то даже подвинувшись по цене ты остаешься в плюсе. Даже работая за 1 рубль ты можешь остаться в плюсе, если у тебя нет никаких альтернатив.
В общем, учись считать.
Смысла спрашивать, сколько бы мы взяли, мало, так как у нас другие обстоятельства: другие расходы, другой уровень знаний, другой набор заказчиков и альтернатив.
Что именно входит в задачу - не важно, важно, сколько у тебя на нее уйдет времени.
На твоем скриншоте я вижу, что ты запустил программу ssh-keygen и сгенерировал с ее помощью пару ключей. Публичный и приватный ключи были сохранены в виде файлов на диск (там написаны имена этих файлов). На экране выведен хеш публичного ключа по алгоритму SHA256 (и комментарий к нему). Ты эту строчку зачем-то выделил.
Хеши нужны, чтобы на глаз сравнить 2 ключа и понять, они одинаковые или нет.
Не очень понятно, что ты делал дальше и что не получилось.
Алсо непонятно, зачем ты генерировал этот ключ вообще. Ты не можешь дать ссылку на инструкции, которым ты следуешь?
Ну и конечно плохо, что ты сам не понимаешь, что делаешь.
>>930927 http://ideone.com/hrLgHQ Вот еще одно нарушение, уже без имени класса из переменной. Конструктор с другими параметрами ломает метод create() в классе-наследнике. Клиентский код ожидает, что метод будет работать, как и должен в родителе - по принципу Лискова. Но он не работает, тот же самый Fatal error.
Да, верно, получается что при использовании new static в предке наследники обязаны сохранять совместимость конструктора. То есть не всегда, а только в таких отдельных случаях.
Причем, разумеется, сам PHP это не проверят и предупреждений не дает. И по заголовку класса это никак не очевидно. То есть использовать new static - это закладывать мину замедленного действия в код.
Добавлю еще, что new static - это изобретение разработчиков PHP (которые по моим ощущениям ООП вообще плохо понимают), мне оно не нравится, в других языках вроде Java такого бардака нет.
Только вот пример коду у тебя опять неудачный. зачем ты там нагородил статических методов? LSP он про объекты, а не про вызовы статических методов. И он не гарантирует что статические методы потомка совместимы с предком.
Ты сам похоже пока плохо LSP понял.
Метод create должен быть не-статический. Должно быть так:
class Parent { public fnction __construct() {} public function test() { return new static; } }
class Child extens Parent { public function __construct($a, $b, $c) {} }
function doSomething(Parent $p) { $p->test(); }
$o = new Parent(); doSomething($o); // ок $o = new Child(1, 2, 3); doSomething($o); // ошибка
Вот этот код иллюстрирует вредность использования new static.
В общем, вся проблем в нестандартных особенностях PHP, помогающих стрелять себе в ногу.
>>931044 Хм, да, должна быть функция, которая объект принимает, чтобы было где тип родителя указать. Тогда вот так: http://ideone.com/zC5nTV Статические методы в PHP к объекту тоже применяются, значит принимающая объект функция тут же ломается, Лисков нарушен.
Ты опять полагаешься на странности PHP. Вот в этом коде: $object::method()
Это уже не ООП, а какое-то издевательство над ним. Статические методы и поля относятся к классу, а не к объекту, и вызываются на нем.
Ты должен писать ParentClass::method() для вызова статического метода.
А в твоем случае нужен обычный, не статический метод. Тем более, если ты хочешь, чтобы в разных классах он работал по-разному.
Про моему это просто код, написанный в плохом стиле.
Но раз уж ты так пишешь то да, получается, что в твоем конкретном случае наследники должны правильно переопределять статические методы. Но я считаю, это просто кривая реализация ООП в PHP, что так можно делать, из-за этого больше проблем, чем пользы. В частности, все эти тонкости неочевидны и легко сделать ошибку при наследовании. Потому такой код писать не следует.
Например, в Яве сделано по-другому. Там вызвается тот метод, который объявлен в тайп-хинте. То еть в функции:
public void doSomething(Parent p) { p.staticMethod(); }
Всегда будет вызван Parent::staticMethod() независимо от того, какой мы объект передадим. И правильно, нечего использовать статические методы не по назначению.
Пополняю серию. Правильно ли я установил события? http://ideone.com/GY8kav Ориентировался на твои слова:
> Также, в представлении могут быть методы установки обработчиков событий (например "задать обработчик клика по клетке"). Это позволит контроллеру не работать с DOM напрямую, а устанавливать обработчики событий через View.
> Чтобы узнавать о кликах по полю, контроллеру надо как-то подписаться на события. Это достаточно сделать один раз, перед игрой. Он может ставить обработчики событий напрямую, но наверно лучше делать это через представление, чтобы за работу с DOM, поиск нужного элемента отвечало оно.
К сожалению, совсем забыл проверить этого анона, исправляюсь.
https://github.com/masssn/students.loc/blob/master/db%20config.ini В конфиг имеет смысл помещать только то, что может менять пользователь. Опция driver тут явно лишняя, так как твой код скорее всего заточен под опредленную базу данных и с другой работать не будет, значит не надо давать ее выбирать.
> `gender` enum('Мужской','Женский') Тут принято использовать латинские идентификаторы. Для них также стоит сделать константы в коде.
> `group_number` text NOT NULL, Тут надо ограничить длину. Вообще, почитай про типы полей в MySQL.
> email` varchar(20) 20 символов это недостаточно для email
> `password` varchar(8) NOT NULL 8 символов для токена это маловато. Также, надо добавить с помощью слова COMMENT комментарий, что хранится в этом поле, чтобы другим людям было проще разобраться в твоей базе. Вот урок про комментарии: https://github.com/codedokode/pasta/blob/master/db/comments.md
Также, у тебя все файлы, включая конфиг БД, лежат в публичной папке. Если кто-то откроет URL http://example.com/db%20config.ini то он увидит пароли базы данных. Лучше сделать отдельную публичную папку, а все остальное разместить снаружи, почитай, это описано в комментариях к задаче.
https://github.com/masssn/students.loc/blob/master/app/controllers/Controller.php#L29 тут не очень хорошо сделано. Если ты хочешь требовать регистрацию, то надо не выводить форму на любой странице, а делать редирект на страницу регистрации. Если ты хочешь потом вернуться назад, то надо еще передавать URL исходной страницы (а перед редиректом назад проверять, что он на твоем сайте, иначе это будет открытый редирект).
Сама проверка тоже сделана неточно - ты проверяешь наличие куки, но не проверяешь, что она соответствует какому-то пользователю.
В методе action лучше было проверять весь URL, а не только первую часть. У тебя получается для одной страницы множество URL, что в общем-то плохо: /index/1, /index/2 и так далее. Лучше когда у страницы ровно один URL.
Данные надо экранировать по-разному в разных ситуациях. Для вывода на странице - одним способом, для вставки в базу данных - другим. Как ты это сделаешь одной функцией? Никак. На каждый случай должна быть своя функция. А ты просто налепил кучу функций, в надежде, что они тебя защитят, не пытаясь разобраться, что каждая из них делает. Что, если у нас в форме есть поле комментария и в него можно вводить любые символы? Твои кривые функции вырежут половину из них.
Перечитай мои уроки по XSS и SQL и сделай правильную защиту:
> if (!filter_var($datas['birth_year'], FILTER_VALIDATE_INT) && mb_strlen($datas['birth_year']) > 5 || mb_strlen($datas['birth_year']) < 4 || preg_match("^[A-z]^", $datas['birth_year'])) { Слишком много условий. Проще либо написать одно рег. выражение либо проверить что число в диапазоне между X и Y.
Аналогично с суммой баллов, лучше проверить что это число и что оно в определенном диапазоне.
Не очень понятно, почему у тебя везде передаются массивы. Не лучше ли сделать объект-модель студента и везде передавать его? В функцию валидации, в форму, в функцию сохранения в БД. Массив плох тем, что непонятно, какие в нем есть поля, а каких нет.
Класс DataHelper надо переименовать, например в StudentValidator.
Имена неймспейсов принято писать с большой буквы. app можно было и не писать вообще.
Неправильно писать datas, так как data это уже множественное число. Вообще, у тебя неудачно выбрано название функции: getNavDatas. Слово data не дает никакой полезной информации, так как любая функция работает с данными. Надо лучше выбирать названия для функций, чтобы они соответствовали предназначению функции.
В данном случае функция рассчитыает параметры пагинации, так и можно ее назвать.
Также, ты старательно избегаешь использования объектов и ООП вообще. Ты не сделал модель для студента, а передаешь везде массивы. В пагинаторе то же самое- ты возвращаешь массив, но лучше было сделать просто объект и у него методы getPagesCount(), getLink() и так далее. Попробуй переделать класс расчета пагинации на использование полей и методов вместо возврата массива.
Контроллер поиска и вывода списка студентов можно объединить в один. Аналогично можно объединить регистрацию и редактирование.
https://github.com/masssn/students.loc/blob/master/app/Singleton.php Зачем это? Не надо использовать паттерны там, где это не нужно. Есди ты хочешь изучить паттерны, изучи код библиотек вроде Symfony Forms или Doctrine, почитай книгу Фаулера (шаблоны разработки корпоративных приложений) и посмотри как их надо использовать на реальных примерах, а не читай статьи от тех, кто дальше синглтона ничего не понял.
https://github.com/masssn/students.loc/blob/master/app/models/StudentsGateaway.php#L40 public function addStudent($params) Эта функция написана неправильно. Она подразумевает, что ей будет передан массив содержащий строго определенные поля в определенном порядке. Причем этот порядок нигде не документирован. Стоит в форме переставить 2 поля местами, как все сломается.
Я советую передавать не массив, а объект студента с строго опредленным набором полей.
> setcookie('user_pass', $params["password"], time() + 3600000); Есть принцип единой ответственности, каждый класс или функция должна выполнять свою задачу. Как установка куки связана с вставкой студента в БД? Никак, ее тут быть не должно вообще.
> public function getLastId() Этот метод плох тем, что его можно вызывать только в опредленный момент, и это нигде не описано. Его тут быть не должно, если надо, то пусть функция вставки студента сохраняет куда-нибудь его id.
> " LIMIT " . $start . "," . $limit; Это надо было делать через плейсхолдеры.
> public function search($search, $sort, $start, $limit) > :x IN(name, second_name, group_number, summary) Для поиска надо использовать LIKE или что-то такое, так как твой вариант не позволяет искать по части фамилии.
> public function getCountBySearch($search) > WHERE > " . $search . " Надо использовать плейсхолдеры.
> <a href="/index/?sort=<?php echo $this->sort; ?>&page=<?php echo $i;?>">[<?php echo $i?>]</a> Не надо собирать ссылку по кускам. Лучше сделать функцию, которая ее генерирует.
> MinesweeperGame.prototype._addCellToDict = function(x, y, dict) { > MinesweeperGame.prototype._isCellInDict = function(x, y, dict) {
Тебе не кажется, что тут есть смысл сделать отдельный объект "двухмерный словарь" и писать dict.addCell(x, y) или dict.hasCell(x, y)?
Потому что сейчас у тебя там перемешаны игровая логика (как открыть и проверить соседние клеточки) и низкоуровневая работа со словарем (поиск в словаре, и тд). Это надо разнести хотя бы по функциям, а еще лучше в отдельный класс.
> И еще, стоит ли писать вот такую обертку вокруг метода реализации чтобы не кидать каждый раз свойства объекта ему в аргументы Если сделать отдельный объект, будет красивее и исчезнет обертка:
> ...ты имел ввиду действительно двумерный массив ([ [true, false], [false, false], [false, true], [true, false]) или словарь ( {1: {1: true, 2:false}, 2: {1: false, 2: false}, 3: {1:false, 2: true})? Если там могут отсутствовать клеточки, то словарь логичнее так как массив подразумевает что в нем все индексы есть, пропусков нет.
> Мне кажется, ты имел ввиду первое, а я делаю через второе и в некоторых местах трудности (например мучаюсь как создать мины при такой структуре чтобы не было вечного рандома. Когда у меня был массив объектов Cell я просто делал на него shuffle и превращал в мины n-ое количество равное числу мин). Можно ограничить число попыток, либо можно сделать отдельный массив координат, перемешать его и выставить мины в словаре.
> Правильно ли я установил события? У меня была идея убрать всю работу с DOM во вью, чтобы контроллер про него ничего не знал. И работал не с натиными событиями браузера, а с искуственными событиями, сгенерированными вью. Это например дает такое преимущество, что изменения в верстке затрагивают только вью, а не контроллер.
> this._domView.setLeftMouseDownEventToCell(function(event) { В общем да, нормально, только может функцию стоит как-то еще переименовать. Вроде addCellLeftClickListener, как-нибудь так.
> that._domView.setFaceType("danger-face"); Вот мне кажется, это должно называться по другому. Что обозначает значок? Что идет обработка события? Тогда логично назвать функцию как setIsBusy(true) или как-то так. И может быть, даже стоит сделать смену значка внутри view.
То есть мне кажется, лучше бы если вью просто выдавал событие клика по клеточке, а не отдельно mousedown/up. И чтобы контроллер не проверял e.which. И чтобы вью передавал в контроллер не event.target (который относится к DOM), а координаты. То есть я предлагаю всю работу с DOM и нативными событиями засунуть в вью, а из контроллера убрать. Разделить зоны ответственности.
> Все еще не ясно, что ты имеешь ввиду под использованием сервисов. В 83 треде ты писал, что: >> $app['validator'] = function() use($app){return new App\Helper\Validator($app);}; >>Это по моему нарушение принципа DI, получается не DI, а Service Locator > Нужно регистрировать сервис провайдеры или что?
Там проблема в том, что ты в сервис Validator передаешь весь $app целиком вместо указания конкретных зависимостей. Это паттерн ServiceLocator, и это описано в моем уроке по DI. В данном случае это плохо, никакого смысла так делать нет.
Надо так: new Validator($app->something, $app->em, $app->helper)
> 1 - я не храню пароль в базе, а в форме он должен быть В Симфони сделано так: там можно добавлять в форму элементы, которые не соответствуют полям в entity, и потом их значения можно брать из этих элементов, по моему так:
То есть часть полей идут напрямую в entity, часть остаются в форме.
> 2 - для проверки полей на UniqueValue() нужно установить doctrine bridge и doctrine bundle Doctrine Bundle в силекс, я думаю, не поставить, так как это кусок фреймворка Симфони.
> в официальной документации приводятся примеры использования yaml конфига, как альтернатива аннотациям, но проблема в том, что я использую силекс, а не симфони и тут все не так, как в симфони. А тебе не особо и нужна инструкция. Ты можешь посмотреть, как сделано в Симфони, и нагородить похожую схему. Там просто нужно создать и настроить объект, который будет читать аннотации из файлов.
> Чем больше модулей симфони прикручивается к силексу, тем больше мне кажется, что он изначально не предназначался для этого. Компоненты Симфони как раз сделаны так, чтобы их можно было использовать где угодно. Но вот часть функционала, которая не в компонентах, а в бандлах, ее придется делать самому. Но там часто просто нужно создать какие-то объекты и задать им нужные настройки.
> Если мы используем модель пользователя для регистрации, то зачем создавать отдельную модель для логина Ну логин все же немного другое, на мой взгляд. Форма логина - это не заполнение информации о пользователе. Это что-то вроде формы поиска.
>>>Я все же думаю, что это уже не задача формы - проверять логин. > Но это же не форма. Это валидатор, в который я передаю форму с констрантой. Не, это валидатор, который ты встроил в форму и который по сути становится ее частью. Мне кажется, проверка логина/пароля должна быть не в ней. А в коде, который использует эту форму. Ты же не встраиваешь сохранение в базу данных в форму. Надо разделять прием данных от пользователя и дальнейшее использование этих данных.
> Этот класс создан специально для того, чтобы проверить есть ли такая связка логин+пароль в базе, и если этот класс не может этого сделать, то зачем он тогда нужен? Он нужен, но должен вызываться в другом месте. Не ставиться как валидатор для формы.
> Что значит использовать сервисы? У тебя есть уроки использования или примеры таких сервисов? Сервис - это класс, который не представляет какую-то сущность, но содержит методы. Это довольно широкое определение получается, вот тут есть еще что-то по теме, но не очень понятно: http://design-pattern.ru/patterns/service-layer.html
Ну например мы можем сделать сервис для работы с БД:
class UserGateway { public function insertUser(User $user); ... }
У тебя в коде контроллера часть кода можно вынести в отдельные функции, а эти функции - в сервисы. Но ты вместо этого пишешь код стеной, не разбивая его на отдельные действия.
- выводом данных (printComments, очень странная функция) - а должен заниматься view - сборкой дерева комментариев (makeCommentTree) - а должна model (кстати используется неэффективный алгоритм, почитай потом урок https://github.com/codedokode/pasta/blob/master/db/trees.md ) - определением id текущего пользователя ($hash = $_COOKIE['fileshare'];) - а лучше сделать отдельную функцию для этого в отдельном сервисе авторизации - генерацией ссылок (return $app->redirect("/download/$fileId");) - а лучше сделать для этого функцию
- генерацией паролей и хешей, что относится к модели ( $user->setSalt(uniqid());, $user->setHash(md5($user->getEmail().$user->getSalt().$data->password));). Очевидно, в модели должна быть функция вроде setUserPassword, ты вместо этого просто пишешь код стеной - установкой авторизационных кук вместо сервиса авторизации
То есть тот код, который логично поместить в другой компонент или вынести в функцию, ты просто вписал в контроллер, даже не вынеся в отдельный метод.
Это и называется толстый контроллер (fat ugly controller).
Это затрудняет понимание и правку кода, мешает повторному использованию. ну например, нам нужно в другом месте получить дерево комментариев. Как это сделать, если код для этого жестко вклеен в контроллер и его нельзя вызвать из другого места? То же касается операций смены пароля, авторизации, генерации ссылок.
И еще. Если ты встроил проверку логина/пароля в форму, то как их проверить без формы? Тот же вопрос по поводу валидации комментариев, пользователей. Можем ли мы достать комментарий из формы или еще откуда-нибудь и проверить на правильность?
То есть, у нас должны быть какие-то классы (сервисы), часть модели, которые содержат операции вроде "сменить пароль", "залогиниться под пользователем X", "проверить правильнсоть комментария", "добавить комментарий" и тд.
Тебе надо изучить теорию про классы и объекты, ну например в учебнике из ОП поста или еще откуда-то. Ты явно какую-то тему проскочил и не понимаешь что такое объект, что такое поле.
$this->first_name это поле объекта $first_name это переменная, аргумент конструктора
> Почему нельзя написать вместо $this->first_name просто $first_name? Потому что в методе say_name нет такой переменной, и если ты не пропустил изучение функций, то должен знать что внутри функции видны только созданные в ней или переданные ей перменные, и $first_name там нет.
Тебе это кажется сложным, потому что ты изучаешь язык не последовательно, а пропустил более ранние темы. Или учебник плохо объясняет.
Ну ты говоришь объекты, это сложно. А реши задачу про Вектор или кошки-мышки из моего учебника без объектов. Будет еще сложнее. ООП как раз придумано чтобы позволить в больших программах разбивать код на отдельные изолированные классы чтобы с ним было проще работать.
Ну и если не использовать объекты, как в программе хранить информацию о каких-то сущностях? Вот у тебя есть гостиница, в ней номера, у каждого номера есть свойства вроде этажа, стоимости и тд. Как ты это будешь хранить и обрабатывать без обектов?
> http://ideone.com/WeGENR - Вопросы с абстрактными классами. В функции checkAnswer лучше было сделать только проверку, без вывода на экран. То есть пусть функция просто проверяет ответ, возврашает 0 или 1 (ну или true/false), или число баллов, а код, который ее вызвал, уже решает, что с этим делать.
Из-за этого у тебя еще и копипаста получилась.
Поле $tip логичнее было поместить в AbstractQustion так как подсказка может быть у вопроса любого типа.
Есть вот такая строка: $user->password = password_hash($data['password'], PASSWORD_DEFAULT); Пароль должен хешироваться в базе, но ниху не получается. Прописывается в таблице обычными символами, т.е. то что ввел юзер при регистрации. Чому так? Где я мог обосраться?
ОпенСервер, PHP 5.5, Апач 2.4, MySQL 5.6, регистрацию через подключенную RedBean
>>921312 >>>Задача 2: сделать функцию addProperty(object, name, initialValue) для создания приватных свойств с геттерами и сеттерами на объекте или прототипе объекта. >> https://jsfiddle.net/sh21j4p1/ >Тут опечатка в коде... Исправил, теперь всё работает: https://jsfiddle.net/sh21j4p1/1/
Я пытался задать метод через прототип и обратиться к нему в "конструкторе" функции, но мне выдалась ошибка о том что этот метод не является функцией: https://jsfiddle.net/3sjvm5gp/ Почему так получилось? Ведь если функция не находиться в объекте она ищется по цепочке в его прототипе.
>>908071 >Задача 3: сделать функцию для добавления в объект или прототип нового метода addMethod(object, name, fn). Что-то у меня не получилось понять подвоха этой задачи: https://jsfiddle.net/zmLjh7ur/ Более того, я не смог понять как работает функция super(): https://jsfiddle.net/b073aLb5/1/ В чем моя ошибка? Здесь же должна быть такая же ситуация, super должен искать метод в прототипе.
>>>Для ЛЭП проще всего указать нули и учитывать их вклад отдельно (сделать у них методы для получения информации, сколько мощности доступно и по какой цене). >> Лучше исключить её из перебора потому, что ЛЭП тоже может вернуть какое-то количество мощности. >Мне кажется, надежнее прописать там ноль, так как мы не знаем, какая у нее мощность. Ну или вообще не делать в ней метода getPower(), чтобы его не пытались даже вызывать. Но мы можем и даже должны иметь возможность узнать её мощность.
>>>> ElectricalNetwork.prototype.countPrice = function() { >>>> price += this.elements.countPrice(balance); >>>> balance = this.elements.countPower(balance); >>>Вот здесь нехорошо, что код расчета закупок/продаж размазан по 2 классам - ElectricalNetwork и PowerLine. Логичнее его оставить только в ElectricalNetwork. Ну подумай сам: кто принимает решение о закупке: электросеть или начальник на конкретной ЛЭП (или руководство удаленной сети, к которой подключена ЛЭП)? Логично, что решение принимают в центре, а на ЛЭП только сообщают, сколько нужно принять или передать, запрашивают цены и тд. Так как сама ЛЭП не знает про баланс энергии в сети. >>С другой стороны электросеть не знает о ценах и о внутреннем устройстве ЛЭП. Моя идея в том, баланс можно просто передать в условный счетчик. Ведь это для ЛЭП свойственно иметь и считать цену. >Электросеть не знает цены и пропускной способности, но она всегда может ее у ЛЭП спросить. ЛЭП сама не может ничего посчитать, так как не знает баланс энергии во всей сети, и не может решить, сколько надо закупать. Потому расчет, сколько энергии купить, должен быть в электросети. А почему ЛЭП не может спросить сколько энергии нужно? Тут дело даже не в этом, ЛЭП сама по себе ничего не спрашивает - мы просто передаем энергию и пользуемся её функцией счетчиком, который работает с её же свойством цена.
>> function PowerLine(power, price) { >> this.power = power; >> this.price = price; >> } >Мне кажется, тут неправильно используется свойство power, так как у ЛЭП это не фактически переданная мощность, а пропускная способность (сколько максимум можно купить/продать), и логично для нее использовать другое название, чтобы не было путаницы. В реальной жизни тоже некоторые свойства могут называться одинакового, не смотря на то что выполняют разные функции.
>> PowerLine.prototype.countPower = function(power) { >> var thispower = this.power;
>> for (var i = 0; i < thispower; thispower--) { >> if (power == 0) { >> break; >> }
>> power += power / -Math.abs(power); >что-то я не могу толком понять, что тут происходит. Зачем мы power делим саму на себя? Получится ведь либо 1, либо -1. Тут явно ошибка. Наверно я сбил столку неправильно назвав функцию - эта функция считает сколько энергии останется после передачи\получения её через конкретную ЛЭП.
power мы делим саму на себя чтобы узнать прибавлять или отнимать энергию каждый раз, чтобы достичь баланса, т.е. узнать обратный знак своего значения. То есть, мы каждый раз либо прибавляем или отнимаем по одному, до тех пор пока значение не станет нулём.
>> if (this.elements instanceof PowerLine) { >> price += this.elements.countPrice(balance); >> balance = this.elements.countPower(balance); >Тут нет расчета, сколько именно нужно купить. Нужно покупать не всю доступную энергию, а только ту, что не удалось произвести. Так баланс это и есть вся энергия которую не удалось произвести \ удалось чрезмерно произвести. Счетчики работают до тех пор пока он не станет нулевым или у ЛЭП не хватит больше мощности.
>Определение типа переменной >>>Недостаточно, надо бы проверить что там есть свойства от 0 до length - 1. >>>от 0 до length - 1 >> А как это выразить в условии >Написать цикл, проверяющий наличие свойств с помощью оператора in. А что с этим циклом делать? Нельзя же вернуть значение только по окончанию цикла, если in всегда были истины.
>>>> for (property in object) { >>>тут есть подвох, for in перебирает не только свойства объекта, но и его прототипов. Если кто-то расширит стандартный Object.prototype, это свойство или метод попадет в цикл. >> Опять же, не могу понять что с этим не так: Если это клон объекта, то этот клон должен иметь тот же прототип что и "донор"(?). >Не, до такой степени скопировать объект мы вряд ли сможем. Достаточно копировать только свойства самого объекта, копировать прототип не требуется. А понял. Подвох в том что копируется не сам прототип а только его свойства, верно же?
>Тут в коде, я вижу, есть поддержка копирования объектов Date и обычных объектов, а что с массивами? Для них ведь надо изначально создавать пустой массив и копировать элементы. А других встроенных объектов это замечание касается?
>Глубокое копирование >> https://jsfiddle.net/j8pydqsg/2/ >> var clone = new object.constructor; >Неприавльно вызывать конструктор. Мы ведь не знаем, какие аргументы у него есть и что в них надо передать. Надо делать так: > >- если источник - это Date, то создать новый Date, можно сразу передать правильное значение даты >- если источник - массив, создать новый массив и скопировать элементы >- если источник - другой объект создать пустой объект и скопировать все его свойства, не относящиеся к прототипам >- иначе, если источник - не объект (а число, строка, null и тд), можно просто вернуть его Переписал всё: https://jsfiddle.net/b0a7tk75/
>>921312 >Тут из-за кучи цитат становится уже трудно понимать некоторые ответы, если что-то непонятно, можно просто задать вопрос отдельно. Простите, я просто обычно делаю всё разом.
>>931926 Ты ОП? Подскажи пожалуйста, я вообще хотел язык программирования - кое-какие операции на компе сделать самым простым способом. Я года 3 назад в этом треде прошёл курс молодого бойца, так что помню что в ПХП есть всякие операции с папками и язык лёгкий. Или есть что получше?
Поясните насчет даты. Её лучше образовывать в бд или php скриптом? В БД с помощью типа DATE можно вывести дату запроса, есть ли смысл писать метку на php?
Подскажите пожалуйста зачем нужны анонимне функции? Уже с год пишу код и знаю о них, но на практике я так и не понял куда их впихивают, почему на собеседованиях про них спрашивают, и вообще почему в своё время столько шуму было про их введение. ведь на практике они как-бы и профитов не дают. Или я неправ?
Давай я тебе дам задачу. Есть какая-то сущность и коллекция этих сущностей (Работник и список работников, Ученик и классный журнал, Товар и Корзина, Товар и Склад). Можешь представить их как объекты или массивы, если не знаешь ООП.
Напиши функцию, определяющую сколько сущностей в коллекции соответствуют какому-то критерию. Критерий может быть любой. Ну например, сколько учеников выше 160 см или имеют среднюю оценку или чья фамилия начинается на гласную.
Напиши функцию, отбирающую массив сущностей, соответствующих определенному критерию.
Напиши функцию, находящую лучшую сущность по произвольному критерию (ученик с самой большой суммой оценок, с самой короткой фамилией, самый тяжелый товар, товар с самой большой скидкой, итд)
Напиши функцию, принимающую на вход массив сущностей и возвращающую массив вычисленных из них по произвольной формуле значений (например: на вход подаем товары с ценой и скидкой, на выходе - массив цен с учетом скидки, на вход - ученики, на выходе - массив средних баллов).
Как ты представишь в своем коде "критерий" или "формула"? Как передать в функцию этот критерий?
Решил поковыряться в массиве в боевом коде напрямую как в объекте через ссылку. Хуй знает как так получилось, но словил какой-то баг или особенность языка которую я не знал, что тупил целый час в итоге выискивал в чем там дело. Попытался этот "баг" сейчас на ideone воспроизвести что бы вам показать и в итоге нихуя.
Суть примерно в том, что в результирующем массиве должен был затираться элемент "6ab" и вместо него повторяться "5ab" еще раз.
Мб версия пыхи старая, мб еще что - не знаю, в общем кто поможет мб понять в чем обсер? http://ideone.com/LMl108
задача про студентов выглядит примерно как гайд "как нарисовать сову", подскажите как мне за нее взяться или что почитать если только прошел предыдущие уроки ОПа
>>932297 для начала установи апач\нгинкс, пхп и базу данных. Настрой все это, чтобы работало. Потом можешь начать с создания страницы с прикрученным к ней бутстрапом. Дальше расширяй и наполняй контентом. Аноны кидают тут свои гитхабы, можешь посмотреть как они делают.
Не нашёл JS тред, куда-то он уплыл с концами. У меня какая-то попобава. Если вставляю в html скрипт, например <input type="text" id="input"> <script> input.onblur = function() { console.log("ок"); }; </script> то он работает. А если вынести его в отдельный файл, подключив его в шапке <script type="text/javascript" src="core.js"></script> то не работает. В консоль браузера сразу при загрузки страницы падает ReferenceError: input is not defined
В другом месте вот такая функция не работает с той же ошибкой: $(function(){ $('td, .table-cell').click(function(e){//ловим элемент, по которому кликнули //.... }); }); Перечитал, как нужно js-скрипты в отдельный файл выносить - никаких особых камней там нет. Подключай сверху, да выноси на здоровье. Не понимаю.
>>932344 Там есть таки подводный камень, в общем у тебя js подключен в шапке, то там должны быть проверки на то что js ждет построения DOM дерева, иначе он будет пытаться выполниться до того как у тебя собственно html отрисовался и ссылаться на несуществующие id или class'ы на html странице.
А вообще ты возможно с путями проебался, попробуй в корень сайта кинуть а не в ту же папку в которой html лежит, ладно я хуевый советчик, простите :(
Прошу глянуть код гостевоху и надавать мне каких-нибудь советов, чтобы избежать ошибок, да хоть по оформлению кода, пока не стал пилить дальше https://github.com/grigoryMovchan/zuihitsu
>>932556 > Подскажите гайдов по парсингу html-страниц. >Хочу сделать страницу с ценами конкурентов. А смысл? Все будет ломаться при малейших изменениях в верстке.
>>932561 Ну так починить не долго, тем более там сайты работают годами на одних и тех же cms и с одной и той же версткой. Просто реально заебывает руками перебирать всех и смотреть кто начал демпинговать.
Здравствуйте, не нашел тред по JS, установил Subline, поставил туда Package Control, установил Emmet, но чет когда нажимаю восклицательный знак и таб - никуя не происходит. Что делать?
Файлы (HTML, JS) не могут загрузиться мгновенно. Они загружаются с какой-то скоростью.
Браузер парсит (разбирает) HTML и картинки поточно, по мере поступления (а вот JS и CSS файлы он сначала загружает целиком, а только потом применяет их).
Соответственно, когда у тебя скрипт в шапке получается такая ситуация:
- браузер запрашивает с сервера HTML страницу - браузер разбирает приходящий с сервера HTML файл по мере поступления - приходит шапка (head), браузер ее разбирает и создает соответствующие DOM элементы - затем браузер видит в HTML коде тег script. Он ставит разбор HTML на паузу и начинает загружать скрипт - когда скрипт загружен целиком, браузер выполняет записанный в нем код. В этот момент созданы DOM элементы только для шапки страницы, которые идут до скрипта и твой инпут видимо еще не создан - после выполнения JS кода браузер продолжает разбирать HTML файл дальше
Почитай статьи про то как работает браузер, например эти
Тебе тут советуют подключать скрипт в конце файла. Действительно, во многих статьях так советуют, но никто не объясняет плюсы и минусы разных подходов. Тут тоже есть недостаток:
- обработчик ставится на инпут не сразу, а только когда загрузится весь HTML файл. Какое-то время страница не будет реагировать на клики, и тд (я очень часто такое вижу). Еще хуже, кстати, когда JS скрипт при инициализации изменяет верстку и она прыгает в момент его срабатывания. Это указывает на уровень профессионализма фронтенд-специалиста. - если в коде ты ссылаешься на функции из файла, ну например <button onclick="something()"> то до загрузки скрипта клик по кнопке будет вызывать ошибку
Некоторые подключают скрипт в начале, но делают инициализацию по событию document.ready (оно срабатывает когда браузер разобрал HTML файл до конца и создал все дерево ДОМ). Этот подход имеет такой же недостаток.
Мне в голову пришел такой способ:
- сделать JS файл, содержащий только функции, но не ставящий никаких обработчиков никуда - подключить его в шапке - сразу после инпута поставить вызов функции инициализации внутри тега script
Также, можно использовать классические обработчики в HTML атрибутах: <button onclick="doSomething()">. Этот метод не всегда подходит (плохо стыкуется с ООП кодом).
Если не понимаешь, что я написал, то тебе надо изучить DOM получше и почитать статью по ссылке выше. И тогда станет понятно.
И что интересно, мало где описывается то, что я написал. Такая вот индустрия, такие вот люди в ней работают. Прыгающая верстка и не сразу работающие кнопки это норма для них. Вот киви кошелек например, на нем кнопки начинают работать только после загрузки страницы целиком. Зато у них используется ангулар и все на аяксе. А твиттер это вообще один большой сборник антипаттернов по построению интерфейсов. Кнопка "назад" в нем работает как генератор случайных чисел и никогда не знаешь, куда она тебя приведет. Алсо, меня периодически перебрасывает на мобильную версию по непонятной причине.
http://ideone.com/oDVbum можно ли делать вот такой return false как у меня в 14 и 16 строке? Не выбрасывать же исключение, если пользователь мисскликнул флагом по открытой клетке. На счет значка не совсем тебя понял что с ним делать. Это пикрелейтед 2 когда идет mousedown, и пик1 когда mouseup.
http://ideone.com/B91hZ0 перенес dom-заботы во View. Это нормально, что я всегда кидаю координаты из event.dataset к вызову любой функции func? Не знаю еще каким образом их можно передать из контроллера в представление.
Изучаю адаптивную вёрстку и заметил, что не получается уменьшить окно браузера меньше чем дом 480 пикселей примерно. Почему так? На видео вижу как люди уменьшают его до практически до 1 пикселя. Пробовал на всех браузерах.
> можно ли делать вот такой return false как у меня в 14 и 16 строке? Можно. Выбрасывать исключение или нет определяется требованиями к функции, как ты ее спроектировал. Но желательно в комментарии к функции писать об этом. В твоем случае этот return false ни на что не влияет, но в других случаях, если не проверить результат функции, может появиться какая-то ошибка.
> this._flags.addCell(x, y); > this._flagsCounter--; А мы не можем вычислять число оставшихся флагов через разницу между числом мин и числом в this._flags? Можно было бы избавиться от лишнего поля и и риска его рассинхронизации с другими полями.
> На счет значка не совсем тебя понял что с ним делать. Это пикрелейтед 2 когда идет mousedown, и пик1 когда mouseup. Я предлагал рассмотреть вариант, когда переключение значка делается во View, и контроллер о нем даже не знает. Если он переключается только при клике и никак не связан с игровой логикой.
> this._domView.preventContextMenuOnField(); Вот это явно ведь должно быть во view. Ведь это особенность браузера, что правый клик открывает меню, и пусть вью борется с этим явлением сам.
Я рассуждал так: можно сделать всю работу с DOM во вью, чтобы он наружу выставлял только методы и события, которые никак с DOM не связаны (в общем, инкапсулировать работу с DOM внутри вью). Этакое абстрактное игровое поле, и внешний код не знает ничего о том, как оно там внутри реализовано, и вообще используется ли там DOM.
Условно, если мы завтра поменяем полностью верстку или вообще сделаем вывод поля на другой, не-DOM технологии (например, будем рисовать на канвасе), контроллер останется неизменным. Но даже если мы ничего не будем переделывать, разделение ответственности делает код организованнее и понятнее.
Соответственно, сообщать отдельно о нажатии и отпускании кнопки мыши в контроллер не требуется (если я правильно все понял) - ему достаточно лишь знать о завершившемся клике по клеточке.
> Это нормально, что я всегда кидаю координаты из event.dataset к вызову любой функции func? > каким образом их можно передать из контроллера в представление. Из представления в котроллер, ты имел в виду? Да, можно через аргументы, можно сделать объект события, если хочется усложнить.
Кстати, а ты не хочешь автоматизированные тесты позже к своему саперу попробовать написать, чтобы они проверяли например игровую логику? У меня есть обзорный урок по тестам, и я это всем предлагаю, кто дошел до каких-то абстракций, паттернов, архитектур и тд.
Тестировать естественно в первую очередь модель, это и проще, и полезнее.
Я проверил на Хромиуме, по ширине пустое окно ограничено 337 пикс, по высоте можно хоть 0 пикселей сделать. Фаерфокс - то же самое.
Я думаю, HTML тут не при чем, это особенности браузера, ну например, кнопки и поля на панели инструментов меньше не сделать, или может там просто в коде прописано такое ограничение.
Ты можешь 1) увеличить масштаю, что уменьшит ширину 2) использовать режим тестирования адаптивной верстки, в Хроме это Ctrl + SHift + I -> иконка смартфона, в Фаерфоксе то ли пункт в меню, то ли кнопка в отладчике.
Еще ты можешь сделать iframe любого размера и в нем открыть свою страницу.
Под 1 пиксель проверять верстку не требуется. Проверяй на реалистичных разрешениях, http://mydevice.io/devices/
Скорее всего просто ты не понял логику работы скрипта или что-то не заметил и ты думаешь, что берется одна переменная, а там берется другая, с исходным паролем. Или может сразу из POST он берется.
Если ты думаешь, что проблема в password_hash то просто протестируй ее, дай ей что-нибудь и проверь что будет на выходе.
PHPч, существуют ли какие нибудь API в открытом доступе для совершения переводов средств между клиентами банковских систем типа сбербанк, альфа-банк, запсибкомбанк? А то пока что я увидел только то, что банки просто так не выдают API. С кем то (сбербанк) нужно связываться и говорить, зачем нужен API, у альфа-банка вроде чуть попроще, но всё равно нужно получать токен приложения и всё такое.
Как я понял, у них мок это объект, ожидающий, что на другом объекте (который передался в конструктор мока при создании) будут вызваны определённые методы: var dep = {foo: function() {}}; var depMock = sinon.mock(dep); dpeMock.expects("foo").once();
// передаём объект dep как зависимость тестируемого класса ...
// убеждаемся в том, что на объекте dep был вызван метод foo один раз: depMock.verify()
А что делать если тестируемый объект проверяет переданные аргументы через instanceof? По ссылке на stackoverflow предлагают вместо этого преверять наличие только нужных методов, но это же неудобно, что если их много? Делаю сейчас так: var dep = {foo: function () {}, __proto__: FooClass.prototype} // дальше то же, что и вверху
Нужна другая (нормальная) библиотека для моков, которая бы производила объекты с правильным прототипом (я могу путать, но по моему instanceof просто проверяет наличие прототипа конструктора в цепочке прототипов объекта).
Стандарт, который довольно трудно понять, говорит примерно то же:
> var dep = {foo: function () {}, __proto__: FooClass.prototype} Это неправильно. __ proto __ не определена стандартами и не обязана работать везде и всегда.
>>932401 >иначе он будет пытаться выполниться до того как у тебя собственно html отрисовался и ссылаться на несуществующие id или class'ы на html странице Билять. Вот оно что. А пути правильные, проверял уже (они и так в корне). >>932408 Попробую. >>932461 Хех, читал эту статью. Всё это хрень. Может на собеседованиях и спрашивают, а реально нет смысла гнаться за трендом. Делай так, как работает, и хрен с ним. Заказчику глубоко наплевать. Да и как по мне, самый простой код - самый лучший. Если можно обойтись без усложнения, то лучше это сделать. >>932749 >- сделать JS файл, содержащий только функции, но не ставящий никаких обработчиков никуда >- подключить его в шапке >- сразу после инпута поставить вызов функции инициализации внутри тега script Пожалуй, этот способ самый оптимальный, так и сделаю.
И ведь читал про выполнение кода со страницы, а про вызовы с конкретными id не дошло. Решил, что раз функция срабатывает после некоего события, то до события этот кусок кода просто не используется. А когда используется, все id уже поименованы. Окей, мне стало понятнее.
Сап, пхпач, помогай. Не знаю как реализовать класс с текучим интерфейсом (fluent interface). да, это моё тестовое задание. остальные сделал, а это в душе не ебу как. >Создайте класс, принимающий в конструкторе JSON-строку и позволяющий получить элемент через текучий интерфейс. Конструктор, понятное дело, запилил, это херня. А вот как быть с методом get -- не представляю. Аноны, подскажите как реализовать подозреваю, что тут что-то связано с замыканиями.
Вопрос к ОПу. Вот он пишет, что тех кто говорит про то что одинарные кавчки быстрее двойных, надо пинком скидывать с крыш многоэтажки. Но ведь они и правда быстрее: в двойных кавычках пхп проверяет наличие переменных, а в одинарных не ожидает их встретить. В чем я не прав?
Не, JS это не декларативный язык вроде CSS и конструкция
$('#abc').click(...);
это именно команда: найти все элементы с id = abc, которые есть в данный момент, и повесить на них обработчик. Она не повесит обработчики на добавленные в DOM позже элементы.
А ты попробуй сделать тест, например создать 10000 строк в одинарных кавычках и 10000 в двойных и сравнить разницу по времени при создании одной строки.
Код с одинарными кавычками требует больше времени на написание и хуже читается:
echo 'a=' . $a . ', b = $b'. ...
И это ухудшение не стоит нескольких нано- или микросекунд.
Это называется "микрооптимизация", когда время разработчиков (и деньги) тратится на такие бесполезные улучшения, которые дают сопоставимый с погрешностью измерения выигрыш. Если бы они хотели ускорить код, они бы занялись более полезными вещами: поменяли алгоритм, оптимизировали запросы к базе данных итд.
> в двойных кавычках пхп проверяет наличие переменных, а в одинарных не ожидает их встретить А это важно только на этапе компиляции. При использовании кеширования опкодов (opcache) компиляция длеается только один раз, а дальше скомпилированный скрипт берется из кеша и разницы не будет (как мне кажется).
Давай проверим, во что скомпилируется строка в одинарных и двойных кавычках. для этого нужно расширение vld, которое показывает опкоды, в которые превратилась твоя программа. Оно легко ставится под линуксом, под виндой не пробовал использовать.
> php -dvld.active=1 -r 'echo "Hello world";' line # E I O op fetch ext return operands ------------------------------------------------------------------------------------- 1 0 E > ECHO 'Hello+world' 1 > RETURN null
Как видим, наш код скомпилировался в 2 инструкции, echo и return.
Теперь поменяем вид кавычек:
line # E I O op fetch ext return operands ------------------------------------------------------------------------------------- 1 0 E > ECHO 'Hello+world' 1 > RETURN null
Как видим, коды после компиляции получились точно такие же.
А вот как выглядит результат компиляции программы с переменной внутри двойных кавычек:
> php -dvld.active=1 -r 'echo "Hello $x world";'
line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 1 0 E > ADD_STRING ~0 'Hello+' 1 ADD_VAR ~0 ~0, !0 2 ADD_STRING ~0 ~0, '+world' 3 ECHO ~0 4 > RETURN null
Вот тут действительно видно как строка собирается по кусочкам.
А, хотя в твоем случае надо писать не return $this. Подумай сам, что надо возвращать. Или поищи готовые аналогичные библиоетки, например, phpQuery какой-нибудь.
Я не >>933058, но сделал маленький тест. Сгенерил миллион строк в php 7.1: 3 подстановки vs 6 конкатенаций (оно вообще употребляется во множественном числе?). Подстановки отрабатывают на 15-20% быстрее.
Пытаюсь разобраться с шифрованием. Не могу понять на чём путаюсь.
Допустим я хочу написать сервис по обмену сообщениями, и при этом хочу чтобы эти сообщения ни кто не мог прочитать кроме собеседников. Никогда! Вообще!
Я ознакомился что для шифрование применяется при помощи ключа. Но где хранить этот ключ? Если сохранить его в БД, то доступ будет не только у собеседников, но и у тех у кого есть доступ к БД. Нужно сделать так чтобы ключ оставался только у собеседников. Может для этого выступить сам пароль от сервиса? Сомневаюсь что это будет надежно, потому что пользователи вряд ли будут делать пароли длиннее, к примеру, 12 символов.
1) ^ это операция XOR, а не возведение в степень. Не перепутал? 2) при возведении в степени вроде 10 000 получаются гигантские числа. PHP такие числа хранит в float формате, который сохраняет 8-16 знаков из числа, а нужно точное представление. Потому надо брать расширения для работы с большими целыми числами:
Также, потом советую глянуть расширение openssl, содержащее готовые функции шифрования (но сначала попробуй написать свою): http://php.net/manual/ru/book.openssl.php
Насчет кода - должны получиться именно одинаковые числа. Потому что (x ^ y) ^ z = (x ^ z) ^ y. Остаток от деления нужен для того, чтобы неприятель не мог догадаться, какие были исходные числа, проведя обратную операцию.
Нет, всё равно попобава. С JS-функциями. В index.php стоят две одинаковые кнопки: <div><a href="javascript:void(0)" onclick="show_flights_table()" id="a_save_object" class="a_demo_three b_green" title="Показать таблицу">Показать таблицу</a></div> и <div><a href="javascript:void(0)" onclick="add_line_in_flights_table()" id="a_save_object" class="a_demo_three b_green" title="Добавить строку">Добавить строку</a></div> Там же в хидере подключён скрипт <script type="text/javascript" src="core.js"> В core.js стоят функции function show_flights_table() { ... } и такая же function add_line_in_flights_table() { ... } Нажимаем первую кнопку - всё ок, никаких варнингов, браузер показывает таблицу. Нажимаем вторую - хром ничего не делает, выдаёт Uncaught ReferenceError: add_line_in_flights_table is not defined at HTMLAnchorElement.onclick (index.php:54) А если запустить через файерфокс, то вторая кнопка срабатывает. Правда, там дальше начинает ругаться на $(div).html(data);(ReferenceError: $ is not defined[Подробнее] core.js:262:5), но это уже другой вопрос. Я даже пробовал стирать из второй функции вообще всё между { }. Всё равно not defined. Да как так-то?
>>933643 Я думаю, из-за 2 одинаковых id подряд. > onclick="show_flights_table()" id="a_save_object" >onclick="add_line_in_flights_table()" id="a_save_object"
Скорее всего ты намешал там где то джиквери. когда ты вызываешь "onclick='function()'", она должна быть в глобальной области видимости (принадлежать объекту window), возможно твои функции обернуты во что то, хз, покажи код хоть.
Ну и еще: >a href="javascript:void(0)" Если нет ссылки, почему бы просто не опустить параметр href?
>>933654 >Если нет ссылки, почему бы просто не опустить параметр href? А так можно? Мне казалось, что это что-то вроде стандартной заглушки для большего фен-шуя. >Я думаю, из-за 2 одинаковых id подряд. Да, есть такое. Исправил. Но ошибка та же. >Скорее всего ты намешал там где то джиквери. Чего нет, того нет. По нажатии на кнопку запускается js-скрипт, оттуда аяксом запускается php-скртипт и выполняет что-то там с базой. Раньше так делал, всё работало нормально.
Сап аноны, нужна помощь. написал сайт на yii2. для мультиязычности юзаю куки и сессии ,но какого-то черта yii перезаписывает мою куку для языков чем-то вроде этого ef2e3b878bea166e1a349599475821d6b94b13cb609c8db980144ff065535613a:2:{i:0;s:5:"_csrf";i:1;s:32:"Q7hju019PJ61cOMbR1Y4Bm9V4stpWCpU";} я не ебу что это такое ( ну только догадываюсь) что-то связанное с безопасностью. кто знает как с этим бороться, что делать?
>>933684 Вообще, я тоже для всяких интерактивных элементов использую тег "<a>" без href (НО ТАК НЕ НАДО ДЕЛАТЬ, лол). Например для кнопок есть "<button>" и т.п.
У тебя там жесть какая то в примере. Вот сравни я упростил: https://jsfiddle.net/Lwv50ps3/ - так работает. Вопрос, почему у тебя функции не попадают в глобальную видимость. Если ты там прямо из проекта скопипастил кусок кода, то у меня для тебя плохие новости: ты ничего не понимаешь в хтмл, no offence
>>933780 Ящитаю, это какой-то глюх Хрома. Может быть даже конкретно моего. ФФ даже не морщится. >прикрепил к глобальной видимости (window) И ничего страшного, что прикрепление происходит после самой функции? При чтении, браузер читает сначала всё, что вне функций, а только потом их, так вроде?
>>933782 >И ничего страшного, что прикрепление происходит после самой функции? При чтении, браузер читает сначала всё, что вне функций, а только потом их, так вроде? Первый раз слышу, если честно. Никогда никаких проблем не было с таким подходом.
Обработка GET и POST запросов должна происходить в разных методах с точки зрения MVC? Допустим есть страница с формой. Если приходят по гет, то просто рисуем вид, а если пост, то нужно обработать. Посылать ли в этом случае с формы на другой action чтобы обрабатывать его другим методом? По идее так и надо делать, т.к. метод должен выполнять одну ф-цию
>>933994 > в разных методах с точки зрения MVC? В разных методах класса-обработчика.
>Если приходят по гет. То обрабатываем обработчиком и контроллеру отдаем решать что с ним делать. >а если пост то обрабатываем обработчиком и отдаем контроллеру решать что с ним делать.
>>934007 >класса-обработчика. Что под этим подразумевается? Обычно роутинг настроен так, что запрос от пользователя попадает в метод контроллера (экшн). Меня интересует в разных ли экшенах обрабатывать гет и пост запрос для одной страницы, учитывая, то если запрос гет, то там нужно только вид отрендерить.
>>934081 Нет принципиальной разницы: можно в одном экшне, можно в разных. Если у тебя там мало кода, то, как по мне, проще читать один экшн, да и разделение на 2 экшна вынудит копипастить код.
Анон, помоги решить проблему. Есть ajax-запрос, который отправляет данные к php-файлу. В этом php-файле идёт валидация данных, после чего эти данные записываются в переменную $_SESSION в виде json-массива. Как только это происходит, в теле функции .done() в ajax-запросе происходит переход на поддомен, на котором пыха знать не знает о сессии. То есть, сессия просто NULL. В чём могут быть подводные камни кросдоменных сессий? И какого хуя моя сессия не передаётся на поддомен?
>>934134 После case должна быть не точка с запятой, а двоеточие. И нахуя ты используешь альтернативный синтаксис, если у тебя сплошной код без разрывов?
>>934139 Это суперглобальная переменная, которая хранится вне зависимости от домена. Главное, чтобы на одном сервере. Кстати, проблему решил буквально только что одной строчкой кода:
Нет, тебе сначала надо изучить механизм работы сессий (прежде чем его вообще использовать) так как ты его явно не понимаешь. Сессия это не переменая. $_SESSION это лишь механизм для доступа к одной сессии из хранилища.
Хочу прокачать свой английский в техническому плане, кто как осваивал его? На каком уровне нужно знать пхп, чтоб устроиться на стажировку?что обычно спрашивают на собеседовании, что нужно делать стажировке.
ОП, проясни пожалуйста механизм работы реалтайм-индексов в sphinx. Как я понял, эти индексы непосредственно к таблице никакого отношения не имеют и создаются только внутри сфинкса, так? То есть, применительно к задаче на файлообменник, для того чтобы эти индексы заполнялись при добавлении файла, дополнительно к запросу на заполнение полей таблицы нужен еще и запрос для заполнения реалтайм-индекса? Далее, при использовании реалтайм-индекса невозможно сразу получить все поля строки, т.е. если у нас проиндексировано только имя файла, то сфинкс отдаст в виде результата поиска только айдишник(и), по которым придется еще раз делать запрос, но уже непосредственно в БД, для извлечения строк с найденными сфинксом айди? Или нужно все поля в индекс загонять?
>>934181 читать со словарем, плюс смотреть ютуб и т.д. практика короч. если есть желание фундаментально прокачаться, еще нужно добавить какой-нить видеокурс по произношеию типа american english и учебник по грамматике, допустим English Grammar by Raymond Murphy. я английский знаю норм (не считая литературного), но моей главной проблемой является лень читать на английском, если есть страница на русском, потому что для обработки английского текста требуется больше усилий, даже если все слова известны. но перебарываю себя, надеюсь, однажды эта разница сгладится и мне будет похуй, на каком языке читать.
по поводу собеседований, я был пока на одном, в моем случае были тесты на php (с вопросами на уверенность знания мануала, типа как отработает данная функция с переменной которая внутри указана как global, что вернет функция со ссылками, как отсортировать с изменением индекса в обратном порядке и тд) и в данных тестах было также много вопросов по sql и js, что подпортило мои результаты. в интервью классических вопросов, которые я ожидал (что такое синглтон, чем абстрактный класс отличается от интерфейса и т.д.) не было, зато были вопросы чем апач отличается от нджинкса, что происходит между отправкой запроса и выводом результата. такие вопросы на общую грамотность. возможно это была больше работа из серии "веб-мастер", поэтому там все было с перекосом в эту сторону.
>> На каком уровне нужно знать пхп, чтоб устроиться на стажировку? я для себя понял так, что все, что написано в мануале, нужно знать уверенно, а не на уровне "ээ, я помню где про это написано, нужно залезть освежить".
плюс учебные проекты, которые у тебя есть, нужно максимально причесать, чтобы не говорить "вот тут такой-то функционал не работает, потому что это учебный проект"
>>934504 Если просят, чтоб был опыт в коммерческой деятельности, можно ли обойти это на собеседовании ? С каким редактором лучше работать?(пхпшторм не вариант)
>>934653 Почему пхпшторм не вариант? Единственная нормальная IDE. У меня как-то коллега в саблайме писал, так я подходил к нему и просто охуевал с того, как он каждый класс в глобальном поиске ищет.
Sublime 3 умеет переходить к классу и функции по имени. А к файлам по имени умеет переходить Sublime 2. Не понимаю, зачем там поиск. Наверно чтобы найти все случаи использования класса.
>>934653 если просят чтоб был опыт, то нужно либо соврать, что он был (что вполне реально, допустим найти левый сайт вебстудии и сказать, что клепал там визитки и интернет магазины), но могут заебать вопросами и спалить, либо сказать, что опыта нет, но я вот умею то и это, вот мои готовые проекты. я бы выбрал второй вариант.
если религия найти ключик к шторму в торрентах, то наверное netbeans. я начинал с нетбинс и в принципе было нормально, но потом перешел на шторм и понял, что потерял время. для меня самый большой плюс шторма это документация и туториалы в ютубе.
кстати на собеседовании также могут спросить, каким ide пользуешься, явно ожидая, что ты скажешь "штормом". у меня так и было.
Чому при записи кириллических символов в сессию они потом отображаются в виде Юникода? Например, вот это \u041c\u043e\u0441\u043a\u0432\u0430 = Москва.
>>934039 Я только что понял что значит этот алгоритм. Я думал что среди аргументов есть само сообщение которое нужно зашифровать, и алгоритм конкретно предназначен именно для этого, но оказалось что он только генерирует ключ по которому сообщение будет шифроваться.
Хорошо, на вопрос как одним из способов шифруются сообщения мы ответили, но что если помимо обмена сообщений, я хочу, чтобы сообщения навсегда сохранялись в БД. Если сессия(?) прекратит свое существование, то все параметры который нужны для алгоритма будут утрачены. Я вижу только один вариант с хранением этих параметров или самого ключа в БД. Но я, опять же, тут наступаю на свой хвост: Если ключ храниться в БД, то возможность расшифровать сообщения есть не только у собеседников, но и у тех у кого есть доступ к этой самой БД. Есть ли какие-нибудь решения этой проблемы или я хочу невозможного?
- хранить закрытый ключ в браузере (например в localstorage), если пользователь очистит данные в браузере, то ключ надо создавать новый, старые сообщения не расшифровать - тут есть риск, что злоумышленник, захвативший компьютер пользователя, может извлечь его закрытый ключ. Для борьбы с этим можно зашифровать закрытый ключ паролем - также, остается риск, что злоумышленник захватит сервер и запустит в браузере пользователя свой код, например, извлекающий закрытый ключ и отправляющий его злоумышленнику. Для борьбы с этим надо вместо сайта использовать отдельный клиент, например, расширение к браузеру или вообще отдельное приложение (Electron позволяет создавать приложения на HTML) - можно вообще не хранить историю ни на сервере, ни в браузере
В общем, подумай, что тебе нужно: нужно ли хранить историю, кто должен иметь доступ к сообщениям и тд.
Если ты хочешь хранить сообщения на сервере (для истории и синхронизации), то надо хранить их зашифрованными. А ключ хранить где-то в другом месте. Но может быть лучше вооще их не хранить? Или хотя бы спрашивать пользователя, хочет ли он вести запись истории или нет. Программа, которая уважает приватность пользователя, не должна ничего записывать без его согласия.
>>919074 (OP) Реквестирую гуру книжного php. обмазался за много лет пиком, но так и не начинал читать. сейчас думаю с чего начать, может быть анон мне в этом поможет? хотел бы услышал порядок прочтения этих многобукав
>>935100 я когда спрашивал про книги у своего препода по этому делу (его квалификация у меня сомнений не вызывает, работает тимлидом), он говорит все переведенные книги по php - неактуальное говно, которым надо топить печь. думаю он имел в виду примерно такую литературу, как на картинке.
а рекомендовал он например такие книги: роберт мартин "чистый код" роберт мартин "идеальный программист" чет фаулер "программист-фанатик"
Аноны, установил apache2, php, mysql-server, mysql-client, phpmyadmin на убунту 16.04. При переходе на localhost/phpmyadmin/ отображается php файл как есть, т. е. не интерперетируется. Что я сделал не так?
как можно работая в шторме настроить браузер (или сам шторм), чтобы при изменении php кода в файле браузер рефрешился? live edit, насколько я понял, работает только при редактировании html, css и js.
подскажите кто знает, а то уже заебался. не верю, что тут нет этого, в netbeans же был netbeans connector, который именно эту полезную функцию выполнял.
Я не знаю, есть ли такая функция, но советую отвыкать от такого режима. Лучше сесть, все сделать, и потом проверять, чем обновлять страницу каждые 10 секунд. Если тебе надо отследить, как происходит выполнение кода по шагам, попробуй использовать отладчик.
>>930671 > Ну например, ты требуешь, чтобы все скидки были в процентах, и не даешь возможности написать произвольный алгоритм расчета скидки.
Тогда предлагаю ввести дополнительную абстракцию. Например, нужно добавить такую скидку: если среди товаров есть A и B, то снизить их суммарную стоимость на 20 единиц (не процентов). То есть раньше у нас было "снижение стоимости" основанное на процентах, теперь добавляется "снижение стоимости" в виде фиксированного значения. Код в классе Calculator поменялся с
> Потому дробные числа нельзя сравнивать через ===. Надо проверять, что их разница меньше некоторого значения А мне нужно это реализовывать?
https://2ch.hk/pr/res/898502.html#919067 > Что касается комбинирования скидок - вот я не уверен, что тут его стоило делать. Я такие штуки видел во фреймворках, кажется,что они позволяют строить произвольные комбинации объектов, но на практике это не особо нужно и проще в коде прописать нужное условие.
>>934653 >>934654 Phpstorm никто вам на работах ставить не будет, дорого. Учите netbeans или eclipse, он везде. Как вариант notepad++, но это неудобно.
>>935100 Я бы на твоем месте не читал все это говно, а читал напрямую документацию на http://php.net/manual/ru/ Обязательный раздел справочник языка. Дальше читай книги в шапке (Шлосснгейл, Зандстра). Еще http://www.phptherightway.com/ хорош. PSR стандарты почитай на http://www.php-fig.org/psr/, научат код нормально оформлять и велосипеды не изобретать. Ну и пасты опа конечно все перечитать. Остальные твои книги на потом оставь, будешь читать в последнюю очередь, там все равно обычно ничему хорошему не научат. Зато если их в конце читать будешь, то сразу уже видно будет, когда тебе какое-нибудь говно навязывают, вместо общепринятых практик.
>>935512 ООП освоить надо сначала на примере PHP. Зандстру читай из шапки, очень доступно объясняет. После него уже любая книга по паттернам нормально идет, он там в конце еще и упомянает, какие дальше прочесть можно.
Вкатываюсь в PHP. Поставил PhpStorm и Apache под линуксом. Смущает одна проблема: каждый раз перед запуском приходится деплоит каждый файл отдельно. Думаю, можно это делать как-то более удобно, но нагуглить не получается. Лучше всего чтобы можно было по одному нажатию сразу деплоить и запускать.
>>936017 У тебя работа какая-то не очень правильная, мне с первого дня дали мак (на выбор еще убунта была), два здоровских монитора и лиценщионный шторм. Как можно вообще работать в эклипсе и небинс? Шторм на голову выше всех этих поделок
Сап, аноны. Есть диплом, который написан на symfony. Препод сказал, что это слишком сложно для нашей шараги и нужно писать без фрейма. Что можно сделать, диплом достался нахаляву и писать заного вообще нет желания. В вебе я чуть умнее сапога.
Обычно не пользуюсь pecl'ем, но тут open source проект и автосборка с тестами. Такой вопрос: pecl.php.net всегда работает как говно или сегодня у него просто не тот день?
Всё утро пытался настроить phpunit в своём phpstorm, чтобы он распознавал классы юнит-тестирования. Пробовал и через встроенный композер, и вручную пфар указывал, перезапускал несколько раз, ничего не помогало: жаловася на Undefined class PHPUnit_Framework_TestCase. Потом залез в исходники пфара и посмотрел тамошние неймспейсы, вручную изменил нижние подчёркивания на бекслеши — и заработало. ~_~ Очевидно, проблема в каком-то автолоадере, который не обучен заменять подчёркивания на слеши. Интересно, в каком. И почему это не работает из-коробки? Или, возможно, использовать PHPUnit_Framework_TestCase это устаревший подход?
И вообще, расскажите занимательную историю, почему вы не перекатываете тред после 500 поста? Вам не важно, что он уходит на дно раздела и никому не виден? Вам не нужны здесь новые люди?
http://windows.php.net/ эта блять помойка лежит уже пол дня, и это единственное место где можно скачать PHP под апач. Чтобы авторы и админы это херни сдохли от рака блять.
>>936282 Периодически все равно тред пересоздается же, новые люди приходят. А кто изучать взялся, все равно тут по многу тредов сидит уже. Вот реклама в /b не помешала бы, там часто народ создает треды о программировании и не знает с чего начать, надо бы им сюда ссылку кидать.
А ты разобрался с возможностями PhpStorm? Он немного умеет деплоить, а именно: копировать файлы в другую папку, копировать их по FTP итд. Все нажатием одной кнопки. Как именно у тебя организован деплой? Как настроен сервер, какие папки итд?
Вопрос был больше по особенностям PhpStorm. Я не думаю, что ему нужны сторонние инструменты. Сам я кстати в большинстве случаев использовал самописные bash скрипты. Которые умеют например, копировать только измнившиеся файлы, чем экономят время.
>>936752 > надо бы им сюда ссылку кидать. Ты потом будешь лично код каждого из этих случайных вкатывальщиков из /b проверять? Я так-то тоже случайный, но хотя бы в состоянии без сторонней помощи зайти в раздел по программированию.
>>936977 спасибо, я постараюсь переделать, хотел спросить еще почему при выводе студентов первая запись не отображается, а начинает выводить только со второй, а первую запись выводит уже на 4 странице
Установил ПХП 7.1.2 и Апач 2.4.25 на комп (в данный момент на винду), не работает расширение mbstring. В php.ini прописал(раскоментил): extension_dir = "ext" extension=php_mbstring.dll Апач перезагружал, все равно выдает ошибку 500, если загружать в браузере, в логах PHP Fatal error: Uncaught Error: Call to undefined function mb_strlen
Туповатый вопрос от туповатого вкатывалищика-ньюфага: как вывести элемент из массива, который уже в массиве? К примеру: $massive = array ( 'massive' => array ( 'massive1' => 'govno', 'massive2' => 'ne rabochee' ) ); Вот как мне вывести отдельно "говно" и "не рабочее"? Пишу echo "тут должно быть {$massive['massive']}" - пишет просто "Array", а если что-то уровня echo "тут должно быть {$massive['massive'['massive1']]} и {{$massive['massive'['massive2']]}" - вообще ничего, просто пустота, но не крашится. Может я как-то не так это делаю? Гуглить пытался, но чёт внятного объяснения не нашёл.
Доброго вечерочка, дорогие пыхеры. Я аутист-ньюфаг в пхп и пишу текстовую "игру" да, я ебанутый и пишу игру на пхп, которая будет в основном зависить от рандома и геймплея как такого нет, кроме как читанины отчёта происходящего на момент запуска кода игры. Почти все события и ивенты будут происходить с помощь циклов, рандомизации и условий, ну и других танцев с бубном. Пока что я сделал основные статы и основной эквип для обычного тестовой пробы работоспособности. Вот этот пиздец: http://ideone.com/UhZSsG Так что вот какой вопрос: есть ли способ сделать более-менее приемлемый и не вырвиглазный простой интерфейс для текста с помощью хтмл и чтобы это было реально для ньюфага по сложности? Ну и желательно с возможностью смены данных статов героя и имени, ну или хотя бы пустое окошко для ввода имени, лол.
Делаю студентов. Такой вопрос : нужно 3 страницы выходит а не две? Сам список, форма добавления, и временный профиль студента для редактирования данных. Или сделать форму регистрации и редактирования шаблонами и использовать роутинг у условием?
Насчет фреймворков и то, как они якобы усложняют жизнь. Вот все аноны, кто решал задачу про студентов, писали сами код работы с БД, код вывода таблицы с сортировками, кто-то еще роутинг. А в фреймворке все это уже написано. Нужен роутинг? 10 строчек. Нужно загрузить сущность из БД? 3 строчки. Нужно вывести таблицу с пагинацией и сортировкой? 10 строчек (включая HTML).
Конечно, фреймворк еще надо установить. Несколько команд в консоли надо выполнить.
Вот так вот, по мнению автора статьи, фреймворки "усложняют" жизнь разработчика. Или он какие-то фреймворки неправильные использовал?
Я уже неделю не могу осилить функции. Последний момент, где я клянусь богом - нигде не нашел. http://php720.com/lesson/42
function square($num) $num - что это. На примере урока, это квадрат числа, который задается в $num.
Но сама по себе. Вот эта вот переменная в скобках, она должна существовать до создания функции, или её можно указать впервые в этой скобки.
Каким образом при вызове этой функции, и написания в скобках число, переменная понимает, что это число её? square($num) square(7);
Как это происходит? Вот мы вызвали функцию, написали в скобках число. Функция просчитала все и выдала ответ. Но как она поняла, что число именно приписывается к $num? Точнее так. Смотрите. До создании функции, мне надо создать переменную $num?
Помогите пожалуйста, у меня сейчас голова взорвется.
Я вижу часы, вижу время, но не понимаю как они работают.
> Если игрок попал на мину и игра проиграна, представление должно отобразить соответствующее сообщение с кнопкой перезапуска игры (нажатие на которую тоже обработает контроллер).
А как контроллер обработает попап, если я создам его (попап) только к концу игры? Т.е. для кликов по полю (которое создано до игры) он биндит функции до начала игры, а тут вот такой случай. Создавать попап заранее и держать его где-то чтоли.
>>937392 $num - аргумент этой функции. Это лишь условная переменная которой функция будет оперировать. Когда будешь эту функцию вызывать то можешь класть любое число в качестве аргумента
>>937400 А что такое аргумент с точки зрения функции? Если там, в этих скобках - нужно будет подставить не число, а пример, или слово? Как это работает?
Я бы хотел узнать об этих вот. Словах. АРгумент. Вот. Что это значит? Я все эти учебники смотрю. Там мне дают рыбу, а не удочку. Везде нужно следовать инструкции. И не дают внутрь глянуть прибора.
Я понимаю, все и не сразу. Но хоть жаргонные слова знать, что-бы вот сейчас ты написал мне аргумент, а я даже не знаю что это. А если загуглю - охуею
Функция - это подпрограмма (отдельная маленькая программа), которую мы используем так:
1) объявляем (определяем, создаем) функцию с помощью слова function, например function square($n) { return $n * $n ; }. Мы указали название функции square, список аргументов в круглых скобках, тело функции в фигурных скобках. 2) далее мы вызываем функцию с помощью указания имени и круглых скобок, например echo square(10);
Функция может принимать на вход от 0 до бесконечности аргументов. Они указываются при определении функции в скобках, и выглядят как переменные, например:
function square($n) { ... - один аргумент $n function add4($a, $b, $c, $d) { return $a + $b + $c + $d; } - 4 аргумента
При вызове ты обязан в скобках указать столько значений (цифр, переменных, выражений), сколько у функции аргументов, ни больше, ни меньше. Например:
square(100) - вызываем функцию и передаем ей 100 как значение $n add4(10, $x, 100, 500 + 1) - вызваем функцию и передаем ей 4 значения как $a = 10, $b = $x, $c = 100 и $d = 501
При вызове начинает выполняться тело функции, а переменные-аргументы получают указанные в скобках значения. То есть если ты вызвал функцию как square(100), то внутри нее переменная $n будет иметь значение 100.
Функция не видит переменные, созданные снаружи нее. Передать значения в функцию можно только через аргументы. И наоборот, код снаружи функции не видит созданные внутри нее переменные. Вернуть что-то из функции можно только командой return.
Функция может, если хочет, при завершении вернуть какое-то значение с помощью return. Этот значение вызывающий код может сохранить в переменную или как-то использовать, например, вывести:
Если в функции нет return, то она вернет значение null. даже если функция что-то вернула, ты не обязан сохранять или использовать это значение. То есть можно написать просто
> $num - что это. Это переменная-аргумент функции.
> На примере урока, это квадрат числа, который задается в $num. Это не квадрат числа. Это переменная-аргумент, в которую будет помещено число, указанное при вызове функции.
> Но сама по себе. Вот эта вот переменная в скобках, она должна существовать до создания функции, или её можно указать впервые в этой скобки. Она будет создана при вызове функции автоматически. Она видна только внутри функции. Даже если ты создаешь снаружи переменную с таким же именем, функция не увидит ее, это будет по сути 2 независимых переменных (внешнаяя и внутренняя).
> Каким образом при вызове этой функции, и написания в скобках число, переменная понимает, что это число её? Что значит понимает? Когда ты вызваешь функцию, то значения из скобок присваиваются аргументам в том же порядке, в котором они описаны.
> До создании функции, мне надо создать переменную $num? Если ты не передаешь ее в функцию, то не надо. Я не понял из твоего кода, square($num) - это кусок описания функции или это вызов? Если вызов то такая переменная должна существовать.
Мне нравится этот вопрос, его можно использовать на собеседовании, чтобы избавиться от большинства кандидатов. Попробую сформулировать.
Аргумент - это переменная, которая указывается при объявлении функции. Она принимает значение, которое было передано в скобках в момент вызова функции.
Эта команда значит "создать функцию с указанным именем, аргументами и телом, но пока не запускать".
name(1) значит "вызвать функцию name, передав в качестве значения $arg значение 1". $x = name(1); значит "вызвать функцию и сохранить значение, которое она вернет (через return), в $x".
"вызвать функцию" значит выполнить записанные в ее теле команды.
Со строками все работает так же как и с числами: name("Hello")
Для попапа логично сделать отдельный объект. Ну например, отдельную пару View/Controller или просто отдельный вью или отдельный контроллер (совмещающий обе функции). Так как по идее это отдельное окно и логично его сделать в виде независимой сущности, чтобы не загрязнять код контроллера/вью игрового поля (хотя конечно ты бы мог просто создать невидимый попап в DOM и делать его видимым позже, но это не способствует разделению кода).
Можно даже сделать чуть универсальнее и сделать виджет попапа, которому при создании указывается произвольный текст и заголовок. Тогда один попап можно будет использовать в нескольких местах.
Вот как это может выглядеть:
var popupCtl = new OkCancelPopupController('Повторить попытку?', parentView); popupCtrl.show(); popupCtrl.onEvent(EVENT_CLOSE, function (answer) { // вызывается при нажатии кнопки или закрытии окна }); setTimeout(function () { popupCtrl.close() }, 5000);
Теперь мы можем открывать сколько угодно попапов и мучать пользователя дурацкими вопросами.
Заметь, что я указываю parentView - родительское вью. Это создает связь между родительским и дочерним вью, и позволяет попапу например позиционироваться по его центру и блокировать его. Если у тебя несколько игровых полей на экране, то попап будет знать, к какому именно полю он относится. Также это позволяет попапу уничтожаться при уничтожении родительского вью, перемещаться вместе с ним итд. Хотя можно и без этого, сделать просто попап, перекрывающий весь экран, но в случае с несколькими полями это плохо будет работать.
Иногда функции контроллера и вью объединяют в одном классе. Но это работает только для очень простых виджетов.
Если тебе надо создать сложный диалог (например, диалог настроек с выбором числа мин, сложности и тд), то у этого диалога вполне может быть своя пара View/Controller и может даже отдельная модель для хранения настроек.
Вообще, принято выносить отдельные элементы интерфейса (виджеты) в отдельные классы, чтобы было разделение кода и чтобы их можно было повторно использовать. Ну к примеру, ты можешь сделать виджет-ползунок, который можно двигать, и благодаря вынесению его в отдельные классы ты можешь его использовать повторно на разных экранах.
Современные графические интерфейсы так и сделаны - там есть куча стандартных объектов-виджетов вроде кнопок, выпадающих списков, галочек, диалоговых окон, ползунков, полос прокрутки, выезжающих окон уведомлений, и тд. Мы создаем окно диалога, создаем кнопку и добавляем ее как дочерний виджет на это окно.
Там есть контроллеры или вью виджетов (JFrame, JButton), я не знаю, есть ли у них отдельные M, V и С, или там все объединено в одном классе в силу примитивности кода.
То есть каждое окно/вкладка/виджет в теории может иметь свои V и С. И при желании, M. Контроллер может отстутствовать, если с элементом нельзя взаимодействовать, или может быть встроен в View, если он очень примитивный.
Эти виджеты используются в языках вроде Java, С# при построении интерфейса, и в библиотеках вроде angular, react тоже предусмотрено разбиение интерфейса на отдельные компоненты, хотя и не совсем так. Ну например вместо создания виджетов в коде через new, они описываются в виде похожей на HTML разметки:
<Dialog> <Button label="ОК"/> </Dialog>
То есть если у тебя приложение большое и состоит из множества окон, вкладок, виджетов, то моделей/контроллеров/вьюшек может быть тоже много. И не обязательно одинаковое количество.
Если подумать, то форма регистрации и форма редактирования личных данных - это одна и та же форма. Для нее можно использовать один общий контроллер и один общий шаблон для view. Просто в нужных местах добавить ветвление в зависимости от того, редактируем мы или создаем пользователя.
Во-первых, у тебя тут конечно направшивается использование объектов вместо массивов с характеристиками персонажей. Ты можешь глянуть учебник из ОП поста (я бы конечно его советовал вообще целиком прочесть), там есть глава про ООП и там описано, как использовать объекты.
Насчет вывода данных с помощью HTML. Не вижу никакой проблемы. Тебе надо 2 вещи:
- сделать HTML-шаблоны для вывода данных. По окончании вычислений PHP скрипт будет подготавливать переменные с результатами боя, параметрами героев и передавать их в шаблон, который их выведет. Читай http://www.phpinfo.su/articles/practice/shablony_v_php.html
Насчет ввода данных от пользователя - почитай про HTML-формы. Ты можешь добавить на страницу поля так, что после их заполнения и нажатия кнопки будет отправляться запрос с этими данными на веб-сервер, там будет запускаться скрипт и использовать указанные в форме данные.
Но тут есть проблема, что скрипт запускается каждый раз с нуля, все переменные очищаются. То есть нельзя например делать битву из нескольких ходов, и после каждого давать игроку выбор вариантов, так как каждый раз запускается отдельная копия скрипта. И даже имя игрока скрипт будет забывать после одного запуска.
Для решения этой проблемы надо где-то сохранять состояние игры при завершении скрипта и загружать их оттуда при повторном запуске. Вот где можно хранить состояние:
- в самой HTML-странице в форме можно сделать скрытое поле/поля, хранящее информацию о состоянии игры. Наш скрипт сохраняет информацию в это поле и после отправки формы игроком это сохраненное состояние отправится на веб-сервер вместе с введенными игроком данными - в куках/сессии. Минус - куки/сессия общие для всех вкладок и нельзя вести 2 игры в 2 вкладках параллельно - в файлах. Надо решить проблему, как различать игроков. Это почти то же, что и сессии. - в базе данных.
Ты задал всего один вопрос, значит все остальное тебе понятно? Ну хорошо, а то тут люди жалуются, что для них это равносильно рисованию совы.
Также, сразу посоветую внимательно прочитать комментарии к задаче о студентах, там очень много полезной информации.
Я вижу, что структура твоего кода напоминает фреймворк Yii. Не уверен, что она тут хорошо подходит. Вот, что мне не нравится:
- нет отдельной публичной папки, все файлы по сути доступны извне. Это небезопасно, читай комментарии к студентам. - папки templates и views - непонятно их различие. Обычно в веб-приложении HTML/PHP-шаблон это и есть вью - components - непонятно, что это такое? Что ты называешь "компонент"? Контроллер - это не компонент? - есть папка src (исходный код), но controllers и components почему-то не в ней.
Далее, я не вижу четкого разделения на PHP-код и шаблоны (Controller/View). Вот этот файл: https://github.com/siqel/abiturientlist/blob/master/index.php - он выполняет и функции фронт контроллера (вызвает роутер), и занимается выводом кусков HTML кода. Плохо. Лучше сделать так:
- подготовить все данные - вывести их с помощью шаблона
У тебя подготовка и вывод данных идет вперемешку.
Также, у тебя почему-то в index.php идет какая-то работа с базой данных, если POST не пуст. Разве это не задача контроллера формы регистрации? Идея как раз в том, что каждый контроллер отвечает за свою страницу, а index.php это как бы общая точка входа (фронт контроллер) и она не должна выполнять обязанности одного конкретного контроллера вместо него.
То есть у тебя пока плохо с разделением кода на части, распределением отвественности, кто чем занимается. Ты должен на 100% понимать, какой код за что отвечает, а не вписывать код куда попало.
Я не уверен, что класс Db нужен. Объясни, зачем он нужен, если мы можем просто писать $pdo = new PDO...
Ты ведь его просто скопировал из какой-то статьи, не думая. Не надо так. Ты должен писать каждую строчку кода сам, понимая, зачем она нужна. Не понимаешь - спроси, или перечитай комментарии к задаче.
Иногда нам надо делать какие-то действия в самом начале (настроить автозагрузчик, обработку ошибок, создать какие-то объекты). Для этого можно использовать bootstrap-файл, читай комментарии.
В роутере мне не нравится, что в нем жестко прописан путь к конфигу и идет обращение к _SERVER. Лучше вынести это из него, и передавать список роутов и текущий URL снаружи.
- создаем объект Student - отдельной функцией принимаем данные POST и записываем их в объект - отдельной функцией проверяем на правильнсоть данные в объекте - отдельной функцией сохраняем их в базу данных из объекта
А ты поменял именно тот файл php.ini, который используется? И ты перезапустил веб-сервер Апач после изменения настроек PHP (php ведь работает как модуль внутри Апача)?
Сделай php-файл с кодом <?php phpinfo(); , запусти его через браузер и посмотри там какой именно файл php.ini использовался. Отредактируй его, и перезапусти Апач.
Вообще, если у тебя нет ORDER BY, то это значит, что база данных может возвращать данные как хочет. Без ORDER вообще нельзя сказать, какая запись первая, а какая последняя. Так что начни с его добавления.
А я за пару вечеров смог скомпилировать PHP7 под Windows XP. Пока только ядро, без большинства расширений. Тесты почти все проходят. Надо найти время, доделать все и выложить на гитхаб. Скажем нет навязыванию принудительных обновлений софта, не несущих выгоды пользователям.
У меня тут есть несколько идей, которые не требуются по условиям задачи, но которые, как мне кажется, могли бы пригодиться при разработке новых скидок. Хотя конечно на практике скидки бывают непредсказуемымми. Например, скидка (50 рублей) при предъявлении купона и превышении определенной суммы чека, в опредленные дни. Можно использовать до 5 купонов за раз. В нынешнюю модель она не укладывается.
> Тогда предлагаю ввести дополнительную абстракцию. Например, нужно добавить такую скидку: если среди товаров есть A и B, то снизить их суммарную стоимость на 20 единиц (не процентов). То есть раньше у нас было "снижение стоимости" основанное на процентах...
У меня была идея в том, что объект скидки сам вычисляет цену (на товары, к которым применена скидка) как хочет. То есть хоть вычитает проценты, хоть рубли, хоть применяет произвольную формулу. Максимум гибкости без закладывания каких-то алгоритмов (в задаче это не требуется, но вдруг пригодится). Код выглядел бы так:
Это опять же дает нам больше гибкости, хотя и не требуется по условиям задачи. Например, позволяет делать условия "скидка на товар A, если есть товар B, даже если он уже использовался в скидке". И может даже позволит делать скидки при определенной сумме чека.
И еще, насчет уменьшения цены, я бы может поменял вот это:
Это дает возможность объекту Depreciation делать произвольные операции с ценой, не только уменьшать ее на какую-то величину. А его интерфейс выглядел бы так: public function decrementPrice($originalPrice); Хотя так он не будет знать, с какими именно товарами работает.
Сам класс Calculator мне нравится тем, что он получился очень простым.
> То есть раньше у нас было "снижение стоимости" основанное на процентах, теперь добавляется "снижение стоимости" в виде фиксированного значения. По моему удобнее возвращать не на сколько рублей меньше стали стоить товары (попавшие под скидку), а итоговую их цену. Так наверно код проще будет. Или нет?
>> Потому дробные числа нельзя сравнивать через ===. Надо проверять, что их разница меньше некоторого значения > А мне нужно это реализовывать? Вообще, да. Иначе твои тесты работают неверно. В твоем случае можно просто вручную указать epsilon, меньше которого должна быть разница 2 чисел.
> Так по условию требуется их комбинировать, там ещё написано "Скидки применяются последовательно в порядке описанном выше."
Нет, я имел в виду комбинирование, когда объект скидки создается из примитивных блоков вроде такого:
$discont = new CombinedDiscount([ new DiscountIfProductExists('A'), new DiscountIfAnyProductExists(['B', 'C', 'D']) ]);
Это на первый взгляд дает возможность строить произвольные конструкции, но на практике усложняет код и часто просто не требуется. Лучше избегать такого, если не видна выгода от этого подхода.
Я вижу, ты сделал расчет скидки отдельным объектом (PercentDepreciation). Но нужно ли нам до такой степени разделять скидку на составляющие, раздувая код? Не проще ли просто прописать расчет величины в самом классе скидки? Тут надо взвесить выгоды и недостатки этого разделения. Мы должны разбивать код на части, но где-то мы должны остановиться.
Интуиция мне подсказвает, что на практике такой гибкости скорее всего не потребуется и она будет только мешать. Увы, тут обосновать я это не могу, просто интуиция и опыт. Так что к твоему подходу претензий нет.
Кстати, класс ProductCollection можно было реализовать поверх стандартного SpjObjectStorage - там есть эффективные по скорости методы для склеивания/нахождения разницы/удаления.
> private function isCountDepreciationMapValid Тут я поймал себя на мысли, что в языках вроде Ява эта проверка делается одним тайп-хинтом вроде Map<int, DepreciationInterface>. Может и в PHP когда-нибудь такое завезут (generic types). RFC с идеей уже есть: https://wiki.php.net/rfc/generics
Не очевидно, что метод может удалять товары из переданной на вход коллекции, и надо бы обойтись без этого. Это приведет к труднообнаружимым ошибкам в коде. Самое простое - клонировать коллекцию, но может есть более оптимальное решение.
Также, там вроде надо давать скидку на каждую найденную группу товаров, но у тебя дается скидка только на первую. Ну то есть для набора A, A, B, B и условия, что должны присуствовать A + B надо выдать 2 скидки, а ты выдаешь только одну. Вот я скопирую условие:
> Если одновременно выбраны А и B, то их суммарная стоимость уменьшается на 10% (для каждой пары А и B)
И вот тут еще я нашел подвох:
> Если пользователь выбрал одновременно 3 продукта, он получает скидку 5% от суммы заказа
Эта скидка применяется к итоговой сумме заказа, или только к этим 3 продуктам? У тебя второе, я в принципе не против, так как сама задача неточно сформулирована.
Так в общем, решение хорошее (кроме CombinationDiscount), а все идеи, что я написал - это лишь мысли по улучшению, так-то твой код уже соответствует условиям задачи. Надеюсь что понимание ООП у тебя улучшилось в итоге. Я даже думаю, ты уже можешь читать исходный код Symfony и понимать, что там написано.
Код у тебя довольно легко читается (хотя может это потому, что мы с этой задачей уже не первый день возимся).
На мой взгляд, задачи на ООП должны быть с меняющимися со временем требованиями (имитирующие реальную разработку). Я у себя в задаче про Вектор так и постарался сделать, чтобы проверить, насколько гибкий получается код в итоге.
и я не вижу, откуда взялось число 4000. Его нет в условии задачи. Что, елси мы поменяем исходные данные, программа будет работать корреткно?
Ты наверно считал 4000 как 5000 - 1000. Но это неправильно, так как ты не учел проценты, добавляемые на остаток долга.
Задачу вообще можно решить так:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!) - если остаток маленький, выплачиваем сколько осталось и уходим - иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Скорее всего у тебя не настроено в Апаче выполнение php-скриптов. То есть Апач просто отдает php скрипт, вместо того чтобы выполнить его с помощью mod_php.
Ты может как-то не так установил эти программы? Вроде по умолчанию в дебиане установка PHP добавляет нужные параметры в конфиг Апача.
Да, когда сфинкс индексирует таблицу, он кладет данные в обычные индексы. Они лучше оптимизированы для хранения больших объемов данных, но их нельзя обновить, только пересоздать с нуля целиком. Их обычно переиндексируют нечасто - раз в сутки, раз в час.
Информация в них устаревает. Вот, что может произойти между индексированиями:
- может быть добавлена новая запись в БД - может быть изменена запись в БД - может быть удалена запись из БД
При этом в индексе остаются старые неактуальные данные.
А реалтайм-индексы менее оптимальные для хранения и поиска, но зато их можно менять в реальном времени, с помощью запросов INSERT, UPDATE, DELETE к SQL-интерфейсу сфинкса.
Реалтйм-индексы по моему хранятся в памяти, но бекапятся на диск на случай падения/перезапуска сфинкса и не теряют данные в этой ситуации.
Идея такая: большинство данных хранится в обычных индексах, но объекты, созданные/измененные/удаленные после индексации, сохраняются в реалйтайм индекс до следующей индексации (где они попадут в основной индекс). Важно настроить все так, чтобы данные не терялись ни в каком случае.
- описываем реалтайм-индекс в конфиге - при переиндексировании очищаем реалтайм индекс - в приложении, при создании|удалении|изменении объекта, вставляем его данные в реалтайм-индекс - при поиске ищем и по обычному, и по реалтайм индексу. Исключаем из основного индекса записи, которые есть в основном индексе, но помечены как удаленные или измененные в реалтайм-индексе (то есть данные по которым в основом индексе устаревшие).
Без реалтайм индексов поиск не будет видеть новые объекты, созданные после индексирования.
> То есть, применительно к задаче на файлообменник, для того чтобы эти индексы заполнялись при добавлении файла, дополнительно к запросу на заполнение полей таблицы нужен еще и запрос для заполнения реалтайм-индекса? Да.
> Далее, при использовании реалтайм-индекса невозможно сразу получить все поля строки, т.е. если у нас проиндексировано только имя файла, то сфинкс отдаст в виде результата поиска только айдишник(и) Сфинкс это не база данных, он и не обязан ничего хранить, только искать id записей. Хранение данных только усложнило бы все, например появилась бы проблема их расхождения с данными в БД.
> Или нужно все поля в индекс загонять? Только те, по которым ведется поиск.
У тебя $p очень маленький. Попробуй поставить его повыше, например, 257 или 1001, а то там все единицы получились и непонятно, это все правильно, или ошибка.
Это что? Пакет PEAR? Тогда тебе надо разобраться, как исользовать PEAR, учти что под линуксом и виндой могут быть различия. В ОП посте есть гайд по командной строке.
Также, по моему, пакеты PEAR можно ставить через композер.
ОП, помоги пожалуйста с проверкой одного приложения. Изначально приложение делалось как тестовое задание на Yii2 для одной компании, но не получилось, было много ошибок. Поэтому я решил его поправить и оформить его как небольшой проект для портфолио и заодно натренироваться в php и yii. Прошу помощи от здешних профессионалов, что с их точки зрения неправильно в моем приложении. Это первое относительно серьезное приложение на yii и вообще на php, поэтому возможен говнокод. Я получил список багов от тестировщиков компании. Проблема в том что часть из них я не смог отловить, у меня на локальном сервере все нормально работает, все проверятся, все процессы функционируют. Выкладываю список багов ниже, возможно, вы сможете объяснить мне, в чем я не прав, или указать на новые баги. Проект - https://github.com/kiloman-76/TestMoneyApp Список возможностей программы - http://pastebin.com/GRSiLBK5 Баги - http://pastebin.com/YEFZsrcd
Даун в треде. Не получается понять в чем же отличие паттерна бд Table Data Gateway от DataMapper, ведь в обоих случаях используется один класс для работы с моделью и сущностью?
Датамаппер работает с объектами: https://martinfowler.com/eaaCatalog/dataMapper.html Там код выше будет выглядеть так: $user->setName('Вася'); $user->setAge(21); $mapper->save($user); // Если у $user есть id, то вставляем новые данные, иначе - обновляем старые.
Итого: TDG - более простой, предоставляет только шлюз к БД. Маппер оперирует объектами (маппит объекты на данные БД и наоборот). Почему объекты лучше массивов: объект может понадобиться нам позже в каком-нибудь сервисе (например аутентификации), с объектами проще работать, так как они имеют чёткую структуру (если мы не используем магические свойства и методы), в отличии от массивов.
Аноняши прошу помощи. Заебался заниматься говнокодингом и писать велосипеды с костылями. Подскажите какие лучше цмс и фреймворки учить чтобы взяли хотябы стажером за еду? База есть. Что сейчас наиболее востребовано?
>>937405 return возвращает управление программой модулю, из которого была вызвана функция. Выполнение программы продолжается с инструкции, следующей за местом вызова.
Из мануала. Я вообще ничего не понял. И в твоём посте не понял. Я дурак. Умоляю, помоги на примере, как эта return работает. Ты уже показал пример, но я все равно ничего не понял.
>>937392 >Я уже неделю не могу осилить функции. А что не понятно. Функция - это подпрограмма в твоей программе. Т.е. вызвая ф-ю в своей программе ты как бы используешь еще одну программу. >function square($num) >$num - что это. На примере урока, это квадрат числа, который задается в $num. Это то, с чем твоя ф-я будет работать. Вот у любом программы есть входные данные и данные которые она возвращает с помощью оператора return. Например функция суммы двух чисел: function sum($x, $y) { $sum = $x + $y; return $sum; } Да, только запомни что $sum, например, существует только внутри ф-и. В данном случае sum это программа, входные данные(аргументы) которой это х и у. А переменная $sum это то, что программа отдает на выходе. Теперь в своей программе, допустим homework.php тебе понадобилось подсчитать два сложных числа. Соответственно, ты делaешь следующее: $num1 = 100500; $num2 = 4564564; $summa_chisel = sum($num1, $num2); Вуаля, у тебя в переменной summa_chisel будет сумма переменных нам1 и нам2, ты решил домашку и можешь идти гулять. >Но сама по себе. Вот эта вот переменная в скобках, она должна существовать до создания функции, или её можно указать впервые в этой скобки. Да как угодно. Хоть прямо во время вызова ф-и. >Каким образом при вызове этой функции, и написания в скобках число, переменная понимает, что это число её? >Как это происходит? Вот мы вызвали функцию, написали в скобках число. Функция просчитала все и выдала ответ. Но как она поняла, что число именно приписывается к $num? >Точнее так. Смотрите. До создании функции, мне надо создать переменную $num? Это задается при создании ф-и, только это называется определением ф-и. При определении ф-и в данном случае мы указали, что вызываться она должна с двумя аргументами, иначе она вернет тебе ошибку, попробуй на практике.
>>938041 >Из мануала. Я вообще ничего не понял. И в твоём посте не понял. Я дурак. Умоляю, помоги на примере, как эта return работает. Ты уже показал пример, но я все равно ничего не понял. Есть у тебя скрипт. Допустим function sum($x, $y) { $sum = $x + $y; return $sum; echo "какое-то очень важное сообщение, которое обязаны увидеть все кто использует эту ф-ю"; } $num1 = 100500; $num2 = 4564564; $num1 = 100500; $num2 = 4564564; $summa_chisel = sum($num1, $num2); Твой код читает такая штуковина, которая называется интерпритатор. В данном случае он берет твой пхп скрипт, читает @ выполняет его и возвращает html-код. Так вот. Идет он такой по скрипту, и видит вызов ф-и. Смотрит потом код еще раз, находит ее определение и вызывает. Т.е. как-бы когда он видит ф-ю он входит внутрь нее и выполняет в качестве программы, и когда он видит оператор return он понимает, что ему надо взять то на что оператор указывает(в данном случае он берет $sum), выходит из подпрограммы, (т.е. ф-и) и переходит в программу, в которой был до этого, т.е. идет дальше по скрипту. Соответственно, что там дальше в ф-и его не заботит и пользователь не увидит это важное сообщение. Можешь для практики подумать, что надо сделать что бы пользователь увидел сообщение.
>>938061 Получается, с оператором return, интерпретатор игнорирует все, что не связано с той переменной, что указано при написании return? Вот return $sum;. Значит он выполняет только то, где участвует переменная $sum, а остальное игнорирует?
Или он обрывает выполнение функции на команде return, а все, что ниже написано return - игнорируется?
>>938071 Нет же. Return просто забирает результат каких-то действий и указывает интерпретатору что вот оно, то что требуется вернуть. А что там дальше интерпритатора уже не ебет, после строчки с ретерном он уже не будет читать и выполнять подпрограмму, а до нее ты можешь сколько угодно действий выполнять.
>>938079 Благодарю. Спасибо. Примерно понял. Но чтобы добить. На примере этого урока, http://php720.com/lesson/47 Цитирую: > Т.е в нашем случае, мы посчитали нужное нам выражение, занесли его в переменную $res и вернули через оператор return. Если бы мы этого не сделали, то переменная $z была бы пустая.
А почему бы она была пустая? Исходя из этого, если я хочу получить какой-то результат при выполнении функции, я должен буду всегда в конце функции написать return с указанным аргументом в виде переменной, в которой я хочу получить результат?
>>938087 >> Т.е в нашем случае, мы посчитали нужное нам выражение, занесли его в переменную $res и вернули через оператор return. Если бы мы этого не сделали, то переменная $z была бы пустая. Пустая она была бы потому, что без ретерна ф-я бы ничего не возвращала. Т.е. отработала бы в холостую и все. Интерпритатор штука прямая как шпала, понимает всё буквально, соответственно так в коде и надо выражаться. >А почему бы она была пустая? Исходя из этого, если я хочу получить какой-то результат при выполнении функции, я должен буду всегда в конце функции написать return с указанным аргументом в виде переменной, в которой я хочу получить результат? Ну да. Только не обязательно в ретерне отдавать переменную, можно что угодно - массив, объект или прямо на месте делать вычисление, т.е. можно даже написать return $x + $y в данном случае. Вообще ф-я может и не возвращать ничего, попробуй вместо ретерна написать echo, вызывать не для присваивания а просто так. Такие вещи вообще лучше всего на практике изучать.
Привет, анон. Я новичек в пыхе, и при чтении вводных гайдов возникает вопрос: зачем все рекомендуют устанавливать phpmyadmin? Какие он дает преимущества? Существуют ли задачи, когда его удобнее использовать по сравнению с обычным управлением бд, или же это просто графическая надстройка и без нее можно спокойно жить?
return это команда выхода из функции (завершить выполнение подпрограммы). Ее можно использовать в 2 формах:
return; - выйти из функции и вернуть null return значение; - выйти из функции и вернуть указанное значение. Это может быть число, строка, переменная, выражение.
return прекращает выполнение кода в функциии и возвращает управление к месту, откуда была вызвана функция.
Если return не ставить, то код функции выполняется до конца.
нет. return завершает выполнение функции и потому код после него не выполняется. Переменная тут не при чем.
Ты по моему пропустил самый первый, и самый важный урок - что такое программа. Программа это последовательность команд. Интерпретатор PHP по умолчанию просто выполняет записанные в программе команды последовательно, сверху вниз.
Но некоторые команды меняют порядок выполнения программы. Например, if позволяет не выполнять команды внутри него при опредленном условии, for позволяет выполнить одни и те же команды несколько раз подряд, а функции позволяют создать подпрограмму и позже ее вызывать. Подпрограмму можно вызвать, и из нее можно выйти раньше времени командой return.
Соответственно переменная тут не при чем. Просто return завершает выполнение функиции и команды ниже уже не выполняются.
У меня ощущение, что ты куда-то спешишь и пропускаешь изучение основ. И из-за этого не понимаешь более сложные темы. Я бы советовал взять учебник в ОП посте и прорешать там все задачи подряд, чтобы лучше разобраться, как вообще работают прогаммы, какие есть команды итд.
Если не вернуть из функции какое-то значение явно командой return, то она вернет значение по умолчанию - null. И в переменную сохранится этот null. В том учебнике это называют "переменная будет пустая".
Это программа-клиент для MySQL для опытных программистов, которые в совершенстве знают SQL. Начинающему надо писать запросы руками в консоли, чтобы запомнить синтаксис и научиться получать нужные данные.
>>938141 >для опытных программистов Опытные юзают HeidiSQL или Workbench. Phpmyadmin как раз для нубов с вордпрессами, там тебе ни табов, ни сохранения запросов, ни биндинга, да, скорость черепашья и ошибки через одну валятся. Рекомендуют ее застрявшие в 90х старперы, не освоившие новых инструментов.
>>938191 Битриксы и вордпрессы в жопу, они для криворуких, учи нормальные фреймворки - Symphony, Yii, Laravel. Из cms можно Cake Php, typo3, для магазинов PrestaShop. Если фреймворк освоил, то тебе в принципе CMS и не нужен, можешь на фреймворке все то же самое быстро и легко написать, возможностей и контроля больше.
>>938205 А как же требования? Поддержка и написание функционала к магазинчикам по продаже дилдаков? Фреймворк однозначно стоит брать, но пока я его буду учить у меня кончатся все дошики и я помру с голода, а так устроиться хотябы куда нибудь
Я думаю, можно уже показать: https://github.com/greenTea242/MinesweeperMVC . Посмотри, пожалуйста. Пока что не стал всякие angular, knockout делать, попроще реализацию выбрал из задачи. Несколько вопросов:
Это нормально что я работаю со словарями в таком стиле: dict1.prototype.merge(dict2) изменит dict1 и ничего не возвращает. По другому будет Dict.merge(dict1, dict2) - вернется новый словарь, dict1 не изменится.
Что делать с символом единицы в верстке? Объясню. Если приглядеться, немножко кривые табло флагов и времени. Потому что в css файле я сдвинул span.digit через text-align вправо чтобы получился стиль калькулятора (ты поймешь о чем я, как увидишь). Может двигать только символ единицы?
Можно ли сделать dataset данные (которые цифры) в опциях зависимыми от моих констант? А то можно ошибиться.
Ну и конечно я хочу услышать твое мнение на счет Popup V/C. Не очень правильно реализовал, наверное, тяжеловато приходит понимание MVC. Для каждой менюшки, если по правильному, тоже нужно делать V/C?
> По другому будет Dict.merge(dict1, dict2) Почему? Можно var d = d1.merge(d2);
Вообще, есть 2 подхода:
- создается и возвращается новый объект - модифицируется существующий
В разных ситуациях они имеют свои преимущества и недостатки.
В Руби для различения таких методов тем, которые модифицируют объект, добавляют в имя символ !, например dict1.merge!(dict2)
> Для каждой менюшки, если по правильному, тоже нужно делать V/C? Логичнее сделать 1 конфигурируемый виджет меню (V/C), и в него передавать структуру меню.
Ну и в общем, мне не нравится такой миксин, так как тут нет никакой защиты от того, что в 2 классах могут оказаться поля с одинаковыми именами. В реальном большом проекте с несколькими разработчиками такие конфликты будут, и замучаешься их распутывать. Один человек добавил метод в EventDispatcher и где-то в другом месте что-то сломалось.
PopupController ты реализовал нехорошо, на мой взгляд. Я тебе предложил идею сделать независимый виджет попапа, который ничего не знает про игру, а умеет только показывать/скрывать попап и сообщать о нажатии кнопок в нем. Но ты зачем-то отказался от идея разделения ответственности и влепил в контроллер попапа обращение к модели игры:
> this._parentView.getMinesweeperGame().reset(); Вдобавок ты еще и нагрузил View лишними обязанностями. Задача View - отображать данные, а не предоставлять всем желающим ссылку на объект модели. Однозначно у View не должно быть публичного метода getMinesweeperGame.
То же касается метода DomGameController.prototype.getMinesweeperGame(). Предоставлять ссылку на модель не входит в задачи контроллера.
То, как сделан вывод тут ConsoleGameView.js показывает, что у модели не очень удобный интерфейс предоставления данных:
> var visibleMines = this._minesweeperGame.getVisibleMines(); ...
По моему так лучше сделать либо метод, дающий информацию по конкретной клетке:
game.hasMine(x, y)
Либо дающий объект клетки:
game.getCell(x, y).hasMine();
Это внутреннее знание модели, как именно хранится информация о клеточках. А ты ее выставляешь наружу и предлагаешь всем самостоятельно копаться в каких-то внутренних хранилищах.
Тот интерфейс, что я предложил, как мне кажется, лучше скрывает информацию о хранении данных внутри модели и при рефакторинге меньше придется менять.
> var spacesCounter = 3 - Util.getNumberLength(y); > var pad = Util.repeatString(spacesCounter, " "); Можно объединить в функцию padLeft()
> this._minesweeperGame.addEventListener(GameEvent.CELL_CHANGED > this._minesweeperGame.addEventListener(GameEvent.SEVERAL_CELLS_CHANGED, Только второго события по моему достаточно. Первое избыточно.
> var template = document.querySelector(".template-popup"); > this._popupView = new PopupView(this, template.innerHTML, message); Шаблон попапа наверно должен получаться в PopupView, а не снаружи. То есть это только PopupView знает, где взять шаблон.
removePopup тоже должен быть частью PopupView. Как иначе его повторно использовать, везде копировать этот код?
Попап выгоднее центрировать средствами CSS.
> Dictionary Правильнее назвать CellDictionary или CellList как-то так, это ведь не словарь для любых объектов. А, вспомнил! CellSet. Возможно, что Set - это как раз та структура данных, которая тут нужна: https://tproger.ru/translations/sets-for-beginners/
Set (множество) - это такая структура, куда можно добавлять данные и потом проверять, есть они там или нет.
ПХПач, обьясни, почему если использовать str_repeat() с символом пробела - функция не работает ? В ideone и прочих онлайн компиляторах выводит табличку корректно.
И еще вопрос. Как подружить апач с расширением mbstring ? Если юзаю встроенный пхп сервер - работают скрипты нормально. Когда запускаю на апаче - выдает Fatal error: Call to undefined function mb_strlen().
>>938527 >работает, спасибо. А в чем фишка ? Ну типа, обычные символ пробела может по разному интерпритироваться разными браузерами, или что-то там. А неразрывный проблем это везде неразрывный пробел.
>>938694 Ты имеешь в виду REPL? Да, для PHP он есть встроенный, запускать через php -a в консоли. Если хочешь продвинутый автокомплит с историей, то погугли PsySH.
>>919074 (OP) Господа, еле откопал тред. Кто-нибудь пытался прописывать куки в CodeIgniter?? Почему, если я ставлю куку, то она сохраняется только в пределах одного контроллера?? А еще, если я пишу проверку на куку в каждом методе контроллера типа if(!isset($cookie)){ redirect('/index/', 'refresh'); } $post; то меня при обновлении страницы (например, методом post из формы) выкидывает на главную страницу, т.е. кука удаляется? втф? при этом если страницу не обновлять, то кука типа хранится, но как тогда обновлять страницу не удаляя куку?
В PHP по умолчанию почему-то стоит значение error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
То есть нотисы игнорируются. Если, к примеру, опечататься в имени переменной то PHP в конфигурации по умолчанию ничего не напишет. Ищи потом, где ошибка.
Потому я вынужден в первом уроке в первой программе ставить этот дурацкий error_reporting(-1), хотя без него программа бы смотрелась и короче и логичнее. И начинающим приходится отвлекаться на изучение каких-то магических заклинаний, которые они толком не поймут.
Почему нельзя поставить нормальные настройки по умолчанию? Почему нельзя выкинуть все эти варнинги и перейти на исключения?
В общем, пока убрать это не получится, придется потерпеть. Привыкайте с самого начала, что в работе PHP разработчика не все медом намазано.
>>938841 Я вообще первым языком Си учил, там для хеллоуворлда от новичка требуется гораздо больше заклинаний, не говоря уже о том, что сишка очень низкоуровневая по сравнению с PHP. С PHP новичок может уже в первый день написать что-то интересное, сишка радушно встречает новичка конструкциями fscanf(stdin, "%d", &array_size) и новичку придётся разбираться с указателями, если он хочется продвинуться хотя бы дальше циклов.
Ну и сейчас таки в PHP варнинги понемногу заменяют на исключения. Вот если новичок первым языком JS учит, то это плохо, будет в голове каша из функций как объектов и объектов как ассоциативных массивов, не говоря уже о конвертации типов. Так что error_reporting, как по мне, мелочь. Я когда PHP изучал по учебнику с анимешными картинками, то не придал error_reporting'у никакого значения, просто добавил бездумно.
>>937429 >>937429 В общем начал переделывать код. Класс DB нужен именно для те писать того чтобы не писать консрукцию $pdo = new PDO вместе с [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION], но в общем можно убрать позже. не совсем понятно как bootstrap-файл поможет (настроить автозагрузчик, обработку ошибок, создать какие-то объекты)
То есть если перефразировать то, что ты сказал, то получается, что класс DB нужен ради единственной функции в нем, которая создает объект PDO.
Но тогда напрашивается вопрос, во-первых, почему тогда его не назвать PDoFactory, во-вторых, а почему для других классов такого не сделано? То есть класс, создающий объекты Abiturient, класс создающий объекты AbiturientDataGAteway, объекты PageLinker и так далее?
Пока у меня ощущение, что ты просто скопировал эту идею из какого-то урока, не особо задумываясь.
Помогите ретурду с проблемой. Поставил PhpStorm и xampp, потом столкнулся с проблемой " interpreter not configured phpstorm Все сделал в точь точь, но нихуя не работает код. https://www.youtube.com/watch?v=J-jn6yi3x0c Что делать?
Опять надо клещи доставать. Поясни, что значит "не работает"? Что ты делаешь, что ожидаешь увидеть, что видишь? Если ты что-то открываешь в браузере, напиши какой URL в адресной строке, если запускаешь код, запости куда-нибудь его.
Также, если ты используешь веб-сервер, посмотри его логи ошибок. Для Апача под виндой они хранятся где-то в его папке, в линуксе в /var/log.
Видео пересматривать целиком и угадывать, где именно ты ошибся, это не вариант.
У тебя показано окно CLI interpreters, интерпретатор для запуска в командной строке.
И что с логами? Для 502 ошибки в логе веб-сервера должна быть запись с пояснениями. Попробуй сам найти, где этот лог, если знаешь, если нет, я потом погуглю. Я пока что понятия не имею, какойв шторме использован веб-сервер и как он настроен.
Я у тебя там вижу упоминание xampp установленного на диск c:, поищи логи в его папке и посмотри есть ли там что-нибудь интересное.
Друзья, объясните новичку, кто в Symfony шарит. Я думал с т.з. MVC вывод простой страницы (типа все новости) происходит так: в контроллер добавляем запрос к базе через модель типа
$news = \App\Models\Article::getAll();
Соответственно Article - это модель, которая наследуется от базовой абстрактной модели, где эти общие для моделей методы написаны. Например там же можно сделать манипуляции с этими данными, заменить что-то в тексте и т.д. И добавляем обращение ко view.
Но читаю мануалы по Symfony, там рекомендуют в контроллере делать обращение к доктрине типа
Все работает, но если я допустим хочу к с этой выборкой предварительно сделать что-то до выведения в шаблон, например закешировать текст новости, в котором существуют markdown теги, то мне это где правильнее сделать?
Я бы сам ответил что в Entity, предварительно сделав родительский класс. Так как контроллер вроде как не должен с данными работать. Но скачал проект от них же с типа рекомендованным подходом https://github.com/symfony/symfony-demo и там вообще не подобного кода в моделях и они ни от чего не наследуются. И я хз как делать в итоге.
Короче объясните, куда правильнее добавлять код для манипуляции с данными?
>>939236 >Короче объясните, куда правильнее добавлять код для манипуляции с данными? В репозиторий. Когда ты создаешь entity через консоль, она тебе автоматически генерит пустой repository в той же папке Entity. Туда ты записываешь все необходимые тебе методы работы с данными, для этого у доктрины есть прекрасный QueryBuilder. Потом в контроллере ты можешь получить репозиторий в отдельную переменную через ту же конструкцию $this->getDoctrine()->getRepository() и обращаться уже к тем методам, которым ты сам написал в нем. Встроенные методы типа findAll() и findBy() будут так же доступны.
Поясните за настройку апача. Как сделать отдельные настройки для каждого сайта? Если прописать как в задачке про студентов <VirtualHost *:80> # Имя сервера которое обслуживает этот VirtualHost ServerName example.com # Корневая папка сервера DocumentRoot /var/www/example.com/public # .... это же все мои сайты на локалке заданет.
>>939400 Разобралдся, оказывается я что-то не так делал, раз сначала оно у меня на все сайты влияло. Однако теперь из-за этой хуиты отвалился .htacces. Прописал туда же AllowOverride All - сервер вообще перстал запускаться. ЧЯДНТ? Может мне лучше не париться, а просто через .htacces такое делать?
>>939480 Да я то все понял. Осталось только разобраться почему .htacces не работает, хотя вроде как должно. >Если ты обмазался шпермой, то ничем помочь не могу. А какая разница? Ну кроме как того, что в шинде и красноглазиксах по разному директории пишутся.
Ладненько. В результате гугления я решил прописать в конфиге для моего сайта вот такое: <VirtualHost :80> # Имя сервера которое обслуживает этот VirtualHost ServerName students.local # Корневая папка сервера DocumentRoot путь\public <Directory "путь"> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.)$ index.php [QSA] AddDefaultCharset UTF-8 </Directory> </VirtualHost> И работает. Однако все равно хотелось бы узнать, как заставить в данном случае исполнять директивы из .htacces, так по крайне мере удобней и не надо лезть в конфиги апача если что понадобится.
>>938978 ну в общем я его действительно скопировал и хотел в итоге убрать, но new PDO не принимает больше 4 параметров, то бишь не получалось записать new PDO(host,dbname,user,pass,[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION], я позже уберу этот метод. еще хотел спросить про роутинг, как в мой метод run() в Router добавить 404 error, попробовал сделать такое если не существует вызываемого класса или метода, но выдает ошибку Cannot modify header information function ErrorPage404() { $host = 'http://'.$_SERVER['HTTP_HOST'].'/'; header('HTTP/1.1 404 Not Found'); header("Status: 404 Not Found"); header('Location:'.$host.'404'); } } еще хотел спросить как мне сделать view для подготовки данных на вывод, может в гайде было, перечитаю еще раз
>>939559 Спасибо, не надо, я уже настрадался с этой хуйней. Принесешь курсач на этой херне преподу на флешке - либо все настройки разметки слетят и весь текст поедет, либо вообще не откроется файл. И либре офис, и опенОфис. Пока пересилил лень и не поставил проксю, зашел на рутрекер и не купил там Мелкософт Офисе2013. Не нарадуюсь.
>>939564 Пидор не пидор, а сдавать ему предмет с курсачем и дипломом. У них там везде 2007 седьмого года офис стоит на спермерках. Я даже со своим 2013 испытываю проблемы на их 2007, иногда приходится у них вручную текст доводить. Пиздец в общем.
>>939604 Да разобрался, то я каким-то образом умудрился нагадить в конфиги апача. Алсо, раз уж такие пляски, поясните - когда надо прописывать всякие директивы в .htacces, а когда лучше в конфиг сервера лезть?
Преимущество htaccess в том что он распространяется вместе с проектом и другому человеку не надо в настройки сервера что-то вставлять. При изменении настроек не надо перезапускать сервер.
Недостатки в том, что он поддерживается только Апачом, настройки в конфиге парсятся 1 раз, а не на каждый запрос, и их нельзя изменить без прав администратора (взломщикам чуть труднее навредить получается).
>>939611 Отлично. Извини пожалуйста, но у меня тут проблема. Как запустить свою порнографию? В первый раз при нажатии этой кнопки мне вылезло окошко с выбором php файла. Ну я и выбрал без задней мысли тот, на котором у меня все это написано. А теперь и найти это окно не могу.
>>939621 Ну для исполнения пхп-скриптов тебе нужен сервер, который будет выполнять скрипты эмулируя веб-сервер, у оп-а в уроках это было. Можешь поставить какой-нибудь xamp, или вообще open server - готовая сборка, в которой все работает искаропки. Но для понимания наверное лучше сделать как у ОПа в уроках.
>>939549 >А Error: document root is not specified or invalid Что у тебя там стоит?можешь скинуть или показать какие должны стоять дефолтные настройки там, уже жалею что перешел на пхпшторм
>>939638 Там должен быть путь к исполняеямому файлу php(экзешнику, ёба). В прыщах это /usr/bin/php, в сперме надо задать путь к тому что ты там себе понаставил.
>>939639 Красноглазый называет кого-то пердольщиком. >>939638 Пиздос. У тебя в конфиге сервака прописан документ рут(нгинкс), как там в апаче я не знаю в котором серв ищет индексный файл и вообще считает эту папку рутом кто бы блять мог подумать. Укажи этот рут в шторме.
>>939648 Может быть я чего-то не понимаю, но о каком пердолингк идет речь? Я являюсь почетным спермобоярином и обладаю виртуальной машиной с прыщами. Ни в первом, ни во втором случае вопросов по установке пыхи/нгинкса/мускла не возникало. Я просто не понимаю о чем идет речь, когда кто-то говорит, что у него проблемы с настройкой/установкой на винде.
Если рассматривать PHP и Апач, то есть ровно 2 конфигурации:
- запускать PHP в режиме сервера, как описано в моем уроке. Информация об ошибках при этом пишется в консоль, где запущен сервер - установить Апач, настроить в нем использование PHP, немного описано тут: https://github.com/codedokode/pasta/blob/master/soft/apache-install.md . Информация об ошибках пишется при этом в лог-файл Апача.
PhpStrorm не предлагает ничего нового, и не содержит в себе какого-то своего веб-сервера, он может делать лишь 2 вещи:
- запустить один из вариантов веб-сервера - открыть в браузере страницу, которая будет загружена с запущенного веб-сервера
И настройки в PhpStorm как раз задают, какой вариант вы хотите использовать, где находится корневая папка сервера, где находится exe-файл PHP или Апача. То есть PhpStorm просто за вас может запустить сервер и открыть страницу в браузере. Если вы правильно пропишете настройки.
Обратите внимание, что задачи из учебника можно запускать также в консоли (командной строке). Сервер тут не требуется, так как мы запускаем интерпретатор PHP и наш скрипт напрямую, не используя браузер и веб-сервер. В PhpStrom встроена консоль, и вы можете настроить, чтобы по нажатию кнопки он запускал бы вашу программу и результат отображался в этой встроенной консоли. Так даже может быть проще для наичнающего.
Чтобы это сделать, вам надо сделать 2 вещи:
- указать путь к интерпретатору PHP - настроить, чтобы phpstorm запускал ваш скрипт в режиме командной строки (CLI)
Пожалуйста, ознакомьтесь с теорией, выберите вариант, который вам подходит, проверьте что у вас все установлено и настроено (например попробуйте запустить скрипт без phpstrom, руками) и если после этого вам что-то не понятно или не работает, опишиет вашу проблему подробно, что как настроено, что в логе ошибок и тд.
>>939743 ОПчик, если у тебя когда будет кризис идей - знай, что есть как минимум один анон которому было бы интересно почитать уроки по настройке апача, нгинкса, про .htacces и подобное.
>>939766 Документация на апач то обширная, но мне скорее хотелось бы понимать что надо знать и уметь обязательно, дабы не обосраться в неожиданной ситуации, мало ли когда оно вкатывальщику понадобится.
>>939743 ОП, если ты конечно ОП. Зачем ты что-то объясняешь днищам, которые даже конфигурацию апача осилить не могут, в то время как незабаненные в гугле товарищи эти проблемы решают по щелчку пальцев буквально?
>>939778 Туториалов по настройке апача и .htaccess море, доку можно не читать. Она правда неудобная и нужна только если что конкретное ищешь. Если в гугле не забанен, то за минуту штук 100 нормальных туториалов находится, я хз чего ты от ОПа еще нового хочешь, когда уже во всех подробностях расписано.
>>939857 >Если в гугле не забанен, то за минуту штук 100 нормальных туториалов находится, я хз чего ты от ОПа еще нового хочешь, когда уже во всех подробностях расписано. Читать не умеешь? Я хочу понимать что надо обязательно знать и уметь вкатывальщику, а что в процессе джуниорства можно освоить.
С гуглом не все так просто. Не везде объяснят что такое веб-сервер, как он работает. Часто просто дают конфиг который надо бездумно скопипастить и пользы от таких статей ноль.
Это диалог для запуска композера и установки через него примера приложения от фреймворка. Тебе это не нужно. Как минимум тебе надо сначала изучить композер и нужный фреймворк, прежде чем использовать эту опцию.
Я говорю про настройку по умолчанию, заложенную в PHP. При чем тут сборка ampps, в которую входит PHP? Если люди мой код будут запускать на ideone, то там ведь будут применяться настройки по умолчанию скорее всего.
И у PHP нет отдельных версий для продакшена и для разработки.
Из твоего описания непонятно, в чем проблема. Где буквы выводятся как вопросительные знаки? Что ты сделал? Скорее всего PhpStorm тут вообще не при чем. Ну и на всякий случай глянь ссылки тут, может что есть: >>939743
Обычно надо настроить везде utf-8: кодировку исходного кода в редакторе, тег meta charset, если используется браузер.
Вообще, вопросы по PhpStorm логичнее было бы адресовать в их техподдержку.
> еще хотел спросить про роутинг, как в мой метод run() в Router добавить 404 error, попробовал сделать такое если не существует вызываемого класса или метода, но выдает ошибку Cannot modify header information Прочти про протокол HTTP тут например https://github.com/codedokode/pasta/blob/master/soft/web-server.md
Прочти мануал по функции header().
Там в ответе сначала идут заголовки, потом тело ответа. Если ты вывел хоть один символ, хоть один пробел, то заголовки отравлять уже нельзя. В мануале это написано.
Некоторые делают ошибку, сохраняя файлы в кодировке utf-8 с BOM. BOM это невидимый символ, который вставляется в начало документа до <?php, выводится интерпретатором PHP и не позволяет отправлять заголовки.
Проверь, нет ли у тебя файлов с BOM или файлов с пробелом или еще чем-то, что выводится до заголовков.
Также, у тебя неправильный код. Почитай про пртокол HTTP. Почитай, что такое редирект. Если ты используешь Location то PHP автоматически меняет код статуса ответа на 3xx вместо 404. Соответственно это уже получаеся не страница 404, а что-то другое.
Ты как-то пропускаешь темы. Ну как можно использовать редирект, не изучив, что такое HTTP, как это работает, как его обрабатывает браузер итд. Надо изучать теорию, что происходит при вызове той или иной функции.
AllowOverride должно быть достаточно. Может, там где-то стоит запрещающий AllowOverride, или ты не перезапустил Апач поле правки конфига, или ты опечатался в названии файла .htaccess
Если не можешь помочь, то не надо. Почитай второй пост. У нас тут не тред для хвастовства, у кого глаза краснее.
Ну и мне тоже есть чем похвастаться. Я например, всего за 2 вечера смог пропатчить и скопилировать PHP7 под Windows XP (правда немного костыльно и пока без расширений). Уверен, что в линуксе, даже в какой-нибудь генте с такими задачами сталкиваться не приходится.
Затем изучить документацию Доктрины внимательно, так как без ее хорошего знания в Симфони ты не разберешься.
> Все работает, но если я допустим хочу к с этой выборкой предварительно сделать что-то до выведения в шаблон, например закешировать текст новости, в котором существуют markdown теги, то мне это где правильнее сделать? Правильно сделать сервис получения новостей, в нем настроить кеширование, а в контроллере вызвать его:
Вообще, я советую зайти в мой гитхаб https://github.com/codedokode/pasta/ . Симфони это не фреймворк для чайников и для начинающих. Ты должен изучить процентов 90 из того, что у меня в гитхабе только для того, чтобы читать туториалы для начинающих по Симфони. надо знать MVC, ООП, DI. Ты видимо пропустил основы и взялся сразу за сложное, отсюда и непонимание.
И кстати. чтобы в ней разобраться, мало читать документацию, многие вещи можно узнать только из ее исходного кода. Надо его изучать и разбирать.
> бы сам ответил что в Entity, предварительно сделав родительский класс. Неправильно. Entity просто представляет сущность и ни про какие кеши ничего знать не должна.
Репозиторий это плохое место для кеширования так как репозитории не создаются через DI контейнер и сервис кеша ты туда так просто не внедришь. Репозиторий предназначен только для каких-то операций с БД.
Баги исправить, добавить на сайт какую-нибудь страницу, сделать рассылку писем и тд, зависит от компании. Обычно только какие-то сложные вещи, вроде выбора архитектуры, фреймворков и тд, поручают опытным разработчикам, а все остальное можно и джуниору, почему нет, если задачу правильно поставить.
У кук есть параметр path. По умолчанию он совпадает с URL страницы и может у тебя кука ставится не на весь сайт, а на его подраздел.
> то меня при обновлении страницы (например, методом post из формы) выкидывает на главную страницу, т.е. кука удаляется? Скорее всего у тебя просто ошибки в коде.
Там неправильно сформулировано. Если ты не вернешь значение явно командой return, то функция возвращает значение null. Неправильно говорить "переменная будет пустая".
> я должен буду всегда в конце функции написать return с указанным аргументом в виде переменной, в которой я хочу получить результат?
Невнимательно ты прочел мои объяснения.
Ты не можешь указать переменную, в которую ты хочешь получить результат, так как внутри функции внешние переменные не видны. Ты указываешь после return выражение, которое надо вычислить и значение которого надо вернуть из функции. Примеры:
Местами мануал не очень понятно написан. Давай разберем по словам.
> return возвращает управление программой модулю, из которого была вызвана функция.... Под "модулем" здесь имеется кусок кода, откуда была вызвана функция.
> Выполнение программы продолжается с инструкции, следующей за местом вызова. Инструкция - это команда, из которых состоит программа и которые разделяются точкой с запятой. Вот примеры инструкций:
$x = 1; echo "yes"; doSomething();
Имеется в виду то, что команда return завершает выполнение функции и выполнение программы продолжается с того места, откуда была вызвана функция.return значит "вернуться". Вернуться к месту, откуда была вызвана функция и продолжать выполнять код там.
- выполняется echo "1" - вызвается функция func с аругментом 1. Интерпретатор переходит к ней и выполняет записанные в ней команды - затем, после того, как он выполнит все команды в функции или выйдет из нее по команде return, он возвращается к месту вызова (к строке func(1)) и продолжает выполнять код после нее. - выполняется echo "2" - снова вызвается функция func, но уже с аргументом 2. Выполняются записанные в ней команды - выполняется echo "3" - и так далее
Чтобы изучать фреймворки нужны базовые знания - ООП, DI, MVC, работа с базой. У тебя их возможно нет, потому я советую изучить шапку треда и поизучать что-нибудь оттуда.
CMS предназначены для создания сайта с минимумом программирования. Они в разы проще, но их возможности могут быть ограничены.
Как я понимаю, Data Mapper предназначен в первую очередь для сохранения/загрузки объектов в БД и из нее (сопоставления/отображения объектов в памяти на строчки таблицы в базе данных).
TableDataGateway - это просто класс-сборник методов для работы с таблицей, не только загрузка/сохранение объектов туда, но и любые другие манипуляции. Удаление например или какая-нибудь хитрая обработка записей в базе.
С другой стороны, Data Mapper может быть более продвинутым. Ну например, он сам может находить изменившиеся объекты и записывать изменения в базу. Или например он может доставать не только объект из БД, но и позволять получить связанные с ним объекты.
Можно еще почитать подробные описания паттернов в книге Фаулера (Шаблоны разработки корпоративных приложений) и сравнить их.
Может у тебя просто на локальном сервере отключен вывод ошибок (display_errors в php.ini), они идут в логи, но ты туда не смотришь и думаешь, что их нет? Проверь логи веб-сервера, логи Юи.
Я не вижу никакой ошибки на строке 12, но код по моему некорректный. Вот смотри:
> for ($i = 1; $i <= count($totalArray); $i++) { > if ($i % $skip == 0) { > unset($totalArray[$i]); Эта штука просто удалит элементы, индекс которых делится на $skip. Ну то есть 5, 10, 15, 20, но остальные элементы она не тронет никогда. В PHP при удалении элемента через unset остальные индексы не перечитываются. Используй array_splice если хочешь, чтобы после удаления элементы заново нумеровались от 0 до N.
Там задача про кредит сложная, на ней все спотыкаются. Твое решение считает верно, но я бы вынес из кода числа вроде 1000, 5000 и поместил бы их в переменные в начале программы, чтобы их можно было легко менять.
> if (is_numeric($char)) $currNumber .= $char; Не стоит экономить на фигурных скобках тут.
> exit(); Функция тут не должна делать exit, надо делать return, а то твою функцию 2 раза нельзя будет вызвать. Также, лучше, если функция не выводит ответ, а возвращает, чтобы вызывающий код мог делать с ним что хотел.
>>939965 Прочёл твою заметку. Спасибо. Ответь тогда тому Анону на вопрос про кеширование, раз я ответил неправильно.
Вопрос по файлообменникуАноним24/02/17 Птн 16:19:31#899№940144
ОП, ты писал о том, что валидацию загруженного файла лучше осуществлять в сервисе загрузки файла. Выходит, что сервис загрузки файла должен делать такие вещи: - загрузить файл на сервер, вернуть сущность File в случае успеха. Это сущность нужна контроллеру, чтобы он мог выполнить редирект на страницу с этой сущностью - как-то обработать ошибки и если они есть, отдать их наверх. Получается, что метод upload может вернуть 2 разных объекта в зависимости от валидности файла? Это, наверное, неправильно: нужно делать проверки на instanceof в контроллере. Не понимаю, как сюда вклинить обработку ошибок, набросок сервиса: https://ideone.com/ijUVZR набросок контроллера: https://ideone.com/dgyVC5 Я использую такую абстракцию для файла: https://github.com/symfony/http-foundation/blob/master/File/File.php Почему сразу не использую UploadedFIle: https://github.com/symfony/http-foundation/blob/master/File/UploadedFile.php Его тоже можно переместить, даже если он получен не из HTTP (параметр $test в конструкторе), но, как я понял, параметр $test тут только для тестов.
>>940144 >чтобы он мог выполнить редирект на страницу с этой сущностью А зачем? >Получается, что метод upload может вернуть 2 разных объекта в зависимости от валидности файла? Это, наверное, неправильно: нужно делать проверки на instanceof в контроллере. Зачем? Разве не логичней в случае ошибки вернуть false? Тоже делаю фйлообменник, если что.
>>940151 >> чтобы он мог выполнить редирект на страницу с этой сущностью > А зачем? Ну вот загрузил ты файл на файлообменник и хочешь поделиться ссылочкой. Логично сразу после загрузки произвести редирект. rghost тоже делает редирект на загруженный файл, можешь проверить.
>> Получается, что метод upload может вернуть 2 разных объекта в зависимости от валидности файла? Это, наверное, неправильно: нужно делать проверки на instanceof в контроллере. > Зачем? Разве не логичней в случае ошибки вернуть false? Тоже делаю фйлообменник, если что.
А как ты донесёшь до пользователя причину ошибки? Фразой "Что-то пошло не так"? Я хочу давать внятные объяснения.
>>940144 Если ты используешь силекс, то можешь воспользоваться уникальной возможностью прикрутить к нему симфониевские формы и валидатор. Если же нет, то советую сделать следующее: Сделать контроллер страницы загрузки, куда попадает засубмиченая форма Сразу валидировать форму с помощью сервиса валидации, который отправляет true/false в контроллер Если форма валидна - сохранять файл и редиректить куда тебе надо Если нет, то рендерить тот же шаблон с ошибкой
>>940156 >А как ты донесёшь до пользователя причину ошибки? Фразой "Что-то пошло не так"? Я хочу давать внятные объяснения. Вроде как такое должны делать исключения, не? Типа в контроллере траишь, и если всплыло исключение то вместо редиректа показываешь шаблон с ошибкой. Я бы как-то так делал.
Гайс. Почему действие2 не выполняется? $ears = 0; for ($vklad = 10000; $vklad < 1000000; $vklad 1.1 ) { $ears++; } $earsOld = 16 + $ears; echo "Вкладчику будет $earsOld лет. В банке будет 1000000 через $ears лет.";
Если я его отдельно запилю, то все работает, а в самом цикле - нет. $ears = 0; for ($vklad = 10000; $vklad < 1000000; ) { $ears++; $vklad = $vklad 1.1; } $earsOld = 16 + $ears; echo "Вкладчику будет $earsOld лет. В банке будет 1000000 через $ears лет.";
>>940269 пропустилзнак умножения, но с ним все равно не работает $ears = 0; for ($vklad = 10000; $vklad < 1000000; $vklad * 1.1) { $ears++; } $earsOld = 16 + $ears; echo "Вкладчику будет $earsOld лет. В банке будет 1000000 через $ears лет.";
Пыханы, делаю тестхаб на симфони и возник у меня вопрос. Есть 3 таблицы: User, Test и Question. Они все связаны внешними ключами по типу one to many User => many to one Test one to many Test=> many to one Question. Как вообще обычно делаются заполнения подобных таблиц? Это нужно как-то прописывать в репозитории или что? Пытаюсь передать id юзера в тест вручную, а доктрина при создании теста говорит, что туда нужно пихать инстанс юзера.
И вот допустим я создаю тест и нужно туда создать вопросов и тут 2 варианта: 1 создать сначала пустой тест, а потом по ссылке перейти на форму создания вопросов 2 создавать сразу тест с вопросами В первом варианте недостаток в том. что юзер может спамить пустыми тестами, создавая их до бесконечности, а во втором не понятно как объединить форму теста с формой вопроса, при том, что тест еще не создан, а значит id его не известно(автогенерация) и вопросы не могут быть привязаны к этому тесту.
Есть такой чувак https://kwork.ru/links/1754/ssylki-c-bolee-1000-saytov-s-tits-10-650 который предлагает поставить 1000 ссылок на продвигаемый сайт с других сайтов всего лишь за 500 рублей. Само собой он не будет ставить их вручную а всё сделает автоматически. Для этого пишутся парсеры? Но если сайтов много и они разные выходит для каждого сайта нужно написать свой парсер? как найти подходящие сайты, с которых ссылки будут котироваться поисковыми системами?
>Можно создать новый если хочешь. Хочу. Только было бы неплохо, если бы там помимо меня был ещё кто-то. Вообще, помню, там людей было немало - человек 10-15, вроде.
Так как Доктрины пытается создать видимость, что все объекты находятся в памяти, то связи в них делают через поля с нужной аннотауцией. Если например у Теста есть Автор, то мы так и пишем:
class Test { // аннотация ManyToOne protected $author; }
И Доктрина сама подставит туда либо объект Пользователь, либо прокси-объект для ленивой загрузки.
Ну и ты можешь туда прописать объект Пользователя и при flush() соответствующие внешние ключи в базе может быть будут обновлены (там есть подвох, проверяется только один объект в отношении и надо понимать, какой).
Там надо изучить документацию, так как много особенностей, которые надо понимать. И про коллекции, и про ленивую загрузку и прокси-объекты.
Соответственно для установки связи тебе не нужны id и ты можешь создавать целые графы из объектов:
$author = new User; $test = new Test; $test->setAuthor($author); $question = new Question; $test->addQuestion($question);
$em->persist(...); $em->flush();
> 1 создать сначала пустой тест, а потом по ссылке перейти на форму создания вопросов > 2 создавать сразу тест с вопросами А зачем создавать пустой тест? Что тебе мешает сразу переходить на форму создания теста, не создавая ничего в БД?
> а во втором не понятно как объединить форму теста с формой вопроса, при том, что тест еще не создан, а значит id его не известно(автогенерация) и вопросы не могут быть привязаны к этому тесту. Если ты используешь аякс, то у тебя одна страница с которой ты никуда не уходишь, и проблемы нет (хотя даже в этом случае надо подумать, как сохранять данные на случай например закрытия браузера или неожиднного отключения питания). Если ты не используешь аякс, а используешь обычные формы то да, тебе надо где-то хранить пока еще не сохраненный тест. Тут много вариантов, у каждого свои недостатки:
- хранить все несохраненные данные в скрытых полях формы (например сериализованную версию графа объектов теста), и передавать с одной страницы на другую (сложновато, но зато соответствует идеям REST). В ASP по моему когда-то такая штука использовалась. - хранить в БД, с пометкой, что это не сохраненный тест (чтобы не показывать его в списках). При желании можно написать сборщик мусора, удаляющий старые не сохраненные тесты, но я не уверен, что это хорошая идея. Может лучше их хранить под названием "черновики тестов"? - сделать какое-то временное хранилище, вроде отдельной таблицы, и там хранить сериализованные данные. Что-то вроде сессий, только не на основе кук. - сессии. Не нравится тем, что они удаляются через полчаса неиспользования, и тем что они общие для всех вкладок браузера, неудобно будет редактировать 2 теста одновременно.
Поясню про сериализацию. Доктрина позволяет связывать объекты без id, и ты можешь в конце скрипта сериализовать граф несохраненных в БД объектов теста, вопросов и тд и сохранять его например в скрытом поле формы, а в начале скрипта - восстанавливать его. Правда с восстановлением сохраненных в БД сущностей будут некоторые сложности, но их при желании можно решить.
Тут правда есть проблема: десериализовывать данные, пришедшие от пользвоателя небезоасно, это может привести к уязвимости, были случаи. Так что хранить данные надо не в форме, а на сервере, либо надо их сериализовывать в какой-то безопасный формат вроде JSON и тщательно проверять при восстановлении.
> юзер может спамить пустыми тестами, создавая их до бесконечности, А пустые можно не сохранять. А если юзер что-то ввел, то может он хочет чтобы эти данные сохранились и чтобы он мог продолжить редактирвать тест позже. Насчет места я бы не беспокоился - сейчас в ходу терабайтные диски. Фейсбук например сохраняет даже стертые и не отправленные посты и его это не беспокоит.
>>940862 Скайп блокирует 80 и 443 порт, а они нужны апачу, вмваре и опенсерверу. Так что лучше телеграмм. Ну или ты будешь обьяснять как настраивать скаеп каждому новому ньюфагету.
>>940884 >>940876 >>ты будешь обьяснять как настраивать скаеп каждому новому ньюфагету. Это чат - пусть для новеньких - но, всё-таки, программистов. Если человек не может установить скайп и отправить заявку в группу, ему там, пожалуй, не место, разве нет?
ОП, ты огромный красавчик, честно. Я вот сейчас так поглядел на количество представленного в шапке материала, думаю я бы в свое время гораздо быстрее бы пхп раздрочил + много вещей еще решил пересмотреть. громадный тебе +
https://geektimes.ru/post/286304/ Программисты скоро не нужны будут, DeepCoder от Microsoft сам пишет код из требований заказчика. Будущее за самопищущимся кодом.
>>941289 И сюда это притянули. Ты понимаешь, что даже человеку сложно облачить невнятные требования заказчика в формализованные задачи, что уже говорить о роботах. Программистов если и заменят, то только в последнюю очередь.
Аноны блять помогите с этой хуетой Административная панель: Вывод всех студентов ФИ группа курс кол-во тестов на 3, 4, 5, общее кол-во средний балл (% правильных ответов) средняя оценка с фильтрами по группам, курсам, предметам Сортировки при выводе по ФИ, результатам, дате написания последнего теста, %правильных, по среднему баллу. Добавление, удаление, редактирование записей студентов и о студентах при нажатии на ФИ студента. Статистическую информацию по каждому студенту: Сколько раз решал каждый тест Лучший результат Подробная информация о попытках (сколько ошибок, сколько времени затратил, дата решения теста) по каждой теме предмета и по общему тесту Форма создания и редактирования тестов(вопросов)+перемещение между темами Форма создания и редактирования предметов Форма создания и редактирования тем Предусмотреть что в теме уже могут быть вопросы. для того, чтобы удалить тему, нужно либо удалить вопросы этой темы или переместить в другую тему я вообще хз как это делать
Вопрос по критическим ошибкам в сценариях. Это не про ошибки, возникающие в процессе работы, которые можно бы было выловить с помощью try-catch или exception и обработать, а про ошибки типа fatal (php) typeerror, parsererror (js), которые прекращают текущий сценарий вообще.
JS: Нет мыслей. Тем более важно, что обычно при фатальных ошибках максимум что происходит - это ничего не происходит (кроме сообщения в консоль, но много ли вы видели людей которые лезут в инструменты разработчика, чтобы посмотреть, что же случилось?).
inb4: фатальные ошибки не могут произойти если всё протестировано отлажено... Возможно, могут? Довольно много лазаю по различным сайтам, иногда вижу php нотайсы, ошибки, бывает даже куски кода вылезают наружу. И это у дядек, которые зарабатывают программированием.
>>941269 Бессмысленный вопрос. Если хочешь вкатиться, должен быть подход "даже если все скажут, что нельзя, я все равно вкачусь и выебу этот стереотип" и т.д. и т.п.
Если ты придешь на собеседование и покажешь лучшее владение предметом, чем у всех остальных (а я так понимаю, на джуна большинство кандидатов околонулевого уровня), возьмут конечно тебя.
Как организовывают пагинацию? Я помню как с mysql я это делал, но в PDO как-то застрял. Ведь надо передавать параметры выборки. А я чот не понимаю как это делается.
ОПчик, чисто интересно, а ты никогда не думал запилить онлиан-курсы на платной основе по пхп? Просто ты и так дохуя время на всяких ньюфагов тратишь, а так мог бы еще и заработать неплохо. Просто я смотрел несколько таких курсов, и там по больше части либо учат жуткому говнокоду, либо дают набор несистематизированной инфы, я толко несколько годных нашел. У тебя же куча и уроков, и опыта обучения ньюфагов, мог бы сделать годноту. Срзли, подумай над такой возможностью.
$answers = ['да','нет','не знаю','никогда','это зависит от тебя','спроси у анона']; $question = 'выучил ли ты пхп без смс?'; $answer = $answers[array_rand($answers)];
В задаче на палиндром что нужно использовать, дабы удалить пробелы? В интернете для этого много разных команд выдает.
И ещё вопрос. Вот на прикле я написал, он разве не должен выдать текст со всеми символами в нижнем регистре? Не могу с палиндромом, постоянно ошибку выдает. Хотя предыдущие два задания решил без проблем.
>>942059 у тебя на 14 строке точки с запятой нет. Пробелы в начале и конце строки удаляются функцией trim(). Если нужно удалить вообще все пробелы, то str_replace() или preg_replace()
Скажите, если есть к примеру скрипт admin.php по адресу site.ru/admin, в нем есть переменная $n = 10. Если оттуда происходит переход к скрипту settings.php по адресу site.ru/admin/settings, то будет ли в скрипте settings.php видна переменная $n, как сделать, чтоб она была там видна.
>>942483 > Если оттуда происходит переход к скрипту settings.php Переход это редирект? Если да - то переменная $n в том скрипте видна не будет, так как редирект - это новый HTTP-запрос, а PHP на каждый запрос заново инициализируется и умирает.
> как сделать, чтоб она была там видна. - передавать как get-параметр: settings.php?n=10, либо хуже - писать $n в куки/сессию. В скрипте-получателе выковыривать.
Внезапно столкнулся с проблемой с БД. Пишу себе бложик, никого не трогаю. Ну и в запись вставляю изображение. Тоесть идёт такое повествование, а потом раз, фотка и повествование продолжается. Причём фоток может бять от 0 до 100500. Соответственно выглядит оно как теги с ссылкой на фото <img src="img.jpg"> и вроде всё нормально, но последний Mysql начал адово глючить при виде любой кавычки в таблице. Как стоит поступать в таком случае?
>>942747 А смысл? Я Insert делаю через админ например. Ошибка нигде не проходит, сайт отображает всё отлично. Всё читается, работает и вообще всё отлично. Но вот PHPmyAdmin упорно говорит что я неправ при попытке отредактировать запись или при попытке отредактировать всё что после этой записи. Пикрил например. .
>>942762 Короче, у кого новый оперсервер последней версии, можете смело на него накатывать Myadmin 4,6,6 и переносить конфиги. И будет вам счастье. Старый админ 4,5,7 глючит очень сильно.
Тут кто-то работает с Wordpress? начал изучать его пару дней назад и столкнулся с такой проблемой. Писал на форум их, но ответа не получил. Без понятия, как решить это. Суть проблема такова: хочу установить расширение для Unyson, а именно Конструктор страниц. В треде JS, не помогли
>>942789 Там говорится о том, что при попытке подключиться на локальный порт 1080 твоего компьютера запрос на соединение отклоняется. Значит, то, что должно принять этот запрос, не работает. Что именно? Веб-сервер, может? Может, что-то ещё?
Вообще, тут интересный случай. Порт 1080 используется для сервиса SOCKS (что-то вроде прокси для выхода в сеть через него). Не представляю, зачем расширению доступ к этгому порту.
Опчик, а скажи. Вот эти объектные паттерны, они применимы только к ПХП или они более абстарктны и их можно использовать в любом другом ОО языке, в котором ОО реализовано примерно как в ПХП?
>>942916 Слухай, а у тебя там URL правильный? Я нашел, вроде, файл, отвечающий за обновление. Если ошибку всё ещё не устранил, можно попробовать расставить там var_dump`ы и посмотреть на вывод.
>>942928 > глянуть в исходники и узнать Не понимаю о каком исходнике ты говоришь, ибо тупой:( Можешь название сказать этого исходника, если не затруднит. >>942961 Я так понимаю эта папка отвечает за обнову, но какой файл ты имел ввиду?ведь там сотни их.
>>942995 Матерь Божья, у тебя Windows... Да уж... Ладно, если для тебе сложно, проверь, правильно ли указан URL по которому происходит запрос на обновление.
Товарищи. Решил освоить Laravel, написал простенький однопользовательский бложик, решил взяться за что-нибудь посерьезнее и накалякать имиджборду.
Примерно структура таблиц на пике. Так пойдет? Понимаю, что возможно не самая эффективная архитектура для борды, но 3НФ и с точки зрения моделей Eloquent правильно вроде.
Сейчас мне надо решить главные вопросы, как организовать номера постов, и порядок и смыв тредов. Если делать так как на пике, то порядковый номер треда будет храниться вместе с инфой о треде в колонке ordinal number. Соответственно при поднятии треда все остальные придется опускать и менять им ordinal_number. Можно вообще не хранить порядковые номера тредов, а например (если хранить в boolean сажу для поста) вычислять на ходу по последнему посту без сажи. По идее гораздо больше мороки, придется лопатить все посты и при чтении и при записи. Та же история с номером последнего поста на доске. Можно хранить, можно вычислять. Как кошернее будет? Впрочем любым советам рад буду.
>>943231 У постов и тредов Первичным Ключом id'шник, а не составной потому что Eloquent (местный ORM) составных ПК не понимает. У борд вместо id'шника можно сразу линк использовать, но так проще борды переименовывать.
Поясните за обжект рилейшен мапинг. Хоть убей не могу понять в чем суть это хуиты и почему оно так важно. Это типа проецирование объектов-сущностей на БД и обратно? Может кто совсем простеньких примеров подкинуть?
Анон, помоги разобраться. Разбираюсь сейчас с организацией файлов в проекте. И возник такой вопрос: каким образом ограничивается доступ ко всем директориям, кроме \web, если файл .htaccess сам хранится в директории \web и будет оказывать воздействия только на нее?
>>943385 Можно через .htaccess, я же делал через настройки апача, или что у тебя там. Пишешь в конфиге <VirtualHost :80> # Имя сервера которое обслуживает этот VirtualHost ServerName students.local # Корневая папка сервера DocumentRoot C:\OpenServer\domains\students.local\public <Directory "C:\OpenServer\domains\students.local\public"> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.)$ index.php [QSA] AddDefaultCharset UTF-8 </Directory> </VirtualHost> В <directory> можешь скопипастить содержание .htaccess И он уже считай тебе не нужен.
$pdoStatement->setFetchMode(\PDO::FETCH_CLASS, 'User'); Почему далее запрос возвращает массив? Поля совпадают (пробовал ставить public), все равно не работает
У веб-сервера есть такое понятие, как корневая директория (document root). Надо в конфиге сервера просто поставить корневой директорией нужную папку. Для Апача в конфиге надо найти нужный блок VirtualHost и внутри него поставить директиву
Это да, загрузка и запись в базу данных объектов. Если ты используешь ООП, то в твоем коде есть классы-сущности и надо как-то сохранять и загружать их из БД. Чтобы не писать все это с нуля и не мучаться, есть готовые библиотеки ORM вроде Доктрины. С нуля такое писать год можно, если не больше.
Я советую проектироват базу так: сделать полностью нормализованное решение, а потом добавлять избыточные поля для оптимизации действий с таблицами.
Вообще, ordinal_number у треда это довольно неудачное решение. Это избыточная информация (так как порядковый номер треда можно вычислить через дату добавления последнего поста и наличие сажи). В принципе такие поля можно добавлять ради оптимизации выборки, например, но в твоем случае это довольно неудачное решение, так как при добавлении каждого поста нам надо обновлять все номера тредов, а базы не очень любят большое число операций записи. То есть от него вреда больше, чем пользы получается.
Я бы предложил добавить другое лишнее поле: дату обновления треда с учетом сажи (назовем ее bumpDate - момент последнего бампа треда). Если мы добавляем пост без сажи, и не достигли бамплимита, то мы обновляем bumpDate у треда. Соответственно, после этого мы можем сортировать посты по ORDER BY fixed DESC, bumpDate DESC (индекс по (fixed, bumpDate) отлично оптимизирует сортировку).
Конечно, номер хорош тем, что позволяет оптимизировать постраничную навигацию - мы можем сделать запрос WHERE number BETWEEN 10 AND 20 ORDER BY number, который идеально ложится на индекс. Без номера мы вынуждены использовтаь LIMIT, который не очень оптимально работает дальше N-й страницы (подробнее о недостатках LIMIT ниже).
Также, надо решить проблему вывода 3 последних постов треда. Для эффективной их выборки, скорее всего, надо добавлять дополнительные данные - например, таблицу связи между тредами и постами, или колонку, в которой через запятую хранятся id последних постов (тут правда не получится использовать внешние ключи).
Часть колонок у тебя я не понял. Зачем например колонка timestamps у треда и борды? Из названия понять ее назначение невозможно. Зачем last_post_nubmer у борды?
Зачем post_number у постов? Если тебе надо ставить номера при выводе, то может проще их считать в момент выовда? Хотя, вреда от него особого нет, так как номера не требуется пересчитывать при вставке поста, и получение номера последнего поста хрошо оптимизируется индексом.
Добавлю немного про LIMIT. Он используется повсеместно для пагинации, но у него есть недостатки:
- при очень большом OFFSET запросы получаются неэффективные - в обновляющихся лентах, если ты идешь от 1-й страницы к последней, и добавляются новые посты, ты можешь натыкаться на уже просмотренные посты
Для борьбы с этими проблемами есть особая техника, когда мы используем вместо номера страницы значение поля, по которому сортируются записи, примерно так: /threads?page=4&bumpDate=2017-01-02T12:00:00. Подробнее от этом тут: http://use-the-index-luke.com/no-offset
Такой подход исплоьзуется например на reddit.
И еще, подозреваю, что выборка 500 объектов-постов через ORM будет работать не очень быстро. На таких объемах наверно выгоднее выбирать данные напрямую из БД.
Вообще, борда это довольно тяжелый (но интересный) случай с точки зрения оптимизации, так как тут при чтении треда идет выборка большого объема информации (500 постов - это может быть около 2 Мб текста), и ее трудно сделать быстрой. Мы должны прочитать из БД 2 Мб информации, засунуть ее в шаблон, отформатировать текст, отдать пользователю. Трафик, который может отдать база, он понятное дело, ограничен, и это может стать узким местом. И не только база, канал связи между пользователем и сервером - он тоже ограничен и конечно пересылать маленькие объемы данных было бы выгоднее.
С другой стороны, пользователь, получив тред, будет его долго читать, и может быть, не станет дальше беспокоить сервер запросами. А может он прочтет 2 поста и перейдет к другому треду.
Ну допустим у нас соединение с БД идет по 1 Гбит/с каналу. 2 мегабайта это 16 Мбит, значит мы в принципе не можем в такой ситуации в секунду отдать больше 60 больших тредов в секунду. Это в идеальном случае, если база способна генерировать данные с такой скоростью.
Я знаю, что некоторые борды хранят кеш HTML-кода треда, например в виде файла на диске. При чтении треда мы просто отдаем пользователю файл с диска, а при добавлении поста мы либо перегенерируем файл, либо как-то по-умному вставляем пост в конец треда (что может быть эффективнее). Но тут мы получаем другие проблемы:
- добавление одного поста может требовать перезапись огромного файла. Скорость записи на диск ограничена. То есть мы быстро вставляем 1 пост в базу и не спеша обновляем файл с кешем страницы, и это ограничивает скорость постинга. Более того, диски лучше всего принимают последовательную запись, а когда несколько потоков параллельно пишут треды - общая скорость проседает. - перегенерация кеша треда требует блокировки. Так как если 2 потока одновременно будут перегенерировать один тред, может выйти что-то кривое. - с другой стороны, отдача статических файлов - это то, с чем веб-сервера вроде nginx справляются отлично. То есть мы можем даже не дергать PHP приложение при запросе треда, плюс в линуксе есть разные оптимизации, которые позволяют например нгинксу отдавать файл в сеть, не читая его (ядро само этим займется). - статический файл можно сжать gzip при записи, что снизит нагрузку на диск (так как данных будет меньше, текст хорошо жмется, раз в 5-10) и ускорит отдачу, снизит нагрузку на интернет-канал. С другой стороны, непонятно что тогда отдавать пользователям, не поддерживающим gzip? распаковывать для них файл на лету? Также, в сжатый тред нельзя вставить один новый пост, его можно только переписать целиком (или нет? я не эксперт по gzip). - с третьей стороны, мы можем для кеша вместо реального диска использовать ram-диск (tmpfs в линукс). То есть хранить файлы в оперативной памяти, лучше наверно в сжатом виде. Запись в память идет с максимальной скоростью, и отдача файлов из памяти nginx будет очень эффективна. Мне кажется, что быстрее варианта, чем отдавать нгинксом файлы из памяти, в принципе нет. - с четвертой стороны, кеш имеет те недостатки, что файл получается одинаков для всех пользователей. Представь, что мы хотим написать в углу "здравствуйте, Иван" или подсвечивать посты пользователя. Вся наша схема перестанет работать, так как HTML-код теперь разный для разных пользователей. Мы должны либо задейтствовать PHP, и возможно, базу, либо добавлять нужные данные яваскриптом в браузере. На этой борде используется подсветка через яваскрипт
То есть в итоге, я бы поэкспериментировал с кешированием тредов в tmpfs, может в сжатом виде, и посмотрел бы, можно ли при добавлении поста не перегенерировать тред целиком. Хотелось бы конечно иметь и сжатие, и добавление одного поста.
Некоторые борды также генерировали HTML-файлы для страниц со списком постов (главная, 2-я старница, 3-я и тд), но это по моему неэффективно, так как при каждом добавлении поста мы должны перегенерировать все файлы страниц. Это узкое место. Мне кажется, что страницы выгоднее генерировать на лету. Единственное, что тут можно оптимизировать - можно сделать HTML-кеш в памяти для треда (ОП-пост + 3 последних поста + HTML-обвязка). То есть из базы выбираем id тредов на текущей странице, затем из кеша берем их представление и отдаем пользователю. При обновлении треда либо дропаем кеш, либо обновляем.
Зато тут есть возможности для распараллеливания:
- разные борды никак не связаны друг с другом, и мы можем помещать их на отдельные сервера. Причем в базу друг к другу они не лезут и каждый может использовать свою БД - отдача тредов из tmpfs не параллелится на несколько серверов - отдача списков тредов методом база + кеш параллелится
Вообще, тут конечно мало рассуждать теоретически, надо брать сервер и делать эксерименты, измерения.
Если хочешь, можешь тоже над этим подумать. Можешь кстати потом померять свою борду.
>>943458 >>943530 public function getUserByEmail ($email) { $pdoStatement = $this->pdo->prepare("SELECT * FROM users WHERE `email` = :email;"); $pdoStatement->bindValue(":email", $email); $pdoStatement->execute(); $pdoStatement->setFetchMode(\PDO::FETCH_CLASS, 'User'); $user = $pdoStatement->fetch(); // var_dump($user); return $user; } И еще насчет авторизации: сделал, что, авторизовавшись, пользователь получает код в куки, и он же (код) идет в БД. И в суперкласс Контроллеров добавил свойство Юзер и метод, который по коду в куках возвращает Юзера; метод вызывается в констукторе, но это как-то криво, так как пришлось для Маппера и класса Авторазации добавить поля в супер класс Контроллера, но этого, навеное, можно избежать: лишние зависимости. Что еще можно придумать?
В любом языке. ООП в разных языках использует одни и те же принципы, и тщательно выучив ООП в PHP, решив мои задачки по ООП, а также задачу про скидки, ты сможешь легко разобрться с ООП кодом на других языках.
Ты не учел что с сайтом может работать несколько пользователей и у каждого могут быть свои данные. Лучше передавать через GET/POST. сессии/куки имеют тот недостаток, что они общие для всех вкладок в браузере, а URL в каждой вкладке свои.
Мне кстати не нравится телеграм тем, что надо сдать свою персональную информацию Дурову. Никакой надобности, кроме желания следить за пользователями, в этом нет. Он и вконтакте собирал все, что можно, и тут собирает. Уверен, у него где-нибудь есть бекап базы ВК.
> http://ideone.com/sRvu3e - мини "калькулятор"; Там внизу ошибка: ты забыл поставить скобки после error_reporting(-1);
В остальном все верно.
> http://ideone.com/8x1TeV - Игра в кубики с Пекой; Тут вместо кучи exit лучше было сделать большой блок if/esleif/elseif/else. В таком блоке может выполниться только одно из условий и exit не нужен.
> http://ideone.com/8GN4S3 - депозит; Нет скобок после error_reporting, также в задаче требовалось ответить, когда накопится миллион на счету. Видимо ты не очень внимательно прочел условие.
Попробуй поставить setFetchMode перед execute. Если это поможет, проверь что при перестановке обратно проблема вернулась, и напиши тут об этом. Я хочу в этом случае написать разработчикам PHP, чтобы они либо добавили предупреждение в код при неправильном использовании функции, либо хотя бы задокументировали это. Давайте поможем сделать PHP лучше.
> И в суперкласс Контроллеров добавил свойство Юзер и метод, который по коду в куках возвращает Юзера;
Вообще, это, мне кажется, неправильно. На каком основании ты решил этот код внедрить во все контроллеры? Не логичнее ли сделать отдельный класс, отвечающий за авторизацию?
Вот это плохая идея, сегодня ты добавил авторизацию, завтра еще что-нибудь и у тебя базовый контроллер превратится в god object.
Что касается зависимостей, в Симфони например контроллер получает DI контейнер (через метод setContainer) и может сам брать из него что нужно. Хотя никто не запрещает использовать DI и передавать зависимости контроллеру в конструктор.
>>943044 Я сдаюсь, слишком мало скиллов, чтоб понять что от меня хотят. Пошел Drupal пытаться осваивать, может там повезет больше, спасибо за ответы :p
Какая замечательная система линукс. Обожаю когда ничего не работает. Даже не хочется писать что не получается.
Поставил апач, пхп. Пытаюсь создать "Hello World", сохраняю в дефолтную папку var/www/html - "Нет доступа". КАЕФ.
Решил поступить другим путем: поменять директорию. Открываю etc/apache2/apache2.conf, пытаюсь изменить <Directory /var/www/> Хм, странно. Индексная странница находиться в /var/www/html/, а прописано что в www Ха, нельзя сохранить - нет доступа.
Гуглю как получить доступ, затем пишу в терминале хаахаххахаха в терминале редактирую файл))00000))) sudoedit... Ничего не сработало, корневая директория по прежнему осталась стандартной.
Гуглю дальше, пишут что нужно поменять ещё в etc/apache2/sites-enabled/000-default.conf Очень странно. Пытаюсь его отредактировать выдается ошибка: sudoedit: etc/apache2/sites-enabled/000-default.conf: editing symbolic links is not permitted
В гугле не очень нашлось по этому. Попробовал написать иначе sudo nano... Хах, редактор открылся, причем тот же самый что и при sudoedit. Но ничего не поменялось.
>>943696 1) Убунта кусок говна. Ставь федорку 2) Если поменяешь бубунту на норм дистр, то сможешь использовать su и su - c " " вместо sudo 3) В sites-enabled лежат симлинки на конфиги из sites-available, правь их там
>>943711 Чтобы сохранять нормально в папку дай себе на нее права таки. chown -R user:group /path/to/folder (рекурсивно сменить владельца) chmod -R 777 /path/to/folder (рекурсивно выставить максимальные права доступа для всех на все что лежит в папке)
>>943713 А вообще правильнее так будет: 1) владельцем ставишь себя 2) группой владельца группу под которой запущен апач 3) себе ставишь полный доступ 4) остальным можешь вооще закрыть 6) группе апача чтение на все и запись на папку куда загружаешь файлы (uploads какой-нибудь)
Костыли. Как организовать работу (права) над сайтом, если надо дать доступ нескольким пользователям + запускать cli программы? И гарантировать, что из-за дефолтного umask 022 например не получатся защищенные от записи файлы и каталоги?
В гайде Симфони рекомендуют использовать ACL, так как стандартные юниксовые права там плохо работают.
>>943719 Пост читал, следущие два ответа тоже мои. Убунта реально глючный кусок говна. Fedora тоже не сахар, как-никак тестовый полигон красношапки, но бубунта умудряется быть даже более глючный чем тестовый полигон. К тому же дистр, который за меня решает можно ли мне логиниться под рутом или нельзя ненужон и место его в мусорном ведре. И не костыли, а стандартная рабочая схема. Права на создаваемые файлы тоже редактируются если правильно помню. Нескольким пользователям с такой моделью доступа никак.
И во вьюхе уже по отношению, мы вытаскиваем $thread->posts()->where('op_post', true)->first()->topic
2) моделька пожирнее, где мы скажем довляем функцию op_post, а во вьюхе пользуем просто $thread->op_post()->topic
3) В контроллере или модели собрать структуру данных не являющуюся отражением модели, но хранящую всю нужную информацию для построения вьюхи и передавать вьюхе уже ее, чтобы она сама БД не дергала
Представляете, а у меня все работает на убунте, после того как я заново запустил виртуальную машину. Я клянусь, я делал рестарт апача apache2 -k restart
А ещё и кусок кода начал работать после перезагрузки.
Всем спасибо за помощь. Все советы были полезными.
Аноны, RewriteCond %{REQUEST_FILENAME} !-f исключает из редиректа не только статические файлы, но .php. В итоге есть доступ ко всему. Из-за чего такое может быть?
>>943931 Я в этом новичок, думал -f уберет все статические файлы, а .php оставит. Конструкция !\.(css|js) работает как надо. Но тогда непонятно зачем -f и -d во все гайды добавляют. Разве из-за этого не может возникнуть дыра в безопасноти?
>>943581 >Попробуй поставить setFetchMode перед execute. Не вышло, попробую сегодня студентов начать делать, может, увижу косяк, когда на ясную голову. >Вообще, это, мне кажется, неправильно. На каком основании ты решил этот код внедрить во все контроллеры? Не логичнее ли сделать отдельный класс, отвечающий за авторизацию? Я понимаю, что это неправильно, и класс у меня для авторизации есть, только так как вызывать мне нужно было его каждый раз при переходе на страницы, то я и сделал создание объекта класса Авторизация и его вызов в конструкторе Контроллера, чтобы всегда проверялось, авторизован ли пользователь. >Что касается зависимостей, в Симфони например контроллер получает DI контейнер. А разве это не становится тем самым ServiceLocator, то есть лишней зависимостью, от которой должен по идее избавлять DI Container? Я так понимаю в файле инициализации создается DI Container (например, Pimple), которому задаются все схемы зависимостей (функции), а далее с ним как в идеале? Или констуктору нужного Контроллеру передавать или глобальный объект, что плохо? Просто опять-таки не вижу разницы между ServiceLocator, кроме удобного интерфейса, который и не относится к самой идее DI Container. Думаю, у меня в этом вопросе некоторое недопонимание. И еще несколько вопросов: Как эффективнее назначать класс active текущей странице из навигационного меню. Можно в контроллере иметь поле name, а в шаблоне шапки сайта константы (можно ли такое в шаблоне хранить?), в самом меню условие: <li <?=($name==HOME)?'class="active"':''?>><a href="/">Главная</a></li> <li <?=($name==GOODS)?'class="active"':''?>><a href="/goods">Товары</a></li>
>>944003 Когда-то тоже задавал вопрос по поводу внедрения DI-контейнера прямо в контроллер. Да, это именно сервис-локатор, так как зависимости контроллера скрываются, непонятно что нужно класть в контейнер, чтобы контроллер работал. В Symfony/Slim есть такое понятие как controller-as-a-service: https://symfony.com/doc/current/controller/service.html То есть в контейнер кладётся контроллер и в качестве его зависимостей указываются нужные сервисы. В Slim можно писать как-то так: $container['UserController'] = function ($container) { ____return new \UserController($container->get('renderer')); }; Тогда контроллер будет иметь прозрачные зависимости. Но в этом не очень много смысла так как хороший тонкий контроллер юнит-тестировать не нужно: он выступает лишь прослойкой между HTTP и моделью. Если возникает желание юнит-тестировать контроллер, то он скорее всего содержит что-то лишнее.
Вот кстати, эта схема с кучей вложенных коллбеков действительно сложная. В PHP, в React promise сделано интереснее: там есть 2 объекта: Deferred и Promise. И Deferred как раз используется для разрешения или отклонения промиса.
Для тех, кто не в курсе, промисы - это абстракция для асинхронных операций, то есть операций, которые выполняются в фоне в течение какого-то времени. Например, скачивание файла. Функция скачивания файла запускает процесс и возвращает промис, не дожидаясь его окончания. Когда файл скачается, промис разрешится в его содержимое, или в исключение, если произойдет ошибка. Получатель промиса может подписаться на событие, и указанная функция будет вызвана, когда результат будет готов.
Понятия не умею, но могу предположить. Программы устанавливать уметь например, удалять, перемещать и копировать файлы, убивать зависшие программы, обновлять драйвера, не пугаться панели управления Windows. В общем-то то, что наверно сегодня каждый школьник умеет так как без этого в ГТА не поиграть.
>>944431 Кек, только что прочитал и хотел запостить сюда. А ты няша :3 По поводу наглядности: в JS уже если привычно работать то не задумываешься над сложностью конструкций, тем более фреймворки предоставляют свою встроенную реализацию промисов, есть библиотеки опять же (Q)...
https://ideone.com/InOBOk Есть такой вот метод с подстановкой данных через плесйхолдеры. Данные передаются хорошо, однако вот такая ошибка в итоге 0SELECT name, second_name, group_number, summary FROM students ORDER BY :sort LIMIT :start, :limit Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', '5'' at line 5 in C:\OpenServer\domains\students.local\app\Models\StudentsGateaway.php:78 Stack trace: #0 C:\OpenServer\domains\students.local\app\Models\StudentsGateaway.php(78): PDOStatement->execute() #1 C:\OpenServer\domains\students.local\app\Controllers\FrontController.php(42): models\StudentsGateaway->getAll('name', 0, 5) #2 C:\OpenServer\domains\students.local\app\Controllers\FrontController.php(27): Controllers\FrontController->actionIndex() #3 C:\OpenServer\domains\students.local\public\index.php(4): Controllers\FrontController->route() #4 {main} thrown in C:\OpenServer\domains\students.local\app\Models\StudentsGateaway.php on line 78 ЧЯДНТ? Данные передаются правильно, если просто вставить без всяких бинд велью - работает.
> Я понимаю, что это неправильно, и класс у меня для авторизации есть, только так как вызывать мне нужно было его каждый раз при переходе на страницы, то я и сделал создание объекта класса Авторизация и его вызов в конструкторе Контроллера, чтобы всегда проверялось, авторизован ли пользователь. Это не то что бы неправильно, недостаток использования конструктора в том, что этот код вообще всегда будет вызываться, даже если мы не будем выводить шапку с информацией о пользователе.
Может стоит в конструкторе сохранять ссылку на сервис авторизации, а также сделать функцию, собирающую данные для шапки, если там будет не только авторизация. Но если у тебя там только проверка авторизации, можно конечно и в конструкторе ее оставить.
Вопрос про контролллеры и ServiceLocator
Тут есть 2 подхода. Первый: контроллер - это сервис, надо использовать DI, класть его в контейнер. Все красиво и логично, но требует лишней писанины. Второй: контроллер - это не совсем сервис, это скорее стартовая точка приложения и проще использовать тут паттерн ServiceLocator.
Главная проблема ServiceLocator это то, что класс становится зависимым от контейнера со всем его содержимым. Мы не можем этот класс в другой проект перенести или оформить как независимую библиотеку. И мы не можем поменять контейнер, не трогая класс. Ну и некрасиво, что зависимости неточно указаны.
Но контроллер это не повторно используемый код. Он намертво привязан к конкретному проекту и значит, ничего плохого в том, что он знает о контейнере и использует его, нет.
Выбирай сам, какой вариант тебе лучше подходит.
> Просто опять-таки не вижу разницы между ServiceLocator, кроме удобного интерфейса, который и не относится к самой идее DI Container Никто не запрещает в DI контейнере тоже сделать такой интерфейс, я думаю.
> Можно в контроллере иметь поле name, а в шаблоне шапки сайта константы (можно ли такое в шаблоне хранить?), в самом меню условие: В шаблоне точно константы объявлять непраивльно. Сделай какой-нибудь класс с вспомогательными функциями и в нем объяви лучше. Либо можно использовать встроенную константу SomeController::class (или CLASS), содержащую имя класса. Вообще, не надо делать константы, соответствующие классам, так как такие константы уже есть.
Вместо поля с именем контроллера лучше просто передавать в шаблон переменную с названием текущего пункта меню.
> Но в этом не очень много смысла так как хороший тонкий контроллер юнит-тестировать не нужно: он выступает лишь прослойкой между HTTP и моделью.
Это непрактично и сложно, так как контроллер вызывает кучу других методов и мы можем лишь протестировать его работу в сочетании с другими классами. Ну и да, логики как правило там минимум и тестировать особо нечего.
Ты скорее всего не задумываешься, так как ты только пишешь код. А ты попробуй разобрать чужой код, где много коллбеков.
Я в PHP кое-что писал на промисах и там можно голову сломать от сложности, которая получается (асинхронный запуск разных внешних процессов с разными ветвлениями и таймаутами).
Data Mapper заточен именно на загрузку и сохранение объектов (он пытается сделать видимость, что базы нет, а есть просто набор объектов в памяти), а TDG это класс с набором любых действий с таблицей. Также, Data mapper может быть более продвинутым, например, сам уметь обнаруживать изменения в объектах и сохранять их в БД.
Более точные различия можно поискать в книге Фаулера "Шаблоны проектирования корпоративных приложений", где они и описаны.
>>944578 Разобрался, лол. Оказывается, без дополнительных указаний PDO эмулирует строки(добавляет кавычки) на основе всего этого. Соответсвенно, мне надо сделать такой финт - $sth->bindValue(":start", $start, \PDO::PARAM_INT); Однако все равно не работает сортировка, и вот тут я уже не пойму. Даже если вырубить эту эмуляцию через $this->dbh->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false ); все равно сортировка не работает.
Через плейсхолдеры вставляются только значения, цифры и строки в кавычках. Имена полей нельзя. Их придется вставлять напрямую, перед этим проверив по белому списку разрешенных полей, чтобы избежать уязвимостей.
Выключение эмуляции значит, что PDO не будет подставлять данные в запрос сам, а попросит базу это сделать, при условии что она поддерживает такую возможность (иначе он все равно подставит сам).
>>944617 Понял, что-то уже слышал об этом. >>944618 Значит для безопасности мне надо написать код, который проверяет значение $order на существование такого поля в таблице? Бля, у меня и без того есть всякие методы, которые выглядят как не пришей к пизде рукав.
>>944628 А как проверить на несоответствие какому-то элементу массива? Да в любом случае мне надо делать метод, т.к. сортировка у меня не один раз будет, а копипаст это западло, не?
В треде за тысячу постов и вопрос скорее всего утонет, так что напомню: >940144
>>940172 Тоже насчёт исключения думал. 1. В FileService валидируем файл. 2. Если есть ошибки - кладём их в исключение, выбрасываем наверх 3. Наверху кладём ошибки в форму? Они ведь в ней и так содержатся.
Бывают ситуации, когда надо вернуть нескоько результатов. Тут есть такие варианты:
- можно вернуть массив вида ['error' => null, 'file' => $file] - можно вернуть массив вида [$file, $error] - его удобно распаковать через list(..) = ... - можно вернуть $file через return, а ошибку как аргумент переданный по ссылке:
$error = null; $file = upload(..., &$error);
- можно сделать объект UploadResult с 2 полями (больше всего писанины)
Не очень удобно конечно, в других языках вроде Го есть синтаксис для возврата нескольких значений с указанием типов: func something() (File, Error) { ... }
Насчет кода - стоит ли FileNameGenerator делать полноценной зависимостью? Может проще метод вроде generateName поместить в этот же класс?
> Почему сразу не использую UploadedFIle: https://github.com/symfony/http-foundation/blob/master/File/UploadedFile.php > Его тоже можно переместить, даже если он получен не из HTTP (параметр $test в конструкторе), но, как я понял, параметр $test тут только для тестов. UploadedFile это именно что загруженный в $FILES файл, хранящийся во временной папке, его возвращать нелогично.
> как я понял, параметр $test тут только для тестов. Именно так.
Насчет исключений есть разные мнения. Есть те, кто считает что исключения мжно выбрасывать при валидации, есть мнение что неправильно.
Мне больше нравится идея возвращать объект исключения, если это не фатальная ошибка и выбрасывать, если что-то например передано неправиьно. Например, в комментарии не указан IP адрес автора.
>>944654 Тогда как насчёт такого алгоритма: - собрать форму без валидатора - если форма отправлена - вытащить из неё файл и передать его в FileService#upload, получить результат с объектами ConstraintViolationList и Entity\File - если список ошибок пуст, перенаправить пользователя на страницу с файлом - если не пуст, положить ошибки в форму, отрисовать страницу с формой Если ничего не упустил, то такой FileService можно и из консоли запускать.
>Может проще метод вроде generateName поместить в этот же класс? Думаю, что проще, раз FileGenerator больше ни одному из сервисов не нужен.
ОПчик, ты недавно проверял моих судентов, поясни зачем вот это >тут не очень хорошо сделано. Если ты хочешь требовать регистрацию, то надо не выводить форму на любой странице, а делать редирект на страницу регистрации. Если ты хочешь потом вернуться назад, то надо еще передавать URL исходной страницы (а перед редиректом назад проверять, что он на твоем сайте, иначе это будет открытый редирект). Я то понял как, только зачем?
>>944805 Ты кириллицу туда вводишь? Простой strlen() показывает тебе количество байтов, тогда как кириличный символ два байта занимает, т.е. длину кириличной строки ты так не определишь, юзай mb_strlen().
Я не понимат, кому выше и каким образом кидать виджет-ивенты, если я использую сложные V/C виджеты.
Попробовал вот так: в методе PopupController.prototype._attachToPopupView я кину искусственное событие в parentView. Правильно?
Так же вопрос #2, как ловить вот такие события. Так как popup у меня вроде как динамический, я решил сделать количество кнопок по выбору. Их количество и текст внутри зависит от параметра массива optionTxt и его длины, соответственно. Ну а как мне обозначать тип таких событий вот здесь - см. строку "вопрос 2" в коде? Мне всего лишь надо передать номер в старший класс (DomGameView в моем случае) где уже с выбранной опцией вызовется нужный метод из модели. Не делать же заранее 100 констант с номером опций попапа?
Пока не проверяй на гитхабе моего сапера, я коммит готовлю с исправлениями твоих первых правок.
Уточню на счет второго вопроса. В методе dispatcher.addEventListener(EVENT.SOME, func) (его код кстати здесь https://github.com/greenTea242/MinesweeperMVC/blob/master/src/models/EventDispatcher.js , напоминаю что это не нативный addEventListener) первое событие уникальное. А у меня может n-ое количество ивентов, так как кнопок может быть много. });
popupCtrl.getDispatcher().addEventListener(Popup.EVENT_SELECT, function (buttonId) { ... });
Вот этот код выше можно прописать в контроллере игрового поля. View игрового поля про попап тогда знать не обязательно.
Также, я не вижу смысла передавать в контроллер попапа объект его view. Можно наверно создавать view прямо в нем. Все равно ведь никто другой этот view использовать не будет.
Еще может быть стоит подумть об объединении PopupView и PopupCtrl, например в PopupView. В случае с игровым полем - может смысл есть разделять, так как там относительно сложный код, мы можем использовать view без контроллера для отображения данных итд. А тут не очень понятно, в чем выгода.
Может сделать один класс с такими методами?
- addButton() или setButtons() - задают кнопки - show() - создает HTML-код и ставит обработчики на кнопки - destroy() - закрывает попап - getDispatcher() - позволяет подписаться на событие закрытия попапа кнопкой
Вариант с таким кодом: parentViewDispatcher.dispatchEvent(new PopupEvent(PopupEvent.CLOSE_OPTION)); явно сомнительный, так как мы лезем в другое вью и от его имени выбрасываем какие-то события. Это нарушение инкапсуляции, один объект не должен выбрасывать события от имени другого.
И также тут не нужен this._parentContainer.addEventListener("click" - события логично ловить в самом попапе. А твой код пытается ловить события и в родительском вью.
> Не делать же заранее 100 констант с номером опций попапа? Делать или не делать константы - это задача того, кто вызывает попап, а не попапа.
> напоминаю что это не нативный addEventListener) первое событие уникальное. А у меня может n-ое количество ивентов, так как кнопок может быть много.
Можно сделать единственное событие, соответствующее закрытию попапа, хранящее, какой опцией или кнопкой он закрыт.
Вообще, у нас конечно сложноватая схема получилась. Такие иерархии из виджетов обычно используются при построении GUI в десктопных приложениях.
Для сравнения, напишу, как это реализуется в HTML-фремворках вроде angular/react:
- там мы не пишем код для view в виде класса, не пишем код создания дочерних виджетов, а только делаем HTML-шаблон для компонента, в котором могут указываться ссылки на другие компоненты примерно такого вида:
- вместо явной подписки на события мы указываем название метода-обработчика из контроллера в HTML-разметке
- для обновления данных на странице и чтения данных с нее используется data-binding, когда мы например можем привязать инпут к переменной и она будет автоматически обновляться при вводе туда данных, и наоборот, при изменении значения переменной обновляется инпут.
Это в сумме позволяет избавиться от написания рутинного кода работы с DOM (поиск элементов по селектору, подписка на события, обновление HTML), в итоге view у нас просто представлен куском HTML-подобной разметки, и controller не содержит работы с DOM. Ну к примеру, чтобы обновить текст на экране, мы в контроллере просто меняем значение переменной, которая привязана к этому блоку текста.
Примерно так получается (тут используется синтаксис ES6):
// компонент (по сути контроллер из MVC) class Counter extends React.Component {
// в реакте view описывается разметкой прямо в компоненте render() { return <div>Count: {this.state.count}</div> <button onclick={increment}>+1</button> } }
Как видишь, много рутинного кода для работы с DOM здесь выкинуто. Ну это конечно такой простой пример, где мы данные храним прямо в контроллере. Если ты захочешь добавить какую-то сложную модель, то код конечно усложнится, придется городить всякие хранилища, преобразователи (redux) и прочее, так как сама по себе эта штука отслеживать изменения в модели не умеет.
Но для попапа, у которого нет модели, этот подход дал бы такой же простой код, как в примере выше.
Надеюсь я тебя заинтересовал после реализации MVC без фреймворков посмотреть на react. Но сначала с тем, что есть, разберись.
ну а куда развиваться то? на работе будет тоже самое, что курс хохла про интернет магазин же, я хз. Как они синьоров отличают? Три сайта в день шлепает вместо одного?
Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме. ОПу ведь все это читать придется.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут:
Еще предыдущие треды в архиве:
- 83: https://2ch.hk/pr/arch/2016-12-26/res/880700.html
- 82: https://2ch.hk/pr/arch/2016-12-01/res/864640.html
- другие: https://www.google.ru/search?q=site:2ch.hk/pr/+%D0%BA%D0%BB%D1%83%D0%B1+php
Мейлач лежит? Есть запасной тред: http://dobrochan.org/s/res/23225.xhtml#i46467
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост, прежде чем писать код).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
- для начала прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- установи Апач + PHP (советы выше и ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, PDO, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a
- Если ты все решил, переходи к Symfony 2/Doctrine 2
- Почитать про паттерны http://designpatternsphp.readthedocs.org/ru/latest/README.html (если ты не изучил ни одного фреймворка, то это будет рановато), тут с примерами кода http://designpatternsphp.readthedocs.org/ru/latest/README.html . Имей в виду что без примеров использования их учить бесполезно - не поймешь, хочешь увидеть примеры использования паттернов - ковыряй исходники Симфони, например Symfony Forms. Не заучивай паттерны - смотри код и думай, зачем тут они использованы.
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Может тебе понадобится пользоваться командной строкой, вот гайд https://github.com/codedokode/pasta/blob/master/soft/cli.md
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://github.com/codedokode/pasta/blob/master/db/databases.md
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
У ОПа нет аккаунтов и групп вконтакте, в фейсбуке, в твиттере, все "пхп-треды" там поддельные.
Платиновые вопросы
- Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.
- Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета)
- Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery
- Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/.
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев
- Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm
- Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
- Что самое главное для программиста? Умение аккуратно оформлять код.
- ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
- Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.