Como passo valores entre templates no Laravel?[fechado]
Pergunta
Estou usando o Laravel Framework 4.1.30.
Como você passa dados de um modelo para outro sem passar por rota ou controlador?
Especificidades:Recebi um modelo de blade "Principal" que é estendido por um modelo de blade "Sign-in".Meu objetivo é colocar quaisquer erros que apareçam no modelo "Sign-in" e exibi-los em uma seção de rodapé do modelo "Principal".
Meus códigos para o modelo principal dentro da tag "body" são os seguintes (observe que existem alguns códigos para formatar minha visualização):
<!-- Serving as Header -->
@include('layout.navigation')
<!-- Serving as left content/status displays -->
@include('layout.frameleft')
<!-- Serving as right content/entry point -->
@yield('content')
<!-- Serving as Error Notification/footer -->
@if (Session::has('global'))
{{ Session::get('global') }}
@endif
O modelo blade que chama Main é codificado assim:
@extends('layout.main')
@section('content')
... more code here / input fields ...
{{ $errors->first('email')}}
... more code here / input fields ...
@stop
Pelo que entendi (bastante novo no Laravel), o conteúdo deve ser lido primeiro, antes da sessão ser exibida globalmente.
Eu esperava que uma simples variável passando entre os modelos fosse suficiente (se existir) para resolver o problema.Desejo passar o valor do erro do conteúdo de volta para o modelo principal na parte da seção de rodapé sem voltar ao controlador.
Estou ciente de que existem soluções alternativas, como em vez de esperar que o controlador envie os erros para o modelo, eu poderia passar os erros diretamente para a variável global por meio da sessão (ou para o layout) do Controlador.Atualmente, o seguinte código de trabalho é o que eu implementei, mas estou apenas me perguntando o que aconteceria se os dados já tivessem sido passados para o modelo.
public function postSignin() {
$validator = Validator::make(Input::all(),
array(
'email' => 'required|email',
'password' => 'required'
)
);
if ($validator->fails()) {
$errors = $validator->errors();
$formErrors = 'Errors: ';
foreach($errors->all() as $error ) {
$formErrors .= sprintf("%s", $error);
}
return Redirect::route('account-sign-in')
->withErrors($validator)
->withInput()
->with('global',$formErrors);
} else {
...more codes here...
O motivo pelo qual estou fazendo isso é que originalmente meu código no controlador é exatamente assim.
if ($validator->fails()) {
return Redirect::route('account-sign-in')
->withErrors($validator)
->withInput();
Agora parece tão grande.Acho que se eu pudesse aliviar o controlador com um loop, meu programa seria mais eficiente.
Solução
De Documentação Laravel (ênfase deles):
Entretanto, observe que não precisamos vincular explicitamente as mensagens de erro à visualização em nossa rota GET.Isso ocorre porque o Laravel sempre verificará se há erros nos dados da sessão e os vinculará automaticamente à visualização, se estiverem disponíveis. Então, é importante ressaltar que um
$errors
variável estará sempre disponível em todas as suas visualizações, em todas as solicitações, permitindo assumir convenientemente que a variável $errors está sempre definida e pode ser usada com segurança.O$errors
variável será uma instância deMessageBag
.
Porque o Laravel Redirect... withErrors()
método faz isso, você não precisa adicionar os erros à Sessão novamente manualmente.Em vez de verificar if (Session::has('global'))
, basta fazer isso:
<!-- Serving as Error Notification/footer -->
@foreach ($errors as $error)
<p>{{ $error }}</p>
@endforeach
Isso deve funcionar embora está no layout
e não na visão real, porque a vinculação que se aplica errors
dentro do modelo também os aplica fora dele.
Se não houver erros, o Laravel irá simplesmente pular esse bloco.Se houver erros, eles terão sido automaticamente vinculados ao $errors
variável e será renderizado conforme o esperado.
Outras dicas
Eu estava escrevendo originalmente uma resposta que recomendava Ver compositores, mas reli a pergunta e acredito que o que você precisa fazer é abstrair a validação do formulário para uma classe 'formulário':
interface FormInterface {
public function isValid($input);
public function errors();
}
A ideia básica que tirei da sua pergunta é que você deseja que seu controlador seja parecido com isto:
public function postSignIn()
{
if(!$this->_signinForm->isValid(Input::all())) {
return Redirect::route('account-sign-in')
->withErrors($this->_signinForm->errors())
->withInput()
;
}
// Non-error logic branch
}
Sua classe de formulário conterá basicamente uma referência ao objeto validador.Todos isValid
método deve fazer é basicamente chamar passes()
no validador e todos os error
método simplesmente retornará os resultados da chamada errors()
no validador.
Sinceramente, não tenho ideia de por que você está combinando todas as mensagens de erro em uma única variável. Presumo que seja porque você deseja que todas elas sejam exibidas no mesmo lugar.Se for esse o caso e é assim que você deseja que os erros funcionem, você pode incorporar isso ao seu formulário errors
método.