2013-05-26 5 views
5

Извините, если это глупый вопрос, поскольку многие из Laravel 4 для меня новы. Я пытаюсь переопределить несколько методов в функциональности основного пароля, так как я хочу определить свои собственные правила проверки пароля (жестко закодированные в ядре во время публикации) и изменить метод отчетов об ошибках (массив $ errors, используемый для другие формы, а не сеансовые).Переопределить метод класса Laravel 4

Таким образом, мой подход, чтобы создать новый класс/приложение/Lib/MyProject/User называется Password.php, который выглядит следующим образом:

<?php namespace MyProject\User; 

use Closure; 
use Illuminate\Mail\Mailer; 
use Illuminate\Routing\Redirector; 
use Illuminate\Auth\UserProviderInterface; 

    class Password extends \Illuminate\Support\Facades\Password 
    { 
     /** 
    * Reset the password for the given token. 
    * 
    * @param array $credentials 
    * @param Closure $callback 
* @return mixed 
*/ 
public function reset(array $credentials, Closure $callback) 
{ 
    // If the responses from the validate method is not a user instance, we will 
    // assume that it is a redirect and simply return it from this method and 
    // the user is properly redirected having an error message on the post. 
    $user = $this->validateReset($credentials); 

    if (! $user instanceof RemindableInterface) 
    { 
     return $user; 
    } 

    $pass = $this->getPassword(); 

    // Once we have called this callback, we will remove this token row from the 
    // table and return the response from this callback so the user gets sent 
    // to the destination given by the developers from the callback return. 
    $response = call_user_func($callback, $user, $pass); 

    $this->reminders->delete($this->getToken()); 

    return $response; 
} 

} 

Я скопировал метод сброса от/поставщика/Laravel /framework/src/Illuminate/Auth/Reminders/PasswordBroker.php, который, как представляется, разрешен для основного фасада Password.

Тогда в моем файле composer.json, я добавил следующее автозагрузку: classmap массив:

"app/lib/MyProject/User" 

Наконец, в моем файле /app/config/app.php я внесены изменения в Пароль псевдонима:

'Password' => 'MyProject\User\Password', 

OK. В моем routes.php файла у меня есть следующий, в значительной степени взято прямо из документации:

Route::post('password/reset/{token}', function() 
{ 
    $credentials = array('email' => Input::get('email')); 

    return Password::reset($credentials, function($user, $password) 
    { 
     $user->password = Hash::make($password); 

     $user->save(); 

     return 'saved - login'; 
    }); 
}); 

Когда этот сброс() метод работает, я получаю следующее сообщение об ошибке:

Non-static method MyProject\User\Password::reset() should not be called statically

ДЕБЛОКИРОВОЧНЫХ() в классе, который я расширяю, не является статичным, поэтому меня удивляет, однако установка метода сброса для статической очистки устраняет эту ошибку. Далее, хотя, я получаю следующее сообщение об ошибке:

Using $this when not in object context

который приходит при попытке запустить $ this-> validateReset ($ учетные данные).

Теперь я полностью не в своей глубине. Я иду об этом правильно или полностью с правого пути?

Спасибо за любые советы

+0

Вы когда-нибудь решали это? Если да, можете ли вы отправить ответ или комментарии. Спасибо – Laurence

+0

Нет, боюсь, я этого не сделал. Сначала я зарегистрировал проблему на GitHub в проекте Laravel/Laravel, а затем в проекте Laravel/Framework. Тейлор закрыл его как обман, я думаю, что неправильно, поэтому я собираюсь его снова открыть: https://github.com/laravel/framework/issues/1672 –

+0

Является ли это * еще * проблемой (или, по крайней мере, d как ответ)? Возможно, я объясню поведение, которое вы видите, и, возможно, даже предложите решение. Но я предполагаю, что это настолько старо, что вам все равно, или исправил это. – alexrussell

ответ

2

Вы должны расширяет Illuminate\Auth\Reminders\PasswordBroker класса, а не \Illuminate\Support\Facades\Password.

\Illuminate\Support\Facades\Password класс - это фасад, а не конечный класс.

Вы можете увидеть финальные классы фасадов:

get_class(Password::getFacadeRoot()); 
+0

Пробовал это, но я все еще получаю эту ошибку: Нестатический метод Salesize \ User \ Password :: reset() не следует вызывать статически. И при создании метода reset() static: не удается создать нестатический метод Illuminate \ Auth \ Reminders \ PasswordBroker :: reset() static в классе Salesize \ User \ Password –

2

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

Достаточно сказать, что любой доступ к методу фасада обычно делается статически, поэтому, если вы определяете (публичный) метод на фасаде, вы должны убедиться, что он является статическим. Тем не менее, фасады на самом деле, ну, фасады для базового нестатического класса, используя магические методы для передачи статического вызова на фасад методу экземпляра в базовом классе. Таким образом, вы вообще не хотели бы расширять фасад, определяя статический метод на одном, а вместо этого определяя метод экземпляра в базовом классе. В случае фасада Password базовый класс является экземпляром PasswordBroker.Этот базовый класс dealio обычно настраивается путем регистрации экземпляра в контейнере IoC, а затем на фасаде вы определяете метод getFacadeAccessor в классе фасада, который возвращает ключ IoC для поиска экземпляра. (В случае фасада Password ключ IoC равен auth.reminder.)

Здесь проблема возникает, поскольку вы не можете просто переопределить основной класс Laravel. Самое правильное, что нужно сделать, - это, вероятно, расширить PasswordBroker, а затем установить свою версию класса как ключ в IoC, который обычно использует фасад пароля (auth.reminder). Таким образом, ваш добавленный метод будет доступен на фасаде, btu все остальное по-прежнему будет относиться к классу PasswordBroker.


Вы заметите, что вам не нужно создавать новый фасад, но только переопределить ключ IoC существующего фасада в. Когда делать это может быть немного сложным. Если вы не используете собственного поставщика услуг и делаете это в routes.php или что-то в этом роде, тогда вы, вероятно, будете в безопасности. Однако, если вы используете поставщика услуг для изменения этого поведения паролей, вы не можете (не должны) фактически полагаться на порядок вызова методов Laravel провайдеров register поставщиков услуг (на самом деле, похоже, он находится в том порядке, в котором он установлен вверх в app/config/app.php, но hey игнорировать это, это неопределенное поведение, поэтому не полагайтесь на него). Таким образом, вы не знаете, имеет ли ваш поставщик услуг свой метод register, который вызывается до или после основного поставщика услуг Laravel.

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

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

+0

Это действительно очень полезно и подтверждает поведение, которое я видел.У меня такое чувство, что это все еще имеет место в Laravel 5, потому что мне очень сложно переопределить фасад «Mail» (или что-то вроде «Mail»). Я не думаю, что видел такие ограничения в предыдущих рамках, которые я использовал. Очень болезненный. – dKen

+0

Да, я думаю, что L5 имеет ту же систему в отношении контейнера IoC и классов фасадов. Однако я бы предположил, что переопределение фасада почты намного проще, чем система Auth (так как у нее меньше движущихся частей). На самом деле я бы сказал, что просто перерегистрация вашего собственного класса в IoC под ключом доступа к фактору Mail должна выполнять эту работу, но, возможно, я ошибаюсь. – alexrussell

Смежные вопросы