Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
С https у меня к сожалению опыта нет, а вы так пробовали:
Route::secure('GET', 'login', function () {
return View::make('login');
});
И мне кажется, что если для http у вас было так:
Route::get('/',function(){
//code
});
То для https замыкание должно выглядеть следующим образом:
Route::get('/',array('https', function() {
//code
}));
Или если вы хотите использовать контроллер:
Route::get('/',array('https' => true, 'uses' => 'controller@getsomething'));
Спасибо, русская документация дополнительный повод наконец то взять и заняться изучением L4.
Да, дейсвительно PHP$arr['data']['laravel_auth_drivers_eloquent_login']
идентификатор пользователя необходымый мне.
Странно что я этого сразу не заметил, надо быть внимательнее)))
Вроде бы все просто, вызывается метод
PHPCrypter::decrypt()
идентификатор шифруется симметричным алгоритмом с использованием секретного ключа, т.е. зная сам ключ(который хранится в application/config/application.php) можно повторить внутренностиPHPCrypter::decrypt()/encrypt()
и получить идентификатор пользователя из Cookie
— тут я слегка поторопился, в методе PHPCookie::get()
есть интересный вызов: PHP$value = Request::foundation()->cookies->get($name)
и я плохо себе представляю что тут происходит. Что это такое и как оно работает?
Пожалуй действительно стоит поставить дополнительную куку с идентификатором пользователя(разве что идентификатор пользователя все таки буду шифровать PHPmcrypt_encrypt/mcrypt_decrypt
) и не заморачиватся.
Да, фреймворк использую, PHPCrypter
— класс Laravel.
Метод get() вернет следующее:
array (size=3)
'id' => string 'v9mvGtZd5hH7MoXAoyRGPrwEW0nzyTuJWal9hYfo' (length=40)
'data' =>
array (size=4)
':new:' =>
array (size=0)
empty
':old:' =>
array (size=0)
empty
'csrf_token' => string 'XIcPGCUYCxK8tmnNaFY5dtqS8RrAK0BZbgoudijW' (length=40)
'laravel_auth_drivers_eloquent_login' => int 1
'last_activity' => int 1377033363
где, ’id’ ⇒ string ’v9mvGtZd5hH7MoXAoyRGPrwEW0nzyTuJWal9hYfo’ — предположительно необходимый мне идентификатор пользователя
Мне еще интересно, верна ли моя догадка, действительно ли Laravel сохраняет идентификатор пользователя в Cookie ?(где то же берется идентификатор пользователя при вызове PHPAuth::user()->id
). Или же там хранится только идентификатор сессии, которая в свою очередь хранится в зависимости от выставленной опции driver в application/config/session.php.
Использую стандартный механизм авторизации Laravel 3. Появилась необходимость прочитать идентификатор пользователя который пишется в Cookie при успешной аутентификации, при этом НЕ имея самого фреймворка под рукой.
Вроде бы все просто, вызывается метод PHPCrypter::decrypt()
идентификатор шифруется симметричным алгоритмом с использованием секретного ключа, т.е. зная сам ключ(который хранится в application/config/application.php) можно повторить внутренности PHPCrypter::decrypt()/encrypt()
и получить идентификатор пользователя из Cookie.
Потому как не совсем понимаю все моменты в работе аутентификации порылся по фреймворку и нашел несколько вызовов PHPCrypter::decrypt()
и попытался их воспроизвести:
laravel\session\drivers\cookie.php
$arr = unserialize(Crypter::decrypt(\Laravel\Cookie::get('session_payload')));
echo Crypter::decrypt($arr['id']); //вроде идентификатор пользователя
laravel\auth\drivers\driver.php
$arr = explode('|', Crypter::decrypt('session_payload'));// $arr[0] - идентификатор пользователя
В обоих случаях выдает ошибку:
mcrypt_decrypt() [function.mcrypt-decrypt]: The IV parameter must be as long as the blocksize
Делал что? Запускал PHPartisan
? Применительно к Denwer мне известен только такой способ.
Дело в том что Denwer имеет одну особенность, если попытаться запустить PHP интерпретатор напрямую с диска куда установлен дистрибутив Denwer-а(например диск C:\WebServers\usr\local\php5\php), то при старте можно получить много всплывающих сообщений об ошибках(не найдем такой то dll).
А если запускать PHP с диска который Denwer создает при старте, то все хорошо. Возможно в этом и все дело, именно поэтому я указал глобальный путь(быть может кто то не поленился прописать алиас у себя в системе).
Если очень нужно использовать artisan из под Denwer я делаю следующее:
1. Переходим на диск который Denwer создает при старте(допустим М:\)
cd M:
cd M:\home\mysite
3. Запускаем интерпретатор php(например указав абсолютный путь) и указываем в качестве параметра artisan
M:\usr\local\php5\php artisan [command]
Странно, почему я этого сразу не понял, но запрос приведенный мной выше равносилен этому:
sqlSELECT * FROM gates LEFT JOIN drivers ON gates.gate_type_id = drivers.gate_type_id LEFT JOIN device_types ON drivers.id = device_types.driver_id WHERE device_types.id = 11 AND gates.system_id = 6;
А данный запрос уже запросто переписывается через PHPFluent/Eloquent
:
DB::table('gates')
->left_join('drivers','gates.gate_type_id','=','drivers.gate_type_id')
->left_join('device_types','drivers.id','=','device_types.driver_id')
->where('device_types.id','=',$id_deviceType)
->where('gates.system_id','=',$id_system)
->get();
- Именно Fluent или Eloquent? Зачем тебе Fluent?
Потому что мне точно известно, что Fluent использует подготовленный запросы и защищен от SQL-инъекций. И насколько мне известно Eloquent и Fluent используют различные Query классы. Если ошибаюсь, пожалуйста поправьте.
Что касается запроса, то так я пробовал:
Gate::join('drivers', 'drivers.id', '=', 'device_types.driver_id')
->join('device_types', 'gates.gate_type_id', '=', 'drivers.gate_type_id')
->where('device_types.id', '=', 11)
->where('gates.system_id', '=', 6)
->get();
Gate::left_join('drivers', 'drivers.id', '=', 'device_types.driver_id')
->left_join('device_types', 'gates.gate_type_id', '=', 'drivers.gate_type_id')
->where('device_types.id', '=', 11)
->where('gates.system_id', '=', 6)
->get();
sqlSQLSTATE[42S22]: Column not found: 1054 Unknown column 'device_types.driver_id' in 'on clause' SQL: SELECT * FROM `gates` INNER JOIN `drivers` ON `drivers`.`id` = `device_types`.`driver_id` INNER JOIN `device_types` ON `gates`.`gate_type_id` = `drivers`.`gate_type_id` WHERE `device_types`.`id` = ? AND `gates`.`system_id` = ? Bindings: array ( 0 => 11, 1 => 6, )
На мой взгляд проблема заключается в том, что сначала нужно передать две таблицы для связывание, а уже затем задавать аргументы для ON критериев, только вот как это сделать?
sqlSELECT * FROM gates LEFT JOIN drivers LEFT JOIN device_types ON drivers.id = device_types.driver_id ON gates.gate_type_id = drivers.gate_type_id WHERE device_types.id = 11 AND gates.system_id = 6;
Никак не могу сообразить как его написать с использованием конструктора запросов PHPFluent
Перепробовал кучу различных вариантов, ничего не сработало… чувствую что где то нужно использовать PHPDB::row()
, но как не пойму. Кто либо писал подобные запросы?
Спасибо за ответ. Чувствую что некоторые вещи для меня теперь прояснились! Отдельное спасибо за подробный ответ касательно
sqlSQL
в контроллерах, теперь начну понемногу избавляться от уже написанных запросов в контроллерах, и операции с базой теперь буду стараться делать через модель)))
Но я столкнулся с «проблемой» когда стало необходимо работать с данными, представленными в виде односвязного списка, элементы которого разбросаны по различным таблицам.
Постараюсь как нибудь привести пример кода, просто его там очень туева хуча много, и выбрать отдельный короткий фрагмент который бы демонстрировал всю суть проблемы довольно сложно.
В зависимости от объёма задачи можно либо сделать классы с перекрытыми методами (например, fill($row) — каждый класс берёт для себя то, что нужно, возможно делая дополнительные запросы)
Можно более подробно об этом? Боюсь не совсем понял о чем тут идет речь…можно ли пояснить хотя бы в виде псевдокода/ссылок для прочтения?
Возможно не совсем по теме(изначальный вопрос про L4 + Linux Mint), но считаю необходимым упомянуть про phpDesigner(я использую 8-ую версию) он правда под Windows. Пробовал phpStorm/NetBeans - не очень. В phpDesigner лучше работает авто дополнение для методов и классов Laravel а также есть другие полезные вещи(динамическая подсветка синтаксиса, встроенный ftp/sftp менеджер и прочее).
Рискну задать вопрос касательно шаблона mvc и не начать холивара.
На данном форуме много умных и отзывчивых людей, от которых я не раз получал дельные советы.
Все вокруг кричат об тонких контроллерах и толстых моделях, только вот мне не всегда ясно как именно этого добиться.
Для начала приведу краткий перечень общепринятых правил(если что поправьте) по которым должно
строится mvc приложение + свое личное мнение по каждому из пунктов.
1. Котроллеры — это:
1.1 Только логика, логика и еще раз логика — вроде все ясно.
1.2 Никаких echo или упаси бог html-вставок — тут вопросов никаких.
1.3 Никаких sql-запросов — данный пункт лично мне не совсем понятен, если уж так вышло что в определенном месте мне нужно получить
одно единственное поле из одной единственной таблицы и при этом все необходимые данные у меня есть,
то почему мне не сделать SQL-запрос тут же на месте? Неужели необходимо «звать» модель на помощь?
Если так, то заводить для этого динамический метод как то не очень, можно написать статический метод(хелпер) — вроде все хорошо,
НО если запрос выполняется в одном единственном методе одного единственного контроллера, то
модель просто «захламляется» подобными хелперами.
2. Модели — это:
2.1 Прослойка между контроллерами и бд, т.е. якобы любые обращения к базе должны обрабатывать — в теории все звучит разумно.
2.2 Хранилище для правил валидации и статических методов валидации — тоже все логично.
2.3 Класс который «накладывается» на таблицу и в котором определяются отношения между связанными таблицами — все чудесно!
Laravel содержит прекрасную ORM — отношения между связанными таблицами сэкономили мне действительно много времени.
2.4 Ну и конечно банальная фраза: «Модель содержит бизнес логику» – боюсь, не совсем понимаю, что именно под этим понимают?
3. Виды- это:
В основном гора html-кода оформленного правилами CSS и с вставками в определенных местах управляющих конструкций php PHP(if/else,switch/case,foreach)
— все логично, так и поступаю и никаких проблем не испытываю.
Следовательно, меня уже давно беспокоит следующий вопрос.
Можно ли считать вызов вида PHP$user = new User()/$user = User::find($id)...
в контроллере целесообразным?
На мой взгляд, все хорошо. Подобным образом удобно создавать/изменять записи в различных таблицах, а также
удобно вносить изменения если какие либо поля таблицы были добавлены/удалены(а это происходит довольно таки часто).
Но я столкнулся с «проблемой» когда стало необходимо работать с данными, представленными в виде односвязного списка, элементы которого разбросаны по различным таблицам. Код методов стал очень объемным, и местами появились строки повторяющегося кода,
кое-где удалось воспользоваться статическими методами моделей — и это действительно повысило читабельность и изящество кода.
Но в определенных методах это все равно не выход, так как по моему сделает код еще более запутанным, и когда я к нему вернусь через месяц вносить какие либо коррективы станет еще труднее. Возможно то то уже сталкивался с подобной задачей?
Но с созданием/изменением/удалением данных еще пол беды, вот когда необходимо выбрать данные(т.е. пройтись по цепочке данных расположенных в различных таблицах) в зависимости от определенных условий(условиями также служат определенные выбираемых записей)
я начинаю делать еще более неочевидные и странные вещи. Т.е. для формирования данных дабы избежать вложенных цыклов и множества переменных я формирую одну структуру(по сути массив объектов) вида:
[0] => obj {
'field' => 'val'
'field_two' => 'val_two'
}
[1] => obj {
'field' => 'val'
'field_two' => 'val_two'
}
Для ее формирования я использую такую фичу php как динамическое добавление свойств к объекту, т.е. вся конструкция выглядит следующим образом:
while($condition){
$result[$i] = new stdClass;
$q = DB::first('SELECT * FROM table WHERE condition = ?',condition);
switch($q->field){
case '1':
$result[$i]->name = $q->name;
$result[$i]->direction = $q->direction;
break;
case '2':
$result[$i]->second_name = $q->name;
$result[$i]->anbalog = $q->direction;
break;
}
$condition = $q->condition;
$i++
}
При данном способе нет лишних полей у объектов, т.е. каждый элемент массива содержит только то что необходимо.
Но в итоге размер одного метода контроллера выходит довольно внушительным. Возможно, есть способ более грамотно реализовать данную задачу?
Список затронутых мной вопросов велик, но они уже долгое время не дают мне покоя.
Хотелось бы услышать мнение участников форума, а также возможные советы/ссылки на литературу.
Заранее спасибо.
- Да не за что! Надеюсь помогли хоть советы то??
В start.php добавил строку:
PHPLaravel\Database\Eloquent\Pivot::$timestamps = false
теперь все хорошо .
Можно конечно и в 1-M\laravel\database\eloquent\pivot.php переопределить PHPpublic static $timestamps
, тоже работает)
Для моих целей поля `created_at` и `updated_at`не нужны вовсе.
Поскольку уже есть тема по отношениям типа Many-To-Many пожалуй стоит задать вопрос именно в ней.
У меня следующие модели:
— Модель сценария
class Scenario extends Eloquent
{
public static $timestamps = false;
public static $table = 'scenarios';
public function configuration(){
return $this->has_many_and_belongs_to('Configuration','scenario_to_configuration','scenario_id');
}
}
class Configuration extends Eloquent
{
public static $timestamps = false;
public static $table = 'configurations';
public function scenario(){
return $this->has_many_and_belongs_to('Scenario','scenario_to_configuration','configuration_id');
}
}
Один сценарий может входить в множество конфигураций, одна конфигурация может содержать множество сценариев. Для реализации данного типа отношения существует промежуточная таблица:
sqlCREATE TABLE `scenario_to_configuration` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `configuration_id` bigint(20) unsigned NOT NULL, `scenario_id` bigint(20) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
При запросе вида PHP$conf = Scenario::find($id)->configuration()->get();
Получаю сообщение:
SQLSTATE[42S22]: Column not found: 1054 Unknown column ’scenario_to_configuration.created_at’ in ’field list’
SQL: SELECT `configurations`.*, `scenario_to_configuration`.`id` AS `pivot_id`, `scenario_to_configuration`.`created_at` AS `pivot_created_at`, `scenario_to_configuration`.`updated_at` AS `pivot_updated_at`, `scenario_to_configuration`.`scenario_id` AS `pivot_scenario_id`, `scenario_to_configuration`.`configuration_id` AS `pivot_configuration_id` FROM `configurations` INNER JOIN `scenario_to_configuration` ON `configurations`.`id` = `scenario_to_configuration`.`configuration_id` WHERE `scenario_to_configuration`.`scenario_id` = ?
Если в промежуточную таблицу добавить следующие поля:
sql`created_at` datetime DEFAULT NULL, `updated_at` datetime DEFAULT NULL,
Но хотелось бы разобраться почему так? Ведь в обоих моделях переопределено свойство PHPpublic static $timestamps = false
И таблицы не содержат полей created_at, updated_at. Подскажите как правильно сделать? Нужна ли модель описывающая промежуточную таблицу?
Обычно для REST делается один одинаковый URL, а команда задаётся типом запроса, а здесь получается странный подход - тип DELETE и команда %%.../delete%%. Что будет, если запросить ту же команду через PUT? Или GET?
Если сослаться на один и тот же метод различным типом запроса, то не удастся попасть в обработчик, поскольку каждый роут определен как:
Route::get/post/put/delete('url', array('auth'=>'before', 'controller@method') );
В моем приложении в рамках одного контроллера может присутствовать несколько методов с одинаковым типом запроса(POST/GET/DELETE/PUT), поэтому нужно обеспечить доступ к различным методам посредством разных url в файле routes.php. Возможно, я не правильно спроектировал приложение.
Использовал приведенный вами кусок кода, и все заработало! Спасибо за помощь.
Подскажите правильно ли я понял, выходит я могу не опасаться запросов описанных мною в routes.php как Route::delete(); поскольку они по сути являются запросами POST ?
Спасибо всем за советы касательно WAMP сборок, обязательно попробую все перечисленное.
Все запросы в приложении описаны посредством библиотеки jQuery, и имеют следующий вид:
$.ajax({
type: "DELETE",
url: "system/delete",
data: ({
id_system: idsystem
})
На бэкэнде запросы обрабатываются методами вида:
public function delete_method()
{
if( Request::ajax() ){
//логика метода
}
}
Для форм используются ajax-запросы с типом GET/POST. Посредством запросов PUT/DELETE происходит передача данных на сервер об обновлении/удалении записей, т.е. нет запроса на получение формы с сервера.
Столкнулся с проблемой при тестировании приложения на реальном хостинге. В разрабатываемом приложении некоторые методы классов(контроллеров) определены как Restfull, т.е. имеют префиксы put_ и _delete. На локальном хосте (использую Denwer, знаю что не лучший выбор, зато прост как табуретка. Если кто может посоветовать другую wamp сборку - с радостью попробую ее) проблем не возникало, при тестировании на 'боевом сервере' получил сообщение вида:
405 Method Not Allowed
Method Not Allowed
The requested method DELETE is not allowed for the URL /index.php.
Пробовал добавить в конструктор класса разрешение методов:
public function __construct()
{
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE');
header('Access-Control-Allow-Headers: Content-Type');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Request-Method: GET, PUT, POST, DELETE');
header('Access-Control-Allow-Headers: Content-Type');
parent::__construct();
}
Я так понимаю что методы PUT и DELETE запрещены на сервере, следовательно необходимо настраивать именно Apache(версия 2.2.19). Предположительно необходимо внести настройки хоста в файл apache2.conf. Возможно кто то подобное уже делал, если это так пожалуйста подскажите решение.
При поиске по просторам интернета встречал мнения что разрешать запросы типа PUT, DELETE - не безопасно для веб-сервера. Насколько это верное утверждение? В моем приложение данными запросами просто передаются параметры, которые обрабатывает приложение, в принципе изменить их на POST/GET труда не составит - но тогда на мой взгляд теряется красота использования Restfull контроллеров(Хотя возможно в моем случае использование данного подхода является излишним).
Очень хотелось бы знать мнение сообщества по данному вопросу.
Возможно данный цикл многие уже посмотрели, но поскольку такая тема существует на форуме думаю необходимо упомянуть о tutorials от Anderw Perkins:
http://www.youtube.com/watch?v=m5Jmh9JK … ure=relmfu
Двенадцать видео уроков, на мой взгляд все очень наглядно.
Да действительно, вы правы. Мне это в голову увы не пришло. Спасибо за помощь.
Боюсь я не правильно выразился, прошу прощения за невнимательность, вот это работает:
Gate::find($id)->device()->get();
Так же как и
Gate::find($id)
$id по которому производится поиск корректно, а такая запись в базе данных существует.
Проблема заключается в выражениях:
Gate::find($id)->device()->canal()->get();
Ошибка следующего содержания:
Method [canal] is not defined on the Query class.
Есть необходимость использовать ORM для облегчения взаимодействия с базой данных. Сущности связаны между собой следующими зависимостями:
- Gate один ко многим Device;
- Device один ко многим Canal;
Для для реализации этих зависимостей в моделях были установлены соответствующие взаимосвязи(Relationships).
Модель шлюзы:
class Gate extends Eloquent
{
public static $timestamps = false;
public function system(){
return $this->belongs_to('System');
}
public function gatetype(){
return $this->belongs_to('Gatetype');
}
public function device(){
return $this->has_many('Device');
}
}
Модель устройства:
class Device extends Eloquent
{
public static $table = 'devices';
public static $timestamps = false;
public function gate(){
return $this->belongs_to('Gate');
}
public function gatetype(){
return $this->belongs_to('Devtype');
}
public function canal(){
return $this->has_many('Canal');
}
}
Модель каналы:
class Canal extends Eloquent
{
public static $timestamps = false;
public function canaltype(){
return $this->belongs_to('Canaltype');
}
public function condition(){
return $this->has_many('Condition');
}
public function scnstep(){
return $this->has_many('Scnstep');
}
public function device(){
return $this->belongs_to('Device');
}
}
При данных взаимоотношениях работают конструкции вида:
Gate::find($id)->device()->get();
Но при использовании конструкций вида:
Gate::find($id)->device()->canal()->get();
Я получаю ошибку:
Call to a member function device() on a non-object
Документация, увы, мне не помогла.
Возможно, я неправильно установил взаимоотношения, либо я не правильно понимаю механизм построения запросов.
В чем кроется проблема?