I'm new to laravel. Using version 5.4 and tried to search but don't see what I'm doing wrong. I keep getting an "Undefined variable: post" in my view. I'm also doing form model binding. Model binding works properly when manually entering URL. Just can't click on link to bring up edit view.
My routes:
Route::get('test/{id}/edit','TestController#edit');
My controller:
public function edit($id)
{
$post = Post::find($id);
if(!$post)
abort(404);
return view('test/edit')->with('test', $post);
}
My form:
{{ Form::model($post, array('route' => array('test.update', $post->id), 'files' => true, 'method' => 'PUT')) }}
You're assigning the post value to 'test', so should be accessible with $test rather than $post.
You probably want to do either of these two things instead:
return view('test/edit')->with('post', $post);
or
return view('test/edit', ['post' => $post]);
https://laravel.com/docs/5.4/views
Your controller is sending a variable named "test", but your error says that your blade file doesn't have the $post variable passed into it. This can be fixed by changing "test" to "post" in your controller.
Related
I have a blade component containing $attributes; It would be a bag of attributes when the component called from another blade template but when from the controller via view() the $attributes is undefined! How can I pass data as $attributes from the controller?
Component: sample
<div {{ $attributes->except('content') }}>{{ $content }}</div>
Template: works well.
...
<x-sample class="test" content="test"/>
...
Controller: Error Undefined variable $attributes
$attributes = ['class' => 'test', 'content' => 'test'];
view('components.sample', $attributes)->render();
view('components.sample', ['attributes' => $attributes])->render();
view('components.sample')->with($attributes)->render();
UPDATE (Solution):
It works:
view('components.sample', [
'prop1' => '...',
'prop2' => '...',
'attributes' => new ComponentAttributeBag(['attr1' => '...', 'attr2' => '...']),
])->render();
what is happening is components inherit variable from view, if you define your variable from home view for example, it should work in component from that view. Then when you include the view to about page the variables wont be recognized since they are not inherited from about view. And in Laravel you cannot pass data directly form controller to component. but laravel have solved it by View Composer.
Since I dont like too much complication especially with providers I edited my AppServiceProvider you can create your own provider.
in YourServiceProvider in my case AppServiceProvider in boot() function there are three options you can use one. I recommend there 3rd one since its clean
public function boot()
{
// option1 - Every single view
View::share('shops', Shop::orderBy('name')->get());
// option2 - Gradular views with wildcards
View::composer(['client.*'], function ($view){
$view->with('shops', Shop::orderBy('name')->get());
});
// option3 - Dedicated class
View::composer(['client.includes.*','client.create-product','client.cart'], ShopsComposer::class);
View::composer(['client.includes.*','client.cart'], CartComposer::class);
}
If you use the 3rd method you have to create ViewComposer class
<?php
namespace App\Http\View\Composers;
use App\Models\CartItem;
use Illuminate\Support\Facades\Session;
use Illuminate\View\View;
class ShopsComposer
{
public function compose(View $view){
$shop = auth()->user()->shops->sortBy('name');
$cartItem = new CartItem();
$cartCount = 0;
if (Session::has('cartId')) {
$carts = Session::get('cartId');
$cartItems = $cartItem->with('products')->where('cart_id', '=', $carts->id)->get();
foreach ($cartItems as $item) {
$cartCount += $item->quantity;
}
}
$view->with('shopsComposer', $shop)->with('cartCount', $cartCount);
}
}
The variables you define there will be available to all the views. that includes components. Since component inherit variable from view file.
I am sorry I had to share my working example, since I am running out of time. I hope it works if I understood well your question.
I am saving data from a simple form in my Laravel project.
While submitting, it should go to the route that is predefined for store() method. I use such code:
{!! Form::open(['action' => 'PostsController#store', 'method' => 'POST', 'enctype' => 'multipart/form-data']) !!}
It goes to the route that is for index() method. Any help?
In store() method, I have such code:
$posts = new Post;
$posts->title = $request->input('title');
$posts->body = $request->input('body');
$posts->save();
return redirect('/');
My web.php contains:
Route::resource('/','PostsController');
Your code is correct bro.. The only reason you're going to index is because of the
return redirect('/'); in the store function... Check whether youdata is saved in the database or not...
Have you tested to see if this actually saves the data still? With Route resources, the route will be the same for both store and index methods, just a different HTTP method.
Maybe your code is working well & data saved in the database. You return redirect('/') it to your index() method, so you don't understand the difference. Check your database.
When I click Save on my edit view, my routing brings back my edit view instead of my index view and my update method is never reached.
I noticed that I reach the update method if I remove “UsersRequest $request” from the method parameters. Not sure why, and if it’s related, but I need $request to do my update (see controller code below):
Routes:
Route::get('/users', 'UsersController#index')->name('users.index');
Route::patch('/users/{id}',
[
'as' => 'users.update',
'uses' => 'UsersController#update'
]);
Route::get('/users/{id}/edit', 'UsersController#edit');
Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\UsersRequest;
//public function update($id, UsersRequest $request)
public function update($id) //- with $request removed, the index view is displayed
{
$user = \Auth::user();
$user->update($request->all());
return view('users.index');
}
Edit view:
{!! Form::model($user, ['method' => 'PATCH', 'action' => [ 'UsersController#update', 'user' => $user->id ] ]) !!}
{!! Form::submit('Save', ['class'=>'btn primary']) !!}
{!! Form::close() !!}
Network after save button clicked
URL Protocol Method Result
/myapp/public/users/1 HTTP POST 302 Goes for the update route
http://000.000.000.000/myapp/public/users/1/edit HTTP POST 200 Redirects to the edit route??
.env
APP_URL=http://000.000.000.000/myapp/public
You're failing whatever validation is present in your UsersRequest form request. When the validation fails, it redirects you back to where you came from, which is your edit view. Your edit view should be updated to show the validation errors so that your users know what fields need to be fixed.
The reason it works when you remove the UsersRequest $request parameter is that the validation is no longer being performed.
I have the following code which sends a passowrds recovery mail:
public function recovery(Request $request)
{
$validator = Validator::make($request->only('email'), [
'email' => 'required'
]);
if($validator->fails()) {
throw new ValidationHttpException($validator->errors()->all());
}
$response = Password::sendResetLink($request->only('email'), function (Message $message) {
$message->subject(Config::get('boilerplate.recovery_email_subject'));
});
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->response->noContent();
case Password::INVALID_USER:
return $this->response->errorNotFound();
}
}
Which I found out uses the following template: resources/views/auth/emails/password.php
which is an empty file.
How I can access the token from this template?
Isn't there any built-in view to use from laravel?
The function in your questions doesn't return a view.
Also, I'm unfamiliar with that path to the view that is in your question. Which version of Laravel are you using?
Anyhow, you can get the reset token from the DB, just like any other value in the DB. E.g. from a controller that is returning a view:
$user = User::find(Auth::id());
$remeber_token = $user->remember_token;
return view('to_your_view.blade.php', compact('remember_token');
And then in the view file:
{{ $remember_token }}
This will output it, no need to use echo or anything.
But, again, the function you pasted into your question is not a function that is returning a view, so I'm not sure where to tell you to put the above code.
As for your questoin about Laravel having an in-built view for 'this', in Laravel 5.3, at least, the view I assume you want will be within `resources/views/auth/passwords/'.
<h1>Edit page of {{ $user->username }}</h1>
{{ Form::open(['route' => 'user.store']) }}
... the rest of the view
This is in my login view. The related code in the store method in the controller looks like this:
if (Auth::attempt(Input::only('username', 'password'))) {
$user = Auth::user();
return Redirect::route('user.show', ['user' => $user]);
}
and the show method:
public function show($user)
{
return View::make('user.edit', ['user' => $user]);
}
And I get .../user/%7Buser%7D as URL (and I want it to be, eg. .../user/exampleusername) and also an exception: ErrorException: Trying to get property of non-object.
When I dd($user) in the show method (or in the view, doesn't matter), I get simply string[6] {user}, which means I do not pass the $user successfully to the user.show route.
The official docs give this example: return Redirect::route('profile', array('user' => 1)); which seems relevant to my case, which I think should look like this in my code: return Redirect::route('user.show', ['user' => $user]);?
Funny, though, if in the show method I try to take the user object from the session (Auth::user()), and dump it, as here:
public function show($user)
{
$user = Auth::user();
dd($user);
...
it will still be NULL, but if I dump it in the index method:
public function index()
{
if (Auth::check()) {
dd(Auth::user());
...
, then it returns correct object, full of parameters and values... I have no idea what's going on and why in one method I have the session object, but in the other I don't.
Any suggestions on how to go around this problem?
UPDATE: I narrowed it down to this implementation in the store method:
return Redirect::route('user.show')->with('user', $user);
and in the show method:
$user = Session::get('user');
return View::make('user.edit', ['user' => $user]);
Because apparently the only place where you can pass an array that will explode into single variables is in View::make, whereas in Redirect::to, Redirect::action and Redirect::route, etc., you must use the ->with('key', $value) function. Those values then will be available in the Session singleton.
Nevertheless, I still get .../%7Buser%7D in the URL. And I don't know how to get out of this...
You need to pass the id of the user to the user.show route - not the $user itself.
return Redirect::route('user.show', [$user->id]);