Этого треда уже нет.
Это копия, сохраненная 10 марта в 20:54.

Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Клуб изучающих PHP #135 /php/ 2932466 В конец треда | Веб
Добро пожаловать. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL) и учимся делать сайты. Зачем? Кто-то хочет открыть стартап, кто-то заработать на лапшу быстрого приготовления, кому-то просто нечего делать.

Это тред для начинающих. Слово «классы» у тебя ассоциируется только со школой, а в аттестате тройка по математике? Ты наш человек.

Предыдущий тред был тут: >>2875886 (OP) . Старые треды тут https://2ch.hk/pr/arch/ (М) (искать по слову php).

С чего начать - основы PHP

Наши уроки по PHP собраны по адресу http://codedokode.github.io/phpbook . Это учебник для изучающих с нуля. Там есть задачи, их нужно решать. Но если этот учебник тебе не нравится, можно читать любой другой. Или официальный справочник ( https://www.php.net/manual/ru/langref.php ). Или все сразу.

Если что-то непонятно, запости код и попроси подсказку или поищи задачу в архиве тредов.

Какой редактор использовать

Простые задачки можно решать в онлайн-песочницах вроде https://onlinephp.io/ , https://paiza.io/en/projects/new?language=php , https://www.programiz.com/php/online-compiler/ , но для программ посложнее лучше установить редактор. Есть (дорогая) IDE PhpStorm, есть бесплатный Netbeans и VSCode, условно-бесплатный Sublime Text. Чтобы в последних получить автодополнение для PHP, нужно установить и настроить PHP language server.

Вот инструкции по установке PHP на компьютер: https://github.com/codedokode/pasta/blob/master/soft/php-install.md
Гайд по командной строке: https://github.com/codedokode/pasta/blob/master/soft/cli.md

Что изучать дальше

Зная лишь основы PHP, сайт ты не сделаешь и работу не найдешь. Обычно от начинающего требуют чуть-чуть больше:

PHP, ООП, основы HTTP, HTML/CSS (основы верстки), JS, SQL, PDO, MVC, git, composer, какой-нибудь фреймворк (Laravel или Symfony), основы автоматического тестирования, основы linux, английский.

Вот неофициальный роадмап (карта того, что можно изучать): https://miro.com/app/board/o9J_lbUUBBQ=/

По многим из этих тем у нас есть уроки или задачки:

- для понимания, что такое веб-сервер, прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- для понимая MVC, работы с БД и формами, реши задачу про студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- далее есть более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- задача, близкая по сложности к реальным задачам на Laravel/Symfony: https://gist.github.com/codedokode/8733007
- после нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a
- если ты все решил, переходи к Symfony или Laravel
- почитать про паттерны можно тут https://designpatternsphp.readthedocs.io/ru/latest/ (если ты не изучил ни одного фреймворка, то это будет рановато). Если хочешь увидеть примеры использования паттернов в реальном коде - ковыряй исходники Симфони, например Symfony Forms. Ну и скажем честно, начинающему без опыта, который не видел сложный код, паттерны понять будет сложно.
- для улучшения английского можно читать news.ycombinator.com - там много статей на тему IT.

Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.

- задачи на HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- хороший учебник по JS: https://learn.javascript.ru/
- задачи на 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/
- задачи на SQL: https://github.com/codedokode/pasta/blob/master/db/databases.md

Что еще почитать

- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- https://phptherightway.com/
- Книга: Профессиональное программирование на PHP Джордж Шлосснейгл
- Книга: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- Про Git: https://git-scm.com/book/ru/v2
- Задачи на алгоритмы: https://codeforces.com/problemset

Дополнительно

- скачать учебник: зайди на https://github.com/codedokode/phpbook, нажми зеленую кнопку Code -> Download ZIP, распакуй на рабочий стол и открой index.html
- что будут спрашивать на собеседовании, если 0 опыта - будут гонять по теории, по официальному мануалу PHP, давать дурацкие задачки на переворачивание строк, гонять по SQL (транзакции, внешние ключи, напиши запрос), по JS (как сделать анимацию при нажатии кнопки), ну погугли, не ленись
- сколько времени надо изучать все это? - все зависит от тебя, в районе 12-24 месяцев
very angry anime girl.png1,4 Мб, 1024x1024
2 2932482
Опять в шапке написано не то! Самое важное забыли написать! Сколько можно это терпеть? Выскажи свое справедливое негодование под этим постом и через несколько тредов шапку исправят (но это не точно).
3 2932675
Зачем при работе с куки использовать формат json?
Да и вообще зачем он нужен...
Я ничего сложнее списка студентов не делал, так что не понимаю.
4 2932677
Я вот думаю, не рано ли перекат, позапрошлый тред дошел до ~1к постов, значит ~500 не край?
5 2932716
>>2932677

Много нетерпеливых, которых хлебом не корми, дай только скорее перекатить тред, со сломанной шакой.

>>2932675

В куках он нужен только когда ты хочешь в одну куку поместить сложные данные, а иначе не нужен. А так JSON используется для передачи данных на сервер и с сервера, например, при AJAX запросах.
6 2932729
>>2932675
В куке можно хранить только строку. JSON это объект в виде строки.
7 2932791
>>2932466 (OP)
Как можно теперь шторм поставить себе? Даже купить теперь нельзя, с впном на жетбрейнс не заходит.
9 2933196
>>2932880
Качай с офф сайта, потом ставь вот эту хуйню чтобы за лицухой он наружу не лез https://github.com/libin9iOak/ja-netfilter-all
Обновляться будет как официальный, это по сути даже не кряк.

Я понимаю что сложно, инструкция то не для пхп треда писалась

>1. add -javaagent:/path/to/ja-netfilter.jar=jetbrains to your vmoptions


>/path/to/ja-netfilter.jar


>ja-netfilter.jar

10 2933206
Как научиться докеру и композеру и поставить код сниффер или другой линтер? Какие пср обычно используются? Надо ли их как-то запоминать или хватит линтера? Есть норм гайд с разжёвыванием где как и чего.
11 2933256
>>2933206

>Как научиться докеру и композеру и поставить код сниффер или другой линтер?


В смысле как? Читаешь и выполняешь на практике. Лучший обучающий ресурс на мой взгляд - Хекслет. Начни бесплатный курс по основам PHP https://ru.hexlet.io/courses/php-basics
12 2933284
>>2933196
Ты промазал. Тебе сюда >>2932791
Челик сказал что на офф сайт у него "не заходит".
Я напомнил где качается весь платный софт последние лет двадцать.
13 2933286
>>2933206

>Как гуглить


>Как читать


>Как дышать


Это и многое другое смотрите в тиктоках наших протыков.
14 2933329
>>2933284

>Я напомнил где качается весь платный софт последние лет двадцать.


С торрентов с вирусами качать? Если только в виртуалке юзать.
image.png130 Кб, 1204x411
15 2933370
Что скажете про program with gio? Норм курс?
16 2933685
>>2933256

Человек спросил про докер и композер, а ты тут торопишься вставить рекламу платных PHP курсов. Ты бы хоть вопрос прочел.
17 2933714
>>2933685
Он спросил как научиться. Не только докеру и композеру. Я дал не рекламу, а бесплатный курс, большой хороший бесплатный курс. Была бы реклама, вставил бы реферальную ссылку. И еще, как в прошлом посте написал, считаю этот ресурс лучшим по всем показателям.
18 2933743
>>2933329

>вокруг вирусы, мама, пакупай касперского


Так хули ты на винде, вирусофоб? Ставь пингвина.
19 2933816
>>2933714
Там нет ничего про докер и композер. Ты дал ссылку на базовый курс, который проходится за пару часов.
20 2933981
>>2933816

>базовый курс, который проходится за пару часов


Ебанат, там 42 урока и 47 практических упражнений. Ты за 2 часа даже теорию не успеешь прочитать, а уж новичок и подавно. Там есть про PSR и линтеры. И вообще, пошел на хуй, умник ебаный, не для тебя ссылка.
21 2933992
>>2933981
Там про PSR и линтеры 2 строчки написано, а основного - как всё это скрестить с докером и компотом нет. Про "что это такое" я и в википедии прочитаю без твоего ебучего курса говна.

Оформи-ка ты срыг, маркетолог хуйни.
22 2934056
>>2933992
Как будто мне надо учиться, а не тебе. Хорошо, что такие дураки сразу отсеиваются. Между прочим, это единственное место где есть курс СИКП на PHP и еще некоторые по теме абстракции данных. Хотя тебе это знать бесполезно.
16881291554880.jpg191 Кб, 735x962
23 2934085
>>2934056

>СИКП

24 2934353
>>2934085
Иди говна наверни, как ты любишь.
25 2935118
У меня есть класс-сущность, у него приватные свойства, геттер и сеттер.
Значения в свойствах должна пройти валидацию.
Должен ли я делать посредника между сущностью и валидатором?
Или же валидатору достаточно напрямую обращаться к сущности через геттер, чтобы брать ее значения и проверять?
26 2935226
Уже третий день(!) не могу сделать элементарное: отправить через jQuery AJAX в Ларавел данные вместе с файлами. Если собираю данные так:
let form = $(this).closest('form')
let formData = form.serialize();
и отправляю formData, то всё ок. Они принимаются контроллером. Если же пытаюсь добавить туда файл - не получается. В контролер приходит пустота. Ни файла, ни текстовых данных, ничего. Гуглил и пробовал чуть ли не всё - не помогает. Не работают у меня эти примеры. Напомню, мне нужна отправка именно через аякс. Я спрашивал ЧатГПТ - советует то же самое, что и гугл. Спрашивал на стековерфло - тупо закрыли вопрос, с отпиской "такое уже спрашивали". Но там где спрашивали, мне тоже ни один из примеров не помог. Я в тотальном тупике. Это срань какая-то. Настолько простое действие, но у меня третий, сука, день, не получается понять, что вообще тут блядь не так.

Везде пишут, что-то типа
let form = $(this).closest('form')[0]; // Получаем нативный элемент формы
let formData = new FormData(form);// Создаем объект FormData
и отправляем её в аякс без обработки:
processData: false, // Не обрабатываем данные (нужно для передачи файлов)
contentType: false, // Не устанавливаем Content-Type (также нужно для передачи файлов)
data: formData, // Передаем объект FormData
А в ларе получаем:
$title = $request->input('title');
Но нет. У меня в ларе title = null.

Можете дать пример реально работающего кода?
27 2935245
>>2935226
<form method="post" enctype="multipart/form-data">
28 2935272
>>2935245
Уже. Вот код, который нормально работает без файлов:

<form name="property-form" id="property-form" role="form" enctype="multipart/form-data">
<input type="hidden" id="token" name="token" value="{{ $token }}">
<input type="hidden" id="id" name="id" value="{{isset($data['id']) ? $data['id']: '' }}">
<input type="text" id="title" name="title" value="{{isset($data['title']) ? $data['title']: '' }}">
<input type="file" name="files[]" multiple>
<input type="file" name="files[]" multiple>
<input type="button" id="save-property-button" value="Save" class="btn btn-primary">
</form>

$(document).ready(function (e) {
$('#save-property-button').click(function () {
let form = $(this).closest('form')
let formData = form.serialize();

$.ajax({
type: 'PUT',
url: '/api/info/'+ $('#id').val(),
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
'Authorization': 'Bearer ' + $('#token').val()
},
dataType: 'json',
data: formData,
cache: false,
success: function (response) {
console.log(response);
},
error: function (xhr, status, error) {
console.log(xhr.responseJSON);
}
});
});
});

public function update(Request $request, int $id)
{
return response()->json([
'$request->all' => $request->all(),
'$request' => $request,
'$title' => $request->title,
'$title2' => $request->input('title'),
'$id' => $id,
]);
}

Пишут, что в аяксе нужно ставить
contentType: false,
processData: false,

но у меня с ними тоже ничего не работает.
28 2935272
>>2935245
Уже. Вот код, который нормально работает без файлов:

<form name="property-form" id="property-form" role="form" enctype="multipart/form-data">
<input type="hidden" id="token" name="token" value="{{ $token }}">
<input type="hidden" id="id" name="id" value="{{isset($data['id']) ? $data['id']: '' }}">
<input type="text" id="title" name="title" value="{{isset($data['title']) ? $data['title']: '' }}">
<input type="file" name="files[]" multiple>
<input type="file" name="files[]" multiple>
<input type="button" id="save-property-button" value="Save" class="btn btn-primary">
</form>

$(document).ready(function (e) {
$('#save-property-button').click(function () {
let form = $(this).closest('form')
let formData = form.serialize();

$.ajax({
type: 'PUT',
url: '/api/info/'+ $('#id').val(),
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
'Authorization': 'Bearer ' + $('#token').val()
},
dataType: 'json',
data: formData,
cache: false,
success: function (response) {
console.log(response);
},
error: function (xhr, status, error) {
console.log(xhr.responseJSON);
}
});
});
});

public function update(Request $request, int $id)
{
return response()->json([
'$request->all' => $request->all(),
'$request' => $request,
'$title' => $request->title,
'$title2' => $request->input('title'),
'$id' => $id,
]);
}

Пишут, что в аяксе нужно ставить
contentType: false,
processData: false,

но у меня с ними тоже ничего не работает.
1.png184 Кб, 1042x828
29 2935304
30 2935318
>>2935272
И да ты не можешь бинардые данные жсоном отправлять, если хочешь json то надо файлы кодировать в base64 а на бекенде раскодировать. Например в мидлеваре ларки. Но это нахуй не надо.
31 2935359
Зачем нужны интерфейсы?
Извините за такой вкатунский вопрос, но я серьезно не понимаю практического смысла в интерфейсах.
Код без интерфейсов это плохой ООП-код?
32 2935414
>>2935304
Если я формирую данные для отправки так:
const form = document.querySelector("#property-form")
const formData = new FormData(form)

, то бинарник появится. В консоле браузера, да. А ларавел его не видит. Вообще никакие поля. Все данные пстые. Файла нет, текстовых полей нет.
33 2935432
>>2935272

Ты используешь метод PUT, а PHP анализирует тело запроса только для метода POST, если я не путаю. Попробуй PUT на POST переделать.
1227403054206.jpg4 Кб, 156x200
34 2935460
>>2935432
Анон, СПАСИБО!
Реально PUT не анализируется. Передаю постом с добавлением formData.append('_method', 'PUT') - все данные проходят на бек нормально. А я почти три дня ебался. Браузер говорит "мамой клянусь, я отправил!", а ларавел "мамой клянусь, я не получал!". И так почти три дня. Я уже начал подумывать, что с ума сошёл. Перегуглил всё что можно, даже ютуб смотрел от индусов и французов каких-то.
35 2935486
Для вопросов по ларке выкладывайте код сюда

https://laravelplayground.com/
36 2935489
Мне в прошлом треде посоветовали для каждой проверки в валидации (проверка на пустоту, на минимальное количество символов, на максимальное количество символов, на уникальность емайл, на качество символов) сделать свой отдельный класс (как вариант).
Только вот три класса - проверка на пустоту, на мин. и макс. количество символов будут почти похожи. Получается, что я дублирую код, пусть и частично (вся ведь проверка заключается в том, чтобы узнать сколько символов в строке и сравнить с каким-то стандартом). С одной стороны вроде как это разные проверки, но руки тянутся скинуть все это в одну кучу. Как мне поступить, знающие аноны?
37 2935505
>>2935489
Когда говорят о "дублировании кода" говорят о "дублировании функционала". Причем именно "бизнес функционала". Ты же не сидишь и не думаешь: "ах бля беда какая я дублирую использование сложения и объединения строк, я ДВАЖДЫ написал foreach, мне пизда" ну я на это надеюсь

И вообще ты сидишь и думаешь о хуйне. У тебя будут сотни классов и тысячи методов, нет никакого смысла их считать. Важно чтобы их было удобно читать. Сам факт что что у тебя есть код, который явно выделен как "проверка строки на пустоту" важнее всего остального.
38 2935686
>>2935432
Интересно https://www.php.net/manual/en/features.file-upload.put-method.php
При отправке данных PUT методом они будут доступны как ресрурс php://input
Но нет суперглобала в в который эти данные парсятся

В тоже же время при отправке с multipart/form-data php://input недоступен
https://www.php.net/manual/en/wrappers.php.php
Соответственно нужен заголовок Content-Type: application/x-www-form-urlencoded

О том что такое поведение баг спорят с 2011 https://bugs.php.net/bug.php?id=55815

Типа есть оправдание, что в пыхе все строго RFC
POST - это для процесса обрабатывающего данные. URI идентифицирует обработчик
PUT - для размещения файла на сервере. URI идентифицирует сам ресурс
Соответственно пут не должен парсить (обрабатывать) данные,

мимо крок
39 2935760
>>2935505
Окей...
Просто у меня есть класс, проверяющий на пустоту
Он считает количество символов и сравнивает с нулем.
Другой класс проверяет на минимальное количество символов. Он считает количество символов и сравнивает с...минимальным значением для этого поля.
Следующий класс проверяет на максимальное количество символов. Он считает количество символов и сравнивает с максимальным значением символов для этого поля.
Немного в глаза бросается эта общая схожесть действий.
40 2935791
>>2935760

>Просто у меня есть класс. Он использует умножение.


>Просто у меня есть класс. Он использует перебор массива.


>Просто у меня есть класс. Он использует array_sum.


Что такого особенного в этом "подсчете символов"? Там какие-то специальные правила, про которые знает только написавший этот подсчет?
Допустим там ебейшее дублирование, страшное. Как по твоему это решается? Созданием еще одного класса, в который помещается дублирующаяся логика. Так что классов у тебя один хуй станет только больше.
41 2935799
>>2935791
Да, я думал сделать один класс и назвать "Проверка на количество символов", а там уже были бы свои методы на пустоту, на минимальное количество и максимальное.
Но правильно ли это? Сваливать все три проверки в одном классе.
image.png13 Кб, 254x199
42 2935868
насколько пик правдив?
43 2935870
>>2935799
назови свой класс ValidationHelper и пихай туда все проверки
44 2935882
>>2935799
Ты по прежнему не понимаешь что такое ООП. Объекты это данные + способы работы с этими данными. А у тебя все разбросано. Раз строка содержит в себе буквы, которые надо посчитать. Так создай строку, которая это умеет: https://3v4l.org/XhAE2
А потом учишь свой валидатор работать с умными строками: https://3v4l.org/jGPb4

Ты вместо того чтобы создать объекты с соответствующей этим объектам структурой и поведением используешь их как папки для хранения процедур. Очевидно что при таком подходе тебе от ооп никакой пользы, одни заебы и беготня между шкафчиками и папочками.
45 2935898
>>2935882
Я не знаю что мне делать.
Я начал решать задачу со списком студентов месяц назад и до сих пор я нахожусь на этапе проектирования классов.
И ничего мне не помогает, ни советы анонов из треда, ни книги (читал Банду Четырех, книгу Зандстры). Все равно как дурачок топчусь на одном и том же месте.
Спасибо за код, я разберу его завтра и постараюсь понять какую мысль ты хочешь до меня донести.
46 2935934
>>2935898
Я пробовал менторить вкатунов из треда.
Правило одно единственное было: быть в определенное время, а если не получается - предупредить заранее. Казалось бы хуль еще надо? Да только хуй там. Проебываются постоянно. В лучшем случае за пять минут до созвона сказать что "ну бля никак" и похуй что ты свои дела под это время двигал. А в худшем просто молча проебаться. Короче дело неблагодарное.
47 2935937
>>2935934
Понимаю.
48 2936330
>>2935760

Ну вообще, тогда можно не делать класс проверки на пустоту, или сделать так, чтобы он наследовал класс проверки с мин. числом символов с условием, что там будет минимум 1 символ:

class NotEmptyValidator extends MinLengthValidator
{
...
parent::__construct(1);
49 2936332
>>2935882

Нет, ты даешь плохую идею. В PHP уже есть тип string. Не нужно создавать новый вид строк, так как у тебя в приложении будет 2 вида строк и куча возни с преобразованиями туда-обратно.
50 2936349
>>2933206

Докер

Чтобы нормально изучить докер, тебе надо начать с изучения основ Линукса и работы в командной строке (так как Докер-файл это по сути набор консольных команд). Ищи любой курс, хоть текстовый, хоть видео, по этой теме. Команды для работы с файлами, перенаправление ввода-вывода, управление пользователями и правами, менеджер пакетов.

Если ты не знаком с командной строкой, то тут написано что это (но это не отменяет необходимость учить Линукс): https://github.com/codedokode/pasta/blob/master/soft/cli.md

После освоения Линукса можешь читать любой туториал по Докеру. Должно быть понятно. Докер создает пустой контейнер (что-то вроде виртуальной машины), в который ты с помощью команд устанавливаешь нужный софт.

Композер

Тут все проще - либо читай документацию на англ., либо ищи туториалы.

> поставить код сниффер



С помощью команды composer require (название пакета)

> Какие пср обычно используются? Надо ли их как-то запоминать или хватит линтера?



PSR пока не много, я советую быстро по диагонали (не заучивая) прочитать все в статусе Accepted: https://www.php-fig.org/psr/

Для оформления кода надо тщательно прочесть PSR-1 и PSR-12.

> Есть норм гайд с разжёвыванием где как и чего.



Нет, но ты можешь задавать уточняющие вопросы.
50 2936349
>>2933206

Докер

Чтобы нормально изучить докер, тебе надо начать с изучения основ Линукса и работы в командной строке (так как Докер-файл это по сути набор консольных команд). Ищи любой курс, хоть текстовый, хоть видео, по этой теме. Команды для работы с файлами, перенаправление ввода-вывода, управление пользователями и правами, менеджер пакетов.

Если ты не знаком с командной строкой, то тут написано что это (но это не отменяет необходимость учить Линукс): https://github.com/codedokode/pasta/blob/master/soft/cli.md

После освоения Линукса можешь читать любой туториал по Докеру. Должно быть понятно. Докер создает пустой контейнер (что-то вроде виртуальной машины), в который ты с помощью команд устанавливаешь нужный софт.

Композер

Тут все проще - либо читай документацию на англ., либо ищи туториалы.

> поставить код сниффер



С помощью команды composer require (название пакета)

> Какие пср обычно используются? Надо ли их как-то запоминать или хватит линтера?



PSR пока не много, я советую быстро по диагонали (не заучивая) прочитать все в статусе Accepted: https://www.php-fig.org/psr/

Для оформления кода надо тщательно прочесть PSR-1 и PSR-12.

> Есть норм гайд с разжёвыванием где как и чего.



Нет, но ты можешь задавать уточняющие вопросы.
51 2936352
>>2935118

> Должен ли я делать посредника между сущностью и валидатором?



Нет, ты усложнишь все.

> Или же валидатору достаточно напрямую обращаться к сущности через геттер, чтобы брать ее значения и проверять?



Достаточно. Но для этого, конечно, валидатор должен знать имена полей и правила, которые к ним надо применить.

А вот класс-правило никаких сущностей знать не должен. Валидатор передаст ему нужное значение напрямую.
52 2936366
>>2935359

Урок: https://github.com/codedokode/pasta/blob/master/php/interfaces.md

Основная идея: с помощью интерфейса ты можешь указать требования к классу. И писать код, не имея этого класса либо имея несколько вариантов реализации интерфейса.

Ну например: тебе надо написать код для регистрации с подтверждением по СМС. Но класс отправки СМС поручили писать другому человеку, и хуже того, он его еще не написал.

Ты можешь сделать интерфейс:

interface MessageSender {
public function send(string $phone, string $message);
}

И затем ты даешь свой интерфейс своему коллеге и говоришь: программировай код отправки СМС. А сам пишешь свою часть кода. И если твой коллега не совсем тупой, то когда он напишет класс отправки СМС, то он будет идеально работать с твоим кодом.

Конечно, ты бы мог объяснить требования к классу словами, без интерфейса, а потом сам вручную их проверить. Но зачем это делать, когда PHP может проверять требования за тебя.

Вторая польза от интерфейсов. Допустим, ты хочешь у себя протестировать свой код. Но отправка СМС платная, и тебе не дали ключ доступа к сервису отправки СМС, и вдобавок коллега еще не доделал свой код. Ты можешь написать свой класс, который соответствует интерфейсу, но вместо отправки СМС просто пишет их в файл. И ты у себя тестируешь код с этой заглушкой, а на продакшене используешь реальный отправщик СМС.

Дальше, может вы решите подключиться к нескольким сервисам отправки СМС. И тут опять интерфейс пригодится, так как твоемукоду без разницы, какой класс используется, лишь бы он соответствовал интерфейсу.

Интерфейсы также часто используют в библиотеках и фреймворках, когда автор хочет дать возможность заменять какие-то компоненты. Тогда он делает для этих заменяемых компонентов интерфейсы. Ну например, есть open-source движок для форума, и мы хотим сделать возможность заменять в нем капчу. Мы можем сделать интерфейс для класса генерации и проверки капчи, и тогда пользователь сможет сделать свою собственную капчу, не меняя код движка.
52 2936366
>>2935359

Урок: https://github.com/codedokode/pasta/blob/master/php/interfaces.md

Основная идея: с помощью интерфейса ты можешь указать требования к классу. И писать код, не имея этого класса либо имея несколько вариантов реализации интерфейса.

Ну например: тебе надо написать код для регистрации с подтверждением по СМС. Но класс отправки СМС поручили писать другому человеку, и хуже того, он его еще не написал.

Ты можешь сделать интерфейс:

interface MessageSender {
public function send(string $phone, string $message);
}

И затем ты даешь свой интерфейс своему коллеге и говоришь: программировай код отправки СМС. А сам пишешь свою часть кода. И если твой коллега не совсем тупой, то когда он напишет класс отправки СМС, то он будет идеально работать с твоим кодом.

Конечно, ты бы мог объяснить требования к классу словами, без интерфейса, а потом сам вручную их проверить. Но зачем это делать, когда PHP может проверять требования за тебя.

Вторая польза от интерфейсов. Допустим, ты хочешь у себя протестировать свой код. Но отправка СМС платная, и тебе не дали ключ доступа к сервису отправки СМС, и вдобавок коллега еще не доделал свой код. Ты можешь написать свой класс, который соответствует интерфейсу, но вместо отправки СМС просто пишет их в файл. И ты у себя тестируешь код с этой заглушкой, а на продакшене используешь реальный отправщик СМС.

Дальше, может вы решите подключиться к нескольким сервисам отправки СМС. И тут опять интерфейс пригодится, так как твоемукоду без разницы, какой класс используется, лишь бы он соответствовал интерфейсу.

Интерфейсы также часто используют в библиотеках и фреймворках, когда автор хочет дать возможность заменять какие-то компоненты. Тогда он делает для этих заменяемых компонентов интерфейсы. Ну например, есть open-source движок для форума, и мы хотим сделать возможность заменять в нем капчу. Мы можем сделать интерфейс для класса генерации и проверки капчи, и тогда пользователь сможет сделать свою собственную капчу, не меняя код движка.
53 2936369
>>2935486

О, круто сделано. Может, нам стоит собрать список подобных сайтов и где-то вверху следующего треда повесить?
54 2936373
>>2935489

Можно, кстати, сделать единую проверялку длины с параметрами:

- минимум (можно указать 0 для пропуска)
- максимум (можно указать \INF - бесконечность - для пропуска)

А на основе этого класса унаследовать класс проверки на пустоту, проверяющий, что длина ≥ 1

Или можно сделать единую проверялку, а от нее унаследовать 3 правила: не пусто, длина не меньше X, длина не больше X.
55 2936376
>>2935686

Как я понимаю, идея такая, что если PHP парсит тело, то оно недоступно (так как PHP его прочел и распарсил). А если не парсит, то доступно в php://input.
56 2936378
>>2935799

Не уверен, что надо, так как проверка очень простая и ты пишешь кучу кода, чтобы избежать дублирования одной строчки.
57 2936381
>>2935934

Ну общение в треде тем и удобнее, что каждый приходит когда хочет. Или, что чаще, задает вопрос и уходит в закат.
Sobache-serdtse.jpg160 Кб, 1600x846
58 2936382
>>2936332

>будет 2 вида строк и куча возни с преобразованиями туда-обратно


>__toString


>будет 2 вида строк


Пик релейтед.

>Нет, ты даешь плохую идею. В PHP уже есть тип string.


Ну вот и как учить ооп, когда вокруг дегенераты? То есть джаву и шарп идиоты писали? Почему им нужно, а тебе не нужно?
https://learn.microsoft.com/ru-ru/dotnet/api/system.string?view=net-8.0
https://docs.oracle.com/javase/8/docs/api/java/lang/String.html

То есть ты берешь их концепты, их паттерны, их подходы, но совершенно не понимаешь что и для чего делается. Это даже не карго культ, карго культисты знают чего хотят, просто не знают что по наушникам из кокоса нельзя получить ништяки. Но цель-то ништяки получить у них есть. А тут даже нет понимания что должно получиться в итоге, нахуя все это ооп затевалось, цель этих смешных классов какая.
59 2936385
>>2936381

>Ну общение в треде тем и удобнее


Ну если цель отвлечься на пару минут, шуткануть или пернуть что-то одной строчкой, то да "удобнее".

А если цель чему-то научиться, что-то понять, то нужно сидеть с открытой ide и буквально вместе код писать. И даже так не с первого раза доходит.
17008464433550.jpg251 Кб, 1422x456
60 2938256
Никто не знает как фиксить?
Screenshot 2023-11-26 193913.png377 Кб, 3454x100
61 2938279
2oveql.jpg92 Кб, 756x766
62 2938448
>>2932466 (OP)
Продублирую из прошлого треда.
На Битриксе всегда потогонка ебаная? Вкатился пару месяцев назад что-то обомлел. Задачи заранее оценены лидом - 5 часов, 7 часов и т.д. Я не укладываюсь совсем, приходиться перерабатывать, могу несколько дней просидеть. Плюс прилетают задачи на джсе. Короче работа в авральном режиме, из-за этого куча стресса.
just-house.gif225 Кб, 220x220
63 2938472
>>2938448

>работа в авральном режиме


Ну так не работай в авральном режиме.
64 2938523
>>2938279
А как его running?
65 2938525
>>2938448
Пили кул тру стори как вкатился
67 2938658
Здравствуйте, дайте подсказочку хочу шорткод для вордпресса сделать, который берет текст и ссылку и на страницу выплёвывает <a> тег с атрибутом href в котором ссылка будет.

Зацените плес код. Как его можно улучшить по части веб-безопасности?

https://pastebin.com/eWMnLGC5
68 2938673
>>2938658

>Как его можно улучшить по части веб-безопасности?


Избавиться от массивов и уебанских названий типа atts и esc. Если для этого придется выкинуть к хуям вордпресс - тем лучше для безопасности человечества.
69 2939209
>>2938256

Докер состоит из 2 частей: демон, который работает в фоновом режим, и клиент (это как раз команда docker, которую ты запускаешь). У тебя наверно не запущен демон.
70 2939216
>>2938658

Протестируй, что будет, если в ссылку и текст вставить символы вроде <, >, &, ', ". Будут ли они экранироваться или вставятся как есть? Если второе, то это плохо.

Также, протестируй, можно ли вставлять ссылки вроде javascript:alert(1); или data:12345. Если можно вставлять что-то, кроме http:// и https://, то это тоже уязвимость.
71 2939934
>>2938448
Мда, свой говно вопрос продублировал, а на вопросы не отвечаешь
72 2940000
>>2939934
>>2938525
Я уже расписывал как вкатился в прошлых тредах. Прошел курс Лаврика с торрентов, сделал задачку про Вектор, потратил кучу времени на поиск нормальных курсов по ооп. Проебал чуть не год на все это. Потом какой-то анон в этом треде отписался, что пошел учиться на Хекслет по подписке - я слышал про них, но не знал, что есть подписка. Ну пошел туда, оказалось годнота. Но это было за неделю до начала "сво". Просидел еще год, обосрасля с поиском работы на ларе и пришлось идти в битрикс, се ля ви
32916320.jpg168 Кб, 1351x511
73 2940014
>>2938542
Сейм щит
74 2940019
>>2940014
А всё, на винде через dockerd.exe в папке запускается
32916320.jpg135 Кб, 1415x412
75 2940020
>>2940019
Хотя не, щас такое говно вылезает
76 2940033
>>2940000
Вот теперь заебись.
мимо сам вкатываюсь в битрикс буду страдать как ты
78 2940069
>>2940060
Не помогает, ладно похуй, докер кароче только на линуксе нормально работает
79 2940073
Какие вспомогательные методы правильно прописывать в классе-сущности, а какие следует выносить в отдельный класс?
Как понять, определенный метод лучше оставить в классе-сущности или вынести метод в отдельный класс?
80 2940088
>>2940000
Все курсы Хекслета проходил?
81 2940089
Не до конца понимаю DataMapper в контексте задачи Список студентов.
Есть сущность, в которой хранятся данные из БД (т.е. в объекты этой сущности выгружаются данные из БД).
Есть класс, который обслуживает эту сущность (реализует SQL-запросы).

В списке студентов код работает с данными об абитуриенте.
Сначала он их хранит в сущности Enrollee (мое название).
Значения свойств этой сущности проверяет Валидатор.
Если ошибок нет, данные загружаются в БД.
Ага...с вводом информации в БД понятно, а вот с выгрузкой информации из БД...
Чтобы выгрузить из БД, нужно будет создавать объекты, которые будут хранить эту информацию из БД и тут вопрос...
А что будет этой сущностью? Тот же класс Enrollee (ведь он представляет абитуриента в коде)? Или же нужно создавать отдельный класс-сущность для выгрузки из БД?...
82 2940100
>>2940088
Я бы не стал повторять за этим челом, ты что не видишь как он не смог вкатиться в ларавель и в итоге страдает на битриксе?
Стоит зодуматься...
83 2940102
>>2940089
И еще с кое-чем смежным я путаюсь.
Если у меня есть DIContainer и он один раз создает объект, то как буду создавать эти объекты, которые будут храниться данные из БД, ведь DIContainer только один раз создает объект.
Ага, да...
Простите за глупые вопросы, самому стыдно от своей тупости перед анонами.
84 2940109
>>2940088
Почти все из профессии по пхп, начиная с фунций. По ларе там действительно инфы маловато, в дополнение можно посмотреть ларакасты, повторить пару проектов.
85 2940123
>>2940100
Нужно детали выяснить

>>2940109
А проекты свои на ларе не писал?
86 2940158
>>2940123
Делал последний проект из профессии, прямо чтоб "свои" не писал
87 2940175
>>2940123

>Нужно детали выяснить


Я опираюсь на знания о DataMapper из этой статьи:
https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a

Мб тогда мой пост станет понятным.
88 2940183
>>2940089

>Не до конца понимаю DataMapper


Ты вообще не понимаешь DataMapper.

Есть три самых ходовых варианта абстракции хранилища данных.
1) Table gateway. Это абстракция таблицы в базе. У тебя есть объект "таблица" через который ты взаимодействуешь с её содержимым.

2) Active record. Это абстракция записи в базе. У тебя есть объект "запись в базе", через который ты взаимодействуешь с содержимым. Каждая отдельная запись умеет все что умеет Table gateway. Коннектиться к базе, сохраняться итд.

3) Data mapper. Это абстракция хранилища. У тебя есть некое хранилище, которое хранит не записи в таблице, а нужные тебе объекты. Эти объекты понятия не имеют как их на самом деле хранят. Data mapper "маппит" хранимые данные в объекты с нужной тебе структурой. Часто даже сам факт того что они куда-то сохраняются скрыт.

Зачем вообще используют Data mapper.
1) Структура таблицы в реляционной базе принципиально отличается от структуры объектов. Это называется object-relational impedance mismatch. Например, junction table в которой хранятся связи "многие ко многим" в мире объектов просто не существует. В мире объектов "связь" это не колонка с внешним ключем и не запись в таблице, а просто факт помещения одного объекта в другой.

2) В современном приложении используется несколько хранилищ данных. И только одно из них реляционное. Условный "товар" хранится в основной базе, в кэше и в поисковой системе. Изменилось название, а у тебя абстракция хранилища только для таблицы. В таких ситуациях рожают жутких чудовищ из лапши. А Data mapper позволяет все эти телодвижения скрыть за простым $products->add($changedProduct) или вообще автоматически отслеживать все изменения как доктрина.

Пока писал анон скинул хорошую ссылку >>2940175. Хорошую, но не идеальную. В этом примере у него в Data mapper есть метод save(), в доктрине же никаких save() нет. Сам факт наличия объекта в хранилище должен означать что он сохранен. А большинство хранилищ все равно не гарантирую никакой save и работают асинхронно с твои кодом.
88 2940183
>>2940089

>Не до конца понимаю DataMapper


Ты вообще не понимаешь DataMapper.

Есть три самых ходовых варианта абстракции хранилища данных.
1) Table gateway. Это абстракция таблицы в базе. У тебя есть объект "таблица" через который ты взаимодействуешь с её содержимым.

2) Active record. Это абстракция записи в базе. У тебя есть объект "запись в базе", через который ты взаимодействуешь с содержимым. Каждая отдельная запись умеет все что умеет Table gateway. Коннектиться к базе, сохраняться итд.

3) Data mapper. Это абстракция хранилища. У тебя есть некое хранилище, которое хранит не записи в таблице, а нужные тебе объекты. Эти объекты понятия не имеют как их на самом деле хранят. Data mapper "маппит" хранимые данные в объекты с нужной тебе структурой. Часто даже сам факт того что они куда-то сохраняются скрыт.

Зачем вообще используют Data mapper.
1) Структура таблицы в реляционной базе принципиально отличается от структуры объектов. Это называется object-relational impedance mismatch. Например, junction table в которой хранятся связи "многие ко многим" в мире объектов просто не существует. В мире объектов "связь" это не колонка с внешним ключем и не запись в таблице, а просто факт помещения одного объекта в другой.

2) В современном приложении используется несколько хранилищ данных. И только одно из них реляционное. Условный "товар" хранится в основной базе, в кэше и в поисковой системе. Изменилось название, а у тебя абстракция хранилища только для таблицы. В таких ситуациях рожают жутких чудовищ из лапши. А Data mapper позволяет все эти телодвижения скрыть за простым $products->add($changedProduct) или вообще автоматически отслеживать все изменения как доктрина.

Пока писал анон скинул хорошую ссылку >>2940175. Хорошую, но не идеальную. В этом примере у него в Data mapper есть метод save(), в доктрине же никаких save() нет. Сам факт наличия объекта в хранилище должен означать что он сохранен. А большинство хранилищ все равно не гарантирую никакой save и работают асинхронно с твои кодом.
89 2940188
>>2940102

>Если у меня есть DIContainer и он один раз создает объект, то как буду создавать эти объекты


Di container создает объекты, которым для работы нужны другие объекты или эти объекты нужно как-то сконфигурировать перед использованием.
Твоим объектам из хранилища все это надо? Конечно нет, никому это не надо. В модели все зависимости инжектятся через методы, а не через конструктор.
90 2940195
>>2940188
Да?
А я думал, что DIContainer нужен для того, чтобы инструкции с созданием объекта были в одном месте...
Не претендую на истину, только рассказываю свое понимание вещи, чтобы опытные аноны указали на ошибки (видимо придется постоянно писать эту фразу, иначе аноны будут агриться и думать, что я херь несу с умным лицом)
91 2940201
>>2940195
Ну вопрос остается открытым. Твоим объектам из базы нужны инструкции для создания?
Та же доктрина конструктор вообще не вызывает если че.
92 2940219
>>2940201
Да, я не знаю ничего.
У меня даже ни одного класса для работы с БД нету.
Я только сегодня прочитал статью codedokode про паттерны.
В голове каша пока что, думал что-нибудь проясню, задав вопрос, но не особо.
Завтра на свежую голову прочитаю то, что ты описал про Action Record, DM, TDG.
93 2940291
Объясните мне, глупенькому, почему wsl + docker гавно.
94 2940305
>>2940291

>почему wsl + docker гавно.


Вроде никто не говорил что это говно
95 2940315
>>2940291
Спроси у этого чела >>2940069 . По нему сразу видно как он кайфует.
96 2940323
>>2940305
Кароче, я эту шизу часа 4 устанавливал, порадовался в одном чатике, о том что установил и мне сказали что это гавно и забанили.
97 2940327
>>2940323
У меня виртуализация на винде так и не заработала. Вообще. И уж поверь я сидел с парнями которые больше десяти лет админят и нихуя не вышло. WSL это кал, сынок. Это дерьмо не стоит времени, котрое придется на него убить. Просто поставь линукс.
image.png407 Кб, 1920x1080
98 2940329
>>2940327
у меня обратная ситуация, я пытался установить линукс больше недели, но нихуя не вышло и я решил забить, потом я чета вспомнил про всл и поперло
99 2940338
>>2940329
Звучит как "я пытался снять свитер в течении недели, а потом понял что можно срать не снимая свитер".
Бубунта или и мята ставится с любой флешки на любое железо уже лет десять как.
100 2940342
>>2940327

>я сидел с парнями которые больше десяти лет админят и нихуя не вышло


То что они 10 дет дрочат домен не говорит что они умеют в Hyper-V или WSL. Зачастую они и в домене нихуя не умеют по итогу, и делают всё как в методичках мелкомягких.
101 2940345
>>2940342
Пчел. 90% бухгалтеров работают через виртуалки со старым софтом. У нас в офисе больше тысячи сотрудников. Админы на виртуализации виндовской собаку съели. И через них прошли тысячи разных кампуктеров и ноутов с тысячами конфигураций.

Если ты такой дохуя умный, то давай сконтачимся, застримлю тебе рабочий стол ты будешь говорить что делать. Потом запостишь сюда чем дело кончится.
102 2940346
>>2940338
Я дрочил secure boot, boot legcy, fast boot.
Я делал разметку через MBR и GPT.
Пробовал все доступные файловые системы.
Попробовал разные флешки, разные дистрибутивы.
И НИ-ХУ-Я
Самое обидное что, создав флешку с параметрами по умолчанию через руфус, и вставив её в другой комп которому миллиард лет, мне просто пришлось поставить ее первой в загрузчике.
И ВСЁ БЛЯДЬ ВСТАЛО НАХУЙ
103 2940351
>>2940346
Начнем с того что линукс можно запустить прямо с флешки. Ты это сделал?
104 2940624
>>2940020

У тебя не установлен какой-то компонент в Windows, нужный для работы виртуальных машин. Я не пользуюсь виндой уже много лет, поэтому даже не знаю какой. Выясни и установи.

И да, Докер в Линуксе лучше работает.
105 2940631
>>2940073

Очень абстрактный вопрос.

Обычно, используют принцип "у каждого класса своя зона ответственности" + ориентируются на существующие примеры кода.
106 2940634
>>2940089

> Есть класс, который обслуживает эту сущность (реализует SQL-запросы).



Это скорее всего TableDataGateway.

> Чтобы выгрузить из БД, нужно будет создавать объекты, которые будут хранить эту информацию из БД и тут вопрос...


> А что будет этой сущностью? Тот же класс Enrollee (ведь он представляет абитуриента в коде)?



Да. Зачем тебе для одного студента делать 2 разных класса? Логично использовать тот же класс.
107 2940637
>>2940102

В контейнере обычно хранят сервисы, а не сущности. Контейнер нужен для двух целей:

- чтобы для каждого сервиса был один экземпляр, например, чтобы все классы использовали один и тот же объект подключения к БД
- чтобы внедрять зависимости при создании сервисов

Сущности обычно в контейнере не хранят.
108 2940641
>>2940175

Это старая версия статьи, тут есть чуть более новая: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
109 2940643
>>2940329

Линукс можно ставить в виртуальную машину, только памяти прикупи побольше.
110 2940657
>>2940346

Во-первых, забудь про MBR. Это устаревший формат разбиения диска и если твой комп новее хотя бы 2015 года, то не используй его вообще. Используй GPT. Твой комп должен поддерживать UEFI (если он не совсем старый).

Некоторые дистрибутивы линукс не поддерживают MBR и требуют GPT + UEFI. Если у тебя очень старый комп, то ищи дистрибутив с поддержкой MBR.

Если же у тебя GPT, то тебе нужно лишь создать для линукса раздел(ы). Увы, тут могут быть сложности, так как линуксу нужно минимум 2 раздела:

- корень с системой, обычно ext4 (минимум 100 Гб)
- swap (около 4Гб хватит)

Некоторые дистрибутивы предлагают еще хранить /home и /var в отдельных разделах, но с этим не обязательно соглашаться.

Также, линуксу нужен UEFI boot partition, чтобы положить туда загрузчик, но если у тебя GPT и UEFI, то оно уже наверно есть.

Обычно в установщике линукса ты создаешь эти разделы. Но чтобы их создать, не уничтожая данные на диске, у тебя должно быть свободное место. А если ты ставил винду, то скорее всего у тебя весь диск занят виндой и свободного места нет. В такой ситуации поступают так:

- в винде делают дефрагментирование, чтобы данные были в начале диска
- затем в винде диспетчером дисков ужимаешь раздел винды, чтобы в конце диска появилось свободное пространство
- при желании можешь виндовым диспетчером создать 2 раздела для линукса из свободного пространства, можешь сделать это установщиком линукса

Ну и как тебе правильно написали, попробовать линукс можно вообще не устанавливая. Вставляешь флешку, при загрузке жмешь кнопку типа F10 или F9 для выбора загрузочного устройства и грузишься с флешки.

Также, линукс можно установить в виртуалку. Виртуалке нужно 3Гб памяти и 100 Гб диска.
111 2940662
>>2940346

А, еще бывают просто битые флешки. Я ставил линукс с флешки, которой больше 10 лет, и она просто возвращала для некоторых файлов неправильные данные. Ох, пришлось мне повозиться, я загрузился с флешки, а затем скачал на диск образ устновщика, примонтировал его и устанавливался не используя далее флешку.
112 2940690
>>2940033
Не лезь, оно тебя сожрет. Объем знаний по сравнению с той же ларой просто огромный, документации почти нет, код лютое говнище. Если хочешь залететь по-быстрому, присмотрись к другим направлениям, лучше вообще за пределами разработки
113 2941609
Что анон делает перед тем, как писать код?
У меня всегда, когда я сажусь заниматься программированием, первые 1-2 часа вата в голове. Есть какие-нибудь советы?
114 2941615
>>2941609

>Что анон делает перед тем, как писать код?


Пиздую по морозу до метро.
Еду в ебучем забитом метро в час пик.
Тащусь по снегу до офиса.
Ползу через пост охраны к лифту.
Еду на лифте на восьмой этаж.
Здороваюсь с пацанами у кикера.
Добегаю до рабочего места.
Чекаю личку, мессенджеры, почту, джиру.
Пишу код.

Всего хорошего, заходите на наш пикабу еще.
115 2941669
>>2940183
Я перечитал твой пост.
И это дало мне почти ничего.
Ты не мог бы подробнее рассказать про DM?
Как он устроен?
Мб даже код.
Если, конечно, есть желание этим заниматься.
Я не настаиваю.
Если будешь расписывать, то помни, что я новичок, который никогда не писал код работы с БД и те вещи, которые понятны тебе, ввиду знаний и опыта, не будут понятны мне.
Все, что я нашел - то, что есть сущность, которая представляет что-то и есть маппер. В маппере есть методы сохранения/загрузки из БД (по этой сущности).
И это представление не соотносится с тем, что ты писал.
Я не в смысле, что ты не прав, а в том смысле, что пока что текстовое описание для меня абстрактно звучит и, пытаясь переложить его на тот код, который я видел из интернета, я не вижу ничего общего.
116 2941719
>>2941669

>И это представление не соотносится с тем, что ты писал.


Что ты считаешь несоответствием я конечно должен угадать.

Обучение это двунаправленный процесс. Тебе дают информацию. Ты отвечаешь учителю как ты истолковал его слова. Учитель говорит что ты истолковал неправильно и указывает на ошибки в рассуждениях. Несколько раз предлагал заниматься таким в дискорде с нормальным фидбеком. Никому не надо.

Кидать в пустоту страницы текста, получая в ответ вместо рассуждений "понял/не понял" предельно тупое и неэффективное занятие. Поэтому вот тебе ссылка, там все расписано https://martinfowler.com/eaaCatalog/dataMapper.html читай. У меня таких ссылок две страницы гугла, будем вести обучение в удобном тебе формате.
117 2941720
Как считаете, аноны?
Я правильно понимаю, что в коде лучше использовать не название класса, а название его интерфейса (в том случае, если функции требуется объект определенного класса)?
И правильно ли я понимаю, что если интерфейсы двух классов похожи, это еще не означает, что двум классам стоит реализовывать общий интерфейс?
Пример: у меня есть сущность, представляющая абитуриента и есть сущность, представляющая ошибки валидации.
Общий для них интерфейс - геттер и сеттер, потому что я задал им приватные свойства.
Но дав им общий интерфейс и прописав в одной функции, что я принимаю объекты такого интерфейса, я делаю ошибку...?
Почему я так думаю: у меня есть функция, которая принимает объект, представляющий абитуриента.
Если я вместо названия класса-абитуриента напишу его интерфейс, то функция спокойна будет принимать объект, представляющий ошибки валидации, потому что он реализует тот же интерфейс.
Я не считаю себя правым, не нужно общаться со мной так, как будто я пытаюсь что-то доказать. Я просто вкатун-вкатуночек, который пытается усвоить материал и просит для этого корректировку своих мыслей от опытных анонов.
118 2941721
Знаю жс тайпскрипт рякт цсс си базу плюсов и как срать не снимая свитер
Начинаю оформлять вкат в ваш уютный пхп, чтоб съебать к лету со своей работы
Если не получится отсосу мужику из треда
Аллаху Акбар братья
119 2941722
>>2941719

>Несколько раз предлагал заниматься таким в дискорде с нормальным фидбеком. Никому не надо.


Мне, мб, надо, но вряд-ли я буду общаться голосом.
Но все-таки я не хотел бы, наверное, нагружать настолько чужого человека. Хотя и мои постоянные вопросы в треде - уже значительная нагрузка.
120 2941723
>>2941719

>Поэтому вот тебе ссылка, там все расписано https://martinfowler.com/eaaCatalog/dataMapper.html читай.


Окей, я прочту.
121 2941725
>>2941723
Окей, я прочел...
Я шарил по интернету и читал такой ответ:
DM - Тупо мостик между БД и объектом: считать данные из БД и записать в объект, сохранить объект в БД.
Фактически CRUD. Способ автоматизировать рутинные операции.

Т.е. у меня есть сущность, вокруг которой крутится код, в данной задаче это Абитуриент.
Есть маппер, который берет сущность и сохраняет/загружает данные из БД.
И...все...
Больше я ничего не понимаю в этой теме, если вообще мое понимание правильное.
122 2941729
>>2941722
На собесе/работе будешь языком жестов разговаривать?
Там с тобой церемонится не будут. Стесняешься незнакомого дяди? Так у них очередь из тех для кого это не проблема. Еще и вебку подрубить попросят.
123 2941731
>>2941725

>Я шарил по интернету и читал такой ответ


Не интересно что там в интернете пишут. Давай свои выводы по статье.

>Есть маппер, который берет сущность и сохраняет/загружает данные из БД.


Так а почему он тогда "маппер", а не "сохранятель"?
124 2941732
>>2941729
В контексте учебы мне проще текстом общаться.
Ну, а работа есть работа. Там без вариантов.
125 2941733
>>2941731

>Не интересно что там в интернете пишут.


Так то, что там написано, больше всего ближе к понятному для меня. Вот я и привел цитату.
126 2941735
>>2941732
Лол. А чем учеба от работы отличается? Тот же код, те же задачи, тот же проект, те же митинги с обсуждениями.

>>2941733
Мне не интересны цитаты из интернета. Мне интересно что ты понял из стать и что не понял.
127 2941738
>>2941735

>А чем учеба от работы отличается?


Тем, что с работодателем труднее будет договориться, чем с аноном? Человек, который приходит работать в определенную компанию, обычно принимает условия этой компании, а не предлагает свои (я не отрицаю, что есть возможность предлагать).

>Мне интересно что ты понял из стать и что не понял.


Ты хочешь, чтобы я прямо сейчас разбирал этот вопрос? Я недавно закончил сегодняшнюю учебу и морально отошел от того, чтобы прилагать умственные усилия. Но я могу перечитать и попробовать сформулировать выводы, если ты хочешь.
128 2941740
>>2941738
Вот об этом я и говорю. Мы уже три поста не понимаем друг друга. В войсе это недопонимание разрешилось бы за секунду. Я не буду в третий раз пытаться объяснить одно и тоже.

>Ты хочешь, чтобы я прямо сейчас разбирал этот вопрос?


Я хочу чтобы ты разбирал "этот вопрос", а не "случайный вопрос" из интернета. Ну и разумеется я не хочу терять нить и вспоминать че там кто кому писал десять постов назад на прошлой неделе. Это просто не удобно.
129 2941745
>>2941740
Окей.
В статье написано о том, что представление информации в виде объекта, и предоставление информации в виде БД могут не совпадать.
Это создает какие-то сложности. И чтобы решить эту сложность, нужен DM.
Что я не понимаю, а точнее не представляю, как должны выглядеть объект и таблица, чтобы не совпадать. Т.е. конкретный пример.
130 2941746
>>2941745

>Many parts of an object, such as collections and inheritance, aren't present in relational databases.


Коллекции и наследование.
131 2941748
>>2941746
Я не знаю что такое коллекции.
А когда пытался гуглить, чтобы сформировать хотя бы первичное представление - все равно ничего не понимал.
Ну а наследование, зачем вообще его отображать в БД?
Я думал, в БД просто колонки, где в строчках хранятся значение, зачем БД знать про связи, которые есть у объекта?
132 2941749
>>2941748

>Я не знаю что такое коллекции.


А что такое массив знаешь?

>зачем БД знать про связи, которые есть у объекта?


Затем что потом эти объекты надо из бд восстановить?
133 2941750
>>2941749

>А что такое массив знаешь?


Да.

>Затем что потом эти объекты надо из бд восстановить?


А причем тут наследование?
Недостаточно создать метод ВыгрузитьИзБД и прописать в теле как формировать объект?
134 2941751
>>2941750

>А причем тут наследование?


Так какого наследника создавать, когда данные из базы получил?
135 2941754
>>2941751
Я не знаю.
Я не думал в этом ключе, потому что у меня никакого наследования в коде нет и класс для хранения информации только один (куда я и планировал выгружать данные).
Т.к. я не имел опыт с этой ситуацией, для меня она звучит абстрактно.
Screenshot 2023-11-29 at 15-49-38 Screenshot.png29 Кб, 1440x256
136 2942410
Что не так? phpmyadmin
137 2942477
>>2941609

Ну можешь попробовать начать с перечитывания вчерашних туториалов. Так как ты их уже читал, то тебе будет легче их воспринимать.
138 2942492
>>2941669

Давай я поясню. Надеюсь, ты изучил ссылку https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Data Mapper - "преобразователь данных" - это штука, которая, судя по названию, должна преобразовывать PHP-объекты в строки таблиц в БД и обратно.

По ссылке, которую дал анон: https://martinfowler.com/eaaCatalog/dataMapper.html есть схема Data Mapper.

Основная особенность маппера - это то, что модель (объект Person) ничего не знает о базе данных и таблицах. Это значит, что в нем:

- никак не упоминаются названия таблиц
- нет SQL-кода
- не хранится ссылка на объекты типа PDO или соединение с БД

То есть, даже если у нас нет базы данных, мы все равно полноценно можем использовать объект Person, только сохранять его некуда.

Как работает Data Mapper? Расскажу на примере Доктрины. В Доктрине у тебя есть EntityManager - хранилище сущностей. Когда ты хочешь добавить в базу нового человека, ты делаешь так:

1) создаешь объект Person, и заполняешь его свойства

2) добавляешь этот объект в EntityManager: $em->persist($person). Этим мы добавляем объект в хранилище в памяти.

3) просишь EM скинуть накопившиеся изменения из хранилища в БД: $em->flush()

На первый взгляд, это похоже на TableDataGateway, только вместо вызова $table->save($person) мы тут делаем 2 вызова: persist и flush.

Но плюс Data Mapper проявляется, когда тебе надо внести изменения в несколько объектов. В случае TDG ты должен после внесения изменений для каждого объекта вызвать $table->save($object). В случае с DM все проще: ты просто меняешь объекты, а в конце вызываешь $em->flush() и EM сам обходит все объекты, составляет список изменений и обновляет таблицы в базе.

То есть, DM обычно поддерживает "хранилище" объектов, и умеет обнаруживать изменения в этих объектах и генерировать SQL-запросы для переноса изменений в БД. Ну то есть, если ты поменял в объекте одно поле, то EM выполнит запрос вроде UPDATE.
138 2942492
>>2941669

Давай я поясню. Надеюсь, ты изучил ссылку https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Data Mapper - "преобразователь данных" - это штука, которая, судя по названию, должна преобразовывать PHP-объекты в строки таблиц в БД и обратно.

По ссылке, которую дал анон: https://martinfowler.com/eaaCatalog/dataMapper.html есть схема Data Mapper.

Основная особенность маппера - это то, что модель (объект Person) ничего не знает о базе данных и таблицах. Это значит, что в нем:

- никак не упоминаются названия таблиц
- нет SQL-кода
- не хранится ссылка на объекты типа PDO или соединение с БД

То есть, даже если у нас нет базы данных, мы все равно полноценно можем использовать объект Person, только сохранять его некуда.

Как работает Data Mapper? Расскажу на примере Доктрины. В Доктрине у тебя есть EntityManager - хранилище сущностей. Когда ты хочешь добавить в базу нового человека, ты делаешь так:

1) создаешь объект Person, и заполняешь его свойства

2) добавляешь этот объект в EntityManager: $em->persist($person). Этим мы добавляем объект в хранилище в памяти.

3) просишь EM скинуть накопившиеся изменения из хранилища в БД: $em->flush()

На первый взгляд, это похоже на TableDataGateway, только вместо вызова $table->save($person) мы тут делаем 2 вызова: persist и flush.

Но плюс Data Mapper проявляется, когда тебе надо внести изменения в несколько объектов. В случае TDG ты должен после внесения изменений для каждого объекта вызвать $table->save($object). В случае с DM все проще: ты просто меняешь объекты, а в конце вызываешь $em->flush() и EM сам обходит все объекты, составляет список изменений и обновляет таблицы в базе.

То есть, DM обычно поддерживает "хранилище" объектов, и умеет обнаруживать изменения в этих объектах и генерировать SQL-запросы для переноса изменений в БД. Ну то есть, если ты поменял в объекте одно поле, то EM выполнит запрос вроде UPDATE.
139 2942519
>>2941669

Чтобы тебе было понятнее, попробуй полистать примеры кода в документации к Doctrine (это Data Mapper): https://www.doctrine-project.org/projects/doctrine-orm/en/2.17/reference/working-with-objects.html#persisting-entities
140 2942528
>>2940183

Вот кстати по ссылке на Фаулера ничего не написано про хранилище. Там у маппера есть методы insert/update/delete и все.
141 2942536
>>2942528
Ну расскажи авторам доктрины что они ебланы и надо было как у фаулера делать.
142 2942550
>>2941720

> в коде лучше использовать не название класса, а название его интерфейса (в том случае, если функции требуется объект определенного класса)?



Ты используешь интерфейс, если хочешь, чтобы можно было передать вместо одного класса другой ("абстрагироваться от реализации").

Ну например, тебе надо сохранять фото. Ты можешь конечно все захардкодить и прибить гвоздями, а можешь сделать интерфейс:

interface PhotoSaver
{
public function save(Photo $photo);
}

И к нему 2 реализации: одна сохраняет на диск, а другая в облачное хранилище Amazon. И в тестах использовать диск, а в продакшене Амазон.

> если интерфейсы двух классов похожи, это еще не означает, что двум классам стоит реализовывать общий интерфейс?



Нет. Интерфейс, это когда есть несколько классов, решающих одну и ту же задачу разными способами. Например, выставление счета на оплату по СБП и через ЮКассу. 2 класса, делающих одно и то же - выставление счета - но по-разному.

> Пример: у меня есть сущность, представляющая абитуриента и есть сущность, представляющая ошибки валидации.


> Общий для них интерфейс - геттер и сеттер, потому что я задал им приватные свойства.



Неправильно. Эти сущности разные и у них нет ничего общего. Геттер и сеттер не являются "общей задачей", так как они есть вообще у любого класса. Более того, геттеры у этих классов скорее всего разные (у студента - получить имя, у списка ошибок - получить текст ошибки и название поля с ошибкой).

Это хорошо, что ты пытаешься применить знания про интерфейсы, но тут ты их применяешь не туда, куда нужно.

Я подумал, где можно применить интерфейсы, и нашел. Если у тебя валидатор составной (состоит из основного валидатора и классов-правил), то для правил как раз нужно сделать интерфейс по типу:

interface RuleValidator
{
/** проверяет, что значение соответствует правилу*/
public function validate($value): ?Error; // Можно даже вместо Error сделать ErrorInterface, если у тебя несколько разных классов ошибок
}
142 2942550
>>2941720

> в коде лучше использовать не название класса, а название его интерфейса (в том случае, если функции требуется объект определенного класса)?



Ты используешь интерфейс, если хочешь, чтобы можно было передать вместо одного класса другой ("абстрагироваться от реализации").

Ну например, тебе надо сохранять фото. Ты можешь конечно все захардкодить и прибить гвоздями, а можешь сделать интерфейс:

interface PhotoSaver
{
public function save(Photo $photo);
}

И к нему 2 реализации: одна сохраняет на диск, а другая в облачное хранилище Amazon. И в тестах использовать диск, а в продакшене Амазон.

> если интерфейсы двух классов похожи, это еще не означает, что двум классам стоит реализовывать общий интерфейс?



Нет. Интерфейс, это когда есть несколько классов, решающих одну и ту же задачу разными способами. Например, выставление счета на оплату по СБП и через ЮКассу. 2 класса, делающих одно и то же - выставление счета - но по-разному.

> Пример: у меня есть сущность, представляющая абитуриента и есть сущность, представляющая ошибки валидации.


> Общий для них интерфейс - геттер и сеттер, потому что я задал им приватные свойства.



Неправильно. Эти сущности разные и у них нет ничего общего. Геттер и сеттер не являются "общей задачей", так как они есть вообще у любого класса. Более того, геттеры у этих классов скорее всего разные (у студента - получить имя, у списка ошибок - получить текст ошибки и название поля с ошибкой).

Это хорошо, что ты пытаешься применить знания про интерфейсы, но тут ты их применяешь не туда, куда нужно.

Я подумал, где можно применить интерфейсы, и нашел. Если у тебя валидатор составной (состоит из основного валидатора и классов-правил), то для правил как раз нужно сделать интерфейс по типу:

interface RuleValidator
{
/** проверяет, что значение соответствует правилу*/
public function validate($value): ?Error; // Можно даже вместо Error сделать ErrorInterface, если у тебя несколько разных классов ошибок
}
143 2942567
>>2941748

Коллекция - это объект, который хранит список других объектов или значений. Ну то есть аналог массива, только в виде объекта.

Проблема несовпадения может быть в том, что у тебя внутри объекта есть список других объектов, например:

- у Студента может храниться объект Группа, в которой он учится. А в Группе храниться Факультет, к которому она относится.

Соответственно, сохранить это в БД напрямую не получится: надо Студента сохранять в таблицу студентов, Группу в таблицу групп ит.д. С этим разбираться - как раз задача Дата Маппера.

А без Дата Маппера тебе надо решать эти задачи руками: самому сохранить разные объекты в разные таблицы и проставить в них id друг друга (в таблицу студентов - id группы, в группу - id факультета).
144 2942582
>>2941748

> Ну а наследование, зачем вообще его отображать в БД?



Бывает, что у тебя есть несколько очень похожих сущностей, которые можно представить с помощью наследования.

Например: ты занимаешься доставкой еды. У тебя есть вело-Курьеры и Курьеры на машине. У курьера с велосипедом есть одни свойства, а у курьера с машиной - другие (например: номер машины, модель, итд.). И у них есть общие свойства (например, имя, телефон, район работы).

Логично, что ты захочешь использовать наследование - сделать базовый класс БазовыйКурьер, от него унаследовать ВелоКурьер и АвтоКурьер. А теперь вопрос: как все это разнообразие сохранять в базу? Делать 1 таблицу? делать 2 таблицы?

Ты можешь решать эту проблему руками или использовать Data Mapper с поддержкой наследования, который применит один из 3 паттернов для сохранения таких объектов (нагугли, если интересно):

- Single Table Inheritance
- Class Table Inheritance
- Concrete Table inheritance

Также, бывает еще такая ситуация, как товары и характеристики. У товаров есть сотни характеристик в зависимости от категории (у компьютера - объем памяти, у чашки - объем в литрах). Опять же, чтобы это описать, придется сделать сложную структуру объектов и таблиц.
145 2942586
>>2942410

На веб-сервере не включено выполнение PHP-кода и он просто отдает PHP-файлы как есть вместо их выполнения?
146 2942588
>>2942536

Нет, я хотел обратить внимание, что схема у Фаулера и реальность немного различаются.
147 2942604
>>2942588
Ну тогда может обратишь внимание на то что insert update и delete относится к работе с базой, а не с маппером.
Screenshot 2023-11-29 at 17-52-43 phpMyAdmin.png4 Кб, 369x61
148 2942681
Как эту ебаную ошибку убрать? Ставил config.default.php $cfg['Servers'][$i]['AllowNoPassword'] = false ; на true

Все равно мозги ебет
149 2942685
>>2942681
А всё, надо было config.sample.inc.php переименовать в config.inc.php и там править
150 2942732
>>2942550

>Если у тебя валидатор составной (состоит из основного валидатора и классов-правил), то для правил как раз нужно сделать интерфейс по типу:


Не понимаю зачем тут интерфейс.
Вот код валидатора, который я написал получается, что списал, не я же его придумывал! по советам анонов (ну, или анона): https://3v4l.org/jZ4bH

rules это массив, у которого ключи - названия полей, которые нужно проверить, а значение этих ключей - массив с объектами-правилами.
В классах-правилах есть метод __invoke, чтобы вызывать объекты как методы.
151 2942742
>>2942567

>- у Студента может храниться объект Группа


Зачем Студенту хранить объект Группа?
Почему нельзя сделать свойство, значение которого - группа, просто строка с названием группы.
И если существует объект Группа, то что он из себя представляет и почему, обладая таким содержанием, находится в классе Студента?
152 2942758
>>2942742

>Почему нельзя сделать свойство, значение которого - группа, просто строка с названием группы.


Потому что в модели университета есть студенты и группы, но нет "строк"? Потому что студент университета знает в какой он группе и может об этом рассказать? Потому что каждый год создается новая группа первокуров с тем же названием?
153 2942761
>>2942550

>Более того, геттеры у этих классов скорее всего разные (у студента - получить имя, у списка ошибок - получить текст ошибки и название поля с ошибкой).


Зачем для отдельных полей делать отдельные геттеры/сеттеры?
Я видел примеры такого кода и всегда не понимал зачем, потому что пишу так: https://3v4l.org/ZmK3K
154 2942767
>>2942761
А зачем делать отдельные поля?
155 2942770
>>2942758
Что такое студент в данном случае?
Просто сущность с полями?
Зачем студенту знать что-то о содержании объекта Группа?
Я не понимаю тебя, потому что у меня объекты становятся свойствами только тогда, когда они требуются классу.
Если класс что-то делает и ему нужно получить экземпляр определенного класса, то, да, он становится частью.
А зачем в контексте этого примера ссылка на объект Группа?
156 2942771
>>2942732
А зачем в конструктор валидатора передаются "обнаруженные ошибки"? Это ведь валидатор должен находить ошибки.
157 2942775
>>2942767
Я понял эту строчку так:
Есть отдельный сеттер/геттер для отдельного поля.
Один геттер, чтобы получить значение поля, например, name.
Второй геттер, чтобы получить значение поля, например, surname.
158 2942778
>>2942771
Этот объект не содержит изначально ошибки, он позволяет класть в себя текст ошибки после прохождения валидации.
159 2942780
>>2942770

>Зачем студенту знать что-то о содержании объекта Группа?


За тем что ты моделируешь студента, а студент знает в какой он группе.
Зачем ты моделируешь студента вопрос к тебе.

>А зачем в контексте этого примера ссылка на объект Группа?


Еще раз. Затем что у тебя модель университета. Модель части реального мира. А ты её путаешь со способом хранения данных. То как ты хранишь свои данные никак не влияет на то как работает универ.
160 2942783
>>2942778

>Этот объект не содержит изначально ошибки


И где это отражено? Значения по умолчанию нет. В конструкторе пустой список с ошибками не создается. Чтобы понять как это работает надо каждый раз тебя обо всем спрашивать?
161 2942789
>>2942775

>Я понял эту строчку так:


>Есть отдельный сеттер/геттер для отдельного поля


А я должен понять как из его наличия следует его назначение? Разочарую - оно не следует.
162 2942790
>>2942783

>И где это отражено?


Ну, мб, по этому коду и непонятно, что представляет собой Класс с текстом ошибок.
Но в любом случае, какая разница?
Я же ведь описал текстом.
163 2942798
>>2942789
О чем мы вообще говорим?
Тебе полемику развести охота?
Я иногда видел код, где для отдельных полей делают отдельные геттеры и сеттеры и решил спросить в чем практическая значимость этого, если можно написать функцию, которая будет отдавать значение любого поля.
164 2942804
>>2942790
Ну так должно быть понятно. Сегодня у тебя в башке и на словах одно, завтра другое. Через месяц сам будешь на этот код как баран на новые ворота смотреть.
165 2942814
>>2942804
И что мне делать, по-твоему?
Написать документацию к своему коду?
166 2942819
>>2942798

>О чем мы вообще говорим?


>Тебе полемику развести охота?


Я видел некоторые люди чешут яйца. Зачем? Задавай бессмысленные вопросы - получай бессмысленные ответы.

>если можно написать функцию, которая будет отдавать значение любого поля


Вот это и нужно было написать. "Почему бы не сделать функцию, которая умеет работать сразу со всеми полями объекта?"

И принимать эта функция будет какой тип? А возвращать какой тип? Мне чтобы её вызвать нужно знать что ей передать и что я получу. Откуда я это узнаю?
168 2942836
>>2942819

>"Почему бы не сделать функцию, которая умеет работать сразу со всеми полями объекта?"


Мой вопрос не в этом, мой вопрос в том, почему, имея возможность написать геттер и сеттер, которые будут работать со всеми полями, кто-то пишет геттеры/сеттеры для отдельных полей?
Мб есть какая-то практическая значимость или причина, чтобы так поступать, а я, ввиду неопытности, не знаю ответа?
169 2942841
Я вот так SQL запрос на создание таблицы для списка студентов сделал, подскажите что не так
CREATE TABLE users {
id INT PRIMARY KEY;
first_name CHAR(60);
last_name CHAR(60);
email CHAR(120);
group_num INT(4);
points INT(100);
birth_date YEAR;
locate ENUM;
170 2942848
>>2942841
А пол где?
171 2942853
>>2942830
Так. А откуда мне узнать какую именно строку передать? И как мне работать с результатом? Этот результат можно умножать? Или это объект?

>>2942836
Так. Первое поле должно быть больше десяти, а второе меньше. Как будешь проверять?
172 2942864
>>2942853
Ладно, в пизду.
Хватит меня разводить на полемику.
У тебя какая цель?
Попиздеть о хуйне, задавая как можно больше вопросов там, где их нет?
173 2942880
>>2942864
А как ты хотел? Чтобы я просто сказал "это не удобно"? И хули? Почему неудобно-то? А вот руками по пишешь такую лапшу, сразу дойдет.
174 2942883
>>2942841

>Номер группы в БД надо делать строкой, а не числом. Если номера делать числом, то номер группы 0010 превратится


просто в 10. Число используется для обозначения количества или значения какой-то величины.
Из советов автора задачки.
175 2942896
>>2942880
Я не верю, что ты не понимаешь о чем я.
На этом наш диалог заканчивается.
176 2942908
>>2942814
Писать нормальный код офк.
https://3v4l.org/VvUks
177 2942917
>>2942896
А я не верю что ты не понимаешь о чем я.
Ты спрашиваешь "почему так, а не как я себе нафантазировал". А я тебе говорю: ты не фантазируй, а попробуй действительно так сделать. И сразу поймешь почему так не делают.
А ты ленишься.
178 2942920
>>2942908
Мб мне, который даже не дотягивает по знаниям и опыту до недоджуна, писать код на уровне сеньора?
Чего мелочиться?
Раз пишешь код, так давай с самого первого раза пиши идеальный, по всем правилам.
179 2942934
>>2942920
Ну начни с типизации.
Твои объекты должны работать только так как это было задумано. Ничего лишнего нельзя засунуть, ничего лишнего нельзя вытащить. Нет никакого "на словах". Если что-то может быть использовано не так - оно будет использовано не так.
180 2943011
>>2942492
Хорошо, спасибо за подробный ответ.
Можешь рассказать в чем отличие TDG от DM?
Также я не понимаю как соотносится следующее:
Другой анон пишет:

>Table gateway. Это абстракция таблицы в базе. У тебя есть объект "таблица" через который ты взаимодействуешь с её содержимым.


Статья codedokode про паттерны проектирования, раздел про TDG:
насколько я понял, есть объект, который хранит информацию о сущности и есть класс, который выполняет SQL-запросы по этой сущности.
Т.е. все-таки что такое класс TDG?
Одновременно класс, который хранит данные таблицы и умеет работать по БД или не один класс, а два, где одна сущность (и она при этом одна запись в БД) и класс-сервис?
181 2943015
>>2943011

>не один класс, а два


Имеется ввиду класс у которого ты вызываешь методы. Так-то орм это одна из самых сложных проблем в программировании. Офк там десятки классов под капотом. А доктрина так скорее всего вообще самый сложный софт на пхп написанный.
182 2943109
Какие символы, кроме кириллицы и латиницы может содержать имя человека?
183 2943178
>>2943109
⚰⚰⛼⚣
184 2943256
>>2940637
У меня есть класс-сервис.
Для его работы требуется объект.
Объект является сущностью.
Я должен регистрировать этот объект в контейнере?
Проще будет объяснить свой вопрос так:
Фабрика по созданию класса-сервиса будет выглядеть так:
new SomeClass ($container->get('AnotherClass'));
Или так:
new SomeClass (new AnotherClass).
185 2943262
>>2932466 (OP)
А вот скажите, как лучше поступить с реквестами (в Ларавеле)?
Допустим, у нас есть модель Product. У каждого продукта есть набор статусов и адресов. Конретные адреса и статусы хранятся в Statuses и Addresses. Ну и через таблицы связей и отношения многие-ко-многим прикручены к этим продуктам. Дальше, есть три ресурсных контроллера, по одному на каждую модель. Соответственно, один добвляет/показывает/редактирует/удаляет адреса, другой статусы, третий продукты. И всё ок. Вдруг потребовалось добавить ещё один эндпоинт, который показывает все адреса и все статусы. Просто листинг. Ок, добавляем контроллер InfoController и метод getInfo(). Дальше, как это инфо брать? Заново писать код для сбора адресов и статусов? Некрасиво, лучше просто обратиться к index() соответствующих контроллеров. Обращаемся. Но тут засада, у StatusController метод index() принимает реквест типа StatusRequest, а передать мы можем только пришедший InfoRequest. И как это решить?
1) Прямо на ходу родить экземпляр класса StatusRequest, вкрячить туда нужные данные и отправить в StatusController? Ну херня же.
2) Создать некий общий SharedRequestInterface, определить в нём общие свойства, родить от него InfoRequest и StatusRequest, ну и пользоваться на здоровье. Сложна.
3) Убрать кхуям из контроллеров обращения к моделям и перенести их в репозиторий. Тогда будут цепочки: StatusController принимает StatusRequest, вычленяет из него нужные данные и обращается к методу из репозитория для обращения к базе. Аналогично InfoController принимает InfoRequest, забирает данные и обращается к тому же методу того же репозитория. Вроде, самое адекватное.

Что лучше? Или я вообще фигню несу?
186 2943290
>>2943262

>Дальше, как это инфо брать? Заново писать код для сбора адресов и статусов? Некрасиво


Ты же выше написал

>через таблицы связей и отношения многие-ко-многим прикручены


Написан ведь код сбора адресов уже. Тебе целый элокент для этого даден.

>лучше просто обратиться к index() соответствующих контроллеров. Обращаемся. Но тут засада, у StatusController метод index() принимает реквест типа StatusRequest


А что будет если объект предназначенный для обработки веб запроса использовать не по назначению? Будет весело.

>Убрать кхуям из контроллеров обращения к моделям и перенести их в репозиторий.


Репозиторий не выдает листинги. Репозиторий предназначен для работы с сущностями. А у тебя для этого актив рекорд элокент есть, нахуя тебе вокруг него дата маппер городить?

Ты можешь просто вынести повторяющийся код и назвать его в соответствии с его назначением. Такие невероятно сложные способы рефакторинга как извлечение метода/класса сейчас не в моде? Ctrl+alt+m в шторме, одно нажатие.
187 2943293
Кто-нибудь может подсказать как установить Laravel?
Каждый раз, как не брался за это, всегда все выглядит мудрено: то установить Докер (и разобраться как он работает), то установить Композер (который я также не ебу как работает).
Качать какую-то утилиту сомнительную, которая все якобы тебе скачает, нужное для веб-разработки - тоже не очень вариант.
188 2943295
>>2943293
А тебе зачем?
189 2943297
>>2943295
Действительно.
Нахуя нужна ларка, если человек учит php.
190 2943300
>>2943256

>У меня есть класс-сервис.


>Для его работы требуется объект.


>Я должен регистрировать этот объект в контейнере?


Контейнер тебе зачем? Для инверсии зависимостей. А что написано в "принципе инверсии зависимостей"? "Классы должны зависеть от абстракций, а не от конкретных деталей" там написано. https://en.wikipedia.org/wiki/Dependency_inversion_principle
Так каким хуем твой сервис может зависеть от конкретной сущности, а не от абстракции?
191 2943301
>>2943297
Так учись епты. На работе че какой-то другой докер и другой композер будет что-ли?
192 2943309
>>2943300
Лучше напиши что мне конкретно делать.
193 2943311
>>2943301
Нет, но хочется подвинуть изучение докера и композера на позже. И немного ларку потрогать.
194 2943316
>>2943309
Разобраться в терминах, которыми ты сыпешь. Сущность это вообще из ddd Эванса. Инверсия контроля из солида и чистой архитектуры Мартина. Это две книги минимум, чисто погрузиться. И обе они не по пхп.

Тебе нужно начать с того что научиться объекты грамотно проектировать и методы. А уже потом об архитектуре думать.
MarshakS.Ja.jpg644 Кб, 1469x1920
195 2943321
>>2943311
Не стареющая классика.
196 2943388
>>2943293
Тупой вопрос. Посмотри пару видео по 5-10 минут и разберёшься.
197 2943515
>>2943293
Зачем тебе знать как он работает, берешь и без задней мысли ставишь: composer create-project laravel/laravel Govno
198 2943772
Аноны, хелп. 2 день мучаюсь
почему у меня на пике куча с глазами весь мой стиль на странице ломает?

Я делал машинку все работало, а тут все супер плохо
Даже если смайл не в контейнере держать все тоже самое будет

CSS
.line-container {
display: flex;
position: fixed;
}
.line_bottom {
margin-top: 10%;
width: 100%;
height: 11px;
background-color: rgb(255, 0, 0);
}

.glass-line {
position: relative;
font-size: 60px;
animation: tyda_suda 5s infinite alternate;
}

@keyframes tyda_suda {
from {
left: 0;
}
to {
left: 90%;
}
}

HTML
<div class="line_container">
<div class="line_bottom"></div>
<div class="glass-line line-1">&#x1F4A9</div>
</div>
198 2943772
Аноны, хелп. 2 день мучаюсь
почему у меня на пике куча с глазами весь мой стиль на странице ломает?

Я делал машинку все работало, а тут все супер плохо
Даже если смайл не в контейнере держать все тоже самое будет

CSS
.line-container {
display: flex;
position: fixed;
}
.line_bottom {
margin-top: 10%;
width: 100%;
height: 11px;
background-color: rgb(255, 0, 0);
}

.glass-line {
position: relative;
font-size: 60px;
animation: tyda_suda 5s infinite alternate;
}

@keyframes tyda_suda {
from {
left: 0;
}
to {
left: 90%;
}
}

HTML
<div class="line_container">
<div class="line_bottom"></div>
<div class="glass-line line-1">&#x1F4A9</div>
</div>
image.png3 Кб, 1153x174
199 2943773
200 2943807
>>2943772
Телепатически проникаю к тебе в голову. Вижу как работала машинка и вижу что стало не так с какашкой. Вижу твой стиль каким ты его хочешь, не сломанным...

Че поверил? В деда мороза тоже веришь? Каким хуем кто-то должен понять что у тебя там сломалось в башке твоей? https://jsfiddle.net/v9se6z13/
201 2943837
>>2942604

Нет, insert/update/delete это методы класса Person Mapper. Посмотри внимательно на диаграмму: https://martinfowler.com/eaaCatalog/dataMapper.html
202 2943867
>>2942732

> Не понимаю зачем тут интерфейс.



Вот смотри, допустим я хочу взять твой код и добавить новое правило валидации и класс, который его проверяет. Как я должен писать этот класс? Каким требованиям он должен соответствовать?

Ты мог бы написать документацию в стиле "если вы хотите добавить новое правило, то ...". Но зачем писать, когда можно сделать интерфейс для классов-правил. И я буду знать, что мой класс должен соответствовать этому интерфейсу. А PHP проверит это и выдаст ошибку, если вдруг я что-то забыл.

То есть, для классов-правил надо сделать общий интерфейс.

> Вот код валидатора, который я написал ... https://3v4l.org/jZ4bH



Здесь есть такие недостатки:

1) ты передаешь в конструктор студента для проверки. Это плохо, так как:

а) получается, твой валидатор можно использовать только один раз. Чтобы проверить нового студента, надо создавать новый валидатор. Это так же нелогично, как покупать новую стиральную машину перед каждой стиркой.

б) непонятно, зачем тебе метод carryOutVerification. Ведь все данные уже есть в конструкторе и ты мог бы там сразу сделать проверку.

Лучше передавать проверяемого студента в метод проверки.

2) нелогично, что ты в конструктор еще передаешь список ошибок. Логичнее было бы, если бы метод для проверки возвращал список ошибок. То есть, ты кладешь в валидатор студента и он тебе в ответ возвращает список найденных ошибок.

То есть, на мой взгляд, логично было бы сделать класс так:

class Validator
{
public function __construct($rules) { ... }
public function validate(Enrollee $enrollee): ErrorList { ... }
}

3) ты не в том месте делаешь добавление ошибки. Ты достаешь предудущую ошибку, склеиваешь с ней новую и записываешь обратно. Но это неправильно, так как работа с ошибками это задача класса ErrorList (или как он у тебя назван). Только он знает, как хранить и склеивать ошибки. Соответственно, ты не должен склеивать их в валидаторе, а должен просто вызывать метод $this->detectedValidationErrors->add($key, $errortext)

4) PHP позволяет указывать типа параметров функций, тип результата и тип полей класса. Ты этого не делаешь, из-за этого твой код труднее понимать. Надо прочесть мануал и расставить типы везде, где можно:

- https://www.php.net/manual/ru/language.types.type-system.php
- https://www.php.net/manual/ru/language.oop5.properties.php#language.oop5.properties.typed-properties

У полей тип ставится так: private int $x; private SomeClass $y;
У функций и методов так: public function test(int $x, SomeClass $y, SomeInterface $z): SomeClass

Не согласен - возражай, не понял - спрашивай, иначе жду доработанный код.
202 2943867
>>2942732

> Не понимаю зачем тут интерфейс.



Вот смотри, допустим я хочу взять твой код и добавить новое правило валидации и класс, который его проверяет. Как я должен писать этот класс? Каким требованиям он должен соответствовать?

Ты мог бы написать документацию в стиле "если вы хотите добавить новое правило, то ...". Но зачем писать, когда можно сделать интерфейс для классов-правил. И я буду знать, что мой класс должен соответствовать этому интерфейсу. А PHP проверит это и выдаст ошибку, если вдруг я что-то забыл.

То есть, для классов-правил надо сделать общий интерфейс.

> Вот код валидатора, который я написал ... https://3v4l.org/jZ4bH



Здесь есть такие недостатки:

1) ты передаешь в конструктор студента для проверки. Это плохо, так как:

а) получается, твой валидатор можно использовать только один раз. Чтобы проверить нового студента, надо создавать новый валидатор. Это так же нелогично, как покупать новую стиральную машину перед каждой стиркой.

б) непонятно, зачем тебе метод carryOutVerification. Ведь все данные уже есть в конструкторе и ты мог бы там сразу сделать проверку.

Лучше передавать проверяемого студента в метод проверки.

2) нелогично, что ты в конструктор еще передаешь список ошибок. Логичнее было бы, если бы метод для проверки возвращал список ошибок. То есть, ты кладешь в валидатор студента и он тебе в ответ возвращает список найденных ошибок.

То есть, на мой взгляд, логично было бы сделать класс так:

class Validator
{
public function __construct($rules) { ... }
public function validate(Enrollee $enrollee): ErrorList { ... }
}

3) ты не в том месте делаешь добавление ошибки. Ты достаешь предудущую ошибку, склеиваешь с ней новую и записываешь обратно. Но это неправильно, так как работа с ошибками это задача класса ErrorList (или как он у тебя назван). Только он знает, как хранить и склеивать ошибки. Соответственно, ты не должен склеивать их в валидаторе, а должен просто вызывать метод $this->detectedValidationErrors->add($key, $errortext)

4) PHP позволяет указывать типа параметров функций, тип результата и тип полей класса. Ты этого не делаешь, из-за этого твой код труднее понимать. Надо прочесть мануал и расставить типы везде, где можно:

- https://www.php.net/manual/ru/language.types.type-system.php
- https://www.php.net/manual/ru/language.oop5.properties.php#language.oop5.properties.typed-properties

У полей тип ставится так: private int $x; private SomeClass $y;
У функций и методов так: public function test(int $x, SomeClass $y, SomeInterface $z): SomeClass

Не согласен - возражай, не понял - спрашивай, иначе жду доработанный код.
203 2943871
>>2942742

> Зачем Студенту хранить объект Группа?



В этой задаче достаточно хранить строку с названием.

Но представь, что мы делаем более продвинутую систему, где есть группы, факультеты, преподаватели, корпуса, аудитории, расписание занятий. Там у Группы есть свойства: название, факультет, год обучения. А раз есть свойства, значит нам нужен класс Группа и таблица для хранения групп, и надо как-то указать, какой студент в какую группу входит.

В такой системе у Студента будет свойство, в котором хранится объект Группы, а не название. Чтобы мы могли легко получить, например, к какому факультету относится студент или на каком он году обучения.
204 2943874
>>2942761

Отдельные геттеры и сеттеры нужны, чтобы было сразу видно, какие поля есть у класса и какого они типа.

В твоем коде мы можем написать $enrollee->set('zbcdefgh', 12345) и IDE или статический анализатор не увидит тут никакой ошибки. А если мы напишем $enrollee->setZbcdefgh(12345), то будет сразу видно, что такого метода нету, и IDE тебе подчеркнет это красненьким.

Ну и человеку проще, когда видно какие есть методы, а не когда тебе дают один метод set() и ищи, догадывайся, что в него можно передать, а что нельзя.
205 2943880
>>2942841

- id надо сделать не просто INT, а UNSIGNED INT
- для всех полей, которые обязательны к заполнению, надо указать NOT NULL
- вместо CHAR используют VARCHAR. CHAR это строка фиксированной длины, которая добавляет пробелы при вставке, если символов меньше, чем надо
- по условиям задачи про номер группы написано: "номер группы (от 2 до 5 цифр или букв)". Читай внимательнее требования.
- points INT(100); - 100 здесь не максимально возможное значение, а рекомендуемое количество цифр при выводе
- для ENUM надо перечислить список разрешенных значений
206 2943882
>>2942920

Тебе надо с самого начала учиться писать код нормально. Джун это не человек, который пишет плохой код с ошибками, а человек, у которого мало опыта.
207 2943889
>>2943011

> в чем отличие TDG от DM?



Эти паттерны описаны у Фаулера:

- https://martinfowler.com/eaaCatalog/tableDataGateway.html
- https://martinfowler.com/eaaCatalog/dataMapper.html

TDG это просто класс, где собраны все возможные операции над одной таблицей. Весь SQL-код для работы с таблицей должен быть собран в этом классе, и нигде больше. Если у тебя 5 таблиц, то у тебя будет примерно 5 TDG-классов, для каждой таблицы свой. И в них могут быть разные операции.

TDG не хранит в себе данные из таблиц. Данные хранятся в сущности, и если ты например прочитал из базы 10 студентов, то TDG создаст 10 объектов Student (или Enrollee) для них. На каждую запись создается новый объект.

Если ты совмещаешь в сущности хранение данных и операции, то это называется ActiveRecord - это сущность, которая сама умеет работать с базой. У Фаулера она есть: https://www.martinfowler.com/eaaCatalog/activeRecord.html

TDG это относительно простая штука. Например, в TDG может быть метод вроде updateStudentScore(int $id, int $score) - обновить баллы у студента по id. И другие методы, вроде "добавить студента в таблицу", "удалить студента", "найти студентов по поисковой строке", и тд.

DM это более сложная система. В ней обычно нет конкретных методов вроде "обновить баллы у студента". В ней ты просто загружаешь студента из базы, меняешь ему кол-во баллов, и просишь DM саму найти, что поменялось, и перенести изменения в БД.

DM пытается создать видимость, как будто БД не существует. Ты просто работаешь с объектами, загружаешь их, меняешь их, а DM сама обновляет базу в соответствие с твоими изменениями.

Для сравнения,в TDG, если ты хочешь что-то поменять, ты явно вызываешь нужный метод, вроде updateStudentScore. То есть, TDG намного примитивнее.

DM также обычно реализует паттерны вроде Identity Map, Unit of Work, Lazy Load, поддерживает связи между объектами, наследование и тд.

пример DM для PHP это библиотека Doctrine 2.
208 2943893
>>2943011

> насколько я понял, есть объект, который хранит информацию о сущности и есть класс, который выполняет SQL-запросы по этой сущности.



да

> Т.е. все-таки что такое класс TDG?


> Одновременно класс, который хранит данные таблицы и умеет работать по БД или не один класс, а два, где одна сущность (и она при этом одна запись в БД) и класс-сервис?



TDG это сервис, в котором не хранятся никакие данные, а только есть операции над таблицей. TDG у тебя в одном экземпляре. А Студентов может быть много экземпляров.
209 2943894
>>2943109

Дефис и апостроф: Д`Артяньян (Д'Артаньян) Переяславль-Залесский.
210 2943899
>>2943256

> Я должен регистрировать этот объект в контейнере?



Давай разделим сущности на 2 вида:

1) сущности, которые заполняются данными от пользователя (из формы). Они никогда не кладутся в DI контейнер, так как контейнер не должен получать никаких данных от пользователя.

2) сущности, которые всегда одинаковые либо которые заполняются из конфига. Их можно класть в контейнер. Но такие сущности встречаются редко и в задаче про студентов их нету.

Если у тебя сущность типа 1, то ее обычно не передают в конструктор сервиса.
211 2943904
>>2943256

То есть, твой контейнер не должен содержать в себе что-то, что приходит от пользователя или из формы. Твой контейнер в идеале должен быть всегда одинаковый и в нем не должно быть меняющихся данных.

Почему? Потому что контейнер и сервисы создаются один раз, и могут (в теории) обработать много запросов от разных пользователей. Контейнер св идеале оздается до того, как мы получим данные от пользователя, поэтому он не должен иметь к ним доступа или как-то их использовать.
212 2943914
>>2943262

> Некрасиво, лучше просто обратиться к index() соответствующих контроллеров.



Это неправильно, ты не должен писать в контроллере код, который надо вызвать откуда-то из другого места. Контроллер только обрабатывает запрос от пользователя и все. Он не помогает другим классам что-то найти.

Такой код, который нужен в нескольких местах, ты помещаешь в модель или сервис (или репозиторий, хотя откуда они в Ларавеле).

Далее, если у тебя сущности связаны, то ты должен сделать эти связи на уровне модели. Чтобы ты мог просто взять Product и вызвать метод и получить список его адресов.
213 2943916
>>2943293

Надо изучить композер, а затем Докер. Чтобы изучить Докер, предварительно надо научиться работать в командной строке и выучить основные команды Линукс. Учебников и видео полно по этой теме.
214 2943920
>>2943316

"Сущность" посоветовал использовать я, как название для класса с данными, моделирующего какую-то сущность из предметной области (Товар, Заказ, Комментарий, Пользователь). Как противоположность классу-сервису, который не хранит данные, а выполняет операции над ними. Что тут не так? Зачем для этого изучать DDD?
215 2943921
>>2942848
Надо не пол, а гендер, чтобы никого не ущемлять
216 2943922
Существует ли не фулл-стек вакансии на РНР?
217 2943945
Как вы привыкли вообще писать знак доллара каждый раз?
Это жесть какая-то
218 2943948
>>2943945
Меня больше бесит -> писать вместо точки.
219 2943977
>>2943945
Норм, напоминает что нужно на хх ставить зп в баксах, а не в непостоянной валюте
220 2943984
>>2943880
Ок, спасибо
221 2944046
Зашел на flru, все заказы разные. Это же какой блядь объем знаний нужен чтобы там хоть что то взять? Это пиздец
222 2944079
>>2944046
Тебя наебали с фрилансом. Ты повелся что ли?
223 2944111
>>2943316
И какой итог такого подхода к обучению?
А итог такой: почти 2 месяца прошло, а я где начал задачу, там и остался.
Я согласен с тобой, что нужно учиться правильно кодить, читать литературу.
Я всем этим буду заниматься.
Но я уже так устал.
Меня уже тошнит от этой задачи про Список Студентов.
Тошнит, что я маюсь-маюсь, а конца ей нет, да и продвижения нет.
Я уже согласен написать посредственный код, но чтобы у меня получился хотя бы внешне работающий продукт.
Да и не много ли я с себя требую?
Я всего лишь новичок.
Философию ООП-кода не понимаю.
Много пробелов в знаниях.
Какой еще код ждать от человека, который не умеет кодить и мало знает?
Я считаю, что пусть я напишу плохой код, но пройду дальше, столкнусь с новыми знаниями, они подскажут мне как писать лучше, возможно, встречу толковых людей, указания которых я смогу понять и так и буду расти.
224 2944113
>>2944046

>2024



>фриланс



>россия



Чел...
225 2944122
>>2944079
Да в целом я работал в вордпрессом, модули делал, вукомерс накатывал, с yii2, могу за солид с граспом пояснить и все такое.
Но проблема в том что там куча заказов и везде нужен узкий профиль экспертности, либо делать параллельно изучая область. Задачи пиздец какие разноплановые
226 2944133
>>2944113
А как работать в РФ? Сам самозарядный из плюсов то что работодатель не может принести повестку как на обычной работе и ничего не сообщает в военкомат иначе ему штраф 400к
227 2944137
>>2944133
быстрофикс - самозанятый.
228 2944153
>>2943807
ну и хули, все заработало
а ты говоришь непонятно что описал
спасибо
229 2944192
>>2943867

>получается, твой валидатор можно использовать только один раз. Чтобы проверить нового студента, надо создавать новый валидатор. Это так же нелогично, как покупать новую стиральную машину перед каждой стиркой.


Я не представляю что будет находиться у меня в переменных, если я запущу сервер и моя страница будет
запущена на двух отдельных устройствах и они будут посылать данные на мой сервер.
Т.е. как php-скрипт будет обрабатывать эти данные.
Одни данные перекроют другие? Для каждого браузера будет отдельный php-скрипт, у которого будут полностью чистые
переменные и которые будут очищаться после того как php-скрипт отработает?

>непонятно, зачем тебе метод carryOutVerification


Этот метод запускает отдельные проверятели-правил.
Мне посоветовали в прошлом треде сделать главный класс и классы-проверятели (проверка на пустоту, на количество и т.д.).

>Ведь все данные уже есть в конструкторе и ты мог бы там сразу сделать проверку.


Не понимаю тебя.

>Логичнее было бы, если бы метод для проверки возвращал список ошибок


Я храню текста ошибок в виде объекта, где его свойства - name, surname etc.

>ты передаешь в конструктор студента для проверки


Я отдал его в конструктор, потому что думал, что если для работы Валидатора нужен объект другого класса,
то я должен добавлять зависимости через конструктор, а не отдавать объекты в методы.

>Ты достаешь предудущую ошибку, склеиваешь с ней новую и записываешь обратно.


Я так сделал, потому что иначе бы один текст ошибки перекраивал другой.
Ну, да ладно.

>Только он знает, как хранить и склеивать ошибки


Ну...Мой класс, связанный с ошибками, просто хранит данные.
Он как студент, только вместо имени он принимает текст ошибки.
А чтобы понимать в каком поле пользователь совершил ошибку, я классу, который содержит текст ошибок,
дал поля, которые называются как поля студента (кроме тех, где пользователь не вводит, а выбирает вариант из списка).
Ну, ладно. Я понял. Я должен переписать класс с текстом ошибок.
Добавить в него метод, чтобы он...сам клал значения ошибок и склеивал их.
Окей.

>PHP позволяет указывать типа параметров функций, тип результата и тип полей класса.


Да, я узнал об этом в прошлом треде.
Нет пока что привычки добавлять все это, потому что я учился по урокам, когда указывать типы нельзя было(?).
Да и код я не пишу.
Как не обращусь с вопросом, так сразу неправильно у меня все.
Начинаю вместо кода сидеть думать как правильно строить классы.
В итоге просто бездарно проведенное время, ведь мне не хватает знаний и опыта, чтобы понять и применить с умом то,
о чем говорят в тредах опытные аноны.
229 2944192
>>2943867

>получается, твой валидатор можно использовать только один раз. Чтобы проверить нового студента, надо создавать новый валидатор. Это так же нелогично, как покупать новую стиральную машину перед каждой стиркой.


Я не представляю что будет находиться у меня в переменных, если я запущу сервер и моя страница будет
запущена на двух отдельных устройствах и они будут посылать данные на мой сервер.
Т.е. как php-скрипт будет обрабатывать эти данные.
Одни данные перекроют другие? Для каждого браузера будет отдельный php-скрипт, у которого будут полностью чистые
переменные и которые будут очищаться после того как php-скрипт отработает?

>непонятно, зачем тебе метод carryOutVerification


Этот метод запускает отдельные проверятели-правил.
Мне посоветовали в прошлом треде сделать главный класс и классы-проверятели (проверка на пустоту, на количество и т.д.).

>Ведь все данные уже есть в конструкторе и ты мог бы там сразу сделать проверку.


Не понимаю тебя.

>Логичнее было бы, если бы метод для проверки возвращал список ошибок


Я храню текста ошибок в виде объекта, где его свойства - name, surname etc.

>ты передаешь в конструктор студента для проверки


Я отдал его в конструктор, потому что думал, что если для работы Валидатора нужен объект другого класса,
то я должен добавлять зависимости через конструктор, а не отдавать объекты в методы.

>Ты достаешь предудущую ошибку, склеиваешь с ней новую и записываешь обратно.


Я так сделал, потому что иначе бы один текст ошибки перекраивал другой.
Ну, да ладно.

>Только он знает, как хранить и склеивать ошибки


Ну...Мой класс, связанный с ошибками, просто хранит данные.
Он как студент, только вместо имени он принимает текст ошибки.
А чтобы понимать в каком поле пользователь совершил ошибку, я классу, который содержит текст ошибок,
дал поля, которые называются как поля студента (кроме тех, где пользователь не вводит, а выбирает вариант из списка).
Ну, ладно. Я понял. Я должен переписать класс с текстом ошибок.
Добавить в него метод, чтобы он...сам клал значения ошибок и склеивал их.
Окей.

>PHP позволяет указывать типа параметров функций, тип результата и тип полей класса.


Да, я узнал об этом в прошлом треде.
Нет пока что привычки добавлять все это, потому что я учился по урокам, когда указывать типы нельзя было(?).
Да и код я не пишу.
Как не обращусь с вопросом, так сразу неправильно у меня все.
Начинаю вместо кода сидеть думать как правильно строить классы.
В итоге просто бездарно проведенное время, ведь мне не хватает знаний и опыта, чтобы понять и применить с умом то,
о чем говорят в тредах опытные аноны.
230 2944198
>>2944133
Ну и что, зато теперь же ведомства обязаны инфу передавать в ёнкомат. То есть ты самозарядный и ёнкомат узнает из налоговой, что ты самозарядный и щас дело не в том что принесут повистку, а в том что её тебе в госуслуги закинули, и ты по факту обязан. То есть знал ты или нет - поксуй, не пришел - с тебя штраф 10-30к
231 2944199
>>2943871
Хорошо. Я понимаю.
232 2944202
>>2943874
Ясно.
Я не думал в таком ключе.
233 2944206
>>2943889
Хорошо, спасибо, я понял.
234 2944214
>>2943899
Окей.
235 2944281
>>2944111

>посредственный код, но чтобы у меня получился хотя бы внешне работающий продукт


тогда просто пиши, как получится, забудь пока про эти ооп, паттерны и прочая. Выпиши требования задачи на бумажке или в текстовик (важно - только требования, без комментариев, советов, рекомендаций и т.д.) . Дальше вся работа должна идти в порядке "хочу сделать это > гуглю, если не понятно как сделать > делаю > думаю, что дальше надо делать".
Потом, когда напишешь, прочитаешь ту же шапку снова, сравнишь описываемый "правильный" подход со своим, начнёшь понимать, зачем вообще эти всякие ООПы нужны и как они бы помогли при написании кода. Тогда и дальнейшее изучение пойдёт попроще - это уже будет не абстрактная "философия", а практический инструмент.
236 2944327
>>2944281

>важно - только требования


Даже не знаю.
Прям только-только требования?
Даже без раздела о подводных камнях от автора задачи (ну или человека, который разместил ее в гитхабе)?
Если я буду гуглить, не будет ли это нечто схожее, чем как если бы я спрашивал тут, у анонов, или читал советы по задаче?
И то, мб, это будет хуже.
Потому что тут живые люди, у которых можно переспрашивать.
А если я не смогу нагуглить, я также буду затупливаться, сидеть, думОть, но не кодить.
Да и не бросать же мне те советы, которые уже писали аноны?
Все-таки он(и) дело говорят.
237 2944356
>>2943920

>для класса с данными, моделирующего какую-то


Моделирует "модель". А у сущности другие свойства.

>Как противоположность классу-сервису, который не хранит данные


Сущность противопоставляется не сервису, а классу который полностью определяется его данными. Как адрес или дата.

>Что тут не так? Зачем для этого изучать DDD?


И пользователь и его адрес это модель, и пользователь и адрес хранятся в базе в отдельных таблицах. Только пользователь это сущность, а адрес нет.

Вот как одно от другого отличить и написано у Эванса.
238 2944376
>>2944198

> и ёнкомат узнает из налоговой,


Вообще похуй, нельзя будет открыть с нуля, но то что есть не закрывают.

> же ведомства обязаны инфу передавать в ёнкомат.


ГПХ/Самозанятые работает без этой хуйни. На работе про тебя все твой директор сдает и повестку тебе приносит, от которой уже неоткажешься.

> в том что её тебе в госуслуги закинули, и ты по факту обязан.


Реестра повесток нет, по слухам юристов не ранее 2025, да и должны обеспечить бесплатным инетом и компом ибо нет закона что я обязан все это иметь. Закон - пугалка.

Причина твоей тряски? Хочешь чтобы я на работу устроился или че?
239 2944382
>>2944198
Ну и пока повестка считается врученный когда на ней роспись поставил или заказное письмо пришло и ты его взял или пришел по извещению в почту и отказался. Другие варианты не предусмотрены законом.

Но если ты не запасник, а призывник у которого военника нет, то там свои законы и другая ответственность, более пиздецовая чем для запасников
240 2944447
>>2944327

>Прям только-только требования?


Даже без раздела о подводных камнях от автора задачи (ну или человека, который разместил ее в гитхабе)?
Да. Советы загружают мозг, заставляют думать о правильной структуре приложения, о всяких злых ООП, о том как бы всё сделать красиво и не обосраться, и т.д.

А когда сам пишешь, то всё просто - надо сделать приложение, которое будет иметь такой функционал. И всё. Это развязывает руки.

>Если я буду гуглить, не будет ли это нечто схожее, чем как если бы я спрашивал тут, у анонов, или читал советы по задаче?


Для того, чтобы получить нормальный ответ от гугла, надо уметь гуглить - сформулировать запрос, потыкать по ссылкам, проанализировать ответы, если не подходят, то изменить запрос и загуглить ещё раз, и т.д. Это практический навык, его надо развивать и он очень сильно упрощает дальнейшее обучение.

Для того, чтобы (в теории) получить ответ от анона, надо... уметь писать на русском? При этом можно написать максимально расплывчатый и неконкретный вопрос, вообще не шевеля мозгами и никак не вовлекаясь в процесс. Это не очень сильно помогает и занимает время. Даже если ответ на такой вопрос будет хорошим, то всё равно не будет понятно, где его применить.

>Потому что тут живые люди, у которых можно переспрашивать.


У гугла тоже можно переспрашивать. А ещё от анона ответы приходят за минуты и часы, а от гугла - за миллисекунды. И ещё гугл не устаёт, не бурчит, не спорит, и готов стерпеть самые глупые вопросы (которые даже в треде глупых вопросов бы не прошли).

>А если я не смогу нагуглить, я также буду затупливаться, сидеть, думОть, но не кодить.


Если не получается нагуглить, то гугли по-другому. Гугли руководства к действию: что сделать, чтобы сайт запомнил юзера; что сделать, чтобы из кода залезть в базу данных, что делать, чтобы ...
Результатом будут конкретные инструкции, которые можно попробовать и посмотреть, что получается. И дальше уже думать, как это можно использовать для решения проблемы.

>Да и не бросать же мне те советы, которые уже писали аноны?


Если в какой-то момент возникнет ощущение, что ты можешь применить какой-то совет, и при этом будет ясно, какие именно строчки кода нужно писать для реализации этого совета - то флаг в руки, пиши, пробуй. С другой стороны, если есть только унылое ощущение, что по этой теме что-то советовали, но как реализовать не понимаешь - то не надо.
240 2944447
>>2944327

>Прям только-только требования?


Даже без раздела о подводных камнях от автора задачи (ну или человека, который разместил ее в гитхабе)?
Да. Советы загружают мозг, заставляют думать о правильной структуре приложения, о всяких злых ООП, о том как бы всё сделать красиво и не обосраться, и т.д.

А когда сам пишешь, то всё просто - надо сделать приложение, которое будет иметь такой функционал. И всё. Это развязывает руки.

>Если я буду гуглить, не будет ли это нечто схожее, чем как если бы я спрашивал тут, у анонов, или читал советы по задаче?


Для того, чтобы получить нормальный ответ от гугла, надо уметь гуглить - сформулировать запрос, потыкать по ссылкам, проанализировать ответы, если не подходят, то изменить запрос и загуглить ещё раз, и т.д. Это практический навык, его надо развивать и он очень сильно упрощает дальнейшее обучение.

Для того, чтобы (в теории) получить ответ от анона, надо... уметь писать на русском? При этом можно написать максимально расплывчатый и неконкретный вопрос, вообще не шевеля мозгами и никак не вовлекаясь в процесс. Это не очень сильно помогает и занимает время. Даже если ответ на такой вопрос будет хорошим, то всё равно не будет понятно, где его применить.

>Потому что тут живые люди, у которых можно переспрашивать.


У гугла тоже можно переспрашивать. А ещё от анона ответы приходят за минуты и часы, а от гугла - за миллисекунды. И ещё гугл не устаёт, не бурчит, не спорит, и готов стерпеть самые глупые вопросы (которые даже в треде глупых вопросов бы не прошли).

>А если я не смогу нагуглить, я также буду затупливаться, сидеть, думОть, но не кодить.


Если не получается нагуглить, то гугли по-другому. Гугли руководства к действию: что сделать, чтобы сайт запомнил юзера; что сделать, чтобы из кода залезть в базу данных, что делать, чтобы ...
Результатом будут конкретные инструкции, которые можно попробовать и посмотреть, что получается. И дальше уже думать, как это можно использовать для решения проблемы.

>Да и не бросать же мне те советы, которые уже писали аноны?


Если в какой-то момент возникнет ощущение, что ты можешь применить какой-то совет, и при этом будет ясно, какие именно строчки кода нужно писать для реализации этого совета - то флаг в руки, пиши, пробуй. С другой стороны, если есть только унылое ощущение, что по этой теме что-то советовали, но как реализовать не понимаешь - то не надо.
241 2944697
>>2944447
Ладно, продолжу дальше засирать тред глупыми вопросами.
242 2944937
Бонжур, мон шери, подскажите литературы по Симфони. Мурзилку от создателя Симфони прочитал и его проект ручками пощупал, но этого мало.
171024-dmb0.jpg134 Кб, 1205x767
243 2945037
>>2944937
Мало для чего? Что ты такого с симфони делать собрался что тебе не достаточно открыть доку?
244 2945048
>>2944937
1) Чтение исходиков.
2) xdebug. Деды всегда дебажили код, чтобы понять как он работает. В книжке каждую переменную не опишешь.

А так ты хочешь глотать пережеванную другими пищу.
245 2945189
>>2945037
Мне надо пет-проект написать, а я пока не понимаю как подступиться даже.

>>2945048
Это может на годы затянуться, а я планировал весной вкатиться уже.
246 2945192
>>2945189
А в "Мурзилке от создателя Симфони" вместо того как работать с фреймворком написано как хуй чесать?
247 2945198
>>2945192
Там мало написано, буквально шаг влево, шаг вправо и уже не понимаешь.
Может стоит Лару учить, по ней больше всего написано.
248 2945211
>>2945198
Если надо срочно работу получить, то да изучи битрикс ларавель
249 2945212
>>2945198
И что за шаги ты собрался делать вправо и влево? Тебе фреймворк нахуя? Делай как в доке написано и все.
250 2945219
>>2944111

> Я уже согласен написать посредственный код, но чтобы у меня получился хотя бы внешне работающий продукт.



Не надо так. Надо сидеть и разбираться.

> Философию ООП-кода не понимаю.



А вот в учебнике есть глава про ООП и задача про ООО Вектор, ты ее делал? Она вроде как должна помогать разобраться в ООП. Или можем какую-нибудь другую задачу на ООП-проектирование тебе дать.

> Я считаю, что пусть я напишу плохой код, но пройду дальше



Если ты не разберешься с основами (ООП), как ты пойдешь дальше? Это как пропустить основы арифметики и браться сразу за матрицы и векторы.
251 2945229
>>2944192

> Я не представляю что будет находиться у меня в переменных, если я запущу сервер и моя страница будет


запущена на двух отдельных устройствах и они будут посылать данные на мой сервер.

> Т.е. как php-скрипт будет обрабатывать эти данные.


> Одни данные перекроют другие? Для каждого браузера будет отдельный php-скрипт, у которого будут полностью чистые


переменные и которые будут очищаться после того как php-скрипт отработает?

На каждый HTTP-запрос (неважно, от одного браузера или разных) создается новая чистая среда выполнения с пустыми переменными. Соответственно, если параллельно или по очереди выполняется несколько копий скрипта, они друг на друга не влияют.

Этот передовой stateless-подход, придуманный в PHP много лет назад, сейчас копируют ведующие облачные провайдеры (в сервисе AWS Lambda или Yandex Cloud Functions).
252 2945232
>>2944192

>>непонятно, зачем тебе метод carryOutVerification


> Этот метод запускает отдельные проверятели-правил.


Мне посоветовали в прошлом треде сделать главный класс и классы-проверятели (проверка на пустоту, на количество и т.д.).

Вот смотри, чтобы использовать твой класс, мы должны написать:

$validator = new Validator($rules, $enrollee, $errors);
$validator->carryOutVerification();

Зачем здесь вызов carryOutVerification? Ты мог бы его сразу вписать в конструктор, чтобы он вызывался автоматически.

Правда это будет далеко от ООП. Тебе надо пойти одним из 2 путей:

В ООП-стиле:

// создаем валидатор, который можно многократно использовать
$validator = new Validator($rules);
// используем
$errors = $validator->validate($enrollee);
// используем еще раз
$errors2 = $validator->validate($enrollee2);

В процедурном стиле:

$errors = validate($rules, $enrollee);

Но твой стиль просто выглядит странно и нелогично. Непонятно, зачем вызывать функцию, в которую ничего не передается и которая ничего не возвращает.
252 2945232
>>2944192

>>непонятно, зачем тебе метод carryOutVerification


> Этот метод запускает отдельные проверятели-правил.


Мне посоветовали в прошлом треде сделать главный класс и классы-проверятели (проверка на пустоту, на количество и т.д.).

Вот смотри, чтобы использовать твой класс, мы должны написать:

$validator = new Validator($rules, $enrollee, $errors);
$validator->carryOutVerification();

Зачем здесь вызов carryOutVerification? Ты мог бы его сразу вписать в конструктор, чтобы он вызывался автоматически.

Правда это будет далеко от ООП. Тебе надо пойти одним из 2 путей:

В ООП-стиле:

// создаем валидатор, который можно многократно использовать
$validator = new Validator($rules);
// используем
$errors = $validator->validate($enrollee);
// используем еще раз
$errors2 = $validator->validate($enrollee2);

В процедурном стиле:

$errors = validate($rules, $enrollee);

Но твой стиль просто выглядит странно и нелогично. Непонятно, зачем вызывать функцию, в которую ничего не передается и которая ничего не возвращает.
253 2945253
>>2944192

>>ты передаешь в конструктор студента для проверки


> Я отдал его в конструктор, потому что думал, что если для работы Валидатора нужен объект другого класса, то я должен добавлять зависимости через конструктор, а не отдавать объекты в методы.



Ну ок, значит я плохо написал статью про DI и запутал. Обычно под "зависимостями" понимают другие сервисы. Например, если валидатору нужен лезть в базу данных, то можно передать в него объект для работы с БД как зависимость.

Студент не является зависимостью, он является объектом, который валидатор обрабатывает. Как и список ошибок - это не зависимость, а результат обработки студента.

Более того, в твоем случае еще плохо то, что студент содержит данные из формы, а в DI контейнер не должны попадать такие данные (так как он может создаваться и заполняться до обработки формы).

То есть, в ООП мы передаем студента в метод проверки, и он возвращает список ошибок (желательно объектом).

А вот правила можно передавать 2 способами:

- в конструктор
- в метод проверки

Разберем оба варианта:

1) правила передаются в конструктор. В этом случае правила получаются как бы "заложены" в объект валидатора, и их нельзя поменять (можно только создать еще один валидатор). Но зато тому, кто использует валидатор, не нужно знать эти правила:

// в DI контейнере
// создаем валидатор и закладываем в него правила
// я называю его studentValidator, чтобы показать, что он
// предназначен только для валидации студента и ничего больше
$studentValidator = new Validator($rules);

// если мы хотим проверять что-то еще, то мы должны создать отдельный
// объект-валидатор с другим набором правил

// где-то далеко в другом месте кода, где надо проверить студента
$errors = $studentValidator->validate($enrollee);

Здесь правила заложены в объект. Плюс в том, что когда мы хотим проверить студента, нам не надо знать правила: мы получаем уже объект с встроенными в него правилами.

2) правила передаются в метод проверки

Здесь плюс в том, что одним валидатором можно проверять разные вещи, а минус в том, что теперь тот, кто хочет проверить что-то, должен знать правила. Если мы делаем проверку в нескольких местах, у нас может получиться, что правила будут дублироваться в несколькоих местах кода, что очень плохо.

// в DI контейнере создаем универсальный валидатор
$validator = new Validator();

// в другом месте кода используем его
$erros = $validator->validate($enrollee, $rules);

Вот такие 2 варианта обычно используют в ООП. Такой подход очень часто встречается:

- создаем объект и в конструктор передаем параметры, настройки объекта, которые не меняются
- затем используем объект, передавая данные (сущности, числа, строки) в метод и возвращая из них результат
253 2945253
>>2944192

>>ты передаешь в конструктор студента для проверки


> Я отдал его в конструктор, потому что думал, что если для работы Валидатора нужен объект другого класса, то я должен добавлять зависимости через конструктор, а не отдавать объекты в методы.



Ну ок, значит я плохо написал статью про DI и запутал. Обычно под "зависимостями" понимают другие сервисы. Например, если валидатору нужен лезть в базу данных, то можно передать в него объект для работы с БД как зависимость.

Студент не является зависимостью, он является объектом, который валидатор обрабатывает. Как и список ошибок - это не зависимость, а результат обработки студента.

Более того, в твоем случае еще плохо то, что студент содержит данные из формы, а в DI контейнер не должны попадать такие данные (так как он может создаваться и заполняться до обработки формы).

То есть, в ООП мы передаем студента в метод проверки, и он возвращает список ошибок (желательно объектом).

А вот правила можно передавать 2 способами:

- в конструктор
- в метод проверки

Разберем оба варианта:

1) правила передаются в конструктор. В этом случае правила получаются как бы "заложены" в объект валидатора, и их нельзя поменять (можно только создать еще один валидатор). Но зато тому, кто использует валидатор, не нужно знать эти правила:

// в DI контейнере
// создаем валидатор и закладываем в него правила
// я называю его studentValidator, чтобы показать, что он
// предназначен только для валидации студента и ничего больше
$studentValidator = new Validator($rules);

// если мы хотим проверять что-то еще, то мы должны создать отдельный
// объект-валидатор с другим набором правил

// где-то далеко в другом месте кода, где надо проверить студента
$errors = $studentValidator->validate($enrollee);

Здесь правила заложены в объект. Плюс в том, что когда мы хотим проверить студента, нам не надо знать правила: мы получаем уже объект с встроенными в него правилами.

2) правила передаются в метод проверки

Здесь плюс в том, что одним валидатором можно проверять разные вещи, а минус в том, что теперь тот, кто хочет проверить что-то, должен знать правила. Если мы делаем проверку в нескольких местах, у нас может получиться, что правила будут дублироваться в несколькоих местах кода, что очень плохо.

// в DI контейнере создаем универсальный валидатор
$validator = new Validator();

// в другом месте кода используем его
$erros = $validator->validate($enrollee, $rules);

Вот такие 2 варианта обычно используют в ООП. Такой подход очень часто встречается:

- создаем объект и в конструктор передаем параметры, настройки объекта, которые не меняются
- затем используем объект, передавая данные (сущности, числа, строки) в метод и возвращая из них результат
254 2945268
>>2944192

>>Ты достаешь предудущую ошибку, склеиваешь с ней новую и записываешь обратно.


> Я так сделал, потому что иначе бы один текст ошибки перекраивал другой.


> Ну, да ладно.



Ты поместил этот код не туда, куда нужно. Хранение ошибок это задача объекта СписокОшибок, и код склеивания должен быть в нем. Это не сфера ответственности валидатора, решать, как склеивать ошибки. Он лишь добавляет их в список. А список уже решает, что с ними сделать.

> Я должен переписать класс с текстом ошибок.


> Добавить в него метод, чтобы он...сам клал значения ошибок и склеивал их.



Да.

> Нет пока что привычки добавлять все это



Самое время завести привычку.

> Как не обращусь с вопросом, так сразу неправильно у меня все.



Радуйся, тебя учат и дают новые знания, причем бесплатно.

> Начинаю вместо кода сидеть думать как правильно строить классы.



Так как ты начинающий, то ты перед написанием кода как раз должен был на листочке или на экране расписать структуру приложения: какие классы в нем есть, за что каждый отвечает и как они взаимодействуют. То есть, ты об этом и должен был думать с самого начала.

> ведь мне не хватает знаний и опыта, чтобы понять



Учись задавать вопросы и спрашивать, что непонятно.
254 2945268
>>2944192

>>Ты достаешь предудущую ошибку, склеиваешь с ней новую и записываешь обратно.


> Я так сделал, потому что иначе бы один текст ошибки перекраивал другой.


> Ну, да ладно.



Ты поместил этот код не туда, куда нужно. Хранение ошибок это задача объекта СписокОшибок, и код склеивания должен быть в нем. Это не сфера ответственности валидатора, решать, как склеивать ошибки. Он лишь добавляет их в список. А список уже решает, что с ними сделать.

> Я должен переписать класс с текстом ошибок.


> Добавить в него метод, чтобы он...сам клал значения ошибок и склеивал их.



Да.

> Нет пока что привычки добавлять все это



Самое время завести привычку.

> Как не обращусь с вопросом, так сразу неправильно у меня все.



Радуйся, тебя учат и дают новые знания, причем бесплатно.

> Начинаю вместо кода сидеть думать как правильно строить классы.



Так как ты начинающий, то ты перед написанием кода как раз должен был на листочке или на экране расписать структуру приложения: какие классы в нем есть, за что каждый отвечает и как они взаимодействуют. То есть, ты об этом и должен был думать с самого начала.

> ведь мне не хватает знаний и опыта, чтобы понять



Учись задавать вопросы и спрашивать, что непонятно.
255 2945278
>>2944281

Это плохо работает, лучше сразу учиться писать правильно. А то по твоей логике ему сначала надо Битрикс освоить, прежде чем за фреймворки браться.
256 2945310
>>2944356

> Моделирует "модель".



Этот термин вызывает непонимание:

1) есть domain model - ООП-модель предметной области из кучи классов, связанных стрелочками. Domain model обозначает не один класс, а все вместе.

2) есть model в MVC - это не только сущности, но и вообще весь код с бизнес-логикой. Я пробовал поискать определение, но гуглить такие темы бесперспективная задача. В Вики, например, написано:

> It is the application's dynamic data structure, independent of the user interface. It directly manages the data, logic and rules of the application. In Smalltalk-80, the design of a model type is left entirely to the programmer. With WebObjects, Rails, and Django, a model type typically represents a table in the application's database.



Тут видны противоречия: сначала написано, что в модели содержится "data. login and rules", а потом пишется что в Django модель просто представляет таблицу в БД. Таблица это не то же самое, что data, logic and rules.

В статье Microsoft написано лучше:

> An MVC model contains all of your application logic that is not contained in a view or a controller. The model should contain all of your application business logic, validation logic, and database access logic.



То есть, модель в MVC (по мнению автора) это не просто класс User, а еще куча сервисов для работы с ним. Тут я согласен.

3) многие PHP-разработчики традиционно понимают под "моделью" класс с SQL-запросами к таблице (TableDataGateway), который принимает и возвращает сложные массивы с данными

Поэтому я стараюсь этот термин не использовать вообще, так как он 100% вызовет у начинающего путаницу. Если у тебя есть идеи, какой термин использовать для классов с данными, то предлагай. Если у тебя есть ссылка на справочник где даны четкие и строгие определения (не как в Википедии) - давай.
257 2945333
>>2944356

Вот вообще, ты хорошо критикуешь, но плохо предлагаешь. А я ведь не против улучшить статьи, использовать более точные термины и определения.

> Сущность противопоставляется не сервису, а классу который полностью определяется его данными. Как адрес или дата.



Это ValueObject. Получается, у нас тогда как минимум 3 вида классов: сервисы,сущности и value objects. Но мы все равно можем разбить их на 2 группы: классы с данными без DI и классы с операциями, как правило, использующие DI (вопреки идее ООП, что данные и операции должны быть объединены в одном классе).

> И пользователь и его адрес это модель, и пользователь и адрес хранятся в базе в отдельных таблицах. Только пользователь это сущность, а адрес нет.



А по определению из статьи Entity-Relational Diagram адрес тоже сущность:

> An entity may be defined as a thing that is capable of an independent existence that can be uniquely identified, and is capable of storing data



Адрес существует сам по себе? Конечно. Есть id? Конечно. Хранит данные? Да.
258 2945356
>>2944447

У меня одна просьба ко всем: прежде чем отправлять в Гугл, воспользуйся им сам.

Проблема статей по программированию в Интернете в том, что они:

- часто недостаточно технические и не рассказывают нужные подробности и детали, а просто дают совет в стиле "скопируйте этот код"
- иногда предполагают обширные знания и не рассчитаны на новичков
- часто неточные, некачественные, устаревшие (особенно по PHP таких много)
- используют плохие подходы
- часто не на русском

Ну например, я написал статьи на codedokode/pasta именно потому, что по этим темам не смог ничего нормального найти. Если бы там были нормальные статьи, я бы просто давал на них ссылки, а не писал сам.

Ну например, попробуй погуглить куки и получишь статьи такого уровня: https://skillbox.ru/media/marketing/vsye-chto-nuzhno-znat-o-faylakh-cookie-v-odnoy-state/

А я ждал техническое объяснение: рисунок, на котором показано, как они передаются и хранятся; рисунок, где они показаны в HTTP-запросе и ответе; как их просмотреть в curl и в браузере; какие у кук есть атрибуты; лучшие практики по безопасности; функции для работы с куками.

И чтобы это было понятно начинающему и на русском. Вот такие статьи я хочу в Гугле видеть на первой странице.

Или другой пример, гуглим MVC и вверху выдачи переоптимизированный мусор от хекслета, который тут рекламируют каждый тред: https://ru.hexlet.io/blog/posts/chto-takoe-mvc-rasskazyvaem-prostymi-slovami

В статье написано:

> На сервере Хекслета ваш запрос обрабатывается. Программа достаёт из базы данных все последние тексты из рубрики «Истории успеха», чтобы показать список. Это можно сравнить с кухней и поварами из примера с сэндвичем. Это модель.



А затем в примерах кода модель у них состоит из одной сущности:

> Модель отвечает за данные, которые хранятся и обрабатываются на сервере.



> User: { userName: { firstName, lastName }, friends }



ну вот такого качества статьи заполняют первые страницы Гугла. Прежде чем отправлять в Гугл, проверь результат сам. Или пиши волшебный запрос, который дает нормальные статьи.
258 2945356
>>2944447

У меня одна просьба ко всем: прежде чем отправлять в Гугл, воспользуйся им сам.

Проблема статей по программированию в Интернете в том, что они:

- часто недостаточно технические и не рассказывают нужные подробности и детали, а просто дают совет в стиле "скопируйте этот код"
- иногда предполагают обширные знания и не рассчитаны на новичков
- часто неточные, некачественные, устаревшие (особенно по PHP таких много)
- используют плохие подходы
- часто не на русском

Ну например, я написал статьи на codedokode/pasta именно потому, что по этим темам не смог ничего нормального найти. Если бы там были нормальные статьи, я бы просто давал на них ссылки, а не писал сам.

Ну например, попробуй погуглить куки и получишь статьи такого уровня: https://skillbox.ru/media/marketing/vsye-chto-nuzhno-znat-o-faylakh-cookie-v-odnoy-state/

А я ждал техническое объяснение: рисунок, на котором показано, как они передаются и хранятся; рисунок, где они показаны в HTTP-запросе и ответе; как их просмотреть в curl и в браузере; какие у кук есть атрибуты; лучшие практики по безопасности; функции для работы с куками.

И чтобы это было понятно начинающему и на русском. Вот такие статьи я хочу в Гугле видеть на первой странице.

Или другой пример, гуглим MVC и вверху выдачи переоптимизированный мусор от хекслета, который тут рекламируют каждый тред: https://ru.hexlet.io/blog/posts/chto-takoe-mvc-rasskazyvaem-prostymi-slovami

В статье написано:

> На сервере Хекслета ваш запрос обрабатывается. Программа достаёт из базы данных все последние тексты из рубрики «Истории успеха», чтобы показать список. Это можно сравнить с кухней и поварами из примера с сэндвичем. Это модель.



А затем в примерах кода модель у них состоит из одной сущности:

> Модель отвечает за данные, которые хранятся и обрабатываются на сервере.



> User: { userName: { firstName, lastName }, friends }



ну вот такого качества статьи заполняют первые страницы Гугла. Прежде чем отправлять в Гугл, проверь результат сам. Или пиши волшебный запрос, который дает нормальные статьи.
259 2945361
>>2944697

Тред специально для этого создан.
260 2945364
>>2944937

1) документация
2) туториалы типа SymfonyCasts и ответы на SO
3) чтение исходного кода
261 2945367
Стоит ли перекатываться в Go, или на пыхе збс?
262 2945371
>>2945198

Так читай документацию, вот примеры ссылок по разным копонентам:

- конфиги https://symfony.com/doc/current/configuration.html
- контейнер https://symfony.com/doc/current/service_container.html
- контроллеры https://symfony.com/doc/current/controller.html

и тд
263 2945424
>>2945219

>задача про ООО Вектор, ты ее делал?


Да.

>Она вроде как должна помогать разобраться в ООП.


Когда я впервые читал урок из мануала про ООП, для меня понятия "свойство", "метод", "тайп-хинт",
"модификаторы доступа" и т.д. воспринимались чем-то абстрактным, я не мог усвоить их как само собой разумеющееся.
Раздел с тайп-хинтом я вообще пробежал глазами и решил забыть о нем, потому что тогда ничего не понял, но сейчас уже понимаю.
Так что думаю, прогресс есть.

>Если ты не разберешься с основами (ООП), как ты пойдешь дальше? Это как пропустить основы арифметики и браться сразу за матрицы и векторы.


Здесь я имел ввиду то, что, мне кажется, что я занимаюсь перфекционизмом в решении этой задачи.
Чего я должен добиться этим? Сейчас сесть и с нуля научиться проектировать системы так, как это делают люди с опытом?
Мне кажется, что я много на себя пытаюсь взять. Я понимаю, что от джуна будут требовать понимание основ ООП.
Но ведь от него не будут требовать идеального проектирования системы? Просто мне кажется, что я ухожу не туда.
Мне просто нужно усвоить основы. А что делаю я? Учусь на проектировщика систем?
Я думаю, что мне нужно получить некий базис, который позволит мне кодить.
А потом одни знания лягут на другие и те знания, которые были в тумане, усвоятся.
264 2945440
>>2945229
Окей, спасибо за ответ.
>>2945232

>Зачем здесь вызов carryOutVerification? Ты мог бы его сразу вписать в конструктор, чтобы он вызывался автоматически.


Действительно. Я в таком ключе не думал.

>$errors = $validator->validate($enrollee);


Не понимаю эту строку.
Что из себя представляет $errors и что в таком случае будет возвращать $validator->validate($enrollee)?
И если errors - это объект, то какое у него будет содержание?
265 2945493
>>2945253
Хорошо, я понял.
266 2945513
>>2945268

>Радуйся, тебя учат и дают новые знания, причем бесплатно.


Если ты думаешь, что я негодую от того, что мои решение (лучше сказать - попытки реализовать то, что тут советуют) считают неправильными, то это не так. Я всегда прихожу в тред с пониманием, что я неправ. Мб мои формулировки звучат нагло, но ими я пытаюсь донести какое представление о предмете находится у меня в голове. Я никогда не пытаюсь ничего доказать.
Я очень благодарен всем, кто давал мне толковый совет или объяснение.
267 2945815
>>2945310

>есть domain model


Что значит "есть"? Есть подход "domain model development", который основан на выделении "domain" - "предметной области" и моделировании её. Делается это определенным образом с соблюдением определенных правил. Сущность это часть понятийного аппарата DDD. Термин вырван из контекста (лол) и используется как баззворд.

>есть model в MVC - это не только сущности, но и вообще весь код с бизнес-логикой.


Ты опять описал domain model.

>Я пробовал поискать определение, но гуглить такие темы бесперспективная задача.


А спорить в интернете - перспективная.
В смаллтолк MVC это observer паттерн, который отслеживает изменения в объектах представления. Джаваскрипт, который ловит события типа нажатий на кнопки это оно.
Ко временам джанго и рельс модель из MVC путем баззвординга и непонимания концепта превратилась в "данные между веб запросами". А определение, которое ты считаешь "лучше" совсем бессмыслица, потому что слишком широкое. Согласно этому определению роутинг - часть модели. Потому что содержит логику, валидирует ввод и доступ. При этом роутинг по определению происходит перед контроллером. Чушь и бессмыслица.

>Поэтому я стараюсь этот термин не использовать вообще, так как он 100% вызовет у начинающего путаницу.


Поэтому ты используешь вместо этого термины с другим значением и определением, из других областей и подходов. И никакой путаницы нет, все четко. Ну тут не доебешься, продолжай. Всем все понятно.
268 2945863
>>2945333

>классы с данными без DI и классы с операциями, как правило, использующие DI (вопреки идее ООП, что данные и операции должны быть объединены в одном классе).


Даже я хуй пойму что тут написано. Опять все смешалось.

1) Наличие "данных" ничего не говорит о том является ли объект сущностью. Что является чем диктует исключительно предметная область. Логика работы сервиса вполне может храниться в базе, но сущностью сервис от этого не станет. Так же и адрес не станет сущностью если добавить ему идентификатор. Как только улицу переименуют, все объекты с этой улицей придется изменить одинаковым образом и похуй сколько там идентификаторов.

2) "Объекты с данными" вполне себе могут использовать DI. У них точно так же есть конструктор, и точно так же можно передать зависимость в вызываемый метод. Да, инъекция через метод это тоже DI
269 2945964
>>2945815

>"domain model development"


"domain driven development" офк
270 2946065
>>2944937
Попробуй курс Елисеева навернуть, symfonycast'ы, нагуглить курс отуса мб слили уже
271 2946235
Так,я не тот анон что два дня тут ставит ларавель, но я близок к нему как никогда

есть вариант создать дефолтную пхп.ини?
(не копируя из инета)
272 2946247
>>2946235
Правильно. Копирование - это воровство.
273 2946263
>>2946247
Ну ладно, я хуйню написал и пхп.ини-дев - это норма, пишут что ее просто переименовывают в .ини и не ебут мозги себе
Но вообще, вы все из исходников собираете? Или не страдаете хуйней такой

Чет у меня то расширения при сборке не ставятся, то десять каких-то либ нехватает. А мануала норм свежего не нашел. В итоге 8.1 поставил через апт,лол
274 2946265
>>2946263
А хотя нашел через рра 8.3
Мдауж
275 2946269
>>2946263
Ини, хуини. Все это уже сто лет как ставится через докер. У меня на работе проектов двадцать, и у каждого какая-то особая версия и либы. Какой еблан будет с этим вручную морочиться?
BUS1x.png343 Кб, 1200x395
276 2946270

>1к+ вакансий на БУС


>меньше 100 откликов на каждой


>зарплаты ниже "трушных фрейворков" всего на 20-30%


>вкатыши продолжают катиться в ларабэль (200-500 откликов на каждой, зп не сильно выше, требований больше, много где требуют vue)


Ебало? Имагине? Вкатышей?
277 2946271
>>2946270
Вкатыши на ларабель жрут яблоки и получают не сильно выше зп.
Битриксоиды жрут кал и получают не сильно меньше зп.
Ебало? Имагине?
278 2946273
>>2946271
Будешь и там и там рыться и мучительно разбираться что и как. Из плюсов битрикса: больше работы, много интересных проектов, много смежных технологий (nodejs, laravel).
never-give-up-bitrix.png1,5 Мб, 2799x1649
279 2946274
>>2946273

>Из плюсов битрикса: больше работы, много интересных проектов


Это типа как сметана на говне?
280 2946307
Почему пхпшторм всегда по умолчанию на пятой версии пхп?
281 2946402
>>2946273
>>2946270
На битриксе работаешь?
282 2946406
>>2946270
Ты пробовал с этой парашей работать?
283 2946493
TL;DR: Если подразумевается, что у свойства есть метод для валидации значения, должен ли он вызываться внутри сеттера? Или я в коде должен делать что-то типа if (валидно) { вызвать_сеттер }?

Есть свойство класса, которое, как я знаю, может быть в определённом интервале. Ну, допустим, Yoba::$age, и я знаю, что это целое число 0 < $age < 101
Я добавляю метод Yoba::validateAgePretendent(), который, собственно, выполняет эту проверку.
Вопрос - как быть с Yoba::setAge()? Нужно ли добавлять в него валидацию? Или нет? Или сделать ещё метод типа Yoba::safeSetAge(), который и проверяет значение, и присваивает его?

У меня мысли такие. Наиболее правильно никак сеттер не менять, а обёртку Yoba::safeSetAge() добавлять в случае нужды, если в десяти местах у меня будут появляться

if ($yobaObj->validateAgePretendent($value)) { $yobaObj->setAge($value) }

С одной стороны, в 99.99% случаев, Yoba::$age должен проходить мою валидацию. С другой стороны, а вдруг нет? Вдруг будет какая-то ситуация, которую я не предусмотрел, и в которой такой-то объект на такое-то время должен иметь $age, не вписывающийся в этот диапазон? Если я добавлю проверку в сеттер, то я не смогу этого сделать.

Хотя, я вот сейчас это написал и задумался. Есть же проверка типов в php, $age это, положим, int. И я никак не смогу присвоить $age значение 12.3, будет TypeError. Ибо нехуй. Вот и присваивать $age значение, которое не проходит валидацию, нехуй. Если возникла такая ситуация, значит, валидация кривая и нужно её редактировать.

Короче, хуй пойми. Как делать, чтобы сеньоры говорили малаца?
284 2946653
>>2946493
Погуглив и подумав, начал склоняться к варианту, в котором проверка значения выполняется внутри сеттера. Ещё такой аргумент есть - а нафиг тогда сеттер вообще нужен? Если всё, что он делает и я как бы ожидаю, что будет делать всегда - возвращает значение, то почему бы не сделать свойство public и не редактировать напрямую? Сеттер затем и нужен, что подразумевает возможность добавить валидацию или ещё что-нибудь.
285 2946821
>>2946653
В свойство может прилететь некорректное значение и из-за ошибки в коде программы. Если оно изменяется только через сеттер, то в сеттере можно делать проверку входящего значения и сразу выдавать исключение, если оно некорректное.
286 2946953
>>2946493
Геттеры, сеттеры какие-то. Ты ооп код пишешь или че? Объектами надо мыслить и типами. https://3v4l.org/WksJS#v8.2.13
287 2947152
>>2946953
Это троллинг, или я должен упороться и под каждое валидируемое свойство класса добавлять по ещё 3 класса?
288 2947197
>>2947152
Не "класса", а типа. И в чем проблема? Тебе все равно эти функции писать придется. Если ты пишешь ооп код, так и пиши его в виде взаимодействия объектов. А если пишешь процедурную дрисню, так нахуя тебе тогда все эти di заморочки, модели какие-то.
289 2947277
>>2947197
https://3v4l.org/7ldLa

Сравни количество кода. Это что, в тру-ООП скалярные типы вообще идут нахуй?
290 2947314
>>2947277

>Это что, в тру-ООП скалярные типы вообще идут нахуй?


Ты хотел в нормальном ооп языке? >>2936382

>Сравни количество кода.


Какой же кал, пиздец.
1) Метод setAge не знает каким образом происходит валидация, но с какого-то хуя формирует текст ошибки.

2) Метод ageIsValid не имеет никакого отношения к Yoba. Вынеси его отдельно и он будет точно так же работать.

3) Какого хуя вообще можно поменять возраст? Ты блядь не можешь себе поменять возраст и купить пива, это не так работает.

4) Даже допустим возраст можно менять. Кто это блядь такой умный что этот возраст меняет? Кто вызывает setAge?
cmIDhTR.jpeg60 Кб, 765x208
291 2947382
>>2947314

>1) Метод setAge не знает каким образом происходит валидация, но с какого-то хуя формирует текст ошибки.


Это для примера. На деле, там будет скорее throw new ValidationFailedException, который уже формирует текст.

>Метод ageIsValid не имеет никакого отношения к Yoba. Вынеси его отдельно и он будет точно так же работать.


И? Это плохо? Предпочтительней было бы переписать это как-то так? https://3v4l.org/GCRfZ

>3) Какого хуя вообще можно поменять возраст? Ты блядь не можешь себе поменять возраст и купить пива, это не так работает.


>4) Даже допустим возраст можно менять. Кто это блядь такой умный что этот возраст меняет? Кто вызывает setAge?


Пикрелейтед.
292 2947385
>>2947382
Микрофикс, ageValidate должен тогда void возвращать, забыл исправить. Ну, это ничего не меняет фактически.
293 2947406
>>2947382

>переписать это как-то так?


Теперь этим методом можно провалидировать только возраст Yob'ы, а возраст Zalup'ы нельзя. И залупе придется писать свой валидатор.

>Пикрелейтед.


Ты либо пишешь "модель", которая должна соответствоавть моделируемуму, любо просто какой-то код и тогда вообще похуй как оно там написано.
Точно так же, ты либо пишешь ооп код и тогда ты соблюдаешь все эти инкапсуляции сингл респонсибилити итд, либо катаешься ебалом по клавиатуре и тебе все это не надо.

Это ведь ты выбрал писать "модель" в ооп стиле. Ну так пиши. Не хочешь - не пиши.
294 2947591
Двач, как научиться читать код на абстракциях? Вот мне дали ебаный DDD, решил поправить роутик, ну по классике зашел в экшен, а этот ебаный экшн вызвает формы, те еще какую-то хуйню, а те еще какую-то залупу, а те еще что-то. Репозитории, формы, dto, провайдеры, entity и прочая хуета. Пока пройдешься по цепочке, забудешь к хуям вообще все. По классике никаких комментов в коде нет, сам разбирайся. В итоге горбатюсь над заданием уже 2-й день. Как вообще такое понимать и читать?
295 2947600
>>2947591
Никакого отношения к DDD то что ты описал не имеет.
296 2947889
php лудши питона? проще изучить набор необходимых штук чтоб устроутся на работу?
297 2947963
>>2947889
Нахуй пшел
298 2947966
>>2947963
иди
299 2948003
>>2947889
Нет
300 2948014
>>2947889

PHP более веб ориентированный чем питон, так шо мне больше нравицо. А так похуй один хуй две скриптовые залупы
301 2948021
>>2947889
Для веба на пхп вроде больше вакансий чем на питоне.
На питоне не малая часть вакансий это ии, дата саенс, машин ленин, но это для математиков, а не макак
302 2948038
>>2947963
Двачую адеквата
303 2948046
>>2948038
>>2947963
Сёма, успокойся
304 2948052
>>2945424

> Здесь я имел ввиду то, что, мне кажется, что я занимаюсь перфекционизмом в решении этой задачи.


> Чего я должен добиться этим? Сейчас сесть и с нуля научиться проектировать системы так, как это делают люди с опытом?



Задача учит использованию ООП, работе с базой данных, формами, генерации HTML-страниц через шаблоны. Все это нужно в реальной работе.

Я думаю, что джун должен сразу писать правильный ООП-код. Или ты предполагаешь, что джун может писать как попало, а потом сеньор будет сидеть за него все исправлять? Никто джуна обучать заново не будет, его просто уволят с испытательного и скажут идти читать книжки.
305 2948070
>>2945440

> >$errors = $validator->validate($enrollee);


> Не понимаю эту строку.


> Что из себя представляет $errors и что в таком случае будет возвращать $validator->validate($enrollee)?


> И если errors - это объект, то какое у него будет содержание?



О, хороший вопрос и по делу.

Раз у нас ООП то $errors это объект, который представляет (и хранит в себе) список ошибок валидации студента. Но почему только ошибки валидации студента? Давай обобщим, $errorList это объект класса ErrorList, который способен хранить список ошибок валидации любого объекта.

У ErrorList есть такие методы:

- добавить ошибку к заданному полю (например: добавить ошибку "использованы недопустимые символы" к полю "имя")
- получить список всех ошибок для поля
- узнать, пуст ли список ошибок или в нем есть ошибки

Вот как он используется:

$errorList = new ErrorList(); // создали пустой список

Что касается ошибки, то одну ошибку мы могли бы представить строкой:

$errorList->add('name', 'использованы недопустимые символы');

Метод add тогда выглядит так:

add(string $field, string $error): void

Это допустимо, но тут недостаточно ООП. Чтобы его было больше, будет представлять ошибки тоже объектом:

$errorList->add('name', new Error('использованы недопустимые символы'));

add(string $field, Error $error): void

Плюс использования класса Error такой:

- мы можем делать не просто текстовые ошибки, а ошибки с подробностями, например, с подсказками или еще какими-то дополнительными свойствами

- в тайп-хинте функций очевидно, что они принимают именно ошибку, а не любую строку
305 2948070
>>2945440

> >$errors = $validator->validate($enrollee);


> Не понимаю эту строку.


> Что из себя представляет $errors и что в таком случае будет возвращать $validator->validate($enrollee)?


> И если errors - это объект, то какое у него будет содержание?



О, хороший вопрос и по делу.

Раз у нас ООП то $errors это объект, который представляет (и хранит в себе) список ошибок валидации студента. Но почему только ошибки валидации студента? Давай обобщим, $errorList это объект класса ErrorList, который способен хранить список ошибок валидации любого объекта.

У ErrorList есть такие методы:

- добавить ошибку к заданному полю (например: добавить ошибку "использованы недопустимые символы" к полю "имя")
- получить список всех ошибок для поля
- узнать, пуст ли список ошибок или в нем есть ошибки

Вот как он используется:

$errorList = new ErrorList(); // создали пустой список

Что касается ошибки, то одну ошибку мы могли бы представить строкой:

$errorList->add('name', 'использованы недопустимые символы');

Метод add тогда выглядит так:

add(string $field, string $error): void

Это допустимо, но тут недостаточно ООП. Чтобы его было больше, будет представлять ошибки тоже объектом:

$errorList->add('name', new Error('использованы недопустимые символы'));

add(string $field, Error $error): void

Плюс использования класса Error такой:

- мы можем делать не просто текстовые ошибки, а ошибки с подробностями, например, с подсказками или еще какими-то дополнительными свойствами

- в тайп-хинте функций очевидно, что они принимают именно ошибку, а не любую строку
306 2948079
>>2945815

Я тебе хотел просто сказать, что слово "модель" ассоциируется с несколькими терминами и сбивает начинающих, если они пытаются его гуглить. Поэтому я не хочу его использовать.

Ну то есть ты хочешь называть сущности "модель", но "модель" более широкое понятие и включает в себя и сервисы для обработки сущностей.

Также, судя по датам, понятие domain model старше чем DDD: оно упоминается в книге Фаулера от 2003 года. И MVC старше, чем DDD.

> А определение, которое ты считаешь "лучше" совсем бессмыслица, потому что слишком широкое. Согласно этому определению роутинг - часть модели. Потому что содержит логику, валидирует ввод и доступ. При этом роутинг по определению происходит перед контроллером. Чушь и бессмыслица.



Модель содержит бизнес-логику приложения. Роутинг это не бизнес-логика, а техническая штука.
307 2948083
>>2945863

Хорошо, предложи свои, "правильные" термины для обозначения классов, которые представляют какую-то сущность, и классов с операциями.
308 2948101
>>2946493

Есть 2 подхода:

1) в объекте не может быть невалидных значений ни при каких условиях. В этой ситуации мы ставим проверку в сеттер и при нарушении правил выкидываем исключение и роняем всю программу. Зато мы знаем, что в объекте правильные данные.

Тут надо учесть, что при создании объекта в нем изначально должны быть правильные данные. Это может потребовать ставить значения по умолчанию или передавать значения в конструктор.

2) в объекте могут быть невалидные значения, например, потому что они пришли от пользователя. Тогда мы принимаем все, но перед использованием объекта или записью в БД проверяем валидатором.

То есть, либо мы проверяем значения в момент записи, либо позже, перед использованием. Минус второго способа в том, что можно забыть сделать проверку, а в первом способе у нас просто не существует неправильных объектов. Минус первого способа в том, что он плохо сочетается с формами, так как в форму можно вводить неправильные значения.

Как не надо делать: при передаче неправильного значения просто не сохранять его и ничего не делать. Это самый плохой подход, так как ошибки в коде будут оставаться незамеченными.
309 2948103
>>2946653

> Если всё, что он делает и я как бы ожидаю, что будет делать всегда - возвращает значение, то почему бы не сделать свойство public и не редактировать напрямую? Сеттер затем и нужен, что подразумевает возможность добавить валидацию или ещё что-нибудь.



Да. Даже если тебе не нужна сегодня проверка, то она может понадобиться завтра и с сеттером тебе не придется переписывать пол-программы из-за этого.

Но есть и другой подход, например, в Питоне: там используют свойство напрямую, без сеттера. А если нужно добавить какую-то логику, то там используют магию и добавляют функцию, которая автоматически вызывается при изменении поля. Ну то есть по сути это тот же сеттер, только он вызывается при записи в поле. Просто синтаксис другой, а суть та же.
310 2948113
>>2946953

Вот ты предлагаешь интересные вещи, но ничего не поясняешь,а здесь ведь начинающие сидят.

>>2947152

Это паттерн ValueObject. Идея в том, что значение представлено в виде объекта. То есть, у тебя возраст имеет не тип int, а тип Age. Минусы:

- код увеличивается

Плюсы:

- мы можем с помощью тайп-хинтов указать, что в функцию можно передать только Возраст, а не вообще любое число. Это повышает читабельность и защищает от ошибок
- мы можем добавить в значение дополнительные поля

Вот пример: допустим, у тебя приложение работает с деньгами в разных валютах. И появяется риск, что ты сложишь рубли с долларами по ошибке. Ты можешь защититься от этого, представив деньги в виде объекта Money с полями "сумма" и "валюта":

$tenRoubles = new Money(10, Money::RUB);
$twoRoubles = new Money(2, Money::RUB);
echo ($tenRoubles->add($twoRoubles)->format()); // 12 руб

Так как мы заменили число на объект, теперь для сложения надо использовать метод add, а он проверяет, что суммы в одной валюте. Также, если функция принимает деньги, то это очевидно из тайп-хинта и ничто другое туда не передать (защита от ошибок):

function addToAccount(Money $sum) { ... }

Но я думаю, что делать типы вроде "имя", "возраст" - это уже перебор. Хотя идея интересная.

Но в задаче про студентов все же есть места для ValueObject. Пол и место жительства желательно сделать с помощью Enum (перечислений). Это по сути и есть ValueObject.
310 2948113
>>2946953

Вот ты предлагаешь интересные вещи, но ничего не поясняешь,а здесь ведь начинающие сидят.

>>2947152

Это паттерн ValueObject. Идея в том, что значение представлено в виде объекта. То есть, у тебя возраст имеет не тип int, а тип Age. Минусы:

- код увеличивается

Плюсы:

- мы можем с помощью тайп-хинтов указать, что в функцию можно передать только Возраст, а не вообще любое число. Это повышает читабельность и защищает от ошибок
- мы можем добавить в значение дополнительные поля

Вот пример: допустим, у тебя приложение работает с деньгами в разных валютах. И появяется риск, что ты сложишь рубли с долларами по ошибке. Ты можешь защититься от этого, представив деньги в виде объекта Money с полями "сумма" и "валюта":

$tenRoubles = new Money(10, Money::RUB);
$twoRoubles = new Money(2, Money::RUB);
echo ($tenRoubles->add($twoRoubles)->format()); // 12 руб

Так как мы заменили число на объект, теперь для сложения надо использовать метод add, а он проверяет, что суммы в одной валюте. Также, если функция принимает деньги, то это очевидно из тайп-хинта и ничто другое туда не передать (защита от ошибок):

function addToAccount(Money $sum) { ... }

Но я думаю, что делать типы вроде "имя", "возраст" - это уже перебор. Хотя идея интересная.

Но в задаче про студентов все же есть места для ValueObject. Пол и место жительства желательно сделать с помощью Enum (перечислений). Это по сути и есть ValueObject.
311 2948116
>>2946953

У твоего подхода есть недостаток: ты совместил Возраст и Правила проверки возраста в одном объекте. Представь, что у нас кроме абитуриентов будут еще бакалавры и магистры и у них тоже есть Возраст, но с другими ограничениями. Твой подход не сработает.

Также, зачем ты ставишь скобки после class не по PSR. Ставь нормально и не сбивай людей с толку.
312 2948119
>>2947314

Ты ударяешься в крайности. В реальном коде нужны как мутабельные, так и иммутабельные объекты. На мой взгляд, неправильно требовать, чтобы все было иммутабельно. Это неудобно, так как если у тебя есть например 10 ссылок на один иммутабельный объект, то для изменения данных тебе надо поменять их в 10 местах.

Данные могут меняться. В случае с возрастом - абитуриент мог ошибиться при вводе и хочет исправить это.
313 2948121
>>2947591

Прочти книгу по DDD может быть? Ну или выясни, какой архитектурный паттерн используется и прочти документацию по нему.
314 2948123
>>2948038

Двачую адвоката.
1 315 2948301
Сап хпх хочу вкатиться в пхп есть шансы в 2023
316 2948320
>>2948301
Шансы есть всегда
317 2948327
Какого хуя я уже в третий раз устроился PHP-разрабом, но 90% тасок снова на фронтенд (Vue)?
318 2948390
>>2948327
Фуллстек - это латентный фронтендер
319 2948464
>>2948301
Есть шанс что ты сломаешься и в итоге уйдешь на битрикс как большинство вкатунов
320 2948478
>>2948390
Так я уже стал чисто экспертом по нему. Пиздец.
321 2948481
>>2948478
Это плохо?
322 2948492
>>2948481
Ну я просто изначально в бекенд метил, но сильно перекосило в сторону нюхта и вуе. Единственное, что меня удерживает от вакансий чистого фронта - это ебануштейший отбор и собеседования
323 2948504
>>2948492
В смысле? Ты же эксперт уже. Давно работаешь?
324 2948540
>>2948079

>Ну то есть ты хочешь называть сущности "модель", но "модель" более широкое понятие и включает в себя и сервисы для обработки сущностей.


А я тебе сказал что тебе в твоей терминологии не нужен термин "сущность". Ты все равно используешь его неправильно. Достаточно просто различать классы по их названию и назначению. С тем же успехом ты мог бы говорить: вот этот объект кирпичик, а вот этот сервис, не перепутай. А если перепутаешь, то что? Да ничего. От того что он кирпичик тебе ни жарко ни холодно.

>Также, судя по датам


>гуглить такие темы бесперспективная задача



>Модель содержит бизнес-логику приложения. Роутинг это не бизнес-логика, а техническая штука.


Да ну? Права доступа это не бизнес логика? Параметры ссылки это не бизнес логика?

>>2948083

>термины для обозначения классов, которые представляют какую-то сущность


Классы не представляют никакой сущности. У тебя есть "модель" реального мира, именно по параметру "моделирования" мы и отличаем этот набор объектов от любого другого. Отличать их между собой никакого практического смысла нет. В DDD они отличаются именно из-за способа моделирования. Нет способа - нет отличий.

>>2948113

>Это паттерн ValueObject.


Это паттерн Object. Ну знаешь, из ооп. Ты инкапсулируешь поведение, а система типов гарантирует правильность программы. Оо "ебать его в сраку" п.

>будут еще бакалавры и магистры и у них тоже есть Возраст, но с другими ограничениями. Твой подход не сработает.


И что же мне помешает держать одни ограничения в одном месте, а другие в другом? Тупость?

>Также, зачем ты ставишь скобки после class не по PSR. Ставь нормально и не сбивай людей с толку.


Я делаю это чтобы листинг уместился на один экран. И вообще в 2к23 форматирование это ебля того кому не нравится формат. Отформатируй и перепости - помоги людям не сбиваться с толку. Делов-то - ctrl alt L нажать.

>Данные могут меняться. В случае с возрастом - абитуриент мог ошибиться при вводе и хочет исправить это.


Модель мутабельна когда мы моделируем смену возраста и иммутабельна когда мы моделируем как студень чешет нос. Легко и просто. Железная гарантия что при прикосновению к носу яйца не отвалятся.

Короче все. Завязываем бессмысленный срач. Никакой полезной нагрузки он не несет. "Учиться" чему-то в таком формате невозможно, а писать простыни текста мне впадлу.
324 2948540
>>2948079

>Ну то есть ты хочешь называть сущности "модель", но "модель" более широкое понятие и включает в себя и сервисы для обработки сущностей.


А я тебе сказал что тебе в твоей терминологии не нужен термин "сущность". Ты все равно используешь его неправильно. Достаточно просто различать классы по их названию и назначению. С тем же успехом ты мог бы говорить: вот этот объект кирпичик, а вот этот сервис, не перепутай. А если перепутаешь, то что? Да ничего. От того что он кирпичик тебе ни жарко ни холодно.

>Также, судя по датам


>гуглить такие темы бесперспективная задача



>Модель содержит бизнес-логику приложения. Роутинг это не бизнес-логика, а техническая штука.


Да ну? Права доступа это не бизнес логика? Параметры ссылки это не бизнес логика?

>>2948083

>термины для обозначения классов, которые представляют какую-то сущность


Классы не представляют никакой сущности. У тебя есть "модель" реального мира, именно по параметру "моделирования" мы и отличаем этот набор объектов от любого другого. Отличать их между собой никакого практического смысла нет. В DDD они отличаются именно из-за способа моделирования. Нет способа - нет отличий.

>>2948113

>Это паттерн ValueObject.


Это паттерн Object. Ну знаешь, из ооп. Ты инкапсулируешь поведение, а система типов гарантирует правильность программы. Оо "ебать его в сраку" п.

>будут еще бакалавры и магистры и у них тоже есть Возраст, но с другими ограничениями. Твой подход не сработает.


И что же мне помешает держать одни ограничения в одном месте, а другие в другом? Тупость?

>Также, зачем ты ставишь скобки после class не по PSR. Ставь нормально и не сбивай людей с толку.


Я делаю это чтобы листинг уместился на один экран. И вообще в 2к23 форматирование это ебля того кому не нравится формат. Отформатируй и перепости - помоги людям не сбиваться с толку. Делов-то - ctrl alt L нажать.

>Данные могут меняться. В случае с возрастом - абитуриент мог ошибиться при вводе и хочет исправить это.


Модель мутабельна когда мы моделируем смену возраста и иммутабельна когда мы моделируем как студень чешет нос. Легко и просто. Железная гарантия что при прикосновению к носу яйца не отвалятся.

Короче все. Завязываем бессмысленный срач. Никакой полезной нагрузки он не несет. "Учиться" чему-то в таком формате невозможно, а писать простыни текста мне впадлу.
325 2948600
>>2948052

>Я думаю, что джун должен сразу писать правильный ООП-код


Я с тобой полностью согласен.
Я имел ввиду глубину знаний.
Я себе представляю так, что от джуна требуется определенная глубина знаний в каждом из вопросов.
Просто из этой задачи я ушел куда-то в чтение проектирование систем. Тут еще советуют какое-то DDD. Короче. У меня сложилось впечатление, что я пытаюсь копать так глубо, сколько не требуется пока что от джуна. Я думаю, что знания должны накладываться слоями. От простого к сложному. И для того, чтобы усвоить определенные знания, человек должен быть готов.
Он должен обладать такими знаниями, которые позволят ему понять новое знание.
326 2948634
>>2948070
Окей.
Я это понял так:
Класс errorList состоит из:
Свойств (например, name, surname)
Трех методов, 2 из которых работают с отдельными полями, а один - со всеми.
Что в таком случае класс Error?
Судя по инструкции создания объекта, в конструктор передается строка с описанием ошибки, значит у него есть какое-то поле, которое хранит ошибку.
А что если поле не прошло валидацию сразу по нескольким правилам? В конструкторе должен быть метод, которые берет текст ошибки (которую отдали в параметры конструктора) и склеивает его с другими текстами ошибок, а потом кладет в значение поля?
Спасибо, что отвечаешь мне.
327 2948678
>>2948634
Я тут еще подумал.
Вернемся немного назад.
Мы обсуждали метод класса Validator - carryOutVerification().
Насколько я понял, в теле этой функции нужно вызывать метод класса ErrorList - add().
Касаемо последнего твоего ответа, я снова запутался.
Что все-таки означает строка $error = $validator->validate($enrollee)?
Просто у меня есть такое представление на задворках ума, что
carryOutVerification() ничего не будет возвращать.
Т.е. где-то будет инструкции:
$errorList = new ErrorList;
$validator = new Validator(...);
И потом, возможно, это будет в коде контроллера, инструкция:
$validator->carryOutVerification();
Я руководствуюсь тем, что объект всегда передается по ссылке.
А значит зачем функции что-то возвращать, если она может сложить результат своей работы в объект, предварительно взяв его?
Я не понимаю эту строку "$error = $validator->validate($enrollee)", потому что не понимаю что она возвращает.
Ведь validate это и есть carryOutVerification?
Эта часть "$error =" означает, что в переменную что-то кладется, но что?
Вообще. У меня большая проблема с пониманием того, что и где будет в коде.
Например, с тем же DIContainer. В каком файле я буду описывать регистрацию сервисов? Это лишь пример, чтобы показать, что я пока что не понимаю где какая будет инструкция.
Не знаю, поймешь ли ты меня, я столько каши понаписал.
изображение.png4 Кб, 508x222
328 2948708
>>2947406
Проспавшись и пробздевшись, я, кажется, начал понимать, о чём ты говоришь. >>2948113 Этот помидор подтвердил мои догадки. В таком случае, я бы завёл

class Age

И там внутри уже пердолил всякие проверки и т. д. В данном же случае, Yoba - условно не делим. При большом желании можно, конечно, но зачем? На практике, там не число, а строка определённого формата. И, собственно, класс, в моём примере обозначенный Yoba, и нужен лишь для того, чтобы хранить эту строку определённого формата и не давать его нарушать.

То есть, твои ValidAge NotValidAge ValidateAge - более заёбная правильная наверное реализация того, чем является класс Yoba. А твой User, это, по сути, не мой Yoba, а тот, одно из свойств которого - объект Yoba.

Если следовать твоему пути, то должно получиться вообще как-то так, насколько я понимаю: https://3v4l.org/pJbBI#v8.3.0

>>2948116
Не понял, что у меня не PSR?

>>2948119
Прикольно вы придумали, что я задался этим вопросом в процессе решения какой-то задачи про студентов.

Только ещё вопрос. Я нуб и как-то вообще пропустил момент, это что? Область видимости для аргументов метода? Как оно работает? По каким словам гуглить?
изображение.png172 Кб, 1091x885
329 2948712
>>2948708
А, понял, в 8 появилось. Да, читаю пхпнет на русском, с ебалом всё в порядке.
330 2948713
>>2945253
Я тут еще подумал.
Да. Я сейчас понял, что я снова забыл, что Студент и Список ошибок - не зависимости.
Значит нужно выкинуть их из полей Validator?
Я думаю, строку $error = $validator->validate($enrollee)
Нужно понимать так:
error - переменная, которая будет хранить ссылку на объект.
validate возвращает объект.
331 2948735
>>2948634
Зависимостью называется не любой класс, а только класс из другого модуля. Если оба класса часть "модели" то это не зависимость. Модель не может зависеть сама от себя.
332 2948754
>>2948713

Список ошибок не надо передавать в валидатор. Валидатор сам создаст его и заполнит по итогам проверки.

Ну подумай сам: мы вызываем валидатор, даем ему студента, он нам взамен возвращает список найденных ошибок. Зачем список ошибок передавать в валидатор? Зачем он нужен валидатору? Наоборот, логично: пока мы не передадим студента, мы не получим список ошибок. Нет другого способа его получить (разве что создать и заполнить самому, увы, в PHP это запретить пока что нельзя).

Ты наверно это придумал после чтения статьи про DI. Но в DI мы передаем в конструктор классы-сервисы, настройки, опции. Список ошибок это просто данные, и валидатор его создает сам. У нас также нет нужны подменять список ошибок на что-то другое, и передавать его в конструктор нам не нужно.

Что касается устройства списка, не надо делать в нем никакие поля. Сделай просто массив для хранения ошибок. Тогда у тебя получится универсальный список ошибок, который не только для студентов годится, а для любых других объектов.
333 2948798
>>2948754
Это другой анон или тот же?
А то я начинаю путаться в этом обсуждении.
334 2948809
>>2948735

>из другого модуля


Что такое модуль?
Что такое модель?
Можешь привести примеры в контексте этой задачи?
335 2948852
>>2948464
Что плохого в битрикс?
336 2948899
>>2948852
Все. Архитектура, производительность, коммьюенити, проекты
337 2948903
>>2948852
Ну мне так в треде сказали: >>2940690
15715500756040.webm1,2 Мб, webm,
450x360, 0:58
338 2948911
>>2948809
Так какого хуя ты лезешь в архитектуру если определений не знаешь?
Если ты не умеешь писать код. Не знаешь БАЗУ. То какого хуя ты лезешь туда, куда не каждый мидл полезет?
never-give-up-bitrix.png1,5 Мб, 2799x1649
339 2948917
340 2948942
>>2948911
Я и не собирался лезть в архитектуру, когда начинал решать эту задачу.
Но написав код, я понял, что у меня получается хуйня. И мало того, что хуйня, так мне стало трудно ориентироваться в этой хуйне.
С этого момента и начались эти темы про проектирование, архитектуру.
А вопросы о том, что такое модель и модуль я задал для того, чтобы сообщение, которое написал мне анон, имело для меня практический смысл. Зачем писать что-то человеку так, как он не поймет?
341 2948951
>>2948917
Нифига не понял что написано в коде
342 2948953
>>2948942
У всех хуйня и всем трудно. Начинать надо сначала.
1) Ты не умеешь писать код, никакой, не только ооп.
2) Ты не знаешь базовых определений.
3) Вместо того чтобы нормально учиться ты впитываешь шизоидный поток сознания на двачах.
343 2948954
>>2948951
Конкретно, какой кусок ты не понял?
344 2948959
>>2948953

>Ты не умеешь писать код, никакой, не только ооп.


Да.
И я учусь.
И все эти тупые вопросы, которые я задаю в треде - часть обучения.

>Ты не знаешь базовых определений.


Да, не знаю.

>Вместо того чтобы нормально учиться ты впитываешь шизоидный поток сознания на двачах


Что такое шизоидный поток сознания на двачах?
Что такое нормально учиться?
345 2949002
>>2948959

>И все эти тупые вопросы, которые я задаю в треде - часть обучения.


Если ты получаешь правильные ответы или вообще получаешь вменяемые ответы. Если ты понимаешь что в этих ответах сказано.

>Что такое шизоидный поток сознания на двачах?


Тред, в котором неколько человек одновременно спорят друг с другом в твит формате. Да еще и с рассинхроном больше чем в сутки. Даже человеку, который и так все знает, нужно прилагать большие усилия чтобы просто понять с кем и о чем он пытается говорить.

>Что такое нормально учиться?


Иметь нормальный, последовательный план обучения. Ты в универе учился? Или хотя бы в шараге?
346 2949029
>>2949002

>Ты в универе учился? Или хотя бы в шараге?


По программированию - нет.

>Иметь нормальный, последовательный план обучения.


Какой бы ты список тем для меня составил?
Звучит нагло, но если у тебя есть желание поделиться опытом - можешь написать. Я приму его к сведению и попробую сопоставить с моей организацией обучения.
Сейчас я занимаюсь так:
4 часа на задачу Список Студента (из-за того, что я не решил все вопросы с одним аноном из треда я занимаюсь тем же, чем занимаюсь следующие 4 часа)
4 часа на чтение материала по роад карте.
Вот такое обучение...
Еще я начал читать книгу СИКП.
347 2949057
>>2949029

>По программированию - нет.


Нет никакой разницы.

>Какой бы ты список тем для меня составил?


И как ты себе это представляешь? За несколько минут составить нормальную программу обучения для незнакомого человека, который несколько лет хуй пойми чем занимался. Так не бывает.

>Сейчас я занимаюсь так:


>4 часа на задачу Список Студента


Ты занимаешься хуйней. Если бы ты по четыре часа в сутки писал код всю последнюю неделю, то у тебя была бы сотня вариантов одной только валидации.
348 2949062
>>2949057

>И как ты себе это представляешь? За несколько минут составить нормальную программу обучения для незнакомого человека, который несколько лет хуй пойми чем занимался. Так не бывает.


Да нет, хотя бы набросать список направлений куда смотреть.
Ну да, я виноват, использовал слово "темы".
Ты пишешь "ты не умеешь писать код". Окей. Я согласен с тобой.
В каком направлении мне смотреть, чтобы исправить это?

>Ты занимаешься хуйней. Если бы ты по четыре часа в сутки писал код всю последнюю неделю, то у тебя была бы сотня вариантов одной только валидации.


Ну, мб и хуйней.
В эти 4-ре часа входят не только написание кода, но и разбор ответов с двача, касаемо этой задачи (Да-да, иногда мозги так не работают, что приходится читать-перечитывать), разбор чужого кода (который кидают в треде), чтение статей (связанных с вещами, о которых я должен знать, чтобы решить задачу). Ты можешь сказать, что и это хуйня. Ну, мне и похуй. Я занимаюсь так, как могу.
349 2949087
>>2949062

>Я занимаюсь так, как могу.


Ты просто делаешь вид что занимаешься, вот и все. Это такой способ развлечься на двачах. Только вот анонам ты не рассказал что просто убиваешь время и они всерьез пытаются тебе что-то объяснить. Я тебе предлагал заняться обучением всерьез, но ты сказал "пук среньк".
350 2949100
>>2949087

>Ты просто делаешь вид что занимаешься


Считай так.
Я не преподаватель, чтобы уметь грамотно организовывать учебу.
Если нет варианта лучше чем тот, что уже есть - я остаюсь заниматься по старому методу. Этим я руководствуюсь, когда планирую свое обучение.

>Я тебе предлагал заняться обучением всерьез, но ты сказал "пук среньк".


Если голосом будешь говорить один ты, то, окей, я согласен. Мне голосом говорить нечего. Мои бе-ме вряд-ли тебе хочется слушать. В тексте можно подумать, выбрать формулировку, а в голосе?
351 2949228
>>2948754

>Тогда у тебя получится универсальный список ошибок, который не только для студентов годится, а для любых других объектов.


Почему бы тогда не сделать интерфейс для класса ErrorList?
352 2949229
>>2949228
Или наследование.
353 2949264
>>2948754

>Что касается устройства списка, не надо делать в нем никакие поля. Сделай просто массив для хранения ошибок.


Я не понимаю что это означает.
С тем аноном у нас два класса, связанные с ошибками - ErrorList и Error.
У ErrorList не будет полей name, surname и т.д., а будет одно поле-массив, где ключ - название поля, а элемент - ссылка на объект Error?
Или же ErrorList вообще не класс, а массив?
354 2949277
>>2948070
Вот, посмотри, я дописал классы, которые мы с тобой обсуждали.
Это черновой вариант.
Я не оттачивал его.
Потому что у меня не варит голова.
Да и не все я уточнил у тебя.
https://3v4l.org/ElabY
355 2949280
>>2949277
Ты можешь написать мне, в том ли направлении я тебя понимаю или нет.
Если не в том, то что конкретно исправить и почему.
Если где-то забыл тайп-хинт или перепутал что-то в цикле, то извиняюсь, я хотел лишь в общих чертах набросать то, что мы с тобой обсуждали.
Проверять и исправлять все то, что я там написал, я планирую завтра, на свежую голову.
356 2949373
>>2948320
переформулирую вопрос
реально ли
хочу стэк пхп лар
357 2949384
>>2949373
Да ты заебал, нам откуда знать вкатишься ты или нет?
358 2949404
>>2932466 (OP)
Сап. Работаю бэк разрабом. Есть задание, при определенных действиях удалить все бонусные карты пользователя и создать для него новую. Сперва я хотел создать запрос на удаление всех бонусных карт. Старший разраб сказал, что не все так просто из-за обмена. Из-за этого мы поднимемся на этаж выше, устроим созвон с 1сниками. Я не совсем понял, что за проблема может быть с обменом? Что это значит?
359 2949418
>>2949384
ты тупой, насколько рынок перегрет пхпшниками, например во фронте макак куча
360 2949436
>>2949373
На норм фреймворк только с накрученным опытом
1501643180175359565.jpg26 Кб, 300x400
361 2949444
>>2949404
Посадят тебя на пикрелейтед стул, и начнут спрашивать что такое модель и модуль. Ответишь неправильно - отдадут тебя 1сникам.
362 2949454
>>2949436
Волк-конкурент, спокуха
363 2949738
>>2949454
И в чем я не прав?
364 2949819
Напомните как устроить взлом жопы пхпшторму
365 2949843
>>2949819
создаешь новый аккаунт
@
делоешь пробный период
366 2949880
>>2949819
В прошлых 2-3 тредах было погугли. Если не найдешь, иди на главный торрент-трекер страны, там в комментариях на последних страницах описан способ
367 2949885
368 2950115
У меня есть абстрактный класс AAA. От него наследуются XXXXXX YYYYYY ZZZZZZ. В классе AAA определён метод, который делает примерно следующее:

public function foo () {
echo $this->editable;
}

Свойство $editable у каждого дочернего класса имеет своё значение, у AAA его, по сути, быть не должно, в этом нет смысла. При этом, значение не изменяется и задаётся в коде класса.

Вопрос - как это правильно сделать? По сути, мне нужна абстрактная константа. Чтобы я в AAA её объявил, а в детях задал её значения. Но абстрактных констант в PHP нет.

Или факт того, что я в AAA объявляю метод, который рассчитан на "$this->editable", который в AAA вообще не имеет смысла, а смысл имеет лишь в его детях, в принципе неадекватен? И правильнее скопипастить этот одинаковый метод в каждом из детей?
369 2950190
>>2950115

>Но абстрактных констант в PHP нет.


https://3v4l.org/lgNfS
370 2950254
>>2949264
А зачем делать отдельные поля?
371 2950316
>>2950190
Забываешь добавить Bar::TEST, скрипт не показывает никаких ошибок. Чисто технически, мне полностью подходит объявление в родительском-абстрактном классе абстрактного метода типа:

abstract public function returnConst (): string;

А у детей:

public function returnConst (): string {
return "const-value-1";
}

И т. д. Если забудешь у ребёнка объявить returnConst(), интерпретатор тебе на это моментально пожалуется. Но это отдаёт какими-то костылями, я использую метод там, где по сути нужна константа. Это наталкивает меня на мысль о том, что я вообще херню какую-то горожу, раз нормальными средствами это не делается. Или нет, и ситуация, в которой родительский класс оперирует какими-то значением, которое будет определено в его дочерних классах, это вполне нормально?

https://3v4l.org/Uo2fh#v8.3.0

Вот, гляньте. Оно работает ровно так, как мне надо. Но с семантической точки зрения как будто пиздец, гвоздь забиваю микроскопом. Или всё нормально?
372 2950350
>>2950316
Ну и что ты хочешь услышать? Да, технически это работает. Есть ли какие-то другие варианты? А как блядь об этом узнать если ты не рассказываешь что ты пытаешься сделать, а постишь какие-то невнятные иксы и игреки.
373 2950358
>>2950350
Хочу услышать:

1. Выглядит ли код, который я скинул, как хтонический пиздец, или ничего особо криминального в нём нет.
2. Насколько адекватна ситуация, когда в коде РОДИТЕЛЬСКОГО абстрактного класса используется какое-то значение, которого в этом классе нигде нет. И весь расчёт на то, что оно должно быть объявлено в НАСЛЕДНИКЕ этого класса.

Говорю же, меня напрягает отсутствие абстрактных свойств в PHP. Какие причины для их отсутствия? Просто не завезли, или указание на то, что я хочу чего-то неадекватного?
374 2950392
>>2949819
если не забуду скину
375 2950394
>>2950358
А я тебе ответил. Что если у тебя вариантов нет, то какя хуй разница как оно выглядит, вариантов то нет. А понять какие у тебя варианты можно только если ты объяснишь что пытаешься сделать.
По сути ты показал код и спросил: "как мне сделать? так? или угадай как?"

>Говорю же, меня напрягает отсутствие абстрактных свойств в PHP.


А где они есть? В шарпе? А еще?
376 2950430
>>2950394
У меня есть как минимум два варианта.
1. Забить гвоздь микроскопом. Иди сделать всё чётко. Хуй знает, ты не оцениваешь адекватность моего варианта.
https://3v4l.org/CRNMZ#v8.3.0
2. В родителе объявить функцию как абстрактную, и потом реализовать её для каждого ребёнка. Получится копипаст, потому что содержание этой функции у разных детей отличается натурально одним параметром.
https://3v4l.org/t2mUm#v8.3.0
377 2950463
>>2950430
Ты нахуя используешь абстрактный класс вообще? Чтобы вынести в него повторяющийся код. В одном примере повторяющегося кода нет, в другом есть. Вот и все.

Однако если поведение хотя бы в одном наследнике хотя бы немного начнет отличаться, то придется заново выделять повторяющуюся часть и делать рефакторинг.

И если бы ты не вел себя как баран и привел реальный пример, то можно было бы определить возможные подводные камни. А твои высосанные из пальца синтетические умозрительные конструкции специально подстроены под конкретную ситуацию и ни о чем не говорят. "на 100% одинаков" ага, верю.
378 2950478
Пхпшники, вас часто валят литкодом на собеседованиях? Меня ещё ни разу

мимо фуллстек
379 2950622
>>2950463
Ты чё выёбываешься?

> В одном примере повторяющегося кода нет, в другом есть


Ага, poshatatMakabu() и goToMailRu() это не повторяющийся для всех дочерних классов код. Нахуй там вообще нужен абстрактный класс-родитель? Действительно.

> Однако если поведение хотя бы в одном наследнике хотя бы немного начнет отличаться, то придется заново выделять повторяющуюся часть и делать рефакторинг


Так, блядь, оно и отличается. Отличается одной строчкой (string). Значением одного аргумента, которые передаётся в вызываемую внутри функцию. Больше ничем отличаться не будет. Я либо копипащу этот метод в каждый дочерний класс, меняя одну единственную строчку (ещё раз: не строчку кода, а аргумент string, передающийся в одну из вызываемых внутри функций). Либо ссылаюсь на что-то, чего в родительском классе нет, но должно быть в дочернем. На какую-то константу, свойство, результат выполнения метода. И из этих вариантов третий как будто самый годный.
Константу я могу забыть объявить в дочернем классе, и узнаю об этом, только когда во время работы скрипта он дойдёт до этого момента и упадёт.
Со свойством аналогично. А ещё, чтобы его нельзя было менять по ходу работы скрипта, нужно попердолиться с readonly и добавлением его установки в конструктор. Иначе, существует теоретическая вероятность того, что можно по ошибке в процессе работы изменить значение этого свойства. А это не подразумевается.
Вот абстрактный метод, который просто возвращает значение - как бы заебись. Его точно не забудешь объявить у ребёнка, парсер сразу пожалуется. Возвращаемое им значение неизменно и задаётся в коде.
380 2950735
>>2950622

>Ты чё выёбываешься?


Ссу тебе в рот. Вопросы? Пожелания?
Ну и не рассказывай про свой супер секретный код. Кому он нахуй нужен.
381 2950862
Пхп тред... Здесь злые люди какие-то. Быдло и смерды

Мимо джентльмен из java
1626104.jpg41 Кб, 610x385
382 2950889
>>2950862
Скажи "Спринг круто!".
383 2951025
>>2948540

> Достаточно просто различать классы по их названию и назначению.



Нет, я вижу (в фрейморках, реальных проектах) что классы очень хорошо делятся на классы с данными и классы с операциями, и мне нужны названия для них. Как я без названий буду объяснять это начинающим?

> Да ну? Права доступа это не бизнес логика?


Права доступа проверяются обычно в контроллерах. Так-то это бизнес-логика, но удобнее проверять в контроллере.

> Параметры ссылки это не бизнес логика?


Строго говоря, нет. Бизнес-логика это логика вроде "пользователь должен иметь возможность заказать суши на дом", а не то, через какие параметры мы должны передать его адрес.
384 2951037
>>2948634

> Класс errorList состоит из:


> Свойств (например, name, surname)



Нет. Если ты к свойствам будешь обращаться как $this->$name, то тебе нужны не свойства, а массив.

К тому же, если ты пропишешь туда свойства, то класс сможет хранить только ошибки для студента. А если сделаешь массив, то он сможет вообще для любых полей любого класса хранить ошибки.

Просто делаем массив вида array<string, Error[]> (то есть массив с ключом-именем поля и содержимым в виде массива Error).

> Что в таком случае класс Error?



Класс, представляющий одну ошибку. Хранит ее текст и, может быть, какие-то дополнительные подробности.

> А что если поле не прошло валидацию сразу по нескольким правилам?



Именно поэтому в списке ошибок мы храним для каждого поля не одну ошибку, а массив. Не надо ничего склеивать.
385 2951046
>>2948678

> Просто у меня есть такое представление на задворках ума, что carryOutVerification() ничего не будет возвращать.



Список ошибок это результат работы функции валидации. Для возврата результатов в PHP есть инструкция return. Зачем делать какие-то обходные способы, когда ты передаешь будущий результат в один метод, а потом другой метод его заполняет. Это же просто нелогично и запутывает при чтении кода.

То, что нужно функции, передается через аргументы. Результат работы возвращается через return.

> Я не понимаю эту строку "$error = $validator->validate($enrollee)", потому что не понимаю что она возвращает.



Объект класса ErrorList со списком найденных ошибок (объектов Error).

> Например, с тем же DIContainer. В каком файле я буду описывать регистрацию сервисов? Это лишь пример, чтобы показать, что я пока что не понимаю где какая будет инструкция.



Это зависит от того, как ты реализуешь DI: будешь писать сам или возьмешь готовый. Я покажу 2 варианта самодельных DI:

1) делаем класс с 2 методами: описать сервис и получить сервис. Выглядит это так:

$container = new Container();
// регистрируем сервис, то есть, описываем как его создать
// в качестве имени сервиса используем имя класса
$container->register(SomeService::class, fn () => new SomeService(1, 2, 3));
// в другом месте получаем сервис по имени
$svc = $container->get(SomeService::class);

Обрати внимание, что для любителей создавать контейнеры есть рекомендация PSR-11: https://www.php-fig.org/psr/psr-11/ . Наверно, стоит ей следовать в таком случае.

2) делаем не по PSR: делаем класс, в котором для получения каждого сервиса сделан свой метод

class Container
{
public function getSomeService(): SomeService
{
// создаем или возвращаем ранее созданный объект
return $this->createOrReturn(fn() => new SomeService(1, 2, 3));
}
}

Минус - здесь все сервисы захардкожены в классе. Плюс - простота и хорошая поддержка типизации (у каждого метода указан тип возврата).
385 2951046
>>2948678

> Просто у меня есть такое представление на задворках ума, что carryOutVerification() ничего не будет возвращать.



Список ошибок это результат работы функции валидации. Для возврата результатов в PHP есть инструкция return. Зачем делать какие-то обходные способы, когда ты передаешь будущий результат в один метод, а потом другой метод его заполняет. Это же просто нелогично и запутывает при чтении кода.

То, что нужно функции, передается через аргументы. Результат работы возвращается через return.

> Я не понимаю эту строку "$error = $validator->validate($enrollee)", потому что не понимаю что она возвращает.



Объект класса ErrorList со списком найденных ошибок (объектов Error).

> Например, с тем же DIContainer. В каком файле я буду описывать регистрацию сервисов? Это лишь пример, чтобы показать, что я пока что не понимаю где какая будет инструкция.



Это зависит от того, как ты реализуешь DI: будешь писать сам или возьмешь готовый. Я покажу 2 варианта самодельных DI:

1) делаем класс с 2 методами: описать сервис и получить сервис. Выглядит это так:

$container = new Container();
// регистрируем сервис, то есть, описываем как его создать
// в качестве имени сервиса используем имя класса
$container->register(SomeService::class, fn () => new SomeService(1, 2, 3));
// в другом месте получаем сервис по имени
$svc = $container->get(SomeService::class);

Обрати внимание, что для любителей создавать контейнеры есть рекомендация PSR-11: https://www.php-fig.org/psr/psr-11/ . Наверно, стоит ей следовать в таком случае.

2) делаем не по PSR: делаем класс, в котором для получения каждого сервиса сделан свой метод

class Container
{
public function getSomeService(): SomeService
{
// создаем или возвращаем ранее созданный объект
return $this->createOrReturn(fn() => new SomeService(1, 2, 3));
}
}

Минус - здесь все сервисы захардкожены в классе. Плюс - простота и хорошая поддержка типизации (у каждого метода указан тип возврата).
386 2951049
>>2948678

> В каком файле я буду описывать регистрацию сервисов?



Для варианта с PSR-11 контейнером- можно в bootstrap-файле или в подключаемом из него файле. Для варианта 2 - прямо в классе-контейнере.
387 2951065
>>2948708

У него идея, что для представления возраста используется не 1, а сразу 2 класса: ValidAge с гарантированно валидным содержимым и NotValidAge с невалидным. И ты можешь с помощью тайм-хинтов просто запретить передавать невалидный возраст в функцию.

Хотя мне нравится использование типов для защиты от ошибок, но мне кажется, тут не очень удачно это придумано.
388 2951067
>>2948798

Тут минимум 2 человека тебе отвечает + иногда случайно заскочившие аноны.
389 2951078
>>2948540

Вот кстати, если тебе неохота, как ты выражешься, писать "простыни текста", то можно же скидывать сюда ссылки на голосовые сообщения через какой-нибудь сервис (только без регистрации плиз и чтобы запись не исчезала через день). Я без проблем их прослушаю, и анон, который учится, думаю, тоже.
390 2951079
>>2949228

Потому, что у нас всего одна реализация и больше не планируется.

Например, что касается классов-правил валидации, у нас их много и можно дописывать новые. Нам надо как-то объяснить людям, как добавлять эти правила. Тут явно нужен интерфейс.

А список ошибок у нас один, и другие нам не понадобятся. Поэтому для него не нужен интерфейс или наследование.
391 2951080
>>2949264

Будет поле типа: array<string, list<Error>>. Для каждого поля мы храним массив объектов Error.

Если тебе непонятен синтакис, то можно посмотреть тут: https://psalm.dev/docs/annotating_code/type_syntax/array_types/
392 2951086
>>2951078
Пчел. Просто создай канал в дискорде и не еби мозги. За пол часа можно обсудить больше чем тут за две недели написано. Записывай, хоть обзаписвайся если тебе это надо.
393 2951087
>>2949277

- добавляй тайп-хинты везде, где можно, чтобы я мог быстрее читать и понимать твой код и все другие, кто его увидит, тоже.

- так как PHP не позволяет описывать структуру массива в тайп-хинте, будет здорово, если ты научишься описывать ее через phpDoc и расширенные аннотации отсюда https://psalm.dev/docs/annotating_code/type_syntax/array_types/

> Код этой функции тоже черновой, потому что я пока что не думал куда всунуть строку "$errorList = new ErrorList;"



С этой строкой все нормально, не надо ничего в ней менять, разве что скобки добавить для конструктора, так как в PSR это требуется.

> foreach ($this->rules as $key => $value)


Надо использовать нормальные имена, а не key/value

> if (empty($result)==false) {


empty очень общая штука, лучше писать более конкретную проверку, вроде $result !== null

> $errorList->add($key);


$errorList->add($key, $error);

> use Getter;


use принято писать в начале описания класса

ErrorList я бы сделал массивом, так как ты к полям обращаешься только через $this->$field, то есть ты с ними работаешь, как с массивом. Но твой вариант конечно тоже можно оставить, только тогда правильнее класс назвать EnrolleeErrorList, то есть не универсальный список ошибок, а список ошибок только для студентов.

> //Я сделал эту функцию приватной, потому что подумал, что она нужна только для работы errorListIsEmpty()



Тебе нужна еще функция для получения списка ошибок для вывода их в форме. Мы же добавляем ошибки, чтобы их выводить потом.
393 2951087
>>2949277

- добавляй тайп-хинты везде, где можно, чтобы я мог быстрее читать и понимать твой код и все другие, кто его увидит, тоже.

- так как PHP не позволяет описывать структуру массива в тайп-хинте, будет здорово, если ты научишься описывать ее через phpDoc и расширенные аннотации отсюда https://psalm.dev/docs/annotating_code/type_syntax/array_types/

> Код этой функции тоже черновой, потому что я пока что не думал куда всунуть строку "$errorList = new ErrorList;"



С этой строкой все нормально, не надо ничего в ней менять, разве что скобки добавить для конструктора, так как в PSR это требуется.

> foreach ($this->rules as $key => $value)


Надо использовать нормальные имена, а не key/value

> if (empty($result)==false) {


empty очень общая штука, лучше писать более конкретную проверку, вроде $result !== null

> $errorList->add($key);


$errorList->add($key, $error);

> use Getter;


use принято писать в начале описания класса

ErrorList я бы сделал массивом, так как ты к полям обращаешься только через $this->$field, то есть ты с ними работаешь, как с массивом. Но твой вариант конечно тоже можно оставить, только тогда правильнее класс назвать EnrolleeErrorList, то есть не универсальный список ошибок, а список ошибок только для студентов.

> //Я сделал эту функцию приватной, потому что подумал, что она нужна только для работы errorListIsEmpty()



Тебе нужна еще функция для получения списка ошибок для вывода их в форме. Мы же добавляем ошибки, чтобы их выводить потом.
394 2951088
>>2949404

Обмен это значит данные из вашей БД копируются в 1С и обратно. Может там к этим картам привязан бухучет (сколько денег потрачено на бонусы), ты их удалишь и у них баланс не сойдется. Глупо же.

Обычно такие данные не удаляют, а лишь скрывают.
395 2951091
>>2950115

Тебе не нужны поля. В базовом классе делай метод

abstract public function foo(): bool;

В наследнике делай метод

public function foo(): bool { return true; }

Вот и все.
396 2951092
>>2950316

Надо использовать абстрактный метод и не пытаться изобрести "абстрактные поля" (что?) или "абстрактные константы".

Также, базовый класс не имеет права обращаться к полям или методам, которых в нем нету, и которые будут добавлены только в наследниках.
397 2951095
>>2950358

> 2. Насколько адекватна ситуация, когда в коде РОДИТЕЛЬСКОГО абстрактного класса используется какое-то значение, которого в этом классе нигде нет. И весь расчёт на то, что оно должно быть объявлено в НАСЛЕДНИКЕ этого класса.



Выглядит как полное непонимание наследования. Так делать нельзя.

> напрягает отсутствие абстрактных свойств в PHP.



А в чем смысл абстрактного свойства. Ты говоришь: хочу, чтобы в каждом наследнике было свойство int $x. Ну так объяви его в базовом классе, зачем его копипастить в каждом наследнике?

А вот абстрактные методы нужны, так как они могут быть разными в каждом классе. Их и надо тут использовать.
398 2951102
>>2951086

Во-первых, тред и ответы в нем видны всем, он даже архивируется.

Во-вторых, в тред я прихожу когда удобно и никого не жду.

В-третьих, в реальном времени начинающему трудно все понять. Ему надо 10 раз погуглить, написать 3 неработающих варианта кода, прежде чем до него дойдет.

Просто если кому-то неохота писать, а удобнее голосом сказать, можно оставить голосовое сообщение.
399 2951150
Аноны, хелп. день мучаюсьпочему у меня на пике куча с глазами весь мой стиль на странице ломает?Я делал машинку все работало, а тут все супер плохоДаже если смайл не в контейнере держать все тоже самое будетCSS .line-container { display: flex; position: fixed;} .line_bottom { margin-top: %; width: %; height: px; background-color: rgb, , ;}.glass-line { position: relative; font-size: px; animation: tyda_suda s infinite alternate;}@keyframes tyda_suda { from { left: ; } to { left: %; }}HTML<div class="line_container" <div class="line_bottom" </div <div class="glass-line line-" &#xFA</div </div
400 2951154
>>2951102

>Во-первых, тред и ответы в нем видны всем, он даже архивируется.


Старая песня. Дискорд тоже видно всем и там тоже все архивируется. Создай свой канал и прилепи в шапку. Дело не в том кому что ты хочешь показать. Я тебе уже сказал - записывай и пости куда хочешь. Дело в соотношении "сигнал/мусор". У тебя треть поста состоит из цитат, треть ты не договариваешь потому что надо в абзац уложиться, а последнюю треть у тебя переспрашивают.

Средняя статья только по одной из тем в этом треде занимает несколько экранов текста и представляет из себя бедную выдержку из целой книги или даже нескольких. И это еще и в фрагментарном формате. Когда мы просто вываливаем на человека кусочек нашей картины мира, а он без понятия как эта картина сложилась. А потом он спрашивает как мне заинжектить сущность в сервис с помощью di. Совершенно не одупляя ни что такое сущность, ни что такое di, ни зачем вообще что-то куда-то инжектить.

Да чего далеко ходить. Прямо в предыдущем посте ты не понял смысл абстрактного свойства, то ли перепутав его с шизой про "только в наследнике" то ли еще почему. Хотя очевидно что было бы удобно иметь свойство объявленное в базовом классе и которое нужно обязательно переопределять в наследнике. Сколько времени пройдет пока вы просто поймете что хотели друг другу сказать в начале разговора? День? Два?

>Во-вторых, в тред я прихожу когда удобно и никого не жду.


Очень удобно. А главное столько времени сэкономил. Мне интересно сколько тредов эпопея с валидатором займет. Месяц он с ним сидит точно, может больше. Через пол года может выдаст что-то вменяемое. Такая-то учоба.

>В-третьих, в реальном времени начинающему трудно все понять.


Точно так же как и не в реальном. Только в реальном времени есть человек, который сразу уточнит, напишет сниппет, тыкнет пальцем в книгу, приведет пример. И не придется сидеть ждать до завтра чтобы еще раз переспросить, чтобы ты переспросил в ответ.

>Ему надо 10 раз погуглить, написать 3 неработающих варианта кода, прежде чем до него дойдет.


Опять же пусть сидит и гуглит при тебе, пока не дойдет как это правильно делать. Можешь ради интереса поспрашивать что по теме поста нагуглил "валидатор". Гарантирую - фейспалмом ебло разобъешь. То же самое с кодом. Ничего они не пишут, а мгновенно впадают в ступор. Нужно буквально за руку вести, пока они кода бояться перестанут. И нужно обязательно убедиться что он именно зашел в логический тупик, действительно столкнулся с проблемой. понял почему этот вариант не работает. А потом объяснить как этой проблемы избежать. Удачи сделать это в треде, особенно когда тебе даже реальный код не показывают, лол.

Говорил что не буду простыни писать, а в итоге опять насрал. В общем если ты настолько глупенький, что тебе все это нужно объяснять по пять раз, то все еще печальнее. В лучшем случае учеба будет проходить где-то параллельно с тредом. Имаджинировать лицо человека, который реально "учился" в этом потоке сознания лично я не могу.
400 2951154
>>2951102

>Во-первых, тред и ответы в нем видны всем, он даже архивируется.


Старая песня. Дискорд тоже видно всем и там тоже все архивируется. Создай свой канал и прилепи в шапку. Дело не в том кому что ты хочешь показать. Я тебе уже сказал - записывай и пости куда хочешь. Дело в соотношении "сигнал/мусор". У тебя треть поста состоит из цитат, треть ты не договариваешь потому что надо в абзац уложиться, а последнюю треть у тебя переспрашивают.

Средняя статья только по одной из тем в этом треде занимает несколько экранов текста и представляет из себя бедную выдержку из целой книги или даже нескольких. И это еще и в фрагментарном формате. Когда мы просто вываливаем на человека кусочек нашей картины мира, а он без понятия как эта картина сложилась. А потом он спрашивает как мне заинжектить сущность в сервис с помощью di. Совершенно не одупляя ни что такое сущность, ни что такое di, ни зачем вообще что-то куда-то инжектить.

Да чего далеко ходить. Прямо в предыдущем посте ты не понял смысл абстрактного свойства, то ли перепутав его с шизой про "только в наследнике" то ли еще почему. Хотя очевидно что было бы удобно иметь свойство объявленное в базовом классе и которое нужно обязательно переопределять в наследнике. Сколько времени пройдет пока вы просто поймете что хотели друг другу сказать в начале разговора? День? Два?

>Во-вторых, в тред я прихожу когда удобно и никого не жду.


Очень удобно. А главное столько времени сэкономил. Мне интересно сколько тредов эпопея с валидатором займет. Месяц он с ним сидит точно, может больше. Через пол года может выдаст что-то вменяемое. Такая-то учоба.

>В-третьих, в реальном времени начинающему трудно все понять.


Точно так же как и не в реальном. Только в реальном времени есть человек, который сразу уточнит, напишет сниппет, тыкнет пальцем в книгу, приведет пример. И не придется сидеть ждать до завтра чтобы еще раз переспросить, чтобы ты переспросил в ответ.

>Ему надо 10 раз погуглить, написать 3 неработающих варианта кода, прежде чем до него дойдет.


Опять же пусть сидит и гуглит при тебе, пока не дойдет как это правильно делать. Можешь ради интереса поспрашивать что по теме поста нагуглил "валидатор". Гарантирую - фейспалмом ебло разобъешь. То же самое с кодом. Ничего они не пишут, а мгновенно впадают в ступор. Нужно буквально за руку вести, пока они кода бояться перестанут. И нужно обязательно убедиться что он именно зашел в логический тупик, действительно столкнулся с проблемой. понял почему этот вариант не работает. А потом объяснить как этой проблемы избежать. Удачи сделать это в треде, особенно когда тебе даже реальный код не показывают, лол.

Говорил что не буду простыни писать, а в итоге опять насрал. В общем если ты настолько глупенький, что тебе все это нужно объяснять по пять раз, то все еще печальнее. В лучшем случае учеба будет проходить где-то параллельно с тредом. Имаджинировать лицо человека, который реально "учился" в этом потоке сознания лично я не могу.
13892160.png30 Кб, 800x600
401 2951158
>>2951150
Не мучайся, братишка. На - попустись.
402 2951159
>>2951150
Типичный битриксойд!
403 2951227
>>2951091
А если в foo() много кода, и этот код будет повторяться в каждом классе-наследнике, за исключением одного аргумента?

public function foo () {
someCode();
someCode2();
someCode3();
// ...
bar($this->editable); // $this->editable - единственная строка, которая будет различаться в реализациях разных классов
someCodeA();
SomeCodeB();
}
Пытался примерно отразить это здесь https://3v4l.org/CRNMZ#v8.3.0 только там всего два метода для демонстрации. Я, конечно, не говорю, что там огромный метод на тысячу строк на деле. Но строчек 50-100 есть. И это копипасть каждому классу-наследнику ради изменения одного string-аргумента, передаваемого в функцию?

>>2951095

> Выглядит как полное непонимание наследования. Так делать нельзя.


Вот меня что-то и напрягало. Ситуацию не спасает то, что класс-родитель - абстрактный? То есть, реализован объектом он быть не может.
Как ты прокомментируешь этот код: https://3v4l.org/obOn0#v8.3.0 ?
В родительском абстрактном классе вызывается свойство, которого он сам не содержит. Из расчёта на то, что оно есть в классе-наследнике. То, что я тут изобразил, не подходит мне по двум причинам:
1. Second::$foo не readonly, можно по ошибке в процессе выполнения изменить значение. Ок, допустим, readonly можно сделать. Тогда, правда, придётся инициализирующее значение задавать в конструкторе. Ведь я не могу сделать
private readonly string $baz = "42";
Будет ошибка
Fatal error: Readonly property Second::$baz cannot have default value in /tmp/preview on line 11
Readonly свойство, значение которого задано не в конструкторе, это константа по сути. Я и хотел изначально абстрактную константу.
2. Есть и вторая причина. Если бы я забыл в классе Second объявить свойство $foo, я бы узнал об этом только по факту вызова showInfo()
Warning: Undefined property: Second::$foo in /tmp/preview on line 5
Он бы мне не пожаловался на этапе парсинга кода, мол, в ребёнке обязательно нужно объявить $foo, ты чё, охуел. С методами так можно, со свойствами - нет.

> Ну так объяви его в базовом классе, зачем его копипастить в каждом наследнике?


Затем, что его значение фиксировано, как у константы. И для каждого класса-наследника оно отличается. Повторюсь, по смыслу это константа. Не переменная, в которую я кладу значение, извлекаю, меняю и т. д. А какое-то статичное значение. Уникальное для каждого из классов-наследников.
403 2951227
>>2951091
А если в foo() много кода, и этот код будет повторяться в каждом классе-наследнике, за исключением одного аргумента?

public function foo () {
someCode();
someCode2();
someCode3();
// ...
bar($this->editable); // $this->editable - единственная строка, которая будет различаться в реализациях разных классов
someCodeA();
SomeCodeB();
}
Пытался примерно отразить это здесь https://3v4l.org/CRNMZ#v8.3.0 только там всего два метода для демонстрации. Я, конечно, не говорю, что там огромный метод на тысячу строк на деле. Но строчек 50-100 есть. И это копипасть каждому классу-наследнику ради изменения одного string-аргумента, передаваемого в функцию?

>>2951095

> Выглядит как полное непонимание наследования. Так делать нельзя.


Вот меня что-то и напрягало. Ситуацию не спасает то, что класс-родитель - абстрактный? То есть, реализован объектом он быть не может.
Как ты прокомментируешь этот код: https://3v4l.org/obOn0#v8.3.0 ?
В родительском абстрактном классе вызывается свойство, которого он сам не содержит. Из расчёта на то, что оно есть в классе-наследнике. То, что я тут изобразил, не подходит мне по двум причинам:
1. Second::$foo не readonly, можно по ошибке в процессе выполнения изменить значение. Ок, допустим, readonly можно сделать. Тогда, правда, придётся инициализирующее значение задавать в конструкторе. Ведь я не могу сделать
private readonly string $baz = "42";
Будет ошибка
Fatal error: Readonly property Second::$baz cannot have default value in /tmp/preview on line 11
Readonly свойство, значение которого задано не в конструкторе, это константа по сути. Я и хотел изначально абстрактную константу.
2. Есть и вторая причина. Если бы я забыл в классе Second объявить свойство $foo, я бы узнал об этом только по факту вызова showInfo()
Warning: Undefined property: Second::$foo in /tmp/preview on line 5
Он бы мне не пожаловался на этапе парсинга кода, мол, в ребёнке обязательно нужно объявить $foo, ты чё, охуел. С методами так можно, со свойствами - нет.

> Ну так объяви его в базовом классе, зачем его копипастить в каждом наследнике?


Затем, что его значение фиксировано, как у константы. И для каждого класса-наследника оно отличается. Повторюсь, по смыслу это константа. Не переменная, в которую я кладу значение, извлекаю, меняю и т. д. А какое-то статичное значение. Уникальное для каждого из классов-наследников.
404 2951796
Когда я смотрю на конструкцию if () {}, я ее быстрее понимаю, чем когда смотрю на ту же конструкцию, но записанную с помощью тернарного оператора.
Хотелось бы узнать, это я не привык с первого взгляда такое читать и наличие таких инструкций нормально для кода или лучше отдавать предпочтение if, а не тернарному оператору?
406 2951830
Нашел такую статью: https://habr.com/ru/articles/431866/
Неужели стоит так много учитывать?
Я планировал просто проверять каждый символ строки со списком разрешенных значений.
Например, для имени - только a-z A-Z а-я А-Я, пробел, апостроф, дефис.
exploitsofamom2x.png65 Кб, 1480x456
407 2951837
408 2951838
>>2951837
Даже если отбросить SQL-инъекцию (потому что это задача уже плейсхолдеров, а не валидации), то имя, написанное как SQL-запрос выглядит тупо.
Теперь я понимаю, что побуквенно проверять - глупая идея.
Но все равно.
Чего так сложно все с подбором регулярок для валидации?
Какое обсуждение не откроешь - множество мнений.
409 2951839
>>2951838
Хотя стоп.
Ну, мб SQL-запрос не прошел бы, но
какая-нибудь чепуха в виде И'вАн - прошла бы.
410 2951844
>>2951838
С английским беда. Написано же "sanitize".
Тебе придется согласиться что любой вводимый пользователем текст это юникод. Иначе даже казахские братушки отпадают. То есть в имени может быть литерали: ⚰️⚰️🪦🏳️🌈. И ничего страшного в этом нет. Потому что самое хуевое что можно сделать - это отказать в обслуживании кому-то потому что у него казахское ебало.

А от "страшного" избавляется именно санитайзер. В каждом фреймворке есть подобный функционал. Санитайзер автоматически изменяет данные. Например преобразует в число, удаляет пробелы в начале строки или удаляет определенные html теги.
411 2951845
>>2951844
Ты хочешь сказать, что мне нужно делать упор не на то, чтобы уметь отбрасывать некорректные имена, а принимать их и заменять в коде некорректные символы?
412 2951849
Мб я слишком мудрю и на вопрос о том, какие символы являются корректными стоит смотреть иначе?
Не: какие вариации имен/фамилий существуют
А: какие вариации имен/фамилий готов принять мой сайт
Я ведь, да и другие аноны не кривят лицом, когда их просят в документах написать ФИО не кириллицей, а латиницей.
0b427146545d19141ec88ce0ad503a9c.jpg64 Кб, 800x599
413 2951850
>>2951845
Нет, я хочу сказать что охуенно посрал. А что там получилось что-то про санитайзер? Перепутал, не туда запостил.

Посрал охуенно, и хуем до потолка стрельнул.
414 2951852
https://selectel.ru/blog/network-protocols/
Почему IP-протокол находится в разделе о протоколах транспортного уровня, если он, вроде как, является протоколом сетевого уровня?
415 2951860
>>2951852

>selectel


Твои протыки?
416 2951871
>>2951806
Это сахарок ака Null Coalescing Operator, с труъ тернарными оператором получилось бы так:
return is_null($values[$number]) ? (is_null($defaultValue) ? 'value not found' : $defaultValue) : $values[$number];
417 2951951
Спрашивают ли на собесах паттерны проективрования? Нужно ли их учить?
418 2951987
>>2951951
Спрашивают. Посмотри например те же реальные собеседования от канала с areaweb.

мимо фулстек
419 2952097
>>2951154

Идея вообще была в том, чтобы учиться по статьям, а в треде уточнять непонятные моменты и проверять задания. Статью можно написать один раз, а прочтет ее много человек и это лучше, чем каждому объяснять лично.
420 2952107
>>2951227

Так аргумент можно вынести в абстрактную функцию:

public function foo () {
someCode();
someCode2();
someCode3();
bar($this->getEditable());
someCodeA();
SomeCodeB()
}

abstract private function getEditable(): string;

Не понимаю, в чем проблема.
421 2952116
>>2951227

> Вот меня что-то и напрягало. Ситуацию не спасает то, что класс-родитель - абстрактный? То есть, реализован объектом он быть не может.


> Как ты прокомментируешь этот код: https://3v4l.org/obOn0#v8.3.0 ?



Ну это плохой код, и ты сам расписал, почему. Я не понимаю, что тебе мешает использовать абстрактный метод, который для таких случаев и придуман.

> И это копипасть каждому классу-наследнику ради изменения одного string-аргумента, передаваемого в функцию?



Ну вот тут https://3v4l.org/CRNMZ#v8.3.0 никакой копипасты нет же.

И кстати этой твой пример я бы сделал вообще так: https://3v4l.org/BsCvr#v8.3.0
422 2952150
>>2951796

Просто не привык. Иногда удобнее тернарник, иногда удобнее if написать, главное, чтобы код был понятным.

>>2951830

Там статья про имена во всем мире, которые, действительно, могут писаться самыми разными способами. Но мы можем ограничить себя только допустимыми в России (или в твоей стране, если ты не из России) именами. И для них можно попробовать найти официальные списки допустимых символов.

Официального списка символов я не нашел, но вот, какие символы разрешает использовать налоговая при обмене данными: https://www.consultant.ru/document/cons_doc_LAW_410788/763145d8bce1267a0501117c28ebd122104c1b8e/

Вот пример того, как люди мучаются из-за невозможности передать данные в ГНИВЦ: https://forum.gnivc.ru/index.php?/topic/2176-zabrakovany-soobscheniia-znaki-prepinaniia-v-polia/

Вот пример, как кредитные организации мучаются при передаче данных в кредитное бюро: https://asros.ru/upload/iblock/190/2y1xw5anyssa7scmdh5xfxcmklo9wxa7/output-_14_.pdf

Видимо, в госорганах тоже нет единого стандарта, и они добавляют разрешенные символы в ответ на обращения.
423 2952155
>>2951844

Это плохой совет. sanitize значит, что ты принимаешь от пользователя любые данные, но по-тихому удаляешь из них запрещенные символы, вместо того, чтобы указать на ошибку.

Не надо так делать.

> в имени может быть литерали: ⚰️⚰️🪦🏳️🌈.



Не может.

> Санитайзер автоматически изменяет данные.



ну и глупость. Получается, ты в базу запишешь не то, что ввел пользователь, то есть неверные данные.
424 2952160
>>2951852

Мне кажется, что IP протокол сетевого, а TCP - транспортного уровня. Но тут, конечно, лучше бы смотреть авторитетный источник. То есть определения уровней OSI и проверять, каким уровням он соответствует.

Надо понимать, что OSI это скорее абстракция, как можно разбивать протоколы на уровни. В реальности они могут не соответствовать OSI, хотя в общем, эта модель довольно близка к реальности.
425 2952502
>>2952155

>Не надо так делать.


Не надо кому?
В реальном мире за то что кто-то вообще попал на твою страницу заплачены деньги. Если этот кто-то развернется и уйдет из-за того что у него буква некрасивая в email'е хуже только тебе.

На самом деле вариантов всего два: экранирование и санитайзинг.
426 2952590
>>2952502

Ну так надо использовать экранирование. А санитайзинг не надо вообще нигде использовать, кроме технических вещей (типа номера страницы в URL, который пользователя руками не вводит).

И проверка валидности есть. Не знаю, как сейчас, а в магазинах типа DNS номер телефона не только проверяется на формат, но и проверяется через СМС. У тебя только стационарный телефон или вообще нет телефона? Иди тогда отсюда.

То же самое касается телеграмов, соцсетей, доставки, госуслуг. Они все проверяют и если ты вводишь что-то не то, то тебе отказывают в получении услугу.

Так что не рассказывай мне про реальный мир.
Screenshot 2023-12-06 163650.png144 Кб, 1548x1074
427 2952641
>>2952590

>Ну так надо использовать экранирование.


Сколько раз? Надо ли экранировать экранирующие символы?
Если ты никогда в реальном проекте не работал, то нахуй ты это пишешь? Кто реально пытался текст экранировать глядя на пикрелейтед пример нервно икает.
Гений, можешь хотя бы предположить почему так получилось?
428 2952784
Я вкатун и я не понимаю вот чего:
Допустим что стэк у меня Нджинкс и пхп-фпм, как мне сделать чтоб ссылка не содержала расширений пхп?
429 2952787
>>2952641

Экранирование делается в том месте, где данные используются, а не в начале обрабочика. Если ты хочешь вставить данные в SQL-запрос, ты используешь подготовленные запросы. Если ты хочешь их вывести в HTML, ты используешь шаблонизатор с поддержкой экранирования.

И все символы отображаются и сохраняются корректно, и ничего не ломается.

А ты со свои санитайзеры из какого-то древнего неграмотного учебника достал скорее всего.

Как я уже писал выше, очистку можно применять для технических данных, которые пользователь не вводит вручную: номера страниц в URL, id комментария и тд.
430 2952808
>>2952784
Вроде напал на нужный след в гугле
Но если есть хороший человек готовый написать где это в конфиге сразу,то тысяча поцелуев ему
431 2952854
>>2952784
Ссылка на что?
Есть твой сервер с файлами, в твоем случае php скриптами и php-fpm для их выполнения.
Есть промежуточное звено nginx, которое получает ссылку, читает её и решает какой из файлов на твоем сервере был запрошен.

Не нравятся прямые ссылки на файлы - добавляешь в nginx настройку согласно которой любая ссылка со словом "пидар" будет направлена на pidar.php

Очевидно что прописывать каждый вариант руками и настолько сильно зависеть от настроек ngix не выгодно. Поэтому обычно прописывают одно правило: все ссылки с твоим доменом ведут на index.php на твоем сервере, а уже index.php смотрит на параметры ссылки и решает какой скрипт выполнить.
432 2952879
>>2952787

>И все символы отображаются и сохраняются корректно, и ничего не ломается.


Ты слепой или тупой? Я тебе привел пример как все сломалось. Потому что оно постоянно будет ломаться.

Я потому и сказал что ты ни дня в реальном проекте не работал. Хранить у себя sql инъекции и xss скрипты в надежде что ты все правильно сэкранировал. Это каким же ебланом надо быть.
433 2952933
>>2952854

>доменом ведут на index.php на твоем



Спасибо дядя, тоже сейчас в ходе поисков наткнулся на эту инфу,
поцеловал в пенис
434 2953286
>>2951087
Наверное я должен показывать код, да?
Код Validator: https://3v4l.org/AC3p8
Код ValidationError: https://3v4l.org/u0bd4
Код ErrorList: https://3v4l.org/HPpGT
Код, который проверяет качество символов по регулярному выражению: https://3v4l.org/Z3pIi
Код, который проверяет минимальное количество символов:
https://3v4l.org/eThug
Код, который проверяет максимальное количество символов: https://3v4l.org/UIZpF
Код, который проверят пустое значение или нет: https://3v4l.org/CequU

Минимальное и максимальное количество символов для каждого поля:
Имя: 1/20;
Фамилия: 1/45;
Номер группы: 2/5;
Емайл: 4/50;
Баллы ЕГЭ: 2/3;
Год рождения: 4/4.

Регулярные выражения для каждого поля:
имя: /^[А-ЯЁ]{1}[а-яё '-\.,\(\)А-ЯЁ?IV]{0,19}$/gm
фамилия: /^[А-ЯЁ]{1}[а-яё '-\.,\(\)А-ЯЁ?IV]{0,44}$/gm
номер группы: /^[0-9а-яёА-ЯЁ]{2,5}$/gm
email: /^[a-zA-Z]{1}[a-zA-Z\.\-_0-9]+@{1}[a-z]+\.{1}[a-z]+$/gm
баллы ЕГЭ: /^[0-9]{2,3}$/gm
год рождения: /^[0-9]{4}$/gm

Класса, который проверяет уникальность емайл - пока что нет, потому что я не добрался до написания класса работы с БД.
Я решил, что сначала напишу его, а потом допишу проверку.
434 2953286
>>2951087
Наверное я должен показывать код, да?
Код Validator: https://3v4l.org/AC3p8
Код ValidationError: https://3v4l.org/u0bd4
Код ErrorList: https://3v4l.org/HPpGT
Код, который проверяет качество символов по регулярному выражению: https://3v4l.org/Z3pIi
Код, который проверяет минимальное количество символов:
https://3v4l.org/eThug
Код, который проверяет максимальное количество символов: https://3v4l.org/UIZpF
Код, который проверят пустое значение или нет: https://3v4l.org/CequU

Минимальное и максимальное количество символов для каждого поля:
Имя: 1/20;
Фамилия: 1/45;
Номер группы: 2/5;
Емайл: 4/50;
Баллы ЕГЭ: 2/3;
Год рождения: 4/4.

Регулярные выражения для каждого поля:
имя: /^[А-ЯЁ]{1}[а-яё '-\.,\(\)А-ЯЁ?IV]{0,19}$/gm
фамилия: /^[А-ЯЁ]{1}[а-яё '-\.,\(\)А-ЯЁ?IV]{0,44}$/gm
номер группы: /^[0-9а-яёА-ЯЁ]{2,5}$/gm
email: /^[a-zA-Z]{1}[a-zA-Z\.\-_0-9]+@{1}[a-z]+\.{1}[a-z]+$/gm
баллы ЕГЭ: /^[0-9]{2,3}$/gm
год рождения: /^[0-9]{4}$/gm

Класса, который проверяет уникальность емайл - пока что нет, потому что я не добрался до написания класса работы с БД.
Я решил, что сначала напишу его, а потом допишу проверку.
435 2953305
>>2952107
Так я так и сделал, ёпт! Глянь >>2950316
Просто начал сомневаться на тему того, адекватно ли так делать, или я забиваю гвоздь микроскопом. Метод, который по сути ведёт себя как константа, возвращая всегда одно и то же неизменяемое значение.

>>2952116

>https://3v4l.org/BsCvr#v8.3.0


Ну нет, это вообще мимо. На практике же дочерние классы своими внутренностями отличаются сильнее. В одном такие-то дополнительные методы, в другом иные.

В общем, всем спасибо, остановлюсь на абстрактном методе, потому что чисто технически это работает именно так, как мне надо. А из обратной связи я получил, в сущности, следующее:
1. Твой код полная хуйня, а мать - шлюха.
2. Делай абстрактный метод.
Первое не слишком конструктивно, остаётся второе.
436 2953331
А часто вам формошлепить на пыхе приходится на своих работах?
Или всё таки уже норм распространен подход с отдельным жс кодом на вью\реакте?
437 2953337
Как глубоко надо задрачивать фронт? Разбираться в css-in-js/css-modules/БЭМ? Или это уже не нужно, если ты в основном бекендер, а не фуллстек? Или всё-таки надо прям настолько погружаться? Или хватит просто HTMl/SCSS/JS и просто умение именовать по БЭМ (мой текущий уровень знаний)?
438 2953394
>>2953305
Я тебе сразу указал что один вариант исключает дублирование кода, а другой нет.
А когда спросил какая у тебя цель - ты полез в залупу.
Очевидно что если цель "избавится от дублирования кода", то нужно выбирать вариант без дублирования. Но ты-то блядь свою цель так и не озвучил.

>Вот код. Он работает так как мне надо?


>А как тебе надо? Что ты делаешь вообще?


>Секрет.



А теперь ты пишешь: "это работает именно так, как мне надо". В натуре не очень конструктивно. Закидывать долбоебу в черный ящик какой-то код, чтобы услышать так ли он с его точки зрения работает. С первоклассником конструктивнее общаться, чем с шизами с двачей.
439 2953422
Сегодня только узнал про существование такой темы как "Структуры данных".
Пока я решал свои вкатунские задачи, я пользовался переменными, массивами...И не чувствовал ощущения, что мне чего-то не хватает.
Пробежался по гуглу.
Узнал, что есть всякие стеки, очереди.
Но так и не понял зачем они нужны.
Вот я решаю задачу.
Как понять, что стоит представить данные в виде определенной
структуры данных?
Насколько вообще часто программист имеет дело с чем-то кроме массива?
440 2953466
>>2953422
Ты пхп макака, твой код выполняется в виртуальной среде у тебя даже массивов нет, только хеш мапы и объекты.

Стек он стек именно потому что при такой структуре нужно меньше действий процессора и памяти. Ну напишешь ты стек на пхп, и чего? Прироста нет, пользы нет, лишняя абстракция.

>Как понять, что стоит представить данные в виде определенной


структуры данных?
Никак. Структуры данных выбираются исходя из приоритетов в расходовании производительности/памяти, пикрелейтед. А написать что-то быстрее пхпшных "массивов" ты физически не можешь, потому что они написаны на C.

У пхп есть своя сфера низкоуровневых оптимизаций. Называется "опкоды" https://php.watch/articles/php-dump-opcodes Это то во что транслируется твой пхп код. И можно написать код, который будет транслироваться в меньшее количество действий и будет немного производительнее. На практике таким никто не занимается, потому что для веба пхп достаточно быстрый и если не творить хуйню типа регулярных выражений в цикле, то сам пхп никогда бутылочным горлышком не будет.

Если посмотришь на трассировку симфони, то твой код это та маленькая синенькая пиздюлька перед твигом, а любой запрос в базу, даже SELECT 1; будет выполняться минимум 10ms, то есть в двое дольше.
441 2953649
>>2953466
Анон, ты вроде шаришь, подскажи если смысл лезть вкатуну в пхп в 2024? И почему/зачем ты сидишь на пхп?
442 2953680
>>2953649
Сижу потому что слезать = становиться опять джуном, со всеми вытекающими.

Если с полного нуля, то нет. Единственное преимущество пхп - меньше ебланов с улицы ломятся в джуны. Больше преимуществ я не вижу.

Если нужны быстрые бабки, то есть вротэнд.
Если нужна карьера, то любой энтерпрайз язык. Изучишь один - считай изучил все. А изучив пхп ты изучил только микромир пхп.
Для души и хобби тоже нахуй не надо. Пхп многосложный, косноязычный, забитый мусором. Красиво на нем не сделаешь.

Тебе зачем пхп вообще?
443 2953889
>>2953286

> if (!$result===null) {



надо писать !== , или можно просто if ($result), это работает так как if преобразует значение в тип bool как описано в мануале https://www.php.net/manual/ru/language.types.boolean.php#language.types.boolean.casting

> $errorList->add($fieldName, new Error($result));



лучше если класс-правило будет сразу возвращать Error, а не строку. Ведь при проверке ты можешь захотеть к ошибке добавить какую-то дополнительную информацию (например: подсказку или вариант исправления), а для этого нужен объект.

То есть, если ты решил обозначать ошибку объектом Error, то не надо ее возвращать как строку, возвращай сразу объект Error везде.

Непонятно, зачем в ValidationError ты сделал Setter. Зачем тебе менять содержимое ощибки? Ошибка это не какая-то сущность, которую можно редактировать. Ошибку логично бы сделать иммутабельным (неизменяемым) объектом для "защиты от дурака". Ошибка явно подходит под паттерн ValueObject, про который я писал выше.

То есть, думай, какие объекты делать мутабельными, а какие нет. Нужно ли тебе это и зачем.

> private array $listOfAllErrors;



лучше назвать просто $errors

> $result = $this->listOfAllErrors[$fieldName];



Здесь может быть ошибка, что в массиве нет такого ключа. Надо добавлять ?? [] для защиты от такой ошибки.

> errorListIsEmpty ()



Лучше просто назвать isEmpty, ведь ErrorList уже есть в названии класса и зачем его писать второй раз. Также, перечитай PSR-1 и PSR-12:

> Method and function names MUST NOT be declared with space after the method name.



> class CheckForSymbolQuality



Почему ты не хочешь сделать интерфейс для классов-проверяльщиков?

> CheckForSymbolQuality



лучше назвать типа CheckRegexp, ну то есть явно написать, что это проверяльщик регулярок. Вот видишь какая интересная штука ООП, в процедурном программировании ты просто пишешь preg_match, а в ООП пишешь целый класс И строишь архитектуру вокруг preg_match.

Что касается названий классов, то вот как классы-проверяльщики названы в Symfony:

NotBlankValidator, LengthValidator, RegexValidator, и другие названия можно увидеть тут: https://symfony.com/doc/current/reference/constraints.html

> Это поле может содержать следующие символы - %s. Проверьте, не использовали ли Вы символ, который не входит в этот список.



А почему тупая железяка не может проверить сама и написать, какой символ неправильный, а не загадывать ребусы человеку?

> public function __invoke (mixed $value): ?string


лучше возвращать ?ValidationError, а не ?string, как я написал выше

> iconv_strlen($value);


Обычно используют mb_strlen... но твой вариант тоже годится.

В регулярке для email проблема: в доменах может быть и минус, и цифры по типу i2N/vanANUSs7-con$pmsultingPUNCTUMo\#Lrg, более того, сейчас есть международные домены типа i:'3vanANUSрусскiTJийPUNCTUMрoo.ф

Некоторые рекомендуют просто проверять, что :

- в email есть @ и хотя бы 1 точка справа от @
- в email нет пробелов и других запрещенных символов (каких, подскажет интуиция)

То есть, проверка email нужна в первую очередь для защиты от опечаток, когда люди забывают ставить собачку либо ставят пробел вместо точки.

Но можно просто доработать твою регулярку.

Проблема с очень сложными регулярками в том, что их сложно читать, проверять на правильность, и трудно сообщать ошибки. Например, твоя регулярка требует писать имя с большой буквы. Если я напишу с маленькой, она мне об этом скажет, или напишет, что я использовал запрещенный символ? Лучше было сделать 2 проверки, одна на запрещенные символы, другая на большую букву в начале (а еще можно автоматически делать первую букву большой и не мучать пользователя).

> год рождения:



желательно проверять, что он не меньше 1900 и не больше текущего - 12.
443 2953889
>>2953286

> if (!$result===null) {



надо писать !== , или можно просто if ($result), это работает так как if преобразует значение в тип bool как описано в мануале https://www.php.net/manual/ru/language.types.boolean.php#language.types.boolean.casting

> $errorList->add($fieldName, new Error($result));



лучше если класс-правило будет сразу возвращать Error, а не строку. Ведь при проверке ты можешь захотеть к ошибке добавить какую-то дополнительную информацию (например: подсказку или вариант исправления), а для этого нужен объект.

То есть, если ты решил обозначать ошибку объектом Error, то не надо ее возвращать как строку, возвращай сразу объект Error везде.

Непонятно, зачем в ValidationError ты сделал Setter. Зачем тебе менять содержимое ощибки? Ошибка это не какая-то сущность, которую можно редактировать. Ошибку логично бы сделать иммутабельным (неизменяемым) объектом для "защиты от дурака". Ошибка явно подходит под паттерн ValueObject, про который я писал выше.

То есть, думай, какие объекты делать мутабельными, а какие нет. Нужно ли тебе это и зачем.

> private array $listOfAllErrors;



лучше назвать просто $errors

> $result = $this->listOfAllErrors[$fieldName];



Здесь может быть ошибка, что в массиве нет такого ключа. Надо добавлять ?? [] для защиты от такой ошибки.

> errorListIsEmpty ()



Лучше просто назвать isEmpty, ведь ErrorList уже есть в названии класса и зачем его писать второй раз. Также, перечитай PSR-1 и PSR-12:

> Method and function names MUST NOT be declared with space after the method name.



> class CheckForSymbolQuality



Почему ты не хочешь сделать интерфейс для классов-проверяльщиков?

> CheckForSymbolQuality



лучше назвать типа CheckRegexp, ну то есть явно написать, что это проверяльщик регулярок. Вот видишь какая интересная штука ООП, в процедурном программировании ты просто пишешь preg_match, а в ООП пишешь целый класс И строишь архитектуру вокруг preg_match.

Что касается названий классов, то вот как классы-проверяльщики названы в Symfony:

NotBlankValidator, LengthValidator, RegexValidator, и другие названия можно увидеть тут: https://symfony.com/doc/current/reference/constraints.html

> Это поле может содержать следующие символы - %s. Проверьте, не использовали ли Вы символ, который не входит в этот список.



А почему тупая железяка не может проверить сама и написать, какой символ неправильный, а не загадывать ребусы человеку?

> public function __invoke (mixed $value): ?string


лучше возвращать ?ValidationError, а не ?string, как я написал выше

> iconv_strlen($value);


Обычно используют mb_strlen... но твой вариант тоже годится.

В регулярке для email проблема: в доменах может быть и минус, и цифры по типу i2N/vanANUSs7-con$pmsultingPUNCTUMo\#Lrg, более того, сейчас есть международные домены типа i:'3vanANUSрусскiTJийPUNCTUMрoo.ф

Некоторые рекомендуют просто проверять, что :

- в email есть @ и хотя бы 1 точка справа от @
- в email нет пробелов и других запрещенных символов (каких, подскажет интуиция)

То есть, проверка email нужна в первую очередь для защиты от опечаток, когда люди забывают ставить собачку либо ставят пробел вместо точки.

Но можно просто доработать твою регулярку.

Проблема с очень сложными регулярками в том, что их сложно читать, проверять на правильность, и трудно сообщать ошибки. Например, твоя регулярка требует писать имя с большой буквы. Если я напишу с маленькой, она мне об этом скажет, или напишет, что я использовал запрещенный символ? Лучше было сделать 2 проверки, одна на запрещенные символы, другая на большую букву в начале (а еще можно автоматически делать первую букву большой и не мучать пользователя).

> год рождения:



желательно проверять, что он не меньше 1900 и не больше текущего - 12.
444 2953896
>>2953305

> Метод, который по сути ведёт себя как константа, возвращая всегда одно и то же неизменяемое значение.



Да, это правильно, так как методы возвращают разные значения в разных классах.
445 2953910
>>2953422

Структуры данных, как правило, неразрывно связаны с алгоритмами и служат целям:

- хранить данные так, чтобы с ними было удобнее работать
- хранить данные так, чтобы быстро их находить или менять
- хранить данные так, чтобы код был понятнее

В PHP есть структуры данных (хотя не скажу, что идеально реализованные), смотри:

- расширение Ds: https://www.php.net/manual/ru/book.ds.php
- встроенное расширение SPL: https://www.php.net/manual/ru/book.spl.php

Ну например, ты хранишь в массиве черный список номеров телефонов (очень много): ['9701234567', '9701234568', ...]. И тебе надо проверять, есть ли номер телефона в черном списке или нет.

Если ты используешь массив, то это не очень хорошо:

- проверка будет медленной и неоптимизированной на больших объемах
- допустим, тебе надо составить черный список. Тебе неочевидно: должны телефоны идти в определенном порядке или нет? какие ключи должны быть в массиве?

А если ты используешь множество, то все будет проще:

- проверка наличия во множестве быстрая
- порядок телефонов во множестве не важен, ключей в нем нету, и читатель кода не задает лишних вопросов
446 2953912
>>2953422

Главная проблема конечно не оптимизация, а читабельность кода. В PHP массив используют вместо списка, неизменяемого списка, множества, хеш-таблицы и при чтении кода приходится догадываться, какой именно массив нужен в этом месте кода.
447 2953925
>>2953466

> у тебя даже массивов нет, только хеш мапы и объекты.



Не пиши, что не знаешь. В расширениях SPL и DS кое-что есть.

> Ну напишешь ты стек на пхп, и чего? Прироста нет, пользы нет, лишняя абстракция.



Код понятнее.

> Если посмотришь на трассировку симфони



ты бы для начала включил режим prod, а не в dev-окружении мерял, оптимизатор. Приходят такие неграмотные в тред и потом мифы про Симфони распространяют, а дураки им верят.

Также, у тебя на профиле нет ли одного запроса на 10ms, и еще у тебя используются подзапросы, что не рекомендуется, но ты похоже не читаешь рекомендации.
blackfire-homepage-prod.png110 Кб, 2712x974
448 2954054
>>2953925

>Не пиши, что не знаешь. В расширениях SPL и DS кое-что есть.


Точно такие же виртуальные обертки над C. Ты один хуй все действия делаешь в виртуальной машине через opcod'ы и zval'ы. Ты хоть знаешь что такое zval, чучело?

>Код понятнее.


Понятнее чем что? Чем array_push/array_pop? Начнем с того что в какой блядь вообще задаче может понадобиться стек? Какие ты блядь деревья такие собрался в пхп обходить? Да даже хуй с ним, пусть и деревья. Зачем может вообще понадобиться структура из которой можно получить ТОЛЬКО последнее значение? В настоящем стеке понятно. LIFO это физическое расположение данных в памяти. Безопасный мультитрединг, меньше процессорных команд, простой указатель. Все это будет работать ТОЛЬКО при гарантиях LIFO. Твой же выдуманный стек лежит в куче, потому что это zval. Нахуя нам запрещать обращаться к любому его элементу, а не только к последнему? Ведь за это уже уплочено. Ресурсы на это потрачены. Какой смысл?

>ты бы для начала включил режим prod, а не в dev-окружении мерял, оптимизатор. Приходят такие неграмотные


Так. Пикрелейтед прод. Что мы там должны увидеть? На проде пхп замедлился? Или запрос в базу ускорился? Какие нахуй мифы, додик? Какие блядь "дураки", кроме тебя офк во что верят? Какие блядь "подзапросы"? Это скриншоты из оф доки симфони https://symfony.com/doc/5.4/the-fast-track/ru/30-internals.html
Особенно смешно как тебя порвало в контексте того что я назвал php быстрым, а бутылочным горлышком запросы в базу.
Зашивайся, знаток.
449 2954197
>>2954054
Казалось, лишь теперь он начал понимать, почему я прятался в руинах.
450 2954500
fullstack php + js реально в 2023 году? А то я смотрю вакансий чет дохуя именно с фуллстеком.

https://hh.ru/vacancy/84045097?from=vacancy_search_list&hhtmFrom=vacancy_search_list&query=php
https://hh.ru/vacancy/90004977?from=vacancy_search_list&hhtmFrom=vacancy_search_list&query=php
451 2954716
Где в MVC могут происходить побочные эффекты? Допустим прилетает запрос и мне надо сгенерировать какой-то файл и отправить на клиент. Где это делать? В контроллере?
452 2954725
>>2954716
Побочные эффекты производят другие программисты. Они решают свои задачи с помощью твоего кода и данных, которые нужны тебе.
Если назначение кода не очевидно, неоднозначно, нужное тебе поведение не изолированно а данные не гарантируют свою целостность.

Вот это поворот, все эти дебильные правила, солиды хуелиды нужны не для приручения злых данных, которые сами вдруг меняются. А для улучшения взаимопонимания и взаимодействия между людьми.
453 2954726
>>2954500
Не реально. Поезд уехал, встретимся в 2024.
454 2954745
А как лучше стили компоновать с пхп?
Бест практисы какие?
В инете нашел такой вариант:
Создавать стайлс.пхп, там указывать заголовок текст\цсс и описывать стили, линком подключить
Почему-то также написали что просто подключать цсс и настроить нджинкс на передачу стилей - хуета
455 2954760
>>2954745
А,я даун, всё без танцев подключилось легко по линку (как обычно)
456 2954762
>>2954745
Для сборки стилей и js скриптов из разных модулей и папок используются gulp и webpack https://doka.guide/tools/gulp/#ispolzovanie
457 2954793
>>2953889
Спасибо за ответ.
Вот исправленный код:
Класс Validator: https://3v4l.org/g8uRs

Класс ErrorList: https://3v4l.org/5cntA
Зачем я сделал это:

>throw new ArrayNotExistsException("Массива под таким ключом не существует. ");


Потому что дальше идет цикл foreach, если result это null, то что он будет делить на ключ и значение?

Класс ValidationError: https://3v4l.org/R6Dtg

Интерфейс ValidatorRuleInterface: https://3v4l.org/E1fAg
С этим интерфейсом есть небольшая проблема.
Ее суть будет изложена, когда я дойду (в этом посте) до класса-проверятеля, который проверяет, что год рождения находится в определенном диапазоне

Класс, проверяющий на пустоту: https://3v4l.org/TMHPR
Класс, проверяющий минимум: https://3v4l.org/AePYA
Класс, проверяющий максимум: https://3v4l.org/AcCki
Класс, проверяющий качество: https://3v4l.org/of0e9
Небольшое объяснение этого класса:
Я подумал, что клепать 10 свойств - тупо и решил сделать одно - $reviewResources, в котором буду хранить все, что нужно для этой валидации. Ведь именно для этой валидации мне понадобилось так много свойств...
Я разделил проверку на две части:
Проверить каждый символ на паттерн, в котором перечислены корректные символы, если символ не проходит совпадение = он некорректный
Проверить каждое значение на то, что его структуру +- нормальная, чтобы не было всяких И,в,а,н,о,в,ы,х,
потому что хоть запятая и разрешена в фамилии, такое ее использование - тупость.
Если хотя бы одна из этих проверок выдает ошибку (в виде массива с некорректными словами или нуля), то формируется текст ошибки, а потом создается объект ValidationError и эта строка отдается этому объекту в конструктор.
Мб паттерны ($patternForSymbols, $patternForString) стоит объединить в один массив ($patterns).
Я не понимаю когда стоит представлять что-то отдельным, а когда массивом. Это касается просто переменных и свойств класса.

Класс, проверяющий адекватность года рождения: https://3v4l.org/3meF5
Вот мы и подошли к проблеме с интерфейсом.
В сигнатуре метода интерфейса указано, что $value должно быть mixed, но, проверяя год, мы же не можем указать mixed, ведь нам конкретно нужен int (года же ведь хранятся в виде int, да? а то я туплю что-то в этом), поэтому я оставил mixed для того, чтобы сигнатуры методов совпадали, но добавил проверку типа в самом классе.
Хуй знает как это исправлять.
Я пока что ничего не придумал.
Минимальный год я выбрал - 1923
Максимальный год - 2023
Итого 100 лет.
Ну, вроде нормальный диапазон.

И насчет регулярного выражения для емайла.
Проверять структуру я буду таким: /@{1}\S*\.{1}/gm
Т.е. одна собачка, потом любой символ и одна точка.
Проверять корректность каждого символа таким:
/[a-zA-Z0-9_\.\-@]/gm
Т.е. заглавные и строчные латинские буквы, цифры, нижнее подчеркивание, точка, минус, собака.
Я это "украл" у майл.ру, от балды вбивал символы и ждал когда будет сообщение об ошибке валидации и просто внес в свою регулярку то, что они считают разрешенным.
457 2954793
>>2953889
Спасибо за ответ.
Вот исправленный код:
Класс Validator: https://3v4l.org/g8uRs

Класс ErrorList: https://3v4l.org/5cntA
Зачем я сделал это:

>throw new ArrayNotExistsException("Массива под таким ключом не существует. ");


Потому что дальше идет цикл foreach, если result это null, то что он будет делить на ключ и значение?

Класс ValidationError: https://3v4l.org/R6Dtg

Интерфейс ValidatorRuleInterface: https://3v4l.org/E1fAg
С этим интерфейсом есть небольшая проблема.
Ее суть будет изложена, когда я дойду (в этом посте) до класса-проверятеля, который проверяет, что год рождения находится в определенном диапазоне

Класс, проверяющий на пустоту: https://3v4l.org/TMHPR
Класс, проверяющий минимум: https://3v4l.org/AePYA
Класс, проверяющий максимум: https://3v4l.org/AcCki
Класс, проверяющий качество: https://3v4l.org/of0e9
Небольшое объяснение этого класса:
Я подумал, что клепать 10 свойств - тупо и решил сделать одно - $reviewResources, в котором буду хранить все, что нужно для этой валидации. Ведь именно для этой валидации мне понадобилось так много свойств...
Я разделил проверку на две части:
Проверить каждый символ на паттерн, в котором перечислены корректные символы, если символ не проходит совпадение = он некорректный
Проверить каждое значение на то, что его структуру +- нормальная, чтобы не было всяких И,в,а,н,о,в,ы,х,
потому что хоть запятая и разрешена в фамилии, такое ее использование - тупость.
Если хотя бы одна из этих проверок выдает ошибку (в виде массива с некорректными словами или нуля), то формируется текст ошибки, а потом создается объект ValidationError и эта строка отдается этому объекту в конструктор.
Мб паттерны ($patternForSymbols, $patternForString) стоит объединить в один массив ($patterns).
Я не понимаю когда стоит представлять что-то отдельным, а когда массивом. Это касается просто переменных и свойств класса.

Класс, проверяющий адекватность года рождения: https://3v4l.org/3meF5
Вот мы и подошли к проблеме с интерфейсом.
В сигнатуре метода интерфейса указано, что $value должно быть mixed, но, проверяя год, мы же не можем указать mixed, ведь нам конкретно нужен int (года же ведь хранятся в виде int, да? а то я туплю что-то в этом), поэтому я оставил mixed для того, чтобы сигнатуры методов совпадали, но добавил проверку типа в самом классе.
Хуй знает как это исправлять.
Я пока что ничего не придумал.
Минимальный год я выбрал - 1923
Максимальный год - 2023
Итого 100 лет.
Ну, вроде нормальный диапазон.

И насчет регулярного выражения для емайла.
Проверять структуру я буду таким: /@{1}\S*\.{1}/gm
Т.е. одна собачка, потом любой символ и одна точка.
Проверять корректность каждого символа таким:
/[a-zA-Z0-9_\.\-@]/gm
Т.е. заглавные и строчные латинские буквы, цифры, нижнее подчеркивание, точка, минус, собака.
Я это "украл" у майл.ру, от балды вбивал символы и ждал когда будет сообщение об ошибке валидации и просто внес в свою регулярку то, что они считают разрешенным.
458 2954818
>>2953889
Можешь ответить еще на несколько вопросов?
Ты предлагал мне заменить несколько свойств в классе ErrorList на одно свойство.
Мне понравилось это решение, потому что код стал меньше и универсальнее.
Но я не понимаю какая логика лежит за этим решением.
Как понять, смотря на совокупность свойств класса, что лучше их представить в виде одного свойства-массива?
И еще вопрос.
У меня есть две переменные. Когда лучше иметь две отдельные переменные, а когда лучше иметь массив с двумя отдельными элементами?
Например, у меня есть две переменные - $patternForSymbols и $patternForString.
Как мне понять, им лучше быть по одиночке или быть элементами одного массива?
459 2954829
>>2953889

>В сигнатуре метода интерфейса указано, что $value должно быть mixed, но, проверяя год, мы же не можем указать mixed, ведь нам конкретно нужен int (года же ведь хранятся в виде int, да? а то я туплю что-то в этом), поэтому я оставил mixed для того, чтобы сигнатуры методов совпадали, но добавил проверку типа в самом классе.


Хуй знает как это исправлять.

Есть такая идея:
У меня есть класс Enrollee с поля name, surname и т.д.
Мб сделать так, чтобы поля year и email хранили не int и string соответственно, а объекты классов Year и Email?
Это не решает проблему с интерфейсом.
Но решает другую проблему.
Если я уберу строку, что класс, который проверяет адекватность года, реализует интерфейс, уберу проверку типа и сделаю тип аргумента int, то функция invoke сможет принимать любое число.
Год имеет тип числа, да. Но ведь в таком случае функция сможет принимать любое число. А нам нужен именно год. Для этого можно представлять числа и емайлы отдельными типами.
460 2954831
>>2954829
Т.е.

Сначала сделать так:

//убрать то, что класс реализует интерфейс
Класс будет объявляться так:
Class ClassName {...}

//сигнатура метода с int
public function __invoke(int $value): ?ValidationError {...}

//сигнатура метода с объектом типа Year
public function __invoke(Year $value): ?ValidationError {...}
461 2954832
>>2954829

>представлять числа и емайлы отдельными типами.


*Представлять год и емайл отдельными типами.
Извиняюсь за опечатки.
462 2954833
>>2954829
Почему я завел речь про емайлы - потому что будет отдельный класс-проверятель на уникальность емайл.
И я думаю, он тоже не впишется в мой интерфейс.
463 2954852
Сколько фронтенда надо знать для битриксоида? Вообще как посоветуете развиваться в направлении битрикс? Сделать пет на чистых языках, только jQuery добавив, интернет-магаз? Или сразу на битриксе? Или и то и то?

Ну и кстати нашёл курс от webformyself длительностью 38 часов, кто-то проходил его? Норм? Походу в сети всего 5 курсов по битриксу: webformyself, Я-Кодер, гикбрейнс, Михаил базаров и офф. курсы битрикса.
464 2954925
>>2954852
Да просто на собес сходи, спрашивают обычно по пхп, на петпроекты всем похуй. По jquery есть старый курс дмитрия лаврика на торрентах "Js для верстальщица". Еще из джса нужен обязательно ajax. В битриксе есть своя всратая библиотека BX она процентов на 80% копирует jquery - ее изучать самому бессмыслено документации толком нет, натаскаешься на РАБоте.
465 2955071
>>2954829
Я сейчас понял чем чревата такая идея.
Сейчас я обращаюсь к свойству Enrollee так:
$enrollee->get("название свойства").
А для года и емайла придется так:
$enrollee->get("название свойства")->get("название свойства");
Вторым способом нужно обращаться только к двум полям, получается, что я теряю универсальность в коде.
Я сейчас сонный, поэтому рассуждения туманные, я написал это, чтобы ты ответил с учетом этого момента.
466 2955085
>>2955071

>$enrollee->get("название свойства")


Пиздец.
467 2955119
>>2954716

Генерация файла это не побочный эффект. Жаль, что ты не пишешь, какой именно файл тебе нужен и мне придется придумывать это за тебя.

Допустим, тебе надо отдавать Эксель-файл с доходами за последний месяц. Формирование данных делается в модели (так как бизнес-логика располагается в модели). Генерация файла - в модели либо в контроллере. Отдача файла - в контроллере.
468 2955127
>>2955119

>Жаль, что ты не пишешь, какой именно файл тебе нужен и мне придется придумывать это за тебя.


На запрос пользователя, надо разбить видео на сегменты, сохранить их на диски и отдать плейлист на клиент.
469 2955128
>>2955127

>диски


Диск*
фикс
470 2955151
>>2954745

Начну с главного: ни в коем случае не помещай все стили и скрипты в один файл. Это приводит к тому, что там получается свалка, в которой невозможно разобраться и из которой нельзя ничего удалить потом.

Используй разные файлы. Для маленького сайта я могу предложить такую схему:

- файл global.css, который подключается на всех страницах
- файлы для каждого раздела типа blog.css, catalog.css, forum.css

И, например, в блоге ты подключаешь global.css и blog.css.

Для большого сайта можно разбивать код еще сильнее. Например, ты сделал форму обратной связи, стили для нее кладешь в отдельный файл. Сделал календарик, тоже стили кладешь в отдельный файл.

Для маленького сайта можно не заморачиваться со сборкой и не тратить на это время. В эпоху HTTP/2 и при маленьком количестве стилей сборка ничего особо не дает.

Для большого сайта можно настроить склеивание мелких файлов в 2 файла: сайт глобальных стилей и сайт раздела.

Отсутствие сборки дает много плюсов:

- разработчику не надо ничего устанавливать, запускать, не нужна нода и npm, не нужно ждать, пока стили соберутся (это часто занимает минуту и больше при холодном старте)
- код в инструментах разработчика выглядит как в оригинале
- браузер может задействовать кеширование, если один файл используется на нескольких страницах
- при этом в HTTP/2 особого выигрыша от сборки нескольких файлов в один не должно быть

Но сборка может понадобиться, если:

- ты хочешь использовать нестандартные языки вроде SCSS, Typescript
- ты хочешь автоматически добавлять CSS-префиксы для CSS-файлов
- ты хочешь транспилировать новый JS в старый для лучшей поддержки старыми браузерами
470 2955151
>>2954745

Начну с главного: ни в коем случае не помещай все стили и скрипты в один файл. Это приводит к тому, что там получается свалка, в которой невозможно разобраться и из которой нельзя ничего удалить потом.

Используй разные файлы. Для маленького сайта я могу предложить такую схему:

- файл global.css, который подключается на всех страницах
- файлы для каждого раздела типа blog.css, catalog.css, forum.css

И, например, в блоге ты подключаешь global.css и blog.css.

Для большого сайта можно разбивать код еще сильнее. Например, ты сделал форму обратной связи, стили для нее кладешь в отдельный файл. Сделал календарик, тоже стили кладешь в отдельный файл.

Для маленького сайта можно не заморачиваться со сборкой и не тратить на это время. В эпоху HTTP/2 и при маленьком количестве стилей сборка ничего особо не дает.

Для большого сайта можно настроить склеивание мелких файлов в 2 файла: сайт глобальных стилей и сайт раздела.

Отсутствие сборки дает много плюсов:

- разработчику не надо ничего устанавливать, запускать, не нужна нода и npm, не нужно ждать, пока стили соберутся (это часто занимает минуту и больше при холодном старте)
- код в инструментах разработчика выглядит как в оригинале
- браузер может задействовать кеширование, если один файл используется на нескольких страницах
- при этом в HTTP/2 особого выигрыша от сборки нескольких файлов в один не должно быть

Но сборка может понадобиться, если:

- ты хочешь использовать нестандартные языки вроде SCSS, Typescript
- ты хочешь автоматически добавлять CSS-префиксы для CSS-файлов
- ты хочешь транспилировать новый JS в старый для лучшей поддержки старыми браузерами
471 2955161
>>2954745

Скажу еще про вебпак. Когда я читал про него статьи, то 10/10 статей хвалили его как идеальный инструмент. Но когда я столкнулся с ним на практике, я был шокирован насколько плохо он продуман:

1) вебпак по умолчанию пытается склеить все ресурсы в один JS-файл. То есть все твои 100 CSS-файлов, 100 JS и 100 картинок склеиваются в один гигантский файл. И пользователь вынужден грузить этот файл, даже если на странице нужно всего 5 скриптов из 100. Гениально придумано.

Чтобы разбить код на несколько файлов, надо добавлять специальные плагины, о чем в большинстве туториалов не пишут. Какие умные люди авторы этих туториалов.

2) так как CSS и картинки вставляются в JS, это ломает инструменты разработчика и делает отладку максимально неудобной.

3) при транспиляции код в браузере выглядит не как исходный. Инвалиды придумали map-файлы, которые должны в теории решать проблему, но в реальности, если у тебя используется несколько плагинов, то map ломаются где-то в одном из них и нужно много часов, чтобы разобраться, в каком. Я решил не тратить на это время, так как неизвестно, возможно ли починить это в итоге.

4) вебпак придумывает свои нестандартные расширения к языку JS вместо того, чтобы следовать стандартам. Он, например, поощряет импортировать картинки и CSS файлы в JS с помощью import. То есть у тебя код будет не соответствовать стандарту EcmaScript.

5) в конфиге webpack по умолчанию используются устаревшие убогие require вместо ES modules.

6) конфиг вебпак это скрипт, а не конфиг, и его невозможно обрабатывать амтоматизированными средствами

7) вебпак не позволяет в dev-среде просто подключать исходные файлы без склейки и обработки. Разработчику удобнее, когда не надо ставить ноду, npm и что-то компилировать и ждать минуту или больше

8) склеивание файлов было придумано как борьба с недостатками HTTP/1. В век HTTP/2 многие недостатки исправлены и я планирую найти время и изучить, можно ли отказаться от сборки вообще
472 2955162
>>2954762

gulp не устарел лет 5 назад?
473 2955195
>>2954793

> validate (Enroll


Зачем ты пробел ставишь? Это нарушает PSR.

> private array $rules;


Здесь хорошо бы добавлять phpDoc-комментарий с описанием структуры массива. А то при чтении кода непонятно, что в него можно передавать. Я давал выше ссылку, как это описывать (добавить phpDoc-тег @var).

> Зачем я сделал это:


>>throw new ArrayNotExistsException("Массива под таким ключом не существует. ");


> Потому что дальше идет цикл foreach, если result это null, то что он будет делить на ключ и значение?



Ты сделал неправильно. Вот представь, ты выводишь форму и хочешь получить список ошибок для поля name. И у тебя будет выбрасываться исключение, если ошибок нет. А должен просто возвращаться пустой массив.

Исключение обычно выбрасывают в исключительных ситуациях. То, что пользователь правильно заполнил форму без ошибок - это стандартная ситуация.

> private string $errorText = "Это поле обязательно для заполнения.";



А не лучше ли тут сделать константу, если ты никогда не меняешь это поле? Почему оно сделано полем? Или ты планировал разрешить указывать другое сообщение через конструктор при создании правила?

> private array $reviewResources =



Мне кажется, тут лучше сделать 4 поля, а не массив с 4 элементами. Так как код будет проще, ты все равно никак не используешь функции работы с массивами. То есть выгоды от использования массива я не вижу, а код без него будет короче и проще.

> public function __construct(string $patternForSymbol, string $patternForString, array $verbalDescriptionOfPatterns)



Длинные заголовки надо переносить по PSR.

> patternForSymbol



Английский язык позволяет записать это как symbolPattern (шаблон символа), что короче.

> $letter = $value[$i];



Так нельзя делать. Чтобы получить i-й символ, надо использовать mb_substr или iconv_substr. А через квадратные скобки ты получаешь не i-й символ, а i-й байт (символ может состоять из нескольких байт, и русскую букву ты так не получишь никогда).

> implode(", ", $resultForSymbol)



Здесь желательно удалить повторяющиеся символы, чтобы не было "вы использовали неправильные символы: &, &, &, &".

> return ($invalidSymbols) ? $invalidSymbols : null;



А зачем ты превращаешь пустой массив в null? Возвращай пустой массив, если все ок.
473 2955195
>>2954793

> validate (Enroll


Зачем ты пробел ставишь? Это нарушает PSR.

> private array $rules;


Здесь хорошо бы добавлять phpDoc-комментарий с описанием структуры массива. А то при чтении кода непонятно, что в него можно передавать. Я давал выше ссылку, как это описывать (добавить phpDoc-тег @var).

> Зачем я сделал это:


>>throw new ArrayNotExistsException("Массива под таким ключом не существует. ");


> Потому что дальше идет цикл foreach, если result это null, то что он будет делить на ключ и значение?



Ты сделал неправильно. Вот представь, ты выводишь форму и хочешь получить список ошибок для поля name. И у тебя будет выбрасываться исключение, если ошибок нет. А должен просто возвращаться пустой массив.

Исключение обычно выбрасывают в исключительных ситуациях. То, что пользователь правильно заполнил форму без ошибок - это стандартная ситуация.

> private string $errorText = "Это поле обязательно для заполнения.";



А не лучше ли тут сделать константу, если ты никогда не меняешь это поле? Почему оно сделано полем? Или ты планировал разрешить указывать другое сообщение через конструктор при создании правила?

> private array $reviewResources =



Мне кажется, тут лучше сделать 4 поля, а не массив с 4 элементами. Так как код будет проще, ты все равно никак не используешь функции работы с массивами. То есть выгоды от использования массива я не вижу, а код без него будет короче и проще.

> public function __construct(string $patternForSymbol, string $patternForString, array $verbalDescriptionOfPatterns)



Длинные заголовки надо переносить по PSR.

> patternForSymbol



Английский язык позволяет записать это как symbolPattern (шаблон символа), что короче.

> $letter = $value[$i];



Так нельзя делать. Чтобы получить i-й символ, надо использовать mb_substr или iconv_substr. А через квадратные скобки ты получаешь не i-й символ, а i-й байт (символ может состоять из нескольких байт, и русскую букву ты так не получишь никогда).

> implode(", ", $resultForSymbol)



Здесь желательно удалить повторяющиеся символы, чтобы не было "вы использовали неправильные символы: &, &, &, &".

> return ($invalidSymbols) ? $invalidSymbols : null;



А зачем ты превращаешь пустой массив в null? Возвращай пустой массив, если все ок.
474 2955207
>>2955162
Да даже если и устарел. Замени название на любимый таск менеджер твоего протыка. По сути ничего не изменится. Есть файлы стилей, есть папка public, в которую их надо высрать.
475 2955209
>>2954793

> Я подумал, что клепать 10 свойств - тупо и решил сделать одно - $reviewResources, в котором буду хранить все, что нужно для этой валидации.



Это плохая идея, заменить свойства на элементы массива, так как:

- код становится длинее, ты пишешь $this->props['someProp'] вместо $this->someProp
- код становится непонятнее, так как у тебя не описано, какие свойства могут быть в массиве, каких они типов
- для свойств проверяются имена и типы данных, которые в них записываются, а в массив можно записать что угодно и ошибки не будет

Я не вижу плюсов. Если бы тебе надо было работать с набором свойств как с массивом, применять функции для работы с массивами, тогда еще можно было бы подумать. Но тут я вижу только недостатки и никаких плюсов. В твоем посте я тоже аргументов в пользу такого решения не вижу.

> Ведь именно для этой валидации мне понадобилось так много свойств...



4 это не много. Много это 50 и больше. Но даже в этом случае надо не заменять свойства на массив, а искать другие идеи (например, разбить класс на несколько классов)
476 2955233
>>2954793

> Проверить каждый символ на паттерн, в котором перечислены корректные символы, если символ не проходит совпадение = он некорректный


> Проверить каждое значение на то, что его структуру +- нормальная, чтобы не было всяких И,в,а,н,о,в,ы,х,



Ну вот это кстати 2 разных задачи. Для их решения лучше сделать 2 разных правила. Ты смешиваешь 2 задачи в одном классе и усложняешь код. Тут надо сделать 2 отдельных класса и все проблемы с кодом решатся сами собой.

> Я не понимаю когда стоит представлять что-то отдельным, а когда массивом



Когда тебе надо что-то хранить, и заранее известны названия и типы данных, используем свойства. Если заранее не известны названия, или элементов может быть сколько угодно, используем массив.

Массив обычно используется для списков каких-то вещей или для "соответствий"/маппингов (например, соответствие номер месяца - название).

Например: у любого студента есть имя, email, дата рождения. Используем свойства. У любого товара есть цена, название, вес. Используем свойства для них.

Другой пример: надо хранить список цветов, в которых доступен товар. У товара может быть сколько угодно цветов. Используем массив (при этом цвета могут быть элементами перечисления Color), по типу:

$this->colors = [Color::RED, Color::BLACK, Color::WHITE];

Пример еще сложнее. Допустим, у товара могут быть разные цвета, и они стоят по-разному. Тут опять нужен массив такого типа:

$this->colors = [
['color' => Color::RED, 'price' => 10000],
['color' => Color::BLACK, 'price' => 20000]
];

Или более красиво, используя объект:

$this->variants = [
new ProductColor(Color::RED, 10000),
new ProductColor(Color::BLACK, 20000),
];

Еще пример. Надо преобразовать номер месяца в название. Используем массив [ 1 => 'Январь', 2 => 'Февраль'...].

Третий пример. Мы загружаем список валют и их курсы. Используем массив, так как валют может быть сколько угодно.
476 2955233
>>2954793

> Проверить каждый символ на паттерн, в котором перечислены корректные символы, если символ не проходит совпадение = он некорректный


> Проверить каждое значение на то, что его структуру +- нормальная, чтобы не было всяких И,в,а,н,о,в,ы,х,



Ну вот это кстати 2 разных задачи. Для их решения лучше сделать 2 разных правила. Ты смешиваешь 2 задачи в одном классе и усложняешь код. Тут надо сделать 2 отдельных класса и все проблемы с кодом решатся сами собой.

> Я не понимаю когда стоит представлять что-то отдельным, а когда массивом



Когда тебе надо что-то хранить, и заранее известны названия и типы данных, используем свойства. Если заранее не известны названия, или элементов может быть сколько угодно, используем массив.

Массив обычно используется для списков каких-то вещей или для "соответствий"/маппингов (например, соответствие номер месяца - название).

Например: у любого студента есть имя, email, дата рождения. Используем свойства. У любого товара есть цена, название, вес. Используем свойства для них.

Другой пример: надо хранить список цветов, в которых доступен товар. У товара может быть сколько угодно цветов. Используем массив (при этом цвета могут быть элементами перечисления Color), по типу:

$this->colors = [Color::RED, Color::BLACK, Color::WHITE];

Пример еще сложнее. Допустим, у товара могут быть разные цвета, и они стоят по-разному. Тут опять нужен массив такого типа:

$this->colors = [
['color' => Color::RED, 'price' => 10000],
['color' => Color::BLACK, 'price' => 20000]
];

Или более красиво, используя объект:

$this->variants = [
new ProductColor(Color::RED, 10000),
new ProductColor(Color::BLACK, 20000),
];

Еще пример. Надо преобразовать номер месяца в название. Используем массив [ 1 => 'Январь', 2 => 'Февраль'...].

Третий пример. Мы загружаем список валют и их курсы. Используем массив, так как валют может быть сколько угодно.
477 2955242
>>2954793

> В сигнатуре метода интерфейса указано, что $value должно быть mixed, но, проверяя год, мы же не можем указать mixed, ведь нам конкретно нужен int (года же ведь хранятся в виде int, да? а то я туплю что-то в этом),



Вот ты и открыл одну из проблем ООП. В ООП есть "принцип Барбары Лисков". Он говорит следующее:

- если код рассчитан на работу с объектом класса A, то в него можно передать объект класса-наследника B и код не должен сломаться.

То есть, при наследовании мы должны сохранять совместимость. Именно по этой причине ты не можешь при наследовании удалить метод - так как в этом случае код, который думает, что в классе есть такой метод, сломается.

Ты можешь расширить список принимаемых значений, но не можешь сузить с mixed до int.

Увы, в нынешней реализации ООП никакого простого способа решить эту проблему нету.

> поэтому я оставил mixed для того, чтобы сигнатуры методов совпадали, но добавил проверку типа в самом классе.



Ок, это допустимо.

> YearIsValid



Вообще, вместо "год правильный" было бы лучше сделать облее общее правило "число лежит в диапазоне". Чтобы его можно было и с баллами использовать, например. Баллы это же тоже число.

> Максимальный год - 2023



Ты 1-летнего ребенка в студенты принимать собрался? Минимум надо лет 10-12 ставить.

> Минимальный год я выбрал - 1923



То есть дискриминируешь 102-летних? Ставь с запасом, чтобы не засудили.

> @\S*.


Звездочка допускает 0 символов
477 2955242
>>2954793

> В сигнатуре метода интерфейса указано, что $value должно быть mixed, но, проверяя год, мы же не можем указать mixed, ведь нам конкретно нужен int (года же ведь хранятся в виде int, да? а то я туплю что-то в этом),



Вот ты и открыл одну из проблем ООП. В ООП есть "принцип Барбары Лисков". Он говорит следующее:

- если код рассчитан на работу с объектом класса A, то в него можно передать объект класса-наследника B и код не должен сломаться.

То есть, при наследовании мы должны сохранять совместимость. Именно по этой причине ты не можешь при наследовании удалить метод - так как в этом случае код, который думает, что в классе есть такой метод, сломается.

Ты можешь расширить список принимаемых значений, но не можешь сузить с mixed до int.

Увы, в нынешней реализации ООП никакого простого способа решить эту проблему нету.

> поэтому я оставил mixed для того, чтобы сигнатуры методов совпадали, но добавил проверку типа в самом классе.



Ок, это допустимо.

> YearIsValid



Вообще, вместо "год правильный" было бы лучше сделать облее общее правило "число лежит в диапазоне". Чтобы его можно было и с баллами использовать, например. Баллы это же тоже число.

> Максимальный год - 2023



Ты 1-летнего ребенка в студенты принимать собрался? Минимум надо лет 10-12 ставить.

> Минимальный год я выбрал - 1923



То есть дискриминируешь 102-летних? Ставь с запасом, чтобы не засудили.

> @\S*.


Звездочка допускает 0 символов
478 2955247
>>2954818

> Но я не понимаю какая логика лежит за этим решением.



Логика такая. Мы делаем класс "список ошибок", который хранит поле и список ошибок в нем. Мы делаем универсальный список ошибок, который может работать с любой формой с любыми полями. Мы заранее не знаем, где он будет использоваться, для каких форм, как в них будут называться поля. У нас тут вариантов, кроме массива, не остается.

Если бы ты делал список ошибок только для студента, то можно было бы и поля использовать, и массив. Но лучше делать более обобщенные классы, более универсальные.

Почему? Потому, что завтра тебя могут попросить добавить к списку студентов список преподавателей, список лекций и еще кучу всего. Если у тебя универсальный валидатор и универсальный список ошибок, то ты сможешь их использовать и там. Если же ты делаешь валидтор только для студентов и список ошибок только для студентов, то ты не сможешь их повторно использовать.

Поэтому надо стараться делать классы более обобщенными, но не переходя в крайности. Не валидатор года, а валидатор целых чисел.

> Например, у меня есть две переменные - $patternForSymbols и $patternForString.


> Как мне понять, им лучше быть по одиночке или быть элементами одного массива?



По одиночке, так как название и тип тут заранее известны.
479 2955255
>>2954831

Это плохая идея. Посмотри, как сделаны валидаторы в Симфони.

Там есть 2 класса - класс, который описывает ограничение (например, Length), и класс, который проверяет ограничение (например, LengthValidator).

Код:

- https://github.com/symfony/validator/blob/7.0/Constraints/Length.php
- https://github.com/symfony/validator/blob/7.0/Constraints/LengthValidator.php

Пример использования:

// задаем ограничение, что длина строки от 5 до 10 символов
$constraint = new Length(min: 5, max: 10);

Пример проверки:

$validator = new LengthValidator();
$validator->initialize($context); // это не важно
// проверка
$validator->validate('aaaaa', $constraint);

У них та же проблема с наследованием. Интерфейс выглядит так: https://github.com/symfony/validator/blob/7.0/ConstraintValidatorInterface.php

> public function validate(mixed $value, Constraint $constraint);



И они в валидаторе с помощью if делают проверки.
479 2955255
>>2954831

Это плохая идея. Посмотри, как сделаны валидаторы в Симфони.

Там есть 2 класса - класс, который описывает ограничение (например, Length), и класс, который проверяет ограничение (например, LengthValidator).

Код:

- https://github.com/symfony/validator/blob/7.0/Constraints/Length.php
- https://github.com/symfony/validator/blob/7.0/Constraints/LengthValidator.php

Пример использования:

// задаем ограничение, что длина строки от 5 до 10 символов
$constraint = new Length(min: 5, max: 10);

Пример проверки:

$validator = new LengthValidator();
$validator->initialize($context); // это не важно
// проверка
$validator->validate('aaaaa', $constraint);

У них та же проблема с наследованием. Интерфейс выглядит так: https://github.com/symfony/validator/blob/7.0/ConstraintValidatorInterface.php

> public function validate(mixed $value, Constraint $constraint);



И они в валидаторе с помощью if делают проверки.
480 2955259
>>2955127

Вся бизнес-логика в модели, генерация плейлиста в модели, в контроллере только извлечение параметров запроса, координация и отдача файла.
481 2955377
>>2955259
Спасибо
482 2955419
>>2955377
Пожалуйста
483 2956085
Есть скрипт php, который запускается nginx через php-fpm. Хочу сделать кастомный конфиг, чтобы через него менять поведение. Как это лучше сделать? неужели каждый раз при запуске читать его?
484 2956087
>>2954925
Спасибо. Но на собес пока не пойду, не хочу тратить попытку впустую. Но идею ты подкинул вери гуд - посмотрю на ютубе собесы https://www.youtube.com/watch?v=qJJBd7YiTK4
485 2956206
>>2956085

Да, читать. Если хочешь ускорить процесс, то есть варианты:

- сделать конфиг в формате php-файла и закешировать его с помощью preload
- кешировать данные конфига в APCu
486 2956276
>>2955195

>Здесь хорошо бы добавлять phpDoc-комментарий с описанием структуры массива. А то при чтении кода непонятно, что в него можно передавать. Я давал выше ссылку, как это описывать (добавить phpDoc-тег @var).


Я раньше не читал про документирование кода.
Погуглив, я понял следующее:
phpDoc - приложение для автоматической генерации документации на основе docBlock.
docBlock - это комментарий в коде, который описывает что-то с помощью краткого описания, более детального и тегов.
Когда берусь за написание такого комментария - встаю в ступор.
Как я понял, опираясь на это: https://docs.phpdoc.org/latest/guide/references/phpdoc/types.html#arrays
Свойство $errors класса ErrorList можно описать так (я не буду писать краткое и детальное описание, а только затрону теги)
/ @var array[] */
Насколько я понял, за тегом идет название типа, который имеют элементы массива.
Но мой массив двумерный и я не знаю как его описывать.
По ссылке, которую ты изначально кинул, я ничего не понял.
Да-да, прости. Да. Туплю.
Спасибо за ответ.
487 2956317
>>2955195
Проверка на структуру значения: https://3v4l.org/GbBpm
Проверка на валидные символы: https://3v4l.org/FgUuP
Проверка на то, что число находится в диапазоне: https://3v4l.org/IZjC3
Проверка на отсутствие пустоты: https://3v4l.org/ugNK6
Класс ErrorList: https://3v4l.org/Uhu5V
488 2956323
>>2956317
Поправил ErrorList, убрал проверку (!$result) {return $result};
https://3v4l.org/UqjhF
489 2956463
Реально ли чистым беком устроится, удаленно?
А то смотрю вакухи и там блядь js. А я ебал в жс ебанутую экосистему влезать с node_modules
490 2956475
Суп вкатуны. Скоро новогодние праздники, будет свободное время, есть идея запилить стрим интенсив для двачеров, написать свой чан. По результату у всех будет возможность форкнуть проект с гита и дальше развивать свои хард скиллы. Развернем докер окружение php Postgres ngnix redis, освоим базовые навыки в формате реального общения на таиче. Фреймворк будет yii2 . Как вам идея?
491 2956502
>>2956475

> Фреймворк будет yii2



Перестать легаси ебать

>>2956463

Конечно. Щас модно апихи делать а фронт отдельной приложухой. Но вообще чаще всего "фуллстэк" это "серверный рендеринг", а значит никакого node_modules. Админка на бутстрапе
492 2956532
>>2956502
Да там пишут список фреймврков иии vue / react и прочее.
Если просто вбить в вакуху на хх название фреймворка то там везде хуйню из жс дописывают.
493 2956536
>>2956532

Ты на Laravel работу ищешь? У этих даунов часто вместе слеплено, потому что они больные и не лечатся.
494 2956562
>>2956536
Да вообще.
И пост для всех, кто знает - ответьте если не трудно.

0. Внизу много чего написано, но вы можете напасать свои знания или что нужно чтобы устроится на работу пыхарем, удаленно и на какие задачи, мол сайты делать, апи писать для мобилок и сайта и прочее, какие задачи там, или инет магазины делать, ну и на какие деньги этот список знаний по технологиям.

1.Если знаешь, напиши как и что искать, на что обращать внимание.
2.Что вообще требуется знать? Про solid, grasp, poeaa, ddd - что спрашивают? Насколько этим обмазываются на работе?
3. Что нужно знать из фреймворков? Что нужно умееть вообще сделать?
4. Как на счет этих знаний oauth2, фильтр товаров, атрибуты товаров EAV, импорт/экспорт обмен товарами между сайтом и 1с какой-нибудь.
5. По базам данных что требуется? Кто должен заниматься проектированием таблиц, или каждый хуярит свою миграцию? Должен ли разраб знать уметь заниматься репликацией,шардированием, партицированием?
6. Что нужно знать и уметь из нагрузки и балансировки нагрузок и маштабировании?
7. А с очередями что? Что должен уметь? Тупо апи вызывать? Или поднимать сервак, подключать апи, настраивать. Какую-нить Сагу замутить следящую?
8. Что по микросервисам, много где требуются? Что из этого знать нужно?
9. Что по Апи? REST API достаточно? Или еще нужно уметь в RPC, SOAP, GraphQL?
10. Докер - понятно. А кубер нужно знать? И Уметь работать с кубером и серверами?
11. Что вы делаете с redis/memcached - храните сессии чтобы люди на разных доменах имели одну сессию между сервисами, или что? Что нужно знать и уметь из этого?
12. Что на счет распределенных данных, баз данных, работа с uuid?
13. Что на счет логов, мониторинга, прометеуса, графаны, ELK стека, ClickHouse и прочее - что из этого нужно знать?
495 2956591
>>2956475
Yii3 ты хотел сказать?
496 2956745
>>2956562

Ты оверпреппишься. Чаще всего тебя на собесе спрорят 5-10 вопросов по php.

5-10 вопросов по базам данных

5-10 вопросов по паттернам и всяким солид хуелид

5-10 вопросов про веб. Ну типа http(как работает протокол), как в вебе делается аутентификация, че такое cookie, че такое сессия.

Ну и все.

Судя по тому что ты высрал, ты уже блять готов. Иди уже на собес бля епта. Все что ты написал это реально пиздатый роадмап, но это не необходимо чтобы найти первую работу(и вторую тоже, лол).

Так шо я советую идти и не ссать. Если не ответишь, узнаешь где не ответил, ответишь потом на другом
497 2957059
Есть из коробки в PHP какой аналог Object.freeze из JS? Типа, превращение объекта в readonly в какой-то момент.
498 2957061
>>2956745
Маам блядь и тут ты меня нашла, хватит меня гнать на работу
499 2957064
>>2956536
Насколько хорошо надо знать фронт, чтобы взяли? Есть вариант вообще без фронта?
500 2957118
>>2957064

>Есть вариант вообще без фронта?



Есть. Знать надо на уровне серверного рендеринга, уметь таблицы наверстать с бутстрапом. Изи короче. Реакт не надо
501 2957305
>>2956562
Ты откуда столько слов знаешь
502 2957306
>>2956475
Хорошая, а где стрим будет?
503 2957307
>>2956475
А, увидел, на твиче
504 2957336
Раз уж затронули тему собесов.
Та роад мапа, которая указана в шапке, это минимум знаний, которыми должен обладать человек, чтобы идти на собес?
505 2957396
>>2957336
Нет. Каждое собеседование уникально
506 2957410
>>2955195
Пока я жду ответа насчет кода валидации, я решил взяться за написание остальных классов.
Посмотри, пожалуйста, эти классы:
https://3v4l.org/i9DUD
https://3v4l.org/rcKTp
https://3v4l.org/hi99gh
Я еще не знаю как буду реализовывать их, поэтому у методов пустое тело и большая часть тайп-хинтов отсутствует.
Я хотел бы, чтобы ты оценил мое разделение функционала между классами и мой выбор функций.
Над модификаторами доступа методов класса Cookie я пока что не думал.
А вот для методов классов регистрации и авторизации, я выбирал модификаторы доступа сознательно. Я думаю, что это неплохо, если я скрою весь функционал за методами authorize() и register()?

Что у меня вызывает сомнение:
Что такое класс Cookie? Часть Модели MVC? Если да, то почему модель лезет в суперглобальную переменную?
Мне в прошлом треде кидали код с классом Cookie.
И там было обращение к $_POST['cookie'], насколько я помню.
Поэтому я думаю, что и мне придется прописывать это.

Я начал писать класс TDG.
И для того, чтобы добавить объект Enrollee в БД, мне нужно было пройтись по его полям.
Я подумал, мб для этой цели мне нужно сделать в классе Enrollee метод "получить список названий всех свойств"?
public function getBlaBlaBla(): array;

$result = $enrollee->getBlaBlaBla();

array - это массив, где ключи - цифровые индексы, а элементы - строки.
пример: array[0] = "name".

Думаю, что будет лучше, если я просто скину код, в котором покажу как буду добавлять новые записи в БД: https://3v4l.org/ZUk8u

Я хотел бы, чтобы ты в первую очередь оценил логику. Можно ли так загружать данные в БД? А потом указывал на ошибки в синтаксисе.

Еще я также подумал о том, что раз у меня и так универсальные геттер и сеттер, то почему бы не сделать их магическими?
Чтобы вместо записи:
$enrollee->get("name");
писать:
$enrollee->name;

Спасибо за то, что отвечал мне.
Извини, если я много тебя напрягаю.
Мой код очень сильно преобразился благодаря твоим ответам.
Я стал чувствовать себя более увереннее.
506 2957410
>>2955195
Пока я жду ответа насчет кода валидации, я решил взяться за написание остальных классов.
Посмотри, пожалуйста, эти классы:
https://3v4l.org/i9DUD
https://3v4l.org/rcKTp
https://3v4l.org/hi99gh
Я еще не знаю как буду реализовывать их, поэтому у методов пустое тело и большая часть тайп-хинтов отсутствует.
Я хотел бы, чтобы ты оценил мое разделение функционала между классами и мой выбор функций.
Над модификаторами доступа методов класса Cookie я пока что не думал.
А вот для методов классов регистрации и авторизации, я выбирал модификаторы доступа сознательно. Я думаю, что это неплохо, если я скрою весь функционал за методами authorize() и register()?

Что у меня вызывает сомнение:
Что такое класс Cookie? Часть Модели MVC? Если да, то почему модель лезет в суперглобальную переменную?
Мне в прошлом треде кидали код с классом Cookie.
И там было обращение к $_POST['cookie'], насколько я помню.
Поэтому я думаю, что и мне придется прописывать это.

Я начал писать класс TDG.
И для того, чтобы добавить объект Enrollee в БД, мне нужно было пройтись по его полям.
Я подумал, мб для этой цели мне нужно сделать в классе Enrollee метод "получить список названий всех свойств"?
public function getBlaBlaBla(): array;

$result = $enrollee->getBlaBlaBla();

array - это массив, где ключи - цифровые индексы, а элементы - строки.
пример: array[0] = "name".

Думаю, что будет лучше, если я просто скину код, в котором покажу как буду добавлять новые записи в БД: https://3v4l.org/ZUk8u

Я хотел бы, чтобы ты в первую очередь оценил логику. Можно ли так загружать данные в БД? А потом указывал на ошибки в синтаксисе.

Еще я также подумал о том, что раз у меня и так универсальные геттер и сеттер, то почему бы не сделать их магическими?
Чтобы вместо записи:
$enrollee->get("name");
писать:
$enrollee->name;

Спасибо за то, что отвечал мне.
Извини, если я много тебя напрягаю.
Мой код очень сильно преобразился благодаря твоим ответам.
Я стал чувствовать себя более увереннее.
507 2957421
Объясните кто-нибудь, приватные свойства наследуются?
Т.е. они как бы есть в классе, но нет возможности к ним обратиться? Или их нет в классе, который наследует?
508 2957422
>>2957410

>$_POST['cookie']


Блять, что я написал.
*$_COOKIE
:^)
509 2957424
>>2957410
Я думаю, что, мб, для того, чтобы Cookie не обращался к $_COOKIE, нужно сделать класс, который будет хранить куки?
Контроллер будет создавать объект такого класса с куки, а Cookie извлекать информацию о куке из него?
510 2957427
>>2957410

>Еще я также подумал о том, что раз у меня и так универсальные геттер и сеттер, то почему бы не сделать их магическими?


Наверное это плохое решение, если окажется, что я где-нибудь забуду инициализировать свойство.
511 2957429
>>2957424
Таким образом Cookie разделился бы на два класса:
https://3v4l.org/hPJgF
https://3v4l.org/qE5QO
512 2958080
>>2956276

phpDoc это приложение для генерации документации из кода и синтаксис для аннотаций. Аннотации пишутся в комментариях тегами вроде @var. Синтаксис там довольно старый, потому к нему придуманы нестандартные расширения, на которые я давал ссылку https://psalm.dev/docs/annotating_code/type_syntax/array_types/

Хотя эти расширения синтаксиса нестандартные, их понимают IDE вроде PhpStorm и анализаторы phpstan, psalm. С их помощью ты можешь описать структуру массива.

> Свойство $errors класса ErrorList можно описать так



Это массив, где ключом является строка, а значением - список объектов Error:

@var array<string, list<ValidatonError>>

PHP дает возможность указать только тип array, а с помощью нестандартных расширений ты можешь описать структуру массива, что делает код понятнее.
513 2958085
>>2956317

> private string $format =


Это можно сделать константой, если не планируется никогда менять.

В остальном, нормально.

В методе ErrorList#getListOfFieldErrors возможно, стоило бы возвращать не строки, а объекты, но строки тоже можно.
514 2958086
>>2956323

Ок, норм.
515 2958088
>>2956475

Хотел бы предупредить, что Yii2 очень устаревший фреймворк.
516 2958090
>>2957059

Думаю, что нет. В Симфони делают так:

- есть класс XBuilder, в котором можно менять значения
- у него есть метод build(), который возвращает объект класса X с неизменяемыми значениями

То есть, делают 2 класса: X и XBuilder. Иногда с помощью трюков (добавлятся поле "isReadonly") их совмещают в один.
517 2958095
>>2957410

Класс Cookie правильнее назвать типа CookieManager, так как он не представляет одну куку, а класс для управления куками.

Вообще, в ООП-фреймворках обычно запрос (с GET, POST, куками) представляют как объект Request, а ответ (с установленными куками, заголовками, телом) как объект Response. И куки добавляют в Response. И никто не лезет в GET/POST и тд напрямую.

Можешь глянуть, как это сделано в Симфони: https://symfony.com/doc/current/components/http_foundation.html

Также, для объектов запроса/ответа есть рекомендация PSR с интерфейсами для них: https://www.php-fig.org/psr/psr-7/

Если делать свое, то лучше по PSR. Но, возможно, для этой задачи это уже перебор.

> class Authorization



Тут стоит сделать такие публичные методы: залогинить человека, разлогинить, определить текущего пользователя. Ты можешь сделать, чтобы все функции работали с объектом Enrollee, либо чтобы в них передавался только токен(пароль). Но чтобы было везде одинаково, а не в одной функции пользователь, а в другой только токен.
518 2958101
>>2957410

> Что такое класс Cookie? Часть Модели MVC?



Вспомогательный класс, который будет вызываться из контроллера наверно. Я бы лично его в MVC никуда не относил.

> Я подумал, мб для этой цели мне нужно сделать в классе Enrollee метод "получить список названий всех свойств"?



Можно. Но вообще, твой TDG не универсальный, потому список полей можно записать в TDG. Так даже логичнее, ведь это TDG отвечает за работу с БД и только он знает, какие в ней есть поля. А студент про базу данных ничего не знает. Тем более, что в студенте в будущем могут быть поля, не сохраняемые в БД.

> Можно ли так загружать данные в БД?


Можно.

> Еще я также подумал о том, что раз у меня и так универсальные геттер и сеттер, то почему бы не сделать их магическими?



Потому что тебе придется все время писать $this->$name. Лучше сделать магические геттер и сеттер тогда через __call.
519 2958103
>>2957421

Да, наследуются, они есть в объекте, но просто недоступны из наследников и предков. Обратиться к ним можно только через методы класса, где они объявлены (то есть наследник может вызвать такой метод и через него что-то сделать).
520 2958104
>>2957421

Вот кстати интересный пример, который любят на собеседованиях:

class A
{
private int $x;
}

class B extends A
{
private int $x;
}

$b = new B();

Ты можешь подумать, что здесь одно и то же свойство $x. Но реально это 2 разных свойства. Код в классе A под именем $x видит свое свойство, а код в классе B свое. То есть, в объекте $b реально 2 свойства с одинаковым именем, но разной областью видимости.
521 2958106
>>2957429

Можно сделать и так. Хотя смысла особо не вижу. В Симфони каждая кука, которую ты ставишь, это это объект класса Cookie, а вот получаемые куки по моему просто идут как строка, а не объект.

https://symfony.com/doc/current/components/http_foundation.html#setting-cookies
522 2958590
>>2958104
Да, интересный пример.
523 2958637
>>2958590
дя интэрэсный прымер)
524 2958663
Хочу написать свой пет-проект, но задумался, стоит ли работать через ORM фреймворка (Ларавель) или с базой через PDO? Есть какие-нибудь рекомендации по пет-проектам?
525 2958686
>>2958637
И к чему ты это высрал, долбаеб?
Пиздец, с какими же даунами приходится сидеть в одном треде.
526 2960545
>>2958663
пиши через ларавель, с сидерами и фабриками, сразу покрывая тестами. Какие-то нативные запросы делаются на этапе оптимизации хайлоада, для получения каких-то особо выёбистых данных или в целом для ускорения сложных выборок. До этого даже не заморачивайся
527 2960901
>>2958663

На практике используют и то, и то.

Если тебе надо получить 20-50 объектов, берем ORM. Если нужен заковыристый запрос с группировками, суммированием, пишем на SQL, иначе глупо будет выбирать из базы >1000 объектов только чтобы циклом сложить пару полей в них.

Ну то есть, надо смотреть по ситуации, какие именно данные тебе нужны.
528 2961319
>>2960901
В ларавеле есть sum, и прочие стандартные арифметические плюшки типа модуля от числа, экстремумы, среднее арифметическое и т.д. И со строками он тоже нормально работает, и даже с чем-то более сложным типа json и датой. Так что я бы посоветовал пользовать функционал ларавеля до победного, пока не упрешься в действительно большие просадки по запросам
529 2961350
>>2958106
Спасибо за ответ.
Я решил отложить пока что написание классов в сторону.
Потому что нужно прояснить общую картину.
Я хотел бы, чтобы ты помог мне с этим.
Я чувствую, что я не понимаю как устроен мой проект и как его составляющие (файлы) взаимодействуют между собой.
Напишу, что у меня есть сейчас в проекте, а ты, мб, сможешь помочь мне прояснить ситуацию.
У меня есть папка public. По твоему совету (если ты codedokode) я вынес корень сервера в нее.
В ней есть index.php
Я положил в public .htaccess и сделал index.php обработчиком всех запросов.
У меня есть папка src. Я скидывал в нее все файлы, в которых объявляются классы.
В этой папке также находится conf.ini (содержит значения для соединения с БД) и init.php (который я завел, опираясь на твой текст, смутно его понимая).
Я сделал автозагрузку классов через composer.
Таким образом моя файловая структура проекта выглядит так:
-public/
--index.php
--.htaccess
-src/
...classes...
--conf.ini
--init.php
-vendor/

У меня нет пока что шаблонов. У меня нет CSS-файлов.
Я не знаю куда я буду их класть, если они будут.
А точнее: как будут называться папки для них, где в моей файловой структуре они будут находиться (на том же уровне, что и public? или внутри public?).

Я не знаю как должна быть устроена папка src.
Я должен выделить в ней отдельную папку Controllers, чтобы положить туда два своих контроллера (я решил назвать их homePage.php и form.php)? А что делать с остальным содержимым? Я должен завести папку Models, куда должен положить свои классы?

Вообще, у меня очень туманное представление о том, как будут выглядеть мои контроллеры.
homePage.php даже не существует, а form.php только недавно начал заполняться содержимым (и он точь-в-точь выглядит так, как ты описывал код для регистрации/редактирования информации в своей статье про Формы).

Я еще очень плохо понимаю как у меня работает автозагрузка через composer.

В файле composer.json есть строка:
"psr-4": {"Acme\\": "src/"}
Это не мое название неймспейса, я скопировал содержимое composer.json из примера какой-то статьи. Автозагрузка у меня работает, если что.

Как я понял, любой файл, чей namespace === Acme, и который находится в папке src, будет подгружаться composerом.

И если я хочу использовать в глобальном пространстве имен (или любом другом, который отличается от неймспейса, в котором находится Validator) Validator, у которого неймспейс, пусть будет Acme, то я должен писать: $validator = new Acme\Validator();
или в начале use Acme\Validator;

Кстати, наверное можно написать и так в composer.json (я видел в одном примере, но тупил и у меня не получилось повторить):
"psr-4": {"": "src/"}
Таким образом будет подгружаться любой файл из src?
И использовать namespace не нужно будет?

Также: я не понимаю зачем конкретно мне использовать namespace, потому что я не собирался подключать сторонние библиотеки. И мой проект - довольно маленький.
Я понимаю, что попади я в большой проект, это могло бы мне аукнуться. У меня ощущение, что я использую namespace без нужды. Т.е., что, конкретно, в моей ситуации они не нужны.
Я не против namespace, но ведь нужно же с умом применять что-либо, понимая нужно оно тебе или нет.

Сейчас, чтобы попасть на страницу localhost (ага, да)/form,
должна осуществиться следующая цепочка:
0) index.php включит файл autoload.php от composer, чтобы подгружать классы (наверное стоит написать "файлы", ведь класс это файл, который содержит объявление класса, кстати, я вот этот момент туплю: composer подключает только файлы-классы или любые файлы, в которых namespace Acme и они находятся в папке src? т.е. будь там контроллер, он бы подключил? да, из-за того, что у меня большая часть кода не написана, я не знаю реализации, не знаю какие ситуации могут быть в моем коде и мне трудно понимать что происходит)
1) Пользователь вводит в адресной строке браузера localhost/form
2) index.php разбирает url, находит строку "/form"
3) index.php включает файл-контроллер form.php
4) form.php прописывает в начале инструкции use namespace для классов, которые он содержит.
5) Если у пользователя не будет ошибок валидации, то нужно вызвать следующую функцию:
header('Location: http://localhost/redirect) (я не думал еще над редиректом, ну, пусть, это будет отдельная страница)
6) Этот запрос также уйдет index.php
7) index.php найдет строку "/refirect" и подключит файл
redirect.html, допустим
Конец.

Да, прости, пожалуйста, что я написал такие обрывки.
Я уже второй час сижу и пытаюсь сформулировать эту ситуацию.
Можешь прокомментировать мои обрывки, сказать где я заблуждаюсь.
Пожалуйста, используй конкретные советы.
Как если бы ты сидел сейчас за моим компьютером и сам бы все это делал. Я уже начитался общих формулировок в стиле: ну то, что не хочешь показывать пользователю - не кидай в public.
Это, конечно, в силу возможности. Я понимаю, что всех деталей моего проекта ты не знаешь.
529 2961350
>>2958106
Спасибо за ответ.
Я решил отложить пока что написание классов в сторону.
Потому что нужно прояснить общую картину.
Я хотел бы, чтобы ты помог мне с этим.
Я чувствую, что я не понимаю как устроен мой проект и как его составляющие (файлы) взаимодействуют между собой.
Напишу, что у меня есть сейчас в проекте, а ты, мб, сможешь помочь мне прояснить ситуацию.
У меня есть папка public. По твоему совету (если ты codedokode) я вынес корень сервера в нее.
В ней есть index.php
Я положил в public .htaccess и сделал index.php обработчиком всех запросов.
У меня есть папка src. Я скидывал в нее все файлы, в которых объявляются классы.
В этой папке также находится conf.ini (содержит значения для соединения с БД) и init.php (который я завел, опираясь на твой текст, смутно его понимая).
Я сделал автозагрузку классов через composer.
Таким образом моя файловая структура проекта выглядит так:
-public/
--index.php
--.htaccess
-src/
...classes...
--conf.ini
--init.php
-vendor/

У меня нет пока что шаблонов. У меня нет CSS-файлов.
Я не знаю куда я буду их класть, если они будут.
А точнее: как будут называться папки для них, где в моей файловой структуре они будут находиться (на том же уровне, что и public? или внутри public?).

Я не знаю как должна быть устроена папка src.
Я должен выделить в ней отдельную папку Controllers, чтобы положить туда два своих контроллера (я решил назвать их homePage.php и form.php)? А что делать с остальным содержимым? Я должен завести папку Models, куда должен положить свои классы?

Вообще, у меня очень туманное представление о том, как будут выглядеть мои контроллеры.
homePage.php даже не существует, а form.php только недавно начал заполняться содержимым (и он точь-в-точь выглядит так, как ты описывал код для регистрации/редактирования информации в своей статье про Формы).

Я еще очень плохо понимаю как у меня работает автозагрузка через composer.

В файле composer.json есть строка:
"psr-4": {"Acme\\": "src/"}
Это не мое название неймспейса, я скопировал содержимое composer.json из примера какой-то статьи. Автозагрузка у меня работает, если что.

Как я понял, любой файл, чей namespace === Acme, и который находится в папке src, будет подгружаться composerом.

И если я хочу использовать в глобальном пространстве имен (или любом другом, который отличается от неймспейса, в котором находится Validator) Validator, у которого неймспейс, пусть будет Acme, то я должен писать: $validator = new Acme\Validator();
или в начале use Acme\Validator;

Кстати, наверное можно написать и так в composer.json (я видел в одном примере, но тупил и у меня не получилось повторить):
"psr-4": {"": "src/"}
Таким образом будет подгружаться любой файл из src?
И использовать namespace не нужно будет?

Также: я не понимаю зачем конкретно мне использовать namespace, потому что я не собирался подключать сторонние библиотеки. И мой проект - довольно маленький.
Я понимаю, что попади я в большой проект, это могло бы мне аукнуться. У меня ощущение, что я использую namespace без нужды. Т.е., что, конкретно, в моей ситуации они не нужны.
Я не против namespace, но ведь нужно же с умом применять что-либо, понимая нужно оно тебе или нет.

Сейчас, чтобы попасть на страницу localhost (ага, да)/form,
должна осуществиться следующая цепочка:
0) index.php включит файл autoload.php от composer, чтобы подгружать классы (наверное стоит написать "файлы", ведь класс это файл, который содержит объявление класса, кстати, я вот этот момент туплю: composer подключает только файлы-классы или любые файлы, в которых namespace Acme и они находятся в папке src? т.е. будь там контроллер, он бы подключил? да, из-за того, что у меня большая часть кода не написана, я не знаю реализации, не знаю какие ситуации могут быть в моем коде и мне трудно понимать что происходит)
1) Пользователь вводит в адресной строке браузера localhost/form
2) index.php разбирает url, находит строку "/form"
3) index.php включает файл-контроллер form.php
4) form.php прописывает в начале инструкции use namespace для классов, которые он содержит.
5) Если у пользователя не будет ошибок валидации, то нужно вызвать следующую функцию:
header('Location: http://localhost/redirect) (я не думал еще над редиректом, ну, пусть, это будет отдельная страница)
6) Этот запрос также уйдет index.php
7) index.php найдет строку "/refirect" и подключит файл
redirect.html, допустим
Конец.

Да, прости, пожалуйста, что я написал такие обрывки.
Я уже второй час сижу и пытаюсь сформулировать эту ситуацию.
Можешь прокомментировать мои обрывки, сказать где я заблуждаюсь.
Пожалуйста, используй конкретные советы.
Как если бы ты сидел сейчас за моим компьютером и сам бы все это делал. Я уже начитался общих формулировок в стиле: ну то, что не хочешь показывать пользователю - не кидай в public.
Это, конечно, в силу возможности. Я понимаю, что всех деталей моего проекта ты не знаешь.
530 2961985
>>2961350

> У меня нет пока что шаблонов.


Можно сделать папку templates

> У меня нет CSS-файлов.


Они должны раздаваться наружу, поэтому можно сделать папку public/css/

> Я должен выделить в ней отдельную папку Controllers, чтобы положить туда два своих контроллера (я решил назвать их homePage.php и form.php)?



Если это классы, то названия файлов должны быть с большой буквы. Если не классы, то не обязательно. Название form.php не очень удачное, так как форм в будущем может быть много. Лучше назвать studentForm.php (или enrolleeForm.php).

> Я должен завести папку Models, куда должен положить свои классы?



Вообще, это сложный вопрос: как раскладывать классы по папкам. Вот ты гуглил? Я не вижу учебников, которые бы этому учили. Симфони использует такую структуру: https://symfony.com/doc/current/best_practices.html#use-the-default-directory-structure

Они группируют классы по типу: все контроллеры в одну папку (можно с поддиректориями если их много), все сущности в другую, все формы в третью итд, все сервисы в четвертую, все исключения в пятую.

Но проблема в том, что обычно в больших приложениях больше всего классов-сервисов и в Симфони они все отправляются в одну и ту же папку, хоть и отвечают за разные вещи. Ты можешь создавать подпапки, но у тебя функционал получается раскидан по разным папкам. Например: сущности для форума лежат в Entity/Forum, сервисы в Service/Forum, формы в Form/Forum.

Вот другой подход, движок для создания интернет-магазинов разбивает код на модули, каждый модуль в своей папке: https://github.com/magento/magento2/tree/2.4-develop/app/code/Magento

То, что я чаще вижу (и в других языках) это разбить проект на компоненты по назначению. А компоненты в свою очередь на более мелкие компоненты так, что классы, делающие похожую задачу, лежат вместе. Например, если у тебя есть форум, блог, новости, то ты делаешь для каждого свою папку. А также папку или папки для общих сервисов, которые нужны везде, вроде загрузки картинок, валидации:

Controllers/
Blog/ все для блога
.....Post/ Посты
.....Comment/ комментарии
.....Rating/ голосование и расчет рейтинга
Forum/
.....Posts/ посты
.....Polls/ функционал опросов
.....Topics/ темы
News/ новости
Users/ регистрация, авторизация
....Profile/ профиль
Shared/ общие сервисы
.....Ads/ реклама
.....Images/ обработка картинок
.....Validation/ валидация
.....Metrics/ сбор данных о посещаемости, просмотрах страниц

В твоем случае классов не очень много и можно их поделить на такие компоненты:

- роутер
- контроллеры (этот компонент отвечает за прием и обработку HTTP-запросов пользователя)
- валидация (универсальные классы, без привязки к студенту)
- студент (модель студента, TDG для него, валидатор студента)
- авторизация
- утилиты (работа с куками и другие вспомогательные классы)
530 2961985
>>2961350

> У меня нет пока что шаблонов.


Можно сделать папку templates

> У меня нет CSS-файлов.


Они должны раздаваться наружу, поэтому можно сделать папку public/css/

> Я должен выделить в ней отдельную папку Controllers, чтобы положить туда два своих контроллера (я решил назвать их homePage.php и form.php)?



Если это классы, то названия файлов должны быть с большой буквы. Если не классы, то не обязательно. Название form.php не очень удачное, так как форм в будущем может быть много. Лучше назвать studentForm.php (или enrolleeForm.php).

> Я должен завести папку Models, куда должен положить свои классы?



Вообще, это сложный вопрос: как раскладывать классы по папкам. Вот ты гуглил? Я не вижу учебников, которые бы этому учили. Симфони использует такую структуру: https://symfony.com/doc/current/best_practices.html#use-the-default-directory-structure

Они группируют классы по типу: все контроллеры в одну папку (можно с поддиректориями если их много), все сущности в другую, все формы в третью итд, все сервисы в четвертую, все исключения в пятую.

Но проблема в том, что обычно в больших приложениях больше всего классов-сервисов и в Симфони они все отправляются в одну и ту же папку, хоть и отвечают за разные вещи. Ты можешь создавать подпапки, но у тебя функционал получается раскидан по разным папкам. Например: сущности для форума лежат в Entity/Forum, сервисы в Service/Forum, формы в Form/Forum.

Вот другой подход, движок для создания интернет-магазинов разбивает код на модули, каждый модуль в своей папке: https://github.com/magento/magento2/tree/2.4-develop/app/code/Magento

То, что я чаще вижу (и в других языках) это разбить проект на компоненты по назначению. А компоненты в свою очередь на более мелкие компоненты так, что классы, делающие похожую задачу, лежат вместе. Например, если у тебя есть форум, блог, новости, то ты делаешь для каждого свою папку. А также папку или папки для общих сервисов, которые нужны везде, вроде загрузки картинок, валидации:

Controllers/
Blog/ все для блога
.....Post/ Посты
.....Comment/ комментарии
.....Rating/ голосование и расчет рейтинга
Forum/
.....Posts/ посты
.....Polls/ функционал опросов
.....Topics/ темы
News/ новости
Users/ регистрация, авторизация
....Profile/ профиль
Shared/ общие сервисы
.....Ads/ реклама
.....Images/ обработка картинок
.....Validation/ валидация
.....Metrics/ сбор данных о посещаемости, просмотрах страниц

В твоем случае классов не очень много и можно их поделить на такие компоненты:

- роутер
- контроллеры (этот компонент отвечает за прием и обработку HTTP-запросов пользователя)
- валидация (универсальные классы, без привязки к студенту)
- студент (модель студента, TDG для него, валидатор студента)
- авторизация
- утилиты (работа с куками и другие вспомогательные классы)
531 2962000
>>2961350

> Как я понял, любой файл, чей namespace === Acme, и который находится в папке src, будет подгружаться composerом.



Да. Класс с полным именем Acme\... будет искаться в папке src. То есть: Acme\SomeClass, Acme\Some\Other\Class и тд.

> И если я хочу использовать в глобальном пространстве имен (или любом другом, который отличается от неймспейса, в котором находится Validator) Validator, у которого неймспейс, пусть будет Acme, то я должен писать: $validator = new Acme\Validator();


> или в начале use Acme\Validator;



Лучше использовать use, код будет чище, и многие IDE умеют сами его вставлять. Но можно и ручками писать, пока учишься.

> Кстати, наверное можно написать и так в composer.json (я видел в одном примере, но тупил и у меня не получилось повторить):


> "psr-4": {"": "src/"}


> Таким образом будет подгружаться любой файл из src?



Это не рекомендуется, но это значит да, если класс не соответствует другим правилам (или других правил нет), то он берется из src.

> я не понимаю зачем конкретно мне использовать namespace, потому что я не собирался подключать сторонние библиотеки. И мой проект - довольно маленький.



Чтобы научиться хорошим практикам. Если нет неймспейсов, то может быть конфликт, когда в твоем коде и в какой-то библиотеке класс с одинаковым названием. Или если ты захочешь класс из одного проекта в другой перенести.

> Я не против namespace, но ведь нужно же с умом применять что-либо, понимая нужно оно тебе или нет.



По моему, проще применять всегда, даже если у тебя всего 5 классов в одной папке.
532 2962032
>>2961350

По неймспейсам, кстати, эту статью помжешь прочесть, если не читал: https://github.com/codedokode/pasta/blob/master/php/autoload.md#%D0%BD%D0%B5%D0%B9%D0%BC%D1%81%D0%BF%D0%B5%D0%B9%D1%81%D1%8B-%D0%BF%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D1%81%D1%82%D0%B2%D0%B0-%D0%B8%D0%BC%D0%B5%D0%BD

> наверное стоит написать "файлы", ведь класс это файл, который содержит объявление класса,



Нет, файл это файл, и он содержит описание класса. А "класс" это какая-то абстрактная штука, которая появляется в памяти после того, как PHP прочтет файл. Или, с другой стороны, класс - это "вид" объекта.

> composer подключает только файлы-классы или любые файлы, в которых namespace Acme и они находятся в папке src?



Он подключает только те файлы, которые соответствуют правилам автозагрузки в composer.json и рекомендации PSR-4. Подключает он их в момент первого обращения к классу, используя механизм автозагрузки. То есть если в коде встречается $x = new X(); то срабатывает автозагрузка и вызывается композер для поиска файла с классом X.

> Сейчас, чтобы попасть на страницу localhost (ага, да)/form,


> должна осуществиться следующая цепочка:


Примерно так и есть. При поступлении HTTP-запроса выполняется public/index.php и его задача выдать какой-то ответ на запрос и умереть.
533 2962035
>>2961319

Неэффективно вытягивать тысячи записей через ORM, чтобы просто посчитать сумму и выкинуть эти записи. Эффективнее посчитать сумму на стороне БД.
534 2962510
https://3v4l.org/vR4M1#v8.3.0

Почему так? Почему в первом случае он добавляет

> and defined in <file>:<line>


А во втором

> in <file>:<line>


Куда делось and defined? Там какая-то дофига хитрая проверка под капотом, которая определяет, вывел ли я место вызова в сообщении?
Вопрос, конечно, имеет чисто академический характер. Мне от этого поведения наоборот удобнее, но было неожиданно, что в зависимости от того, что я пищу в сообщении, он меняет автоматически добавляемую часть.
535 2962593
>>2962035
Добрый вечер, ларавелевские аггрегаторы транслируются во вполне адекватные запросы, не выдумывай.
536 2962654
Какая сейчас средняя зарплата у сеньоров? Насколько реально получать 300к?
537 2962659
>>2962654
Просто судя по вакансиям - 250к ещё получать реально, а за 300 придётся работать клоуном у пидорасов с жопой в мыле.

Алсо, есть тут те кто на фрилансе подрабатывает? Насколько реально без головной боли в месяц 50к поднимать?
538 2962734
>>2962032
Спасибо за ответ.
Я немного застрял на роутинге.
Я поступил очень просто:
https://3v4l.org/rVZCl
Это не готовое решение.
Оценивать его составляющие - бессмысленно.
Акцент только на общем принципе работы.
Хоть это решение неплохо смотрится на моем проекте, который состоит из 2-3 страниц, но, наверное стоит сделать это иначе?
Возможно на ООП?
Я попробовал читать Symfony, это дало мне почти ничего.
Это вообще редко мне что-то дает.
Читал другую статью, в которой автор создавал два класса Route (представляет собой маршрут) и Router (умеет работать с маршрутами). Сначала было понятно, а потом он ушел в какую-то кашу, которую я не понял.
Как ты считаешь, если действительно, стоит сделать маршрутизатор в ООП виде, то как мне стоит это реализовывать?
Извини, если это нагло звучит.
У меня часто так получается, что люди искаженно понимают настроение, с которым я пишу им сообщение.
Если писать откровенно, то я не знаю где грань в нашем диалоге.
Наверное это неправильно, что я засыпаю и засыпаю тебя вопросами.
Но я также понимаю, что мне нужна обратная связь.
Что я многое не знаю.
Не знаю даже как прогугливать определенные темы.
Я стараюсь сначала разобраться в теме сам.
Вообще, если бы не ты, я бы так и сидел, пытаясь делать валидацию.
Только благодаря тебе я смог закончить этот этап создания проекта.
Ну или я бы сидел с той кашей, которую написал, когда принимался за эту задачу.
539 2962871
>>2962734

Насчет роутинга, я вижу 2 варианта:

1) по-простому, как у тебя, с использованием if. Просто, но не очень интересно и не помогает в изучении ООП.

2) по-сложному с использованием ООП.

Делаем класс Route ("маршрут"), представляющий один роут, со свойствами: URL, контроллер. Делаем класс Router ("маршрутизатор"), который в конструктор принимает список роутов, и содержит метод "маршрутизировать" route(string $path): ?Route, который по URL находит и возвращает подходящий роут.

Выглядеть будет так:

$router = new Router([
new Route('/test', 'Controller/test.php'),
new Route('/example', 'Controller/example.php'),
...
]);

$route = $router->route($url);

Обрати внимание, если роут не найден, нужно отдавать страницу ошибки с кодом HTTP-состояния 404. Для этого можно сделать отдельный контроллер.

Также обрати внимание, в REQUEST_URI могут быть еще параметры, по типу /student?x=1&y=2. Их надо отрезать с помощью parse_url(), чтобы они не мешали роутингу.
540 2962880
>>2962734

Что касается роутинга в Симфони, там как раз сделан ООП-роутер, довольно навороченный. Ты описываешь список роутов либо в конфиге в формате YAML, пример:

blog_list:
path: /blog
# the controller value has the format 'controller_class::method_name'
controller: App\Controller\BlogController::list

Либо ты можешь описать роут прямо в коде класса-контроллера с помощью атрибутов PHP8:

class BlogApiController extends AbstractController
{
#[Route('/api/posts/{id}', methods: ['GET', 'HEAD'])]
public function show(int $id): Response
{
....

Также, как ты наверно заметил, в Симфони в роутах могут быть параметры по типу

/api/posts/{id}

Здесь вместо {id} может стоять любое число. Оно будет извлечено из ротуа и передано в аргумент $id у метода show().

То есть при обращении к странице /api/posts/123 будет автоматически создан объект класса BlogApiController и будет вызван его метод show с параметром $id = 123. И как ты видишь из тайп-хинта, он должен сгенерировать ответ и вернуть объект Response.

Я скажу больше, Симфони умеет даже находить объект в БД по id из URL автоматически. То есть, мы могли бы написать:

...
#[Route('/enrollee/view/{id})]
public function viewEnrollee(Enrolllee $enrollee)

И Симфони автоматически найдет в БД студента с id, указанным в URL, и передаст в контроллер.
540 2962880
>>2962734

Что касается роутинга в Симфони, там как раз сделан ООП-роутер, довольно навороченный. Ты описываешь список роутов либо в конфиге в формате YAML, пример:

blog_list:
path: /blog
# the controller value has the format 'controller_class::method_name'
controller: App\Controller\BlogController::list

Либо ты можешь описать роут прямо в коде класса-контроллера с помощью атрибутов PHP8:

class BlogApiController extends AbstractController
{
#[Route('/api/posts/{id}', methods: ['GET', 'HEAD'])]
public function show(int $id): Response
{
....

Также, как ты наверно заметил, в Симфони в роутах могут быть параметры по типу

/api/posts/{id}

Здесь вместо {id} может стоять любое число. Оно будет извлечено из ротуа и передано в аргумент $id у метода show().

То есть при обращении к странице /api/posts/123 будет автоматически создан объект класса BlogApiController и будет вызван его метод show с параметром $id = 123. И как ты видишь из тайп-хинта, он должен сгенерировать ответ и вернуть объект Response.

Я скажу больше, Симфони умеет даже находить объект в БД по id из URL автоматически. То есть, мы могли бы написать:

...
#[Route('/enrollee/view/{id})]
public function viewEnrollee(Enrolllee $enrollee)

И Симфони автоматически найдет в БД студента с id, указанным в URL, и передаст в контроллер.
541 2962882
>>2962734

Что касается вопросов, то этот тред специально сделан для начинающих и их вопросов. Лучше ты тут будешь вопросы задавать, чем потом сеньоров отвлекать.
542 2962887
>>2962510

Не вижу пло ссылке слов "and defined in"
изображение.png94 Кб, 1037x952
543 2962928
544 2963344
>>2962659
Не знаю, для меня выбить 150к - это уже что-то на грани невозможного. Но я забугром сейчас, ищу удаленку.
Вообще, фирмам по большому счету уже плевать сколько платить, для бизнеса это вопрос десятой важности. Всё равно сколько бы ты айтишке не плати, расходы на разработку программного продукта в процентном соотношении к общей выручке минимальные. Сейчас мода наоборот идёт на то, чтобы выцепить из потока айтишной массы самых лучших, как начинающих, так и сеньоров пиздаболов. Я вот например живая посредственность, у меня хоть и есть относительно большой опыт и какие-то знания, меня никуда не берут, потому что нет нужных софт скилов и таланта прыгать выше головы, не чувствуется амбициозность. А знакомый Вася Пупкин, знающий столько же сколько и я, но имеющий себя продать, имеет оффер в 250к
545 2963419
>>2963344

> Не знаю, для меня выбить 150к - это уже что-то на грани невозможного. Но я забугром сейчас, ищу удаленку.


Сколько лет опыта у тебя? Учился ли новому после трудоустройства или хуи пинал?
546 2963534
>>2962928
>>2962510

Кажется, ответ найден в исходном коде функции Exception#__toString (она на языке Си и входит в состав PHP): https://github.com/php/php-src/blob/master/Zend/zend_exceptions.c#L683

https://3v4l.org/hdZqa#v8.3.0

Если класс ошибки TypeError или ArgumentCountErrror и в тексте есть фраза ", called in ", то к сообщению дописывается defined in.

Похоже на хак какой-то.
547 2963625
>>2963534
Ну, собственно, очередная причина почему пхп говноязык.

>Error is the base class for all internal PHP errors.


Вот бы можно было сделать свой класс приватным, чтобы всякие ебланы не использовали его не по назначению и не удивлялись чей-то он работает не так как им надо.
Да не хуйня какая-то. Мама учила делиться.
548 2963656
Сап, что посоветуете изучить джуну?(вкатился на работку, но чувствую что надо прокачивать скиллы и хочется учить что-то вне работы) Интересно узнать мнение сеней
549 2963663
>>2963656
Куда блять вкатился? Ты битриксойд что ли?
550 2963674
>>2963656
Советую пройти курс по русскому языку и курс оператора эвм.
Гениям, которые могут два слова нормально напечатать, сразу лычку мидла дают. А когда научишься знаки препинания ставить - переведут в сеньоры и дадут почетную грамоту "Не еблан".
Дерзай.
551 2963693
>>2963663
laravel
552 2963737
>>2962654
Забавно, что когда речь заходит о зарплате - в треде/чатах сразу наступает молчок. Пыхари, вы там за идею работаете, просто вам стыдно в этом признаться?
553 2963759
>>2963656
Рассказывай как вкатывался
554 2963917
>>2962880
Спасибо за ответ.
Класс Route: https://3v4l.org/BIkla
Класс Router: https://3v4l.org/PmVCS
index.php: https://3v4l.org/XjAUB

>Обрати внимание, если роут не найден, нужно отдавать страницу ошибки с кодом HTTP-состояния 404. Для этого можно сделать отдельный контроллер.


У меня контроллер это просто скрипт.
Что будет делать контроллер, который отвечает за 404-страницу?
Просто подключать 404-page.html?

Кстати, до этого мы обсуждали файловую структуру проекта.
Symfony разделяет понятия "форма" и "шаблон"?
Я так подумал, пройдя по этой ссылке: https://symfony.com/doc/current/best_practices.html#use-the-default-directory-structure
Там есть отдельная папка для templates и для form
Почему?
Я думал, что шаблон это HTML-файл, в котором есть php-переменные (я знаю про разделение HTML и php),
а форма - частный случай шаблона.
Т.е. форма - это HTML-страница с полями для ввода, в которую также можно вставлять php-переменные,
например, для того, чтобы вывести уже заполненные пользователем данные или ошибки валидации.
Короче, я думал, что буду класть в папку templates HTML-страницы, одна из которых будет графически отображать поля для ввода (т.е. форма).

Представление в MVC, в частности в моем проекте, это же просто HTML-страницы, которые
будут подключаться контроллером так: require_once(somePage.html)?
Т.е. вызвать представление = подключить HTML-файл?

Также ты упоминал про атрибуты.
С ними еще связаны аннотации.
Можешь по-простому ответить на следующие вопросы (в контексте php)?
Что такое аннотация?
Что такое атрибут?
Чем они отличаются кроме синтаксиса?
Когда нужно использовать аннотацию, а когда атрибут?
Что получит полезного разработчик, если будет использовать аннотации или атрибуты (не общие примеры, а конкретные,
когда я пытался разобраться в этой теме, у меня сложилось впечатление, что атрибуты нужны для того, чтобы IDE могло
лучше подсказывать что есть в коде)?
Стоит ли мне, новичку, лезть в эту тему? Не рано ли мне это? Просто я еще не понимаю зачем мне все это нужно, я даже
комментарии не пишу в коде, а с момента когда я узнал про тайп-хинты, ведение документации выглядит в моих глазах как нечто
лишнее.
Если мне действительно стоит начать заниматься документированием своего кода, то с чего мне начать?
Что вообще гуглить?
Я пробовал гуглить, смотреть на ютубе.
Но либо я не умею гуглить (что вполне может соответствовать истине), либо я еще не готов к такой информации.
Еще у меня сложилось впечатление, что атрибуты/аннотации это не просто комментарий, текст, а будто что-то большее.
Если это так, то, что это?
Если я добавлю атрибут или аннотацию в код, что-то изменится?
У меня начнет иначе работать код?
554 2963917
>>2962880
Спасибо за ответ.
Класс Route: https://3v4l.org/BIkla
Класс Router: https://3v4l.org/PmVCS
index.php: https://3v4l.org/XjAUB

>Обрати внимание, если роут не найден, нужно отдавать страницу ошибки с кодом HTTP-состояния 404. Для этого можно сделать отдельный контроллер.


У меня контроллер это просто скрипт.
Что будет делать контроллер, который отвечает за 404-страницу?
Просто подключать 404-page.html?

Кстати, до этого мы обсуждали файловую структуру проекта.
Symfony разделяет понятия "форма" и "шаблон"?
Я так подумал, пройдя по этой ссылке: https://symfony.com/doc/current/best_practices.html#use-the-default-directory-structure
Там есть отдельная папка для templates и для form
Почему?
Я думал, что шаблон это HTML-файл, в котором есть php-переменные (я знаю про разделение HTML и php),
а форма - частный случай шаблона.
Т.е. форма - это HTML-страница с полями для ввода, в которую также можно вставлять php-переменные,
например, для того, чтобы вывести уже заполненные пользователем данные или ошибки валидации.
Короче, я думал, что буду класть в папку templates HTML-страницы, одна из которых будет графически отображать поля для ввода (т.е. форма).

Представление в MVC, в частности в моем проекте, это же просто HTML-страницы, которые
будут подключаться контроллером так: require_once(somePage.html)?
Т.е. вызвать представление = подключить HTML-файл?

Также ты упоминал про атрибуты.
С ними еще связаны аннотации.
Можешь по-простому ответить на следующие вопросы (в контексте php)?
Что такое аннотация?
Что такое атрибут?
Чем они отличаются кроме синтаксиса?
Когда нужно использовать аннотацию, а когда атрибут?
Что получит полезного разработчик, если будет использовать аннотации или атрибуты (не общие примеры, а конкретные,
когда я пытался разобраться в этой теме, у меня сложилось впечатление, что атрибуты нужны для того, чтобы IDE могло
лучше подсказывать что есть в коде)?
Стоит ли мне, новичку, лезть в эту тему? Не рано ли мне это? Просто я еще не понимаю зачем мне все это нужно, я даже
комментарии не пишу в коде, а с момента когда я узнал про тайп-хинты, ведение документации выглядит в моих глазах как нечто
лишнее.
Если мне действительно стоит начать заниматься документированием своего кода, то с чего мне начать?
Что вообще гуглить?
Я пробовал гуглить, смотреть на ютубе.
Но либо я не умею гуглить (что вполне может соответствовать истине), либо я еще не готов к такой информации.
Еще у меня сложилось впечатление, что атрибуты/аннотации это не просто комментарий, текст, а будто что-то большее.
Если это так, то, что это?
Если я добавлю атрибут или аннотацию в код, что-то изменится?
У меня начнет иначе работать код?
bg,f8f8f8-flat,750x,075,f-pad,750x1000,f8f8f8.u1.jpg66 Кб, 750x1000
555 2963946
>>2963625

>чтобы всякие ебланы не использовали его не по назначению



ГУГЛИШЬ - А ЕСТЬ ЛИ В PHP ТИПИЗИРОВАННЫЕ МАССИВЫ?
@
ИХ НЕТ
@
НАХОДИШЬ ОБСУЖДЕНИЕ ПРЕДЛОЖЕНИЯ RFC С ЭТОЙ ФИЧЕЙ
@
ИЗ ОБСУЖДЕНИЯ УЗНАЕШЬ, ЧТО ТЫ - ХУЙ, ТВОЯ МАТЬ - ШЛЮХА, А ИХ ОТСУТСТВИЕ - БАЗА. ЭТО БУДЕТ ОЧЕНЬ ПРОБЛЕМНО РЕАЛИЗОВАТЬ, ПОТОМУ ЧТО ЧИТАТЬ ДАЛЕЕ
@
НО НЕ ПЛАЧЬ, МАКАКА. ВСЕГДА МОЖНО СДЕЛАТЬ ДЛЯ ЭТИХ ЦЕЛЕЙ КЛАСС-ОБЁРТКУ С МЕТОДОМ PUSH(), КОТОРЫЙ БУДЕТ КИДАТЬ TYPEERROR, ЕСЛИ ПЕРЕДАННЫЙ В НЕГО ЭЛЕМЕНТ НЕ ЯВЛЯЕТСЯ INSTANCEOF ОЖИДАЕМОГО ТОБОЮ КЛАССА
@
НО ВООБЩЕ, КЛАСС TYPEERROR ДЛЯ ВНУТРЕННЕГО ИСПОЛЬЗОВАНИЯ, ПОШЁЛ НАХУЙ
556 2964013
>>2961985

>В твоем случае классов не очень много и можно их поделить на такие компоненты:



Кстати, у меня есть 2 трейта и интерфейс.
Куда мне стоит их отнести в файловой структуре?
Раз интерфейс относится к валидации (интерфейс для классов-проверятелей), то его стоит отнести в папку Validation?
А трейты в Utility?

Также:
>>2958095

>class Authorization


>Тут стоит сделать такие публичные методы: залогинить человека, разлогинить, определить текущего пользователя.



Я тебя понял так:
Залогинить человека = определить зарегистрированный пользователь или нет.
Определить текущего пользователя = отличить одного зарегистрированного пользователя от другого.

Как я планирую это делать:
Как отличить зарегистрированного пользователя = посмотреть $_COOKIE, если массив не пустой, то пользователь зарегистрирован (потому что при регистрации в куки сохранится пароль).
Да, я знаю о том, что пользователь может потерять куки.
Но мы же в решении задачи опускаем этот момент?
Как отличить одного зарегистрированного пользователя от другого:
Тут я два варианта придумал:
1) При регистрации пользователя создается же новая запись в БД, тогда нужно брать id новой записи и класть его в куки пользователя.
2) Взять пароль из куки пользователя, получить его соленый хеш, сравнить с солеными хешами в БД, если есть совпадение = отдать id.
557 2964024
>>2962880
Есть еще один момент, который для меня туманен.
Я не могу четко сказать который класс Модель, а который, эм, просто класс?
Эта проблема показала себя, когда мы заговорили про класс, работающий с куки.
Я себе троицу Модель-Контроллер-Представление представлял так, что всю работу делает Модель, а контроллер только говорит что именно делать.
Сейчас думаю о классах Регистрация и Авторизация.
По логике выше, Регистрация и Авторизация это части Модели, потому что они выполняют работу - регистрируют и авторизовывают. В то время как Контроллер может указывать Модели, чтобы она зарегистрировала или авторизовала.
Так...А что насчет класса CookieManager?...
Немного есть сомнение насчет того, что этот класс должен существовать. Потому что там сейчас только 2 метода - установить и получить куки.
Но ведь все это можно сделать и во внешнем коде, без всякого класса(?)
Если только контроллер может лазать в суперглобальные переменные, то, наверное он и должен работать с куки?
И если регистрации или авторизации нужны куки, то отдавать их должен контроллер? Так наверное...
Да, короче, одна каша получается.
Извини, если чтение моего поста вызвало у тебя фейспалм.
558 2964073
>>2963917
В index.php
есть такая строка: require_once($route->get('controllerName'));
Скорее всего нужно будет переписать ее.
Ведь контроллеры будут храниться в отдельной папке
src/Controllers/someController.php
559 2964089
>>2963946

>очередная причина почему пхп говноязык


Yep
560 2964104
>>2963759
Через жопу
561 2964110
>>2964104
А говорил что не битриксойд
562 2964153
>>2964110
Все пхпшники в какой-то мере пидоры, не только битриксойды
IMG20231215152956293.jpg2 Кб, 247x93
563 2964422
Пришел а ваш тредик просить о помощи. Я не разработчик, что там происходит в коде не понимаю. Ситуация следущая, есть один нищий, ебаный сайт на bitrix развёрнут он на centos7 через скрипт bitrix-env с сайта Битрикса собственно. Он работает нормально, но мне нужно его перенести с этой машины на другую где нет этой обвязки Битрикса. Версии mysql и php аналогичные на другой машине. Что я сделал, просто скопировал содержимое /www/ и дамп базы, залил всё на новый сервак и нихуя не работает. При попытке зайти на https://mysite/index.php я получаю такой выпук из жопы если нажать f12:
<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Главная");
?>
<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?>


В браузере это отображается как пикрил. То есть просто содержимое index.php котрый в корне сайта. При этом если выполнить тоже самое на работающей машине, там дохуя всего и собственно сам сайт погружается. В логах сервака ошибок не видно никаких. Есть какие-то идеи у местных php гуру и богов Битрикса? С меня как обычно нихуя
564 2964467
Блядь, какой же ебаный ад пишут битриксоиды. У них понятия качества когда вообще в голове нет никакого.
До меня такой ебанат на проекте такого наворотил и съебал в закат. Баг баги баги баги. Пишет модель в базу, через 400 строк они всегда срут прямо в контроллерах пихает метод где ещё в 400 опять достаются модели, перезаписываются частично и опять сохраняются. Туда-сюда, дрочила ты контуженный, а меня потом просят выяснить почему тормозит. Да потому, что код вам обезьяна с битриксом писала.
Правишь код в одном месте - вообще в другом баги лезут.

Как же у меня от этих макак пригорает.
565 2964526
>>2964024

>всю работу делает Модель


Модель отвечает только за данные. Всю работу должны делать сервисы - это отдельный слой.

>Регистрация и Авторизация


Это методы контроллера. К модели они никакого отношения не имеют.
566 2964588
>>2964526
А что делает модель?
567 2964602
>>2964526
Что значит "отвечает за данные"?
Конкретные действия напиши.
Что такое сервис?
Я думал класс, состоящий из методов, это сервис?
И если сервис это не Модель, то где в MVC он находится?

>Это методы контроллера


Зачем контроллеру регистрировать и логинить пользователя, если можно попросить Модель (вызвав какой-нибудь метод authorize()) и она все сделает?
568 2964607
>>2964422

>Версии mysql и php аналогичные на другой машине.


А настройки у них аналогичные? Сравни что выводит phpinfo().
569 2964710
>>2964607
Ну плюс минус да, понятно что не всё переменные. Но я не думаю, что там это как-то влияет. Нигде не пишут что надо какие-то особые пляски с бубном устраивать. Да и другие сайты на php на этом серваке работают, на вордпрессе например. Так, что я думаю дело в чём-то другом.
570 2964721
>>2964710
Ну раз пишут что не влияет, значит не влияет. Все нормально тогда.
571 2964727
>>2964721
Ну как нормально, не работает нихуя, а в остальном нормально.
572 2964735
>>2964727
Но это не из-за настроек, потому что тебе впадлу их проверять?
Этот тред это какой-то магнит для дегенератов.
573 2964883
>>2964602

>Конкретные действия напиши


Конкретные задачи слоя модели ты сам загуглить можешь.

>И если сервис это не Модель, то где в MVC он находится?


А он и не в MVC. Это слой бизнес-логики.
Пишешь, например, сервис для работы со скидками где есть метод расчета скидки для проперженных стульев только сычей и потом ты его можешь вызвать как из контроллера, так и из cli консольной команды своего приложения. При этом когда ты его пишешь, то отлаживаешь именно через консоль, а не дергая браузер за писюн постоянно. Для него же юнит-тесты можно завезти. Потом просто вызываещь этот метод в контроллере с нужными параметрами из запроса и получаешь скидку для сыча по прореженному стулу красного цвета из осины.
Сервисы вообще база разработки.
574 2964890
>>2964883
Чуть позже никто тебе не мешает в контроллере получать запрос и перекидывать его данные в планировщик и уже из планировщика вызывать этот сервис точно так же. Это называется асинхронная обработка запроса. Хотя теб етакое рановато еще - тут про хайлоад.
Т.е. логика бизнеса у тебя инкапсулирована отдельно, а не в mvc и ты с ней отдельно работаешь.
575 2964892
>>2964890
В смысле - в очередь, для воркеров.
Чот устал сегодня, пойду шаурмы куплю на ужин.
IMG20221114111750.jpg87 Кб, 984x950
576 2964920
>>2964735
Да ты прав, я тут напрасно быканул, мои извинения. Перекинул полностью конфиг php завелось, вопрос только не легли ли другие сайты...чувствую надо это говно по контейнерам распихать и не ебаться.
577 2965758
>>2964467
Ты битриксойд?
578 2965942
>>2964467
Тут соглы - хуярим цикл в цикле, внутри делаем запрос в базу. Особенно пикантно, когда это делается в "компоненте" между html и js-ом в куске пхп-кода
579 2966045
Правильно ли я понимаю, что если я использую какую-нибудь ублюдочную функцию из стандартной библиотеки PHP, у которой один из аргументов - ссылка, я должен использовать какую-то промежуточную переменную, если в качестве аргумента для передачи в функцию используется результат выполнения какого-то метода?

https://3v4l.org/5AsvT

Вот. Я бы мог, конечно, обращаться напрямую к $this->arr, но что это за говнина, зачем геттеры и сеттеры вообще тогда нужны? Вдруг в них какие-то дополнительные проверки, модификации и т. д. Без переменной $tmp тут никак, получается?
580 2966287
>>2966045
Ну давай разберем по частям тобой написанное.
1) Можешь ли ты зафорсить использование геттера снаружи объекта? Да можешь. Если геттер это единственный способ получения данных из объекта у тебя есть гарантия что логика геттера будет выполнена.

2) Можешь ли ты зафорсить использование геттера внутри класса? Нет не можешь. Всегда есть прямой доступ к переменной.

Если нет гарантий что внутри объекта будет вызван геттер, то тупо на это закладываться. А значит в геттер нельзя пихать логику для внутренней работы объекта, а только логику для доступа извне.
581 2966405
>>2966287
Звучит логично, но я не уверен. Сейчас у меня геттер просто возвращает значение, сеттер проверяет каждый элемент переданного массива на соответствие типу. Из твоих слов следует, что я должен нигде внутри не использовать сеттер, а копипастить код переборки и проверки на соответствие типа?

Даже если так. Допустим, внутри сеттеры и геттеры использовать не следует. А если у меня дальше должно упасть какое-то исключение?

https://3v4l.org/44QFC

Понимаю, что пример ущербный, если исключение кидать ПЕРЕД сплайсом, то всё будет нормально. Но я так моментально не могу придумать более реалистичный.

Так или иначе, мне кажется, что алгоритм должен быть примерно такой:

1. Текущее значение списка сохраняем в какую-то промежуточную переменную. Использую я здесь геттер, или напрямую обращаюсь к свойству - вопрос вторичный.
2. Делаем всякое.
3. Если в процессе всякого ошибок не возникло, говняка не вылезло, то сохраняем в $this->arr значение нашей промежуточной переменной.

То есть, получается, промежуточную переменную в любом случае стоит использовать. А будет она в себе хранит результат вызова геттера, или являться результатом прямого обращения к $this->arr - вопрос второй.
582 2966587
>>2966405
То что ты тут пытаешься написать это типичный функциональный код. Есть некоторая структура данных, есть отдельная функция, которая с этими данными работает (у тебя это функция которая использует результат getArr()), а чтобы эту структуру изменить и ничего не сломать мы делаем её иммутабельной и изменяем копию. Классика. Детсадовский пример из хаскеля какого-нибудь.

В чем по сути твоя проблема? В том что в твой массив попали данные, которые туда не должны попасть. Почему? Потому что это блядь массив, в который можно запихнуть любую хуйню.
Если ты пишешь ООП код, то у тебя в место массива должен быть объект в который нельзя поместить хуйню. Потому что объект, в отличии от функциональной тупой структуры данных имеет поведение в виде тех самых инкапсулированных правил, которые просто физически не дадут ему перейти в неправильное состояние.

И как итог у тебя из-за этих ебучих геттеров и сеттеров поведение размазано по коду в нескольких местах. В функциональных языках методы хоть и отдельно от структур данных, но хотя бы в одном и том же модуле лежат. А у тебя будет лютый пиздец, вся обработка данных снаружи. По каким правилам она происходит - пиздуй ищи. Да не забудь перебрать все места где эти функции вызывались.
583 2966659
>>2966587

>Если ты пишешь ООП код, то у тебя в место массива должен быть объект в который нельзя поместить хуйню



Так а что этот объект представляет из себя, если не свойство-массив и всякие методы вроде push, remove и т. д, которые позволяют менять содержимое этого массива, и не дают добавить в него говняк?

https://3v4l.org/5UORL#v8.3.0
584 2966745
>>2966659
Как ты заебал. Ну если ты пишешь в функциональном стиле, так сделай блядь его иммутабельным и не еби мозги ни себе ни людям https://3v4l.org/0jCsX

И все все вопросы отпали нахуй сами собой. Не надо никаких блядских геттеров никаких ебаных сеттеров. И копию надо делать ОБЯЗАТЕЛЬНО. Только к ооп такой код никакого отношения не имеет. Да тебе и похуй на то ооп было.
585 2966756
>>2963625

Во многих языках нет приватных классов. Тебе только бы придраться.
586 2966768
>>2963917

Я советую для иммутабельных классов дополнительно писать у полей readonly, чтобы уж точно не поменять было. В index.php надо вызывать контроллер 404 страницы. Контроллеры не надо класть в public.

> Что будет делать контроллер, который отвечает за 404-страницу?



Ограничено лишь глубиной твоей фантазии, но в минимальной версии надо отдать код состояния HTTP 404 и показать хотя бы надпись, что страница не найдена.

> Symfony разделяет понятия "форма" и "шаблон"?



Формы там это классы, в которых описано, какие в форме поля, какого они типа, и тд, вот пример: https://symfony.com/doc/current/forms.html#creating-form-classes

А шаблон это файл с HTML-кодом + конструкции twig.

> Представление в MVC, в частности в моем проекте, это же просто HTML-страницы



Да

> Что такое аннотация?


> Что такое атрибут?



Это штука, которая позволяет добавить к классу, полю, аргументу функции или методу дополнительную информацию. Какую? Да какую хочешь, атрибут это объект любого класса. Ты создаешь класс-атрибут, а затем указываешь его имя и параметры для конструктора и объект-атрибут создается и прикрепляется к классу или методу:

#[MyClass('xyz')]
public int $x;

Дальше ты можешь скриптом получить атрибуты класса, поля итд. Погугли где-нибудь статью про это.

Это используется напрмер, так:

- можно указывать правила валидации поля с помощью атрибутов, валидатор читает атрибуты и применяет к полю указанные в них правила. Так сделано в валидаторе Доктрины.
- можно указывать информацию для ORM, то есть какой колонке соответствует данное поле, какой таблице соответствует данный класс, и ORM будет это использовать.

Раньше атрибутов не было, а добавлять информацию хотелось, поэтому в комментариях писали аннотации типа @var или @ORM\Column. Для PHP это был ничего не значащий комментарий. Были библиотеки, которые парсили комментарии и извлекали из них аннотации в виде объектов. В PHP8 появились атрибуты, которые стали частью языка. Теперь аннотации используются только для phpDoc (так как он не использует классы), а все остальное надо делать атрибутами.

Хочешь - сделай атрибуты для маппинга в базу. Чтобы у тебя не был где-то прописан список полей, которые надо сохранять, а чтобы у полей класса был атрибут, говорящий, в какую колонку таблицы его надо сохранить. Или хочешь, добавь студенту правила валидации через атрибуты. Заодно изучишь их.
586 2966768
>>2963917

Я советую для иммутабельных классов дополнительно писать у полей readonly, чтобы уж точно не поменять было. В index.php надо вызывать контроллер 404 страницы. Контроллеры не надо класть в public.

> Что будет делать контроллер, который отвечает за 404-страницу?



Ограничено лишь глубиной твоей фантазии, но в минимальной версии надо отдать код состояния HTTP 404 и показать хотя бы надпись, что страница не найдена.

> Symfony разделяет понятия "форма" и "шаблон"?



Формы там это классы, в которых описано, какие в форме поля, какого они типа, и тд, вот пример: https://symfony.com/doc/current/forms.html#creating-form-classes

А шаблон это файл с HTML-кодом + конструкции twig.

> Представление в MVC, в частности в моем проекте, это же просто HTML-страницы



Да

> Что такое аннотация?


> Что такое атрибут?



Это штука, которая позволяет добавить к классу, полю, аргументу функции или методу дополнительную информацию. Какую? Да какую хочешь, атрибут это объект любого класса. Ты создаешь класс-атрибут, а затем указываешь его имя и параметры для конструктора и объект-атрибут создается и прикрепляется к классу или методу:

#[MyClass('xyz')]
public int $x;

Дальше ты можешь скриптом получить атрибуты класса, поля итд. Погугли где-нибудь статью про это.

Это используется напрмер, так:

- можно указывать правила валидации поля с помощью атрибутов, валидатор читает атрибуты и применяет к полю указанные в них правила. Так сделано в валидаторе Доктрины.
- можно указывать информацию для ORM, то есть какой колонке соответствует данное поле, какой таблице соответствует данный класс, и ORM будет это использовать.

Раньше атрибутов не было, а добавлять информацию хотелось, поэтому в комментариях писали аннотации типа @var или @ORM\Column. Для PHP это был ничего не значащий комментарий. Были библиотеки, которые парсили комментарии и извлекали из них аннотации в виде объектов. В PHP8 появились атрибуты, которые стали частью языка. Теперь аннотации используются только для phpDoc (так как он не использует классы), а все остальное надо делать атрибутами.

Хочешь - сделай атрибуты для маппинга в базу. Чтобы у тебя не был где-то прописан список полей, которые надо сохранять, а чтобы у полей класса был атрибут, говорящий, в какую колонку таблицы его надо сохранить. Или хочешь, добавь студенту правила валидации через атрибуты. Заодно изучишь их.
587 2966777
>>2963917

> Если мне действительно стоит начать заниматься документированием своего кода, то с чего мне начать?



С README: что это за проект, как его развернуть. Это первое, что нужно.

А так, надо ставить phpDoc-типы там, где не хватает нативных типов. Например, чтобы указать структуру массива.

Все комментировать не надо, комментировать надо не-очевидные вещи. Приватные методы обычно не комментируют, публичные комментируют. Свойства комментируют. Для полей, методов, переменных надо использовать понятные названия.

Приведу пример:

- если функция называется getSudentCount, не надо комментировать, что она считает количество студентов, это понятно из названия. А вот если она считает количество только подтвержденных аккаунтов студентов, то это не очевидно из названия и надо указать.

- если функция saveStudent может добавить нового или обновить существующего студента, это не очевидно

Обычно в названии все отразить невозможно (оно будет слишком длинным) и комментарии все-же нужны.

Поищи статью про правильное написание комментариев.

> Еще у меня сложилось впечатление, что атрибуты/аннотации это не просто комментарий, текст, а будто что-то большее.



Атрибут это способ добавления произвольной информации к элементам кода.
588 2966780
>>2963917

> Если я добавлю атрибут или аннотацию в код, что-то изменится?


> У меня начнет иначе работать код?



Нет, чтобы он начал работать по-другому, ты сам должен искать атрибуты в коде и менять поведение. PHP безразличны твои атрибуты.
589 2966791
>>2963946

Типизированных массивов не будет, пока нет обощенных типов. Как они иначе могут взяться.

>>2964013

> Раз интерфейс относится к валидации (интерфейс для классов-проверятелей), то его стоит отнести в папку Validation?



Если ты следуешь принципу "класть вместе классы, делающие одно дело", то да. Если ты следуешь принципу "класть классы по типу в разные папки", то интерфейс идет в папку interfaces (не советую).

> А трейты в Utility?



Если они вспомогательные, то да.

> Залогинить человека = определить зарегистрированный пользователь или нет.



Это значит выставить правильные куки, чтобы он был залогиненным.

> Определить текущего пользователя = отличить одного зарегистрированного пользователя от другого.



Проверить куки на правильность и вернуть либо null, либо текущего залогиненного студента как объект.

> 1) При регистрации пользователя создается же новая запись в БД, тогда нужно брать id новой записи и класть его в куки пользователя.



Тогда хакер может положить себе в куки чужой id и взломать твою систему.

> 2) Взять пароль из куки пользователя, получить его соленый хеш, сравнить с солеными хешами в БД, если есть совпадение = отдать id.



Это уже лучше. Только в куке не надо хранить пароль в открытом виде, а тот самый соленый хеш.

Есть еще вариант 3 - при регистрации генерировать длинный случайный токен, и класть его в базу и в куки пользователю. Хакер его точно не подберет.
589 2966791
>>2963946

Типизированных массивов не будет, пока нет обощенных типов. Как они иначе могут взяться.

>>2964013

> Раз интерфейс относится к валидации (интерфейс для классов-проверятелей), то его стоит отнести в папку Validation?



Если ты следуешь принципу "класть вместе классы, делающие одно дело", то да. Если ты следуешь принципу "класть классы по типу в разные папки", то интерфейс идет в папку interfaces (не советую).

> А трейты в Utility?



Если они вспомогательные, то да.

> Залогинить человека = определить зарегистрированный пользователь или нет.



Это значит выставить правильные куки, чтобы он был залогиненным.

> Определить текущего пользователя = отличить одного зарегистрированного пользователя от другого.



Проверить куки на правильность и вернуть либо null, либо текущего залогиненного студента как объект.

> 1) При регистрации пользователя создается же новая запись в БД, тогда нужно брать id новой записи и класть его в куки пользователя.



Тогда хакер может положить себе в куки чужой id и взломать твою систему.

> 2) Взять пароль из куки пользователя, получить его соленый хеш, сравнить с солеными хешами в БД, если есть совпадение = отдать id.



Это уже лучше. Только в куке не надо хранить пароль в открытом виде, а тот самый соленый хеш.

Есть еще вариант 3 - при регистрации генерировать длинный случайный токен, и класть его в базу и в куки пользователю. Хакер его точно не подберет.
590 2966794
>>2964024

Проблема со словом Модель, что его используют в 2 смыслах:

1) модель как часть MVC - весь код с бизнес-логикой
2) модель как класс, который представляет какую-то сущность типа Студент, Заказ, Товар

Из-за этого путаница.
591 2966796
>>2964024

> А что насчет класса CookieManager?...



Может быть, это просто вспомогательный класс.

> И если регистрации или авторизации нужны куки, то отдавать их должен контроллер? Так наверное...



Желательно, да. Либо просить кого-то отдать куки.
592 2966799
>>2964422

У тебя не включена поддержка коротких тегов <?, а только <?php в настройках php.ini. А битрикс похоже использует эти древние короткие теги.
593 2966801
>>2964467

Проверять все же лучше профайлером, а не глядя на код и гадая.
594 2966802
>>2964526

Не согласен, в MVC сервисы это часть M(model). Никакого "отдельного слоя сервисов" в MVC нету.

Слой сервисов - это другой взгляд на код, как тут: https://martinfowler.com/eaaCatalog/serviceLayer.html
595 2966803
>>2964883

Давай ссылку либо точный запрос, по которому будет статья. А то если гуглить, то выпадает куча SEo-мусора. Ты и не гуглил сам наверно, и не проверял.
596 2966809
>>2966045

> , я должен использовать какую-то промежуточную переменную, если в качестве аргумента для передачи в функцию используется результат выполнения какого-то метода?



А как иначе? Ведь по ссылке ты должен передать "место", в которое можно что-то записать. Число или строка не подходят, подойдет переменная.

> Я бы мог, конечно, обращаться напрямую к $this->arr, но что это за говнина, зачем геттеры и сеттеры вообще тогда нужны?



Геттеры-сеттеры обычно для внешнего кода. А внутри класса можно лезть напрямую, ты ведь и так знаешь, есть там какая-то логика или нет. А можно и через сеттеры, хоязин класса - барин.
image.png127 Кб, 842x427
597 2966846
Посоны, расскажите про эти докблоки.
Их самим нужно писать или это автоматом пхпшторм делает? Если я работаю в вскоде, то нужно их делать? Или вот захотел библиотечку на гитхаб залить, нужно эту хуйню делать. И нахуя она вообще нужна?
598 2967032
>>2966768
Спасибо за ответ.

Прочитав несколько раз твое объяснение, прочитав мануал по php, пробуя писать тестовый код, вот что я понял про атрибуты:

Для того, чтобы создать класс-атрибут:

1) Создать просто класс:
class SomeClass {}

2) Дописать сверху #[Attribute]

#[Attribute]
class SomeClass{}

Как использовать?

Если нужно описать что-то с помощью этого атрибута:

#[SomeClass('description')]
public int $number;

Получается атрибут для поля number.

Для того, чтобы получить атрибут:

1) Понять какую сущность описывает атрибут (поля, метод, класс и т.д.)
2) Создать объект соответствующего класса:

ReflectionClass::getAttributes() - Получает атрибуты класса
ReflectionClassConstant::getAttributes() - Получает атрибуты констант
ReflectionFunctionAbstract::getAttributes() - Получает атрибуты функций
ReflectionParameter::getAttributes() - Получает атрибуты параметров

Особенности получения атрибутов, конечно, нужно смотреть в мануале уже.

например, получить атрибуты конкретного поля конкретного класса
$property = new ReflectionProperty('вписать название класса, в котором содержится атрибут поля', 'вписать название поля для которого указан атрибут');
В этой строке я получаю только объект ReflectionProperty.
После этого, как по мануалу, я должен получить атрибуты:
$attributes = $property->getAttributes();
А потом уже могу вызывать методы атрибута (получить аргументы, имя).

У классов, которые начинаются с ReflectionClass... существуют методы:
getAttributes() = получить все атрибуты чего-то конкретного

После получения атрибутов, можно вызывать соответствующие методы:

У атрибута есть методы:
getArguments() = получить аргумент, который передали при создании атрибута
getName() = получить имя атрибута

Как я понял по-вкатунски, раньше люди писали описание в виде комментариев, а теперь можно писать описание и представлять его объектом.
598 2967032
>>2966768
Спасибо за ответ.

Прочитав несколько раз твое объяснение, прочитав мануал по php, пробуя писать тестовый код, вот что я понял про атрибуты:

Для того, чтобы создать класс-атрибут:

1) Создать просто класс:
class SomeClass {}

2) Дописать сверху #[Attribute]

#[Attribute]
class SomeClass{}

Как использовать?

Если нужно описать что-то с помощью этого атрибута:

#[SomeClass('description')]
public int $number;

Получается атрибут для поля number.

Для того, чтобы получить атрибут:

1) Понять какую сущность описывает атрибут (поля, метод, класс и т.д.)
2) Создать объект соответствующего класса:

ReflectionClass::getAttributes() - Получает атрибуты класса
ReflectionClassConstant::getAttributes() - Получает атрибуты констант
ReflectionFunctionAbstract::getAttributes() - Получает атрибуты функций
ReflectionParameter::getAttributes() - Получает атрибуты параметров

Особенности получения атрибутов, конечно, нужно смотреть в мануале уже.

например, получить атрибуты конкретного поля конкретного класса
$property = new ReflectionProperty('вписать название класса, в котором содержится атрибут поля', 'вписать название поля для которого указан атрибут');
В этой строке я получаю только объект ReflectionProperty.
После этого, как по мануалу, я должен получить атрибуты:
$attributes = $property->getAttributes();
А потом уже могу вызывать методы атрибута (получить аргументы, имя).

У классов, которые начинаются с ReflectionClass... существуют методы:
getAttributes() = получить все атрибуты чего-то конкретного

После получения атрибутов, можно вызывать соответствующие методы:

У атрибута есть методы:
getArguments() = получить аргумент, который передали при создании атрибута
getName() = получить имя атрибута

Как я понял по-вкатунски, раньше люди писали описание в виде комментариев, а теперь можно писать описание и представлять его объектом.
599 2967054
>>2967032
Чисто по вкатунски: аттрибуты нужны не для описания и не для комментариев. А за ReflectionClass в коде тебе фанеру пробьют и отправят толчки чистить.
600 2967073
>>2967054

>аттрибуты нужны не для описания и не для комментариев


Окей, для чего они нужны?

>А за ReflectionClass в коде


Почему? И если не так получать атрибуты, то как?
601 2967081
>>2967073

>Окей, для чего они нужны?


Тебе выше написали. Чтобы добавить метаинформацию. Например как свойство класса называется в базе.

>Почему? И если не так получать атрибуты, то как?


Получить их можно только через рефлексию. Почему рефлексия кал наберешь в гугле, это не только к пхп относится.
602 2967086
>>2967081

>Чтобы добавить метаинформацию


Да? А я думал, что описание/комментарии это и есть метаинформация.
Разве метаданные это не данные о данных?
А чем комментарий о том, какой тип у переменной, не метаинформация?
603 2967091
В статье на хабре про Reflection API написано:

>И категорически не рекомендуется использовать в рабочем коде проекта, т.к. это ещё и не безопасно.


Почему использовать Reflection API не безопасно?
604 2967092
>>2967091
Потому что можно поменять любой код прямо во время выполнения?
605 2967095
>>2967086

>А чем комментарий о том, какой тип у переменной, не метаинформация?


Метаинформация. Поэтому информацию о типах давным давно перенесли прямо в код и такие комментарии не нужны.
606 2967106
>>2967092
Это вопрос?
607 2967123
>>2967106
Это вопрос?
608 2967158
>>2966791

>Это значит выставить правильные куки, чтобы он был залогиненным.



Я не понимаю что это значит.
Мне словосочетание "выставить правильные куки" ничего не говорит.

Мой код должен уметь две вещи, относительно запоминания пользователя:
1) Добавлять нового пользователя в БД и помечать этого пользователя как зарегистрированного (как уже внесенного в БД);
2) Определять заходил ли пользователь на страницу и если заходил, то внесен ли он в БД.

>Есть еще вариант 3 - при регистрации генерировать длинный случайный токен


Токен и соленый хеш от пароля чем-то отличаются?
609 2967161
>>2967158

>Токен и соленый хеш от пароля


Имеется ввиду 2 понятия:
Токен
Соленый хеш от пароля.
610 2967182
>>2967032

Во-первых, про Reflection. Это набор классов для получения информации о классах, функциях, методах, свойствах. Например, ты можешь с его помощью узнать тип поля, или от кого наследуется класс, или список методов класса. Также с его помощью ты можешь получить атрибуты.

Объект атрибута создается с помощью ReflectionAttribute#newInstance. Вот работающий пример: https://3v4l.org/P6jBF#v8.3.0

1) создаем класс-атрибут (как правило, это полностью иммутабельный класс)
2) навешиваем его на поле
3) через reflection и newInstance() получаем объект атрибута и используем его как хотим

Как я уже писал выше, атрибуты используются для навешивания дополнительной информации на элементы кода: правила валидации, правила сохранения в БД и подобное. Симфони много где использует атрибуты, с их помощью можно даже роуты назначать контроллеру, например.

Я тебе советую сделать что-то на атрибутах, например: добавление правил валидации к полям через атрибуты и добавление информации о том, какие поля сохранять в базу.

> 1) Создать просто класс:


> class SomeClass {}


> #[SomeClass('description')]



Неправильно. У тебя должен быть конструктор, принимающий description, в классе. Смотри мой пример.

> раньше люди писали описание в виде комментариев



Да. Была библиотека doctrine/annotations, которая парсила эти комментарии и создавала объекты-атриубуты. Сейчас это стало фичей языка и костыли больше не нужны.

Раньше это выглядело так:

/**
* @Validator\Constraints\NotBlank("Должно быть заполнено поле")
*/
private string $name;
610 2967182
>>2967032

Во-первых, про Reflection. Это набор классов для получения информации о классах, функциях, методах, свойствах. Например, ты можешь с его помощью узнать тип поля, или от кого наследуется класс, или список методов класса. Также с его помощью ты можешь получить атрибуты.

Объект атрибута создается с помощью ReflectionAttribute#newInstance. Вот работающий пример: https://3v4l.org/P6jBF#v8.3.0

1) создаем класс-атрибут (как правило, это полностью иммутабельный класс)
2) навешиваем его на поле
3) через reflection и newInstance() получаем объект атрибута и используем его как хотим

Как я уже писал выше, атрибуты используются для навешивания дополнительной информации на элементы кода: правила валидации, правила сохранения в БД и подобное. Симфони много где использует атрибуты, с их помощью можно даже роуты назначать контроллеру, например.

Я тебе советую сделать что-то на атрибутах, например: добавление правил валидации к полям через атрибуты и добавление информации о том, какие поля сохранять в базу.

> 1) Создать просто класс:


> class SomeClass {}


> #[SomeClass('description')]



Неправильно. У тебя должен быть конструктор, принимающий description, в классе. Смотри мой пример.

> раньше люди писали описание в виде комментариев



Да. Была библиотека doctrine/annotations, которая парсила эти комментарии и создавала объекты-атриубуты. Сейчас это стало фичей языка и костыли больше не нужны.

Раньше это выглядело так:

/**
* @Validator\Constraints\NotBlank("Должно быть заполнено поле")
*/
private string $name;
611 2967183
>>2967054

> А за ReflectionClass в коде тебе фанеру пробьют



Не пиши чушь. Если ты пишешь свою библиотеку валидации или ORM, то Reflection и атрибуты как раз можно использовать. Да и во многих других случаях.
612 2967184
>>2967091

Потому что дурак статью писал. Если бы это было небезопасно, он бы показал пример и написал, почему. А если не может, то значит слышал звон, да не знает, где он.
613 2967195
>>2967158

Давай начнем со строгих определений:

> Идентификация — это процесс определения личности пользователя, например, по имени или его адресу электронной почты.



> Аутентификация — это сам процесс проверки подлинности пользователя, чтобы убедиться, что он является тем, за кого себя выдает. Для аутентификации пользователи могут вводить пароль, биометрические данные, СМС-код или другие секретные данные.



> Авторизация — это процесс проверки прав доступа пользователя к определенным ресурсам или функциям. Он проводится после успешной аутентификации. В результате авторизации пользователь может получить доступ к определенным файлам, программам и т. д.



Допустим, пользователь на странице банка вводит логин и пароль. Банк проверяет логин - это "идентификация", определение, кто пытается войти. Затем пароль - это "аутентификация", проверка, что пытается войти именно пользователь, а не хакер. Далее пользователь пытается посмотреть историю операций и банк делает "авторизацию" - проверку, что пользователь A имеет право на просмотр истории операций по счету X.

Заметь, что в случае с вебом, идентификация и авторизация происходят не только на форме логина, но и на каждой странице. Обычно послу успешного логина сайт выставляет куку с каким-то секретом (токеном). Браузер отправляет эту куку при заходе на страницу, и сайт идентифицирует и аутентифицирует пользователя по куке.

Кука используется, чтобы можно было войти один раз, и не надо было вводить пароль на каждой странице снова.

Эти 3 этапа есть всегда, даже если регистрации как таковой нет. В задаче про студентов предлагается такой подход: при вводе своих данных сайт генерирует токен и выставляет куку с ним. Когда пользователь заходит с этой кукой на любую страницу, сайт идентифицирует и аутентифицирует пользователя по этой куке.

>> Это значит выставить правильные куки, чтобы он был залогиненным.


> Я не понимаю что это значит.



"залогинить" - установить куки, по которым сайт сможет идентифицировать и аутентифицировать пользователя. "разлогинить" - удалить эти куки.
613 2967195
>>2967158

Давай начнем со строгих определений:

> Идентификация — это процесс определения личности пользователя, например, по имени или его адресу электронной почты.



> Аутентификация — это сам процесс проверки подлинности пользователя, чтобы убедиться, что он является тем, за кого себя выдает. Для аутентификации пользователи могут вводить пароль, биометрические данные, СМС-код или другие секретные данные.



> Авторизация — это процесс проверки прав доступа пользователя к определенным ресурсам или функциям. Он проводится после успешной аутентификации. В результате авторизации пользователь может получить доступ к определенным файлам, программам и т. д.



Допустим, пользователь на странице банка вводит логин и пароль. Банк проверяет логин - это "идентификация", определение, кто пытается войти. Затем пароль - это "аутентификация", проверка, что пытается войти именно пользователь, а не хакер. Далее пользователь пытается посмотреть историю операций и банк делает "авторизацию" - проверку, что пользователь A имеет право на просмотр истории операций по счету X.

Заметь, что в случае с вебом, идентификация и авторизация происходят не только на форме логина, но и на каждой странице. Обычно послу успешного логина сайт выставляет куку с каким-то секретом (токеном). Браузер отправляет эту куку при заходе на страницу, и сайт идентифицирует и аутентифицирует пользователя по куке.

Кука используется, чтобы можно было войти один раз, и не надо было вводить пароль на каждой странице снова.

Эти 3 этапа есть всегда, даже если регистрации как таковой нет. В задаче про студентов предлагается такой подход: при вводе своих данных сайт генерирует токен и выставляет куку с ним. Когда пользователь заходит с этой кукой на любую страницу, сайт идентифицирует и аутентифицирует пользователя по этой куке.

>> Это значит выставить правильные куки, чтобы он был залогиненным.


> Я не понимаю что это значит.



"залогинить" - установить куки, по которым сайт сможет идентифицировать и аутентифицировать пользователя. "разлогинить" - удалить эти куки.
614 2967197
>>2967158

> Токен и соленый хеш от пароля чем-то отличаются?



Токен генерируется из случайных символов, а хеш из пароля.
615 2967230
>>2967183

>Если ты пишешь свою библиотеку валидации или ORM


А за такое сразу ебасос начистят.
616 2967234
>>2967182
Спасибо за ответ.
Я не понимаю зачем мне нужен ReflectionAttribute#newInstance
Разве я не могу получить массив атрибутов для чего-то конкретного в коде и вызывать getName()/getArguments(), чтобы оперировать
значениями названия класса-атрибута и его параметров?
Как, например, тут: https://3v4l.org/qMWIE
Зачем мне промежуточная стадия в виде вызова newInstance()?
617 2967291
>>2967195
Спасибо за подробный ответ.
618 2967746
>>2967234

Потому, что мы используем ООП. Зачем нам выковыривать параметры из массивов каких-то, когда у нас есть объекты с удобными методами.

Также, при вызове getInstance проверяется, что класс-атрибут реально существует и аргументы правильные. А иначе не проводится никаких проверок.

К тому же параметр может быть записан несколькими способами, например: MyAttr('xyz') или MyAttr(name: 'xyz') и ты будешь получать разные форматы массивов.
619 2967772
>>2965758
Нет, это битриксоида на Ларавел пустили. По моему опыту они всегда как программисты слабые. Скриптописатели скорее.
620 2967824
Вы используете в работе оконные функции?
621 2967828
приветик всем гениям пхп дев. я на этапе обучения верстки (css and html), но не_повезло найти работу и мне тимлид дает задания по бэку, где стеки пыха+ларавель, а я вот пару дней назад только начала изучение пхп, поэтому код не читается и сложно мной воспринимается, если кому-то нехуй делать, поотвечайте на мои вопросики в телеге, пожалуйста

velvss
622 2967887
>>2967828
А не подахуел ли твой тимлид? Тимлидит он, зарплату получает он. А на вопросы должны аноны с двачей отвечать? Вот пусть этот хуйлуша и отвечает, нихуя он четко устроился, на анонах воду возить, черт ебаный.
623 2967953
>>2967746
Окей.
В этой строке:
#[NotBlank('Имя заполнять кто будет?')]
private string $name;

Объект какого класса создается? NotBlank или ReflectionAttribute?

Как я понял по var_dump, в этой строке:
$reflProp->getAttributes()
создается массив из объектов класса ReflectionAttribute
И только у объектов этого класса есть методы: getName(), getArguments().
Если я сделаю так:
$reflProp->getAttributes()[0]->newInstance()
создается объект уже класса NotBlank, но NotBlack не обладает методами getName(), getArguments(), а его свойство является
приватным, как мне добывать информацию из атрибута?
Решение, которое я придумал - добавить в класс NotBlank геттер.
Так приемлимо?
624 2968035
>>2966768

>Чтобы у тебя не был где-то прописан список полей, которые надо сохранять, а чтобы у полей класса был атрибут, говорящий, в какую колонку таблицы его надо сохранить



Поля, которые нужно сохранять в БД, - это поля класса Enrollee.
Следуя этому, я делаю так:
Класс-атрибут: https://3v4l.org/o1LDQ
Класс Enrollee: https://3v4l.org/hV5Yd

Дальше я пишу класс TDG, но тут загвоздка:
чтобы получить атрибут поля, нужно сделать так:
$property = new ReflectionProperty('Enrollee', 'имя поля');

Т.е. мой код все равно должен знать какие поля есть у Enrollee, чтобы получать атрибуты.

Изначально речь шла о списке полей Enrollee (о всех его полях, потому что все они добавляются в БД) внутри TDG, но теперь что...?
TDG будет хранить список полей и еще обращаться к рефлексии, чтобы получать атрибуты?

Мб я должен прикреплять атрибуты не к конкретному полю, а к классу Enrollee, тогда я смогу получать атрибуты, не думая какие поля есть в Enrollee?
625 2968204
>>2967824

Смутно припоминаю, может быть 1 раз когда-то использовал. Обычно они нужны, когда тебе надо посчитать несколько разных группировок по одному набору данных.
626 2968208
>>2967953

Reflection содержит представления для всех элементов кода: классов (ReflectionClass), функций, свойств и тд. ReflectionAttribute это рефлекшен для атрибута, позволяющий получать данные о нем, а также создать его экземпляр.

Когда ты вызовешь newInstance() то ты получишь объект NotBlank.

> создается объект уже класса NotBlank, но NotBlack не обладает методами getName(), getArguments(), а его свойство является


приватным, как мне добывать информацию из атрибута?

> Решение, которое я придумал - добавить в класс NotBlank геттер.



Так и надо. Еще можно сделать свойства публичными, но это будет плохо сочетаться с остальным кодом, который использует геттеры.
627 2968212
>>2968035

Название registration не очень, так как я не вообще понимаю, что оно значит и что содержит. А код должен быть понятным другому человеку (ты же будешь в команде работать). Лучше выбрать другое название и добавить комментарий с пояснением.

Дальше, я бы советовал сделать имя колонки необязательным, чтобы его можно было не указывать, в этом случае класс работы с БД просто возьмет название поля. Зачем 2 раза писать одно и то же? То есть, чтобы было:

#[Column]
private string $name;

#[Column('xyz')]
private int $abc;

> Т.е. мой код все равно должен знать какие поля есть у Enrollee, чтобы получать атрибуты.



Ты можешь с помощью ReflectionClass получить легко список полей и дальше найти среди них поля с атрибутом. Вот рефлекшен тебе и пригодился.
628 2968246
>>2968212

>Дальше, я бы советовал сделать имя колонки необязательным, чтобы его можно было не указывать, в этом случае класс работы с БД просто возьмет название поля. Зачем 2 раза писать одно и то же? То есть, чтобы было


Что ты имеешь ввиду?
Ничего не передавать в конструктор объекту-атрибуту?
Что вообще будет обозначать атрибут?
Его наличие для кода будет означать, что это поле нужно добавлять в БД? Т.е. если у поля есть атрибут Column, то его нужно добавлять в БД? А если нет - то класс работы с БД игнорирует его?

>Ты можешь с помощью ReflectionClass получить легко список полей и дальше найти среди них поля с атрибутом. Вот рефлекшен тебе и пригодился


>Окей, я попробую.


Спасибо за ответ.
629 2968580
Скажите, вот есть API. Как с ним обычно работают?
Допустим есть сайт, к примеру ВК, чтобы получить разную инфу нужно обращаться к API.
Как делать?
Вот юзер открывает мой сайт и я сразу отправляю запрос, далее жду ответ, потом обрабатываю и так последовательно? Т.е. это анальная зависимость от работы чужого сервера? Так делают?
630 2968684
>>2968580
Нет. Есть секретная техника чтобы делать эти запросы мгновенно и без зависимости от серверов ВК.
631 2968794
Кто в РФ работает, у вас на работе у всех PHPStorm?
Или vs код?
Как его добыть? Так неохота вирусню скачивать пиздец на лицензионную винду. Хотя есть вариант под линукс скачать и на виртуал боксе запускать.

В общем основной вопрос - вы все на работах на пхпшторме?
632 2968797
>>2968794

>на работе


>лицензионную винду


Ты баба срака из бухгалтерии что-ли? На работе линукс или мак онли.
633 2968798
Прочитал на Хабре про библиотеку ajv, которую используют фронтендщики для валидации... Какое у них все осталое, в Симфони десятки валидаторов на любой вкус и цвет, а у них JSON Schema. JSON Schema просто плохо подходит для валидации по бизнес-правилам, она чисто чтобы описать структуру документа и все.

Не ну правда, почитали бы документацию по Симфони и не изобретали свои примитивные велосипеды. В очередной раз убеждаюсь, что в PHP все лучше, чем в мире фронтендщиков и других языков.
634 2968803
>>2968798
Просто хочу разобраться, а какую библиотеку используют пхп-чиркаши для валидации json'а?
635 2968819
>>2968797
Да я ебал его с ноута сносить, лицензионный. На виртуалке есть
636 2969946
>>2968803
никакие пошёл нахуй
637 2969975
>>2969946
Злюка :p
638 2970247
>>2968212
Я еще давно написал DIContainer по твоему уроку:
https://3v4l.org/cJOHj

Извини, если я неправильно написал аннотации.
Сегодня смотрел видео по psalm, узнал что это анализатор кода.
Ага! Мне не очень хочется пока что разбираться в утилитах по php. Прости, пожалуйста, да, я очень плохой человек, мне очень стыдно. Просто ты из поста в пост пишешь, что мне следует этому научиться, а я ленюсь.

Ну и как раз вопрос (раз затронулась тема комментирования кода), мб мне нужно описывать структуру массива с помощью атрибутов? Я не знаю еще как.
И, возможно, с многомерными массива будет проблема.

Сегодня я вернулся к DIContainer и решил реализовать в нем интерфейс ArrayAccess.

Если почитать мануал php и посмотреть на эту сигнатуру:
public offsetSet(mixed $offset, mixed $value): void

Я точно знаю, что ключами своего контейнера хочу видеть строки (строками, мб, и правильнее, я читал текст по ссылке, которую ты скинул про PSR-11, ну и да, там был метод has(), на который я забил, это настолько критично?), но тут указывается mixed тип, должен ли я делать проверку (на тип) в начале метода и выкидывать исключение?

Это первый момент, а вот второй:
Интерфейс обязывает иметь этот метод:
public offsetExists(mixed $offset): bool
Как мне следует его реализовывать, держа в уме, что у меня 2 свойства-массива - для зарегистрированных сервисов и для созданных объектов?

Собственно вот какой код DIContainer у меня получился:
https://3v4l.org/Yhuue

Если что это черновик.
Я старался добиться только нужной мне функциональности.
638 2970247
>>2968212
Я еще давно написал DIContainer по твоему уроку:
https://3v4l.org/cJOHj

Извини, если я неправильно написал аннотации.
Сегодня смотрел видео по psalm, узнал что это анализатор кода.
Ага! Мне не очень хочется пока что разбираться в утилитах по php. Прости, пожалуйста, да, я очень плохой человек, мне очень стыдно. Просто ты из поста в пост пишешь, что мне следует этому научиться, а я ленюсь.

Ну и как раз вопрос (раз затронулась тема комментирования кода), мб мне нужно описывать структуру массива с помощью атрибутов? Я не знаю еще как.
И, возможно, с многомерными массива будет проблема.

Сегодня я вернулся к DIContainer и решил реализовать в нем интерфейс ArrayAccess.

Если почитать мануал php и посмотреть на эту сигнатуру:
public offsetSet(mixed $offset, mixed $value): void

Я точно знаю, что ключами своего контейнера хочу видеть строки (строками, мб, и правильнее, я читал текст по ссылке, которую ты скинул про PSR-11, ну и да, там был метод has(), на который я забил, это настолько критично?), но тут указывается mixed тип, должен ли я делать проверку (на тип) в начале метода и выкидывать исключение?

Это первый момент, а вот второй:
Интерфейс обязывает иметь этот метод:
public offsetExists(mixed $offset): bool
Как мне следует его реализовывать, держа в уме, что у меня 2 свойства-массива - для зарегистрированных сервисов и для созданных объектов?

Собственно вот какой код DIContainer у меня получился:
https://3v4l.org/Yhuue

Если что это черновик.
Я старался добиться только нужной мне функциональности.
639 2970842
>>2970247

>Сегодня я вернулся к своему велосипеду и решил добавить в него гребной винт и якорь.


>я читал текст по ссылке, которую ты скинул про сборку велосипедов, там была цепь, на которую я забил, это настолько критично?


>но упоминается руль, должен ли я делать рулевое колесо с гидроусилителем или без?


>Если что это черновик.


>Я старался добиться только нужной мне функциональности.

изображение.png39 Кб, 1073x534
640 2971217
Анализатор синтаксиса 3v4l.org не может в DNF, но сам PHP >=8.2 его обрабатывает. Правильно понял?
641 2971584
Напишите кто-нибудь пример вызова setcookie с httpOnly, где только 4 параметра вбиты: имя, значение, время жизни и httpOnly.
Я читал мануал по php, но у меня какая-то хуйня. Вообще не получается перевести httpOnly в true.
Написал код с чужого примера, оставив только параметры name, value и время жизни с httponly:
setcookie('test-1', 'Значение 1', array(
'expires' => time() + 60 60 24 * 30,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'None'
));
сразу все заработало, как написать тоже самое, но только без массива?
643 2971681
>>2971679
Ага, спасибо, анонче.
Оказывается вот так нужно было писать: httponly: true
А я пытался как $httponly=true
644 2972428
Ситуация: нужно вывести php-переменные в html-коде.
Значения хранятся в объектах.
Не хочу в html прописывать логику получения значения из объекта.
Хочу сделать класс ViewHelper, который будет преобразовывать объект так, чтобы в html его можно было вывести просто как переменную или элемент массива.

Дополнение: чтобы получить значение из объекта, мне нужно писать разные инструкции для каждого объекта, поэтому и возник вопрос.

Какой вариант лучше (мб анон предложит свой вариант)?

Первый вариант:
Сделать 2 метода в одном классе: преобразоватьОбъект1, преобразоватьОбъект2.
Мне не нравится этот вариант, потому что теряется универсальность класса.

Второй вариант:
Сделать 2 класса ViewHelper: для Объекта1, для Объекта2 с соответ. методами.
Мне не нравится этот вариант, потому что метод-то один, как-то тупо создавать класс для одного метода?

Третий вариант:
Сделать просто 2 функции, не методы.
645 2972433
Тред последние дни такой мертвый.
Никто ничего ни спрашивает, ни обсуждает, ни спорит, ни отвечает.
646 2972468
>>2972433
Это значит что настало время переката
Перекатывайте тред
647 2972469
>>2972433
Что лучше учить: Ларавель или Симфони?
648 2972474
>>2972469
битрикс
649 2972477
>>2972474
Почему не вордпресс?
650 2972479
>>2972477
Потому что мы в великой России, а не на загнивающем западе. Здесь работы с битриксом намного больше чем по вордпрессу
651 2972485
>>2972468
И что будет?
Все равно никто не пишет.
Я думаю, что перекат стоит делать на посте ~1000.
Так же можно? А то я не сижу на ваших двачах
652 2972488
>>2972469
Не знаю. Я вкатун. Я даже фреймворк никогда не трогал.
653 2972502
>>2972485

>И что будет?


Тред сейчас на дне находится, после переката может люди хоть увидят что пхп-тред существует и начнут заходить сюда
654 2972505
>>2972502
Ну да, мб и так.
655 2972526
Я был пиратом, но хочу учиться
656 2972910
Никто не хочет перекатить тред?
Я могу подготовить пикчи для шапки.
Сам я перекатывать не очень хочу, никогда такое не делал, вдруг облажаюсь :)
Ну и да, я хуй знает как тут перекат работает, перекатывает определенный человек или тот, кто хочет и может.
657 2972911
>>2972433
Ну так айти всё, вкатуны не нужны, мидлы трясутся
658 2972912
>>2972910
Кому хочется и можется тот и перекатывает, главное чтобы это не навредило самому тредику и его обитателям
659 2972926
Вот кто просит симфони инициализировать гит-репозиторий? Я наверно сам решу нужен он мне или нет, а если да, то какой именно. Сейчас целый час потерял, чтобы исправить свой репозиторий из-за симфони-говна. Пришлось выковыривать этот кусок кала жесткими гит-командами и по новой создавать проект на симфони. И они ещё считают свой фреймворк минималистичным! Тот же Ларавель тащит кучу пакетов с собой, но в гит не лезет.
660 2972963
>>2972910
Ладно, я переоценил свои возможности.
Вышла хуйня, картинок не будет.
661 2973256
>>2972910

Не надо пока что, давай я на выходных перекачу. Мы тут обычно не перекатываем сразу после 500-го поста, раньше и по 1000 постов было иногда.
662 2973260
>>2972926

Ты наверно ставил через create-project или что-то подобное, а можно же просто вручную нужные пакеты поставить через композер.

А так вообще все эти заготовки проектов и установщики дурацко сделаны. Всегда надо ставить минимум всего, а не включать фичи, которые могут не понадобиться.
663 2973263
>>2972926

Ну кстати я слышал, у фронтендщиков еще хуже, там при установке какого-нибудь vue тебе предлагают кучу ненужной фигни заодно уставовить, прямо как мейл ру в свое время.
664 2973265
>>2968803

Для PHP есть библиотеки проверка по JSON Schema, но никто в здравом уме не будет использовать это для бизнес-логики. JSON Schema придумана, чтобы проверить, что данные имеют нужную структуру, а не то, что при заполнении заявки на кредит ты ввел имена и телефоны не менее 5 близких родственников.
665 2973272
>>2970247

DIContainer норм, но ты бы мог сделать его соответствующим PSR-11, это несложно. Для callable можно было бы указать в аннотации тип аргумента.

> Ну и как раз вопрос (раз затронулась тема комментирования кода), мб мне нужно описывать структуру массива с помощью атрибутов? Я не знаю еще как.



Ну я же давал где-то выше ссылку, ты пишешь так:

@var array{ x: int, y: int, s: array<string, int> }

> Сегодня я вернулся к DIContainer и решил реализовать в нем интерфейс ArrayAccess.



Почему бы и нет.

> но тут указывается mixed тип, должен ли я делать проверку (на тип) в начале метода и выкидывать исключение?



Можно, но не должен.

> public offsetExists(mixed $offset): bool


> Как мне следует его реализовывать, держа в уме, что у меня 2 свойства-массива - для зарегистрированных сервисов и для созданных объектов?



ArrayAccess позволяет получать и задавать значения по ключу. Ты должен сам подумать, что у тебя тут будет ключом и значением. Можно, например, получать сервисы по имени, тогда offsetExists проверяет, зарегистрирован ли сервис, но тогда надо запретить их менять через ArrayAccess.

Вообще этот интерфейс придуман для классов, которые реализуют какую-то коллекцию, хранилище чего-то.

> Собственно вот какой код DIContainer у меня получился:



Я тут вижу некоторую нелогичность, что ты записываешь в контейнер функции, а получаешь из него по тому же ключу объекты. Мне кажется, это будет запутывать при чтении кода.
665 2973272
>>2970247

DIContainer норм, но ты бы мог сделать его соответствующим PSR-11, это несложно. Для callable можно было бы указать в аннотации тип аргумента.

> Ну и как раз вопрос (раз затронулась тема комментирования кода), мб мне нужно описывать структуру массива с помощью атрибутов? Я не знаю еще как.



Ну я же давал где-то выше ссылку, ты пишешь так:

@var array{ x: int, y: int, s: array<string, int> }

> Сегодня я вернулся к DIContainer и решил реализовать в нем интерфейс ArrayAccess.



Почему бы и нет.

> но тут указывается mixed тип, должен ли я делать проверку (на тип) в начале метода и выкидывать исключение?



Можно, но не должен.

> public offsetExists(mixed $offset): bool


> Как мне следует его реализовывать, держа в уме, что у меня 2 свойства-массива - для зарегистрированных сервисов и для созданных объектов?



ArrayAccess позволяет получать и задавать значения по ключу. Ты должен сам подумать, что у тебя тут будет ключом и значением. Можно, например, получать сервисы по имени, тогда offsetExists проверяет, зарегистрирован ли сервис, но тогда надо запретить их менять через ArrayAccess.

Вообще этот интерфейс придуман для классов, которые реализуют какую-то коллекцию, хранилище чего-то.

> Собственно вот какой код DIContainer у меня получился:



Я тут вижу некоторую нелогичность, что ты записываешь в контейнер функции, а получаешь из него по тому же ключу объекты. Мне кажется, это будет запутывать при чтении кода.
666 2973273
667 2973449
>>2968794
Кстати, подниму вопрос этого анона, самому интересно. Я пока ещё не работаю, только учусь, а в качестве редактора кода использую SublimeText. Однако понимаю что в будущем придётся накатить PHPStorm, но не знаю как это сделать. У самого тоже винда. С меня нихуя тонны нефти и цистерна чая, если кто скинет гайдик какой.
668 2973450
>>2972433
А что, я задавал сюда вопросы периодически, причём вполне адекватные. Меня игнорили.
669 2973467
>>2973263

>vue


И ещё файлы в сердечки превратить
670 2973470
>>2973450
Мб ты не дожидался ответа?
Тут регулярно отвечали только два человека.
Один из них ОП. Он обычно всем отвечает, но раз в какой-то промежуток времени.
671 2973486
>>2973272
Спасибо за ответ.
Как считаешь, должен ли я считать ReflectionClass зависимостью, если без него не работает мой класс? Почти не работает. Ну, конечно, можно было бы обойтись и без рефлексии, если бы я прописал где-то в классе список полей.
672 2973649
>>2973260

>вручную нужные пакеты поставить через композер


Я так не умею. Тем более надо знать какие пакеты он использует, а я только изучаю фреймворк.
673 2973662
>>2972479
Я на прошлой работе делал сайт на вордпрессе для местной думы
674 2973842
Почему у РНР всё так плохо с литературой? В той же джаве пишут фундаментальные книжки по языку, где Java Core разобрана от А до Я. В РНР же вечно какая-то мурзилка из разряда РНР + MySQL + JS + HTML на 400 страничек, где галопом по европам рассказывают верхушки. А хотелось бы книжку, где копают в глубь, чтоб прям разбирались неочевидные моменты, а также обзор сопутствующих тем типа композера, PSR, модель памяти, как там переменные живут внутри РНР, сборка мусора, JIT и т.п.
675 2974959
Что наиболее адекватно использовать, если я хочу по сути List, т. е. массив с ключами [0 ... n] идущими с шагом +1? Есть SplFixedArray, но у него, как я понимаю, основная фича в том, что он Fixed. Можно, конечно, постоянно при добавлении нового элемента вызывать setSize(), но это звучит как-то наркомански.
Или я действительно должен сделать свой класс, реализующий интерфейс ArrayAccess, и в методе offsetSet() падать, если переданный ключ не является [0 ... n] с шагом +1? А встроенного SplList или чего-то типа нет?
676 2975135
Есть сайт https://www.phptutorial.net/

И там есть раздел PDO

В 2к23 году PDO не считается старьём?
677 2975176
Если у класса приватные свойства, есть геттер и сеттер, но я получаю значение с помощью рефлексии, то я делаю плохую вещь? Получается я нарушаю инкапсуляцию? И как-то нелогично получается - где-то в коде я получаю значения через геттер, а где-то через рефлексию?
678 2975177
>>2975135

Не считается.

>>2974959

Либо написать, либо найти готовую библиотеку, не ты первый с этим сталкиваешься. Есть расширение Ds, например: https://www.php.net/manual/ru/class.ds-sequence.php
679 2975179
>>2975176

Рефлексия оставлена для тех случаев, когда геттер и сеттер использовать нельзя или неправильно. Например: отладчик, показывающий содержимое объектов. Библиотека, которая добавляет к объектам новый фукнционал.

Тебе почти никогда не надо ее использовать.

Например, она используется в ORM Doctrine для создания объектов и установки им свойств.
680 2975183
Когда перекат треда, ОП?
681 2975198
>>2973649

Если не умеешь, то значит надо учиться, а не жаловаться.

Список пакетов можно подсмотреть тут: https://github.com/symfony/skeleton/blob/6.3/composer.json

Также, ты можешь просто установить симфони в новой папке и руками удалить папку .git, и будет Симфони без гита.
682 2975200
>>2975177

>Не считается.


Зуб даешь? Или ты меня сейчас обмануешь как пастой про Хацкель?
683 2975203
>>2975183

Скоро, дай на вопросы ответить сначала.

>>2973486

Нет, ReflectionClass мы не будем считать зависимостью. Тут конечно получается некоторая путаница, но в конструктор обычно передают:

- классы-сервисы
- классы с какими-то настройками, которые можно менять (поэтому их передают снаружи, чтобы мы могли менять эти настройки)
- классы, которые можно подменить на другие

ReflectionClass под эти критерии не подходит, так как это встроенный в PHP класс и вряд ли мы будем заменять его на другой, и у него нет каких-то настроек, которые можно менять.

Вижу, что объяснение в статье про DI не очень понятное и логичное ... но пока не знаю, как его можно переписать.
684 2975222
Этот тред закончился. Проходите в следующий тред: >>2975215 (OP)
image.png58 Кб, 1041x762
685 2975894
>>2973449
Ты мой вопрос поднял. Бесплатный аналог - нетбинс. Но сам сижу с вскодом + обмазанный плагинами удалённого доступа, докер, php, мускл
686 2975979
>>2972910
Зачем шапку менять?
687 2982062
>>2973449
На рутрекере есть раздача с кряком
688 2986233
>>2935868
на 0%
потому что кто как хочет так и дрочит
689 3041215
>>2982062
Там вирус
690 3042587
>>2962734
Как-то по коллежу делал свой мини говнофреймворк mvc, там маршрутизация работала. Но по принципу {method} /[controller]/path
И затем есть методы контроллеров, которые имеют аттрибуи HttpGet и так далее, а в них указан path соответствующий

Там магия рефлексии юзалась)
Можешь подумать об этом
Тред утонул или удален.
Это копия, сохраненная 10 марта в 20:54.

Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
« /pr/В начало тредаВеб-версияНастройки
/a//b//mu//s//vg/Все доски