Как это понять ?

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

и зашел в тупик.

Вот эту выделенную красным часть конструкции:

$user=User::model()->find([color="#FF0000"]‘LOWER(username)=?’,array($username)[/color])

как понимать ?

Ведь это вот [color="#FF0000"]‘LOWER(username)=?’[/color] ни на что не похоже…хотя и понятно

что делает…

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_lower

Хорошо, это понятно, давайте еще раз пробежимся по этому вот выражению:


find('LOWER(username)=?',array($username))

Пусть, к примеру,


$username = 'admin'

, т.е. получим:


find('LOWER(username)=?',array(0=>'admin'))

username - это имя столбца в таблице


User

,

и что же тогда мы получим в результате выполнения этой SQL-функции:


LOWER(username)

  • ?

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

Чтобы получить значение этого поля, сначала надо извлечь из б.д. нужную запись.

Из этой штуки наверное получается такой вот SQL-запрос:

WHEARE LOWER(username)=‘admin’

Хотя тоже сомнительно, ведь там LOWER(username)=?

как ‘admin’ попадает в SQL-выражение непонятно.

В yii, вроде как, есть возможность "журналирования", интересно было бы посмотреть

какой SQL-запрос сгенерировался.

Однако, эта штука, действительно, "как ни странно", работает.

По настоящему создатели тут перемудрили, надо было написать попроще как-нибудь,

например, вот так (предполагается, что при записи в б.д. значение поля username

переводится на нижний регистр):


$username=strtolower($this->username);

$user=User::model()->find('username=:usnv',array(:usnv=>$username));

Хотя это и не хорошо, ведь пользователь хочет видеть свой логин таким каким он его

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

из одного регистра в другой представляется сомнительной - пусть вводит нормальный регистрационный логин и все дела.


Да, вот еще попутный вопрос: если условия в find() таковы, ему удовлетворяет не одна, а множество записей ?

find() возвратит первую запись, или как ?


какая разница - в запросе вы в нижний переводите или через strtolower?:)

про find() - да. для нескольких пользуйте findAll

Что-то я не понял. Если я регистрируюсь под ником Sart, то, естественно, ожидаю, что

и в б.д. я буду храниться как username=‘Sart’.

Если я логинюсь, то ввожу Sart, и получается this->username=‘Sart’.

Если сделать как сделано в примере $user=strtolower(this->username),

то меня будут искать в б.д. как ‘sart’ и никогда не найдут.

Там вот и есть какой-то намек, что функция LOWER(username) должна значение ‘Sart’,

хранящееся в б.д. преобразовать в значение ‘sart’ чтобы потом сравнивать со значением,

которое вводится при логине - $user=strtolower(this->username).

Но чтобы получить LOWER(username), нужно сначала поиметь запись из б.д.

Получается замкнутый круг с этим переходом из регистра в регистр.

заюзай лучше вот это расширение и всё будет пучком

yii-user

http://www.yiiframework.com/extension/yii-user/

Это хорошая работа. Я сделал регистрацию, все работает, за одним

исключением-регистрационная форма не хочет рендиться, если вводятся заглавные буквы …виснет и все тут…

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

нет, все нормально, просто вдумайтесь - в базе хранится Sart, LOWER(username) начинает искать по полю username, предварительно переводя его для себя (только для того чтобы произвести выборку, при этом ничего не изменяя в самой записи.) в нижний регистр, и сравнивает с strtolower($this->username), который также в нижнем регистре. Так что никакой разницы нет, как вы храните запись в базе, LOWER() сам все сделает.

Неправда. Всё зависит от типа сравнения, указанного для поля username. Если оно оканчивается на _ci (cp1251_general_ci), то можете искать хоть SART, хоть sArT, все равно запись Sart будет найдена. И я думаю, что в данном случае нужно не утруждать субд переводом каждого нейма в ловеркейз, а использовать корректный тип сравнения.


CREATE TABLE tbl_user

(

    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,

    username VARCHAR(128) NOT NULL,

    password VARCHAR(128) NOT NULL,

    salt VARCHAR(128) NOT NULL,

    email VARCHAR(128) NOT NULL,

    profile TEXT

);

Символьная переменная, это все что для нее задано. Что там по умолчанию, не знаю, но думаю

сравнение на простое совпадение-это очень естественно задать по умолчанию.

В общем, с этим find(‘LOWER(username)=?’,array(0=>$username)) ситуация, как я вижу, зашла в тупик.

Немного разгребусь, гляну "журналирование"

Sart, всё достаточно прозрачно тут и всё понятно, ни каких заморочек нет. при запросе:


find('LOWER(username)=?',array($username))

переменную $username вы тоже должны обязательно перевести в нижний регистр strtolower($username)

При регистрации также нужно делать сверку в нижнем регистре. Тогда не получится кучу разных пользователей с таким вот логинами: Sart, SarT, sArt и т.п.

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

Корректней сделать это средствами СУБД, выставив уникальный индекс на поле.

Да, действительно, таких логинов Sart, SarT, sArt…нам не надо. Просто у меня совершенно нет

опыта в этих делах.

Но все же какой SQL WHEARE-запрос генерируется из этой конструкции.

Если я пишу, к примеру:


$username = 'admin';

find('username=:usv',array(:usv=>$username))

то получается так:


...

WHEARE username='admin'...

...

А если я пишу:


find('LOWER(username)=?',array($username))

Что из этого может получится ?

WHERE LOWER(username) = ‘admin’

Вообще-то, если придерживаться документации, надо бы писать что-то вроде такой конструкции:

find(‘LOWER(username)=?’,array(’?’=>$username))…

Для начала неплохо с ней ознакомиться:

http://www.php.net/manual/en/pdostatement.bindparam.php

http://www.php.net/manual/en/pdostatement.execute.php

Yii использует PDO и предполагает, что программист с ним знаком.

Да, действительно, ознакомиться надо…спасибо.