Controllers, Models, and updating select properties - laravel

I've gone through quite a few tutorials, and I'm starting to get there with Laravel, however, one thing I've somehow missed in these tutorials/failed to spot, is how to accomplish "selective updating", apologies if that's the wrong wording, however this is my issue.
I have the user model, this contains multiple custom fields on top of the auth fields added by Laravel, the custom fields are:
ConsiderForAccommodation
Attending
I currently have a form in a view that allows the user to set choose whether they would like to be considered for accommodation, this works as follows:
User Model
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'considerForAccommodation'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
User Controller
public function update(Request $request)
{
// Update the given user
$user = auth()->user();
// If the value is null then it's false.
$user->ConsiderForAccommodation = $request->input('ConsiderForAccommodation') != null;
$user->save();
return redirect('/accommodation');
}
Accommodation View (form)
#section('content')
<h1>Accomodation</h1>
<p>This is the accomodation page.</p>
{!! Form::open(['action' => ['UserController#update', Auth::id()], 'method' => 'POST']) !!}
<div class="form-group">
{{Form::label('ConsiderForAccommodation', 'Consider Me For Accommodation')}}
{{Form::checkbox('ConsiderForAccommodation', null, Auth::user()->ConsiderForAccommodation)}}
</div>
{!! Form::token() !!}
{{Form::hidden('_method', 'PUT')}}
{{Form::submit('Submit', ['class' => 'btn btn-primary'])}}
{!! Form::close() !!}
#endsection
Route
Route::get('/', 'PagesController#index');
Route::get('/accommodation', 'PagesController#accommodation');
Route::get('/registry', 'PagesController#registry');
Route::get('/rsvp', 'PagesController#rsvp');
Route::get('/schedule', 'PagesController#schedule');
Route::get('/travel', 'PagesController#travel');
Route::resource('user', 'UserController');
Auth::routes();
As I mentioned, this imlementation works as intended. Now, the issue is I have another seperate form (within a different view), that I would like to contain a form that only updates the "Attending" value against the model. How do I handle this in Laravel?
Do I have to create a seperate controller for each property I wish to update seperatly from the others, or am I looking at this wrong entirely and there's an easy way of doing it?
Any help would be appreciated.

There are many possibilities how to solve this problem. One of them is to create one route that also has a parameter
Route::put('/users/set-parameter/{param}', 'UserController#setParameter');
Then in controller you can set different parameters in single method:
public function setParameter(Request $request, string $param)
{
$user = auth()->user();
$user->{$param} = $request->input($param) != null;
$user->save();
return redirect('/accommodation');
}
Keep in mind that sometimes it is not the best way to handle that. There are pros and cons as almost always.

Related

Why laravel 8 form validation request doesn't work as shown in documentation

I make custom request by
php artisan make:request UserUpdate
and then fill UserUpdate
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name'=>'required|string',
'email'=>'required|email',
];
}
after that call from controller
public function profilepost(UserUpdate $request)
{
$user = Auth::user();
$user->name = $request['name'];
$user->email = $request['email'];
$user->save();
return back();
}
when submit form show error
Target class [app\Http\Requests\UserUpdate] does not exist.
Why that happen? Laravel documentation are not correct? Can someone explain me?
I Know it's solved, but this could be useful!
It's good practice to name the file/class like: UpdateUserRequest or UserUpdateRequest.
Why? It's more readable, other programmers understand what it does faster and
because of the specific name, class name collitions are avoided.
Remember if you have multiple requests on you project it's allways better to organize them in folders, example:
php artisan make:request User/UserUpdateRequest
This should create a request in User folder, and also with: namespace App\Http\Requests\User
Last but not least a better way to define the rules is:
public function rules()
{
return [
'name' => ['required', 'string'],
'email' => ['required', 'email'],
];
}
Why? This gives you the ability to add custom rules to the validations if needed!

Using HasMany relationship when Model and table have different names

Like the title says, my Field model and application_fields table have different names. I already set the table name on the Field model to the correct table name. A set the I have another model, Application, and its controller, ApplicationController. In the index method of the ApplicationController, I am trying to retrieve the application and its fields. The Field model has a belongsTo relationship to Application, and the Application model has a hasMany relationship to Field.
The code seems to work, except it pulls the values for the rows from the applications table. So if the applications table has the following rows:
1 'AppOne' 'An App'
2 'AppTwo' 'Another App'
3 'AppThree' 'A third App'
AppOne, AppTwo, and AppThree are returned as the values for the fields.
Can someone give me some advice?
Here is the code for them( I only copied what was related to the issue, not the entire file):
Application model:
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'application_fields';
public function fields()
{
return $this->hasMany('App\Field');
}
Field model:
public function application()
{
return $this->belongsTo('App\Application');
}
ApplicationController:
/**
* Display the dashboard for a single application.
*
* #param String $id
* #return View
*/
public function show( $id )
{
$app = Application::where('id', $id)->first();
$fields = $app::with('application_fields')->get();
return view('applications.show', [
'application' => $app,
'fields' => $fields,
]);
}
View( I stripped out the HTML):
{{ $application->name }}
{{ $application->description }}
#foreach($fields as $field)
{{ $field->name}}
#endforeach
I would appreciate any advice on what I am doing wrong. Thanks
your show method is wrong, eager loading does not work that way :)
public function show( $id ) {
$app = Application::with('fields')->find($id);
$fields = $app->fields;
return view('applications.show', [
'application' => $app,
'fields' => $fields,
]);
}
you can also use model Binding if your route is like that : applications/{app}
public function show(Application $app) {
$fields = $app->fields;
return view('applications.show', [
'application' => $app,
'fields' => $fields,
]);
}

How to keep user in the same page when register? (laravel)

The idea I want to keep the user on the same page when he registers and shows his message to wait for active his account.
I tried in RegisterController
protected $redirectTo = '/register';
But when I register it redirects me to the home page!
SO How to keep the user in register page and show him the message to waiting to active his
account.
I used Auth of Laravel and my version is 5.8
Thanks
You could use the redirect function in the app/Http/Controllers/Auth/RegisterController.php
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
return redirect()->back()->with('message', 'You will receive a confirmation email');
}
In register.blade.php
#if(session()->has('message'))
<div class="alert alert-success">
{{ session()->get('message') }}
</div>
#endif
EDIT :
How to redirect to previous page after successful register in Laravel?
protected function redirectTo()
{
return url()->previous();
}
You can also create redirectTo method which laravel will give priority when redirecting your users after registration. Then remove redirectTo property, even though method will take precedence.
public function redirectTo() {
return redirect()->back()->with('status', 'message for account activation.');
}
Inside the view (register.blade.php), you can have this.
#if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
#endif
EDIT:
Please ignore the previous answer. It requires custom registration so that you can take control of what happens after registration.
Since you are using Laravel Auth, you can continue and make use of their email verification like so.
Change Auth::routes(); inside routes/web.php to Auth::routes(['verify'=>true]);
Add ->middleware('verified); to the home route. This will prevent user from seeing this page until email is verified. Complete should be like so
Route::get('/home', 'HomeController#index')->name('home')->middleware('verified');
Go to App\User and make sure that the model has the following lines in addition to all other lines you have there at the top. Focus here is on implements MustVerifyEmail
use Illuminate\Contracts\Auth\MustVerifyEmail;
class User extends Authenticatable implements MustVerifyEmail
{
//rest of the code here
}
Lastly, make sure that .env file has the correct email settings. You can use mailtrap, it's free for testing purposes.
Hope this helps.

Laravel 5.4 unable to access data through foreign key in blade

I m new to laravel, and have set up a couple of models and views etc. Anyways, what i am trying to do is, I have a users model, and a teams model. The field 'id' is foreign key for users' team_id.
The user can join any team and the team he joins, its id will be stored in user's 'team_id'.
What I am trying to do it, using the team_id field to get data from the teams model, like the team name and display it on my blade view.
Here is my code for Users model:
protected $fillable = ['name',
'email',
'password',
'date_of_birth',
'team_id', /*references id in teams model*/
'matches_played',
'goals_scored',
'preferred_position',
'phone_number',
'role',
'ban_status',
'team_captain'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function Teams(){
return $this->belongsTo('App\Teams', 'team_id');
}
}
This is my code for teams model:
`protected $primaryKey = 'id';
protected $fillable = ['team_name', 'matches_played',
'matches_lost', 'goals_scored', 'goals_conceded',
'captain_name'];
public function User(){
return $this->hasMany('App\User','id');
}
`
public function showMembers(){
$users = User::with(array('Teams'))->get();
return view('admin.members')->with('users', $users);
}
`
`
and this is how i am trying to show it in blade:
{{$user->team_id->team_name}}
But instead of displaying it, i keep on getting:
Trying to get property of non-object (View: D:\Code\PHP\Code\PlayOn\resources\views\admin\members.blade.php)
Any help would be appreciated!
There are a couple of things you are doing wrong here.
First, to eager load a relationship, in this case, the teams' relationship, this is the way to do it:
$users = User::with('Teams')->get();
Finally, to loop through the Collection, you would need to do something like this:
#foreach($users as $user)
{{ $user->Teams->team_name }}
#endforeach

Get data from another model laravel-api-generator

I am using https://github.com/mitulgolakiya/laravel-api-generator
I would like to get data from another model. When inserting a post pick the category data.
PostController.php
class PostController extends AppBaseController
{
/** #var PostRepository */
private $postRepository;
/** #var CategoriesRepository */
private $categoriesRepository;
function __construct(PostRepository $postRepo, CategoriesRepository $categoriesRepo)
{
$this->postRepository = $postRepo;
$this->categoriesRepository = $categoriesRepo;
}
/**
* Display a listing of the Post.
*
* #return Response
*/
public function index()
{
$posts = $this->postRepository->paginate(10);
$categories = $this->categoriesRepository->all('id', 'desc')->get();
return view('posts.index')
->with('posts', $posts)
->with('categories', $categories);
}
fields.blade.php
{!! Form::select('category_id', Categories::lists('name', 'id'), ['class' => 'form-control']) !!}
How can I do this? Thank you!
You should make the list in controller and pass it to the view.
public function index()
{
$posts = $this->postRepository->paginate(10);
$categories = $this->categoriesRepository->all('id', 'desc')->get();
$categoryList = [ '' => '--select--' ] + $categories->lists('name', 'id');
return view('posts.index')
->with('posts', $posts)
->with('categories', $categories)
->with('categoryList', $categoryList);
}
And use this variable to generate the select.
{!! Form::select('category_id', $categoryList, ['class' => 'form-control']) !!}
I think you should use ViewComposers and pass category list array in fields.blade.php. so it will not affect directly your templates or generator.
Whenever you have a requirement where you always have to pass fields of another model in any view, I think you should use view composer.

Resources