Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Есть два бандла: Member и Admin, оба зарегистрированы в /application/bundles.php
return array(
'member' => array(
'location' => 'member',
'handles' => 'member',
'autoloads' => array(
'directories' => array(
'(:bundle)/models',
),
),
),
'admin' => array(
'location' => 'admin',
'handles' => 'admin',
'autoloads' => array(
'directories' => array(
'(:bundle)/models',
),
),
),
);
Как реализовать раздельный Auth? Ибо оба эти бандла ездят по одной сессии. Технически могу на уровне флажка админа в табличке users и с проверкой на уровне фильтра, но очень не хочется. Хотелось бы совершенно разные login forms и Auth с ползанием в разные таблицы юзеров и админов. И соответственно независимые сессии.
Случайно, на официальном форуме, натолкнулся на сайт сниппетов, может полезно кому будет:
[laravelsnippets.tk]
Отличный плагин под jQuery для создания анимационной иконки загрузки, может пригодится кому
[fgnass.github.com]
А если к примеру в бандле описать фильтр auth, он же сам будет цепляться ко всем маршрутам бандла, без явного указания
array('before' => 'auth', ...
, я правильно понимаю?
Если так, то похоже у меня избыточный код в проекте, почти все маршруты, за исключением паблик цепляют фильтр member::auth, видимо проще будет описать дефолтный auth, а на паблик подцепить nonauth. Надо будет попробовать.
Route::get('/(:any?)', function ($user) {
return Controller::call('home@index', array($user));
});
и соответственно в контроллер:
public function action_index($user) {
// и делаем тут чего хотим с $user
}
можно еще добавить фильтр, мало ли:
Route::get('/(:any?)', array('before' => 'FILTER_NAME', function ($user = null) {
return Controller::call('home@index', array($user));
}));
Насчет Auth::user(), эту штуку я проверяю через фильтр before в маршруте перед вызовом контроллера, но совсем упустил из виду момент, что перейти то юзер перешел, но вот после может провисеть без активных действий до экспаеринга сессии и как только совершит действия, тут от этот нулл и вылезет, а перехвата нет, только что проверил и получил висящего и ничего не понимающего «что происходит?» юзера в мемберке.
PS: действия пользователя шли через Ajax, фильтр то отработал свое, но ничего в обратку JS не вернул, так что все равно — бага
Auth::user()->demoAccount()->fill(array('summa' => "summa+ $credits"))->save();
бросается эксепшен: Method [fill] is not defined on the Query class., заменил на
Auth::user()->demoAccount()->update(array('summa' => "summa+ $credits"));
тут выругался на SQLSTATE[HY000]: General error: 1366 Incorrect decimal value: 'summa+ 1.00' for column 'summa', не желает это цеплять на `summa` = ? в SQL запросе, фиг с ним, заменил в итоге на:
Auth::user()->demoAccount()->update(array('summa' => DB::raw('summa+ ' . $credits)));
и все поехало как надо. Большое спасибо за совет. Теперь чуть лучше представляю себе как это делать через Eloquent, а то с горя думал перевести проект под Fluent
Не совсем врубаюсь пока в механику работы Eloquent’a. Есть следующие модели:
// User
class User extends Eloquent
{
public function account() {
return $this->has_many('Account');
}
}
// Account
class Account extends Eloquent
{
public function user() {
return $this->belongs_to('User');
}
}
$credits = 10;
User::find(Auth::user()->id)->account()->save(array('summa' => DB::raw('summa + ' . $credits));
приводит к Argument 1 passed to Laravel\Database\Eloquent\Model::fill() must be an array, string given, менял условия, упращал вплоть до примера из http://laravel.ru/articles/rees/eloquent — все едино, одна и таже ошибка. ЧЯДНТ?
Вообще, в оригинале, хотелось бы не городить огород с DB::raw вообще, а вынести все операции с базой в модель, где собственно этому и место, что то типа:
// User
class User extends Eloquent
{
public function account() {
return $this->has_many('Account');
}
}
// Account
class Account extends Eloquent
{
public function user() {
return $this->belongs_to('User');
}
public function add_demo_credits($credits) {
if ($this->get_attribute('demo_flag') === 'demo') {
$credits += $this->get_attribute('summa');
$this->set_attribute('summa', $credits);
}
}
}
Поскольку записей в Account приходится по две на одного User, а разница в демо_флаге, то хотелось бы разделить на два метода в модели, чем добавлять условие ->where в запрос контроллера. Но и в этом случае я не знаю как достучаться до этого метода add_demo_credits($credits) отталкиваясь от Auth::user(). Не подскажете, как это сделать просто и красиво?
Продолжаю сражаться со всякими, призрачными хренями. Вот, изловил очередную хрень.
Есть табличка юзера, в ней все стандартно + есть поле status, которое при регистрации принимает значение inactive и поле last_visit. Есть контроллер Auth, который ловит ajax запрос на авторизацию и соответственно при успешном прохождении делает вот так:
if (Auth::attempt($credentials)) {
try {
$user = User::find(Auth::user()->id);
$user->last_visit = date('Y-m-d H:i:s', time());
$user->save();
echo 'success';
} catch (Exception $e) {
echo 'error';
exit;
}
}
Все нормально, last_visit записан, JS редиректит на страницу дэшбоарда. Там ее ловит контроллер с методом, типа:
public function action_index() {
$uid = Auth::user()->id;
if (Auth::user()->status === 'inactive') {
try {
$user = User::find($uid);
$user->status = 'active';
$user->save;
echo "New";
} catch (Exception $e) {
print_r($e->getMessage());
}
} else {
echo "Again";
}
}
xmlUnhandled Exception
Message:
Call to a member function results() on a non-object
Location:
(censored)\laravel\database\eloquent\model.php on line 688
и хоть так, хоть сяк (через сеттер в модели), все один результат. При этом занчение поля status — изменено на active. Voodoo magic?
Похоже это проблема текущей версии (3.2.10) фреймворка, только что сделал следующее:
1. скачал с сайта дистрибутив
2. установил локально, прописал виртуалку в httpd.conf Апачи
3. поменял в application.php строку 'index' => '', (убрал с нее index.php)
4. поменял в нем же строку 'languages' => array('en','ru'),
5. заремарил в routes.php строки:
Route::get('/', function()
{
return View::make('home.index');
});
Route::get('home/(:any?)', 'home@index');
Route::controller(Controller::detect());
7. запустил и обломался, при переходе на http://domain.com/home вылетает No input file specified.
проблема была описана в статье про .htaccess
8. меняю в нем строку RewriteRule ^(.*)$ index.php/$1 [L] на RewriteRule ^(.*)$ index.php$1 [L]
9. запускаю — все поехало, спокойно едет на http://domain.com/home и на http://domain.com/en/home
10. вот только при http://domain.com/en/home/1 выдает:
xmlarray(1) { ["/en/home/1"]=> string(0) "" }
Любого маршрута, вот к примеру:
Route::get('news/(:num)', 'home@news');
вызов:
http://domain.com/en/news/2
контроллер:
public function action_news() {
echo "<pre>\n";
var_dump(Input::all());
echo "<pre>\n";
exit;
}
array(1) {
["en/news/2"]=>
string(0) ""
}
xml<IfModule mod_rewrite.c> Options -Indexes +FollowSymLinks RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?$1 [L] # default: index.php/$1 article: http://forums.laravel.com/viewtopic.php?id=1508 </IfModule>
PS: /public/index.php и остальные настройки среды /config — дефолтные (т.е. ничего не добавлялось, менялись только app ключ, база и добавил 'languages' => array('en', 'ru'), в application.php)
Вероятнее всего все дело в маршрутизации, в определении языка в первом сегменте URI, я делаю вот так:
Route::filter('before', function () {
$langUri = URI::segment(1);
if (strlen($langUri) === 2) {
if ($langUri == 'en' || $langUri == 'ru') {
Cookie::forever('language', $langUri);
}
} else {
$browserLang = Session::get('user.lang');
if ($browserLang == 'en' || $browserLang == 'ru') {
Cookie::forever('language', $browserLang);
return Redirect::to(URL::base() . "/" . $browserLang);
} else {
....
}
}
});
в Session::get('user.lang') содержится язык браузера.
вроде все ездит как надо, кроме пока с непонятной проблемой в Input::all()
насколько я понял, последний релиз Ларавела сам следит за первым сегментом с языком, потому как маршруты у меня ездят без каких либо танцев с бубном:
Route::get('aboutus', 'home@aboutus');
и он всегда приезжает сюда при запросах http://domain.com/en/aboutus, http://domain.com/fr/aboutus
Подсобите советом, пожалуйста.
Есть запрос, который идет из JS, вида:
xml$.getJSON('http://domain.com/en/graph?callback=?', function(data) { alert(data); });
соответственно jQuery сам подставляет что нужно в параметр callback (что то вида jQueryBlablalba…)
есть описание маршрута в routes.php
Route::get('graph/(:any?)(=.*)', function($action = null) {
return Controller::call('graph@index', array($action));
});
Route::controller(Controller::detect());
class Graph_Controller extends Base_Controller
{
public function action_index() {
$data = "...";
return Input::get('/en/graph/callback') . '('.$data.')';
}
}
В таком варианте во всяком случае работает, но вот как то жутко мне не нравится Input::get('/en/graph/callback')
Есть ли более кошерный путь?
Да, спасибо, примерно так и переделал в итоге. Т.е. выставляю просто класс в нужное значение по массиву флажков.
Продолжаю изучать фреймворк (а заодно и восстанавливать знания PHP после многолетней измены ему с другими языками
Наткнулся на странную багу, ниже код:
xml<li><a @if($hl_home == 'yes') class="over" @endif href="#">Home</a></li>
return View::make('home.index')->with('hl_home','yes');
и получаю ошибку:
Unhandled Exception
Message:
syntax error, unexpected T_CLASS
если заглянуть в /storage/views/, то можно посмотреть код уже после работы шаблонизатора, соответственно вижу:
<li><a <?php if($hl_home == 'yes') class="over" <?php endif; ?> href="#">Home</a></li>
xml<li><a @if($hl_home == 'yes') class="over" @endif href="#">Home</a></li>
фактически да, просто хреф перевести на новую строку и шаблон начинает отображается нормально
если снова заглянуть в /storage/views/, там будет:
<li><a <?php if($hl_about == 'yes'): ?> class="over" <?php endif; ?>
href="#">Home</a></li>