приведите пример кода, но вообще если вы укажете with('relation') - Yii сделает агрегирующий запрос с IN clause, вместо n комментарием = n запросов. joinWith - оставили для фильтрации результата с использованием таблицы которой делаете join, на сколько я понял, так как с joinWith Yii AR делает все равно агрегирующий запрос с IN clause, можете проверить и посмотреть в дебагере
Пример 1 raw sql
$username = "'; DROP TABLE user; --";
$sql = "SELECT * FROM user WHERE username = '$username'";
\Yii::$app->db->createCommand($sql)->execute();
Этот пример генерирует SQL:
SELECT * FROM user WHERE username = ''; DROP TABLE user; --' - таблица удаляется.
Пример 2 hash format
User::findOne(["username" => "'; DROP TABLE user; --"]);
Этот пример генерирует SQL:
SELECT * FROM `user` WHERE `username`='\'; DROP TABLE user; --' - возвращается пустота
Пример 3 bind values
User::find()->where("username = :username", [":username" => "'; DROP TABLE user; --"])->one();
Этот пример генерирует SQL:
SELECT * FROM `user` WHERE username = '\'; DROP TABLE user; --' - возвращается пустота
Антон Натаров: Имеет смысл делать два входа: для партнера, для пользователя. Две отдельные формы. На фронте это можно сделать красиво - show\hide форм по клику или еще как-то.
Если у вас 2 поля и вам нужно использовать что-то одно для авторизации пользователя, можно использовать skipOnEmpty
Если я правильно понимаю вашу задачу, вам необходимо авторизовать пользователя по одному из полей. Так же нужно учитывать, что при логине валидация в основном заключается только в том, что поле должно быть не пустое, нет смысла валидировать на email (при регистрации - имеет смысл) и говорить, что email не верен - тогда можно понять по какому полю брутфорсить, именно для этого ошибки генерируют общие, типа "Неверно email\nickname\телефон или пароль". Вся остальная механика ложится не на валидатор, а под капотом.
Берете поле 1 - ищите, не нашли, пробуем по 2-му полю - не нашли ? добавляем error "Неверно email\nickname\телефон или пароль".
Но мне кажется странным атворизация по 2-м полям, если это не какая-то специфическая задача, как например в slack, где нужно вводить еще имя команды.
Антон Натаров: насколько я понимаю, валидатор не должен защищать от SQL injection, этим занимается PDO, нужно использовать bind при поиске поля.
static::findOne('email = '.$email) - это выражение подвержено SQL injection
static::findOne(['email' => $email]) - это не должно - тут нужно уточнить на самом деле
static::findOne(['email'=>':email'],[':email'=>$email]) - а поиск через params bind хорошо решает данный вопрос
HaruAtari: Спасибо за такой развернутый комментарий. Тут я описал свой аргумент обобщенно, как "удобство в разработке", но в споре мои аргументы были очень близки к вашим.
Да, конечно я и коллега понимаем, что теряется автокомплит в IDE, но это слабый аргумент, мне так кажется, против аргументов моего коллеги, возможно есть какие-то более весомые аргументы ?
1-й пункт. Например при генерации CRUD, Gii создает UserSearch модель. В эту модель выносить фильтры (которые использует в GridView) и в эту же модель можно, например, добавить свою логику которая касается данной задачи.
Если, например нам нужно привести к формату имя пользователя и таких сервисных методов бывает достаточно много, а так же Model::afterFind, etc - не лучший ли будет все эти методы (которые кстати перезапишутся при использовании Gii) выделить в отдельный класс, назовем его условно UserHelper ?
В таком случае, будет след. иерархия
UserHelper - методы(уникальные для данной модели), валидаторы, rules
UserSearch - фильтры, сортировки
Они унаследуют User модель, которая будет являться только описанием и в случае, когда нам необходимо будет добавить несколько полей в таблицу, при повторной генерации Gii мы не потеряем: методы, rules и прочее
Проверьте, это не займет больше 30-40 минут. Я думаю, что проблем быть не должно.