Laravel 4 - Repopulating form for edit with multiple check boxes - php

I'm having a hard time figuring out how to repopulate a form for edit that has check boxes in it. I think the most confusing part is because they are coming from a pivot table.
I have users, permissions, and users_permissions tables.
For a quick demonstration of what the tables look like, I ran this query and included a screen clip of the results.
return $userPermissions = User::with('permissions')->find($id);
In my form I just have two permissions check boxes for now until I get the concept working, then I will add a foreach loop and grab them all from the database, but now I have the following:
<div class="form-group">
<label>
{{ Form::hidden('permissions[4]', '0', ['class' => 'checkbox-inline']) }}
{{ Form::checkbox('permissions[4]', '1', ['class' => 'checkbox-inline']) }}
Manage Content
</label>
</div>
<div class="form-group">
<label>
{{ Form::hidden('permissions[3]', '0', ['class' => 'checkbox-inline']) }}
{{ Form::checkbox('permissions[3]', '1', ['class' => 'checkbox-inline']) }}
Manage Users
</label>
</div>
I'm not sure if this is useful information, but when I first create the user, I create a permissions array to attach to the new user. Here is the code for that,
public function createUserPermissionsArray($input)
{
$permissionsArray = [];
$permissions = $input['permissions'];
foreach ($permissions as $id => $value)
{
if ($value == 1)
{
array_push($permissionsArray, $id);
}
}
$this->saveNewUserToDatabase($input, $permissionsArray);
}
I really need some direction here about how to solve this problem. Thanks

I recently worked on something similar, except I had groups with permissions assigned to them, which users were then assigned to. For example, for GroupController::edit() I had this code:
public function edit($id)
{
if(!permitted('group.edit')) {
return Redirect::route('user.dashboard');
}
$group = Group::find($id);
$permissions = Permission::all();
return View::make('admin.group.edit', [
'group' => $group,
'permissions' => $permissions,
'assigned' => $group->permissions->lists('id')
]);
}
Then within the form partial for the view (admin.group.partials.form), I had the following code to handle permissions:
#foreach($permissions as $permission)
<div class="row">
#if(isset($assigned))
{{ Form::checkbox(
'permissions[' . $permission->ident .']',
$permission->id,
in_array($permission->id, $assigned))
}}<label for="permissions">{{ $permission->ident }} - {{ $permission->description }}</label>
#else
{{ Form::checkbox(
'permissions[' . $permission->ident .']',
$permission->id)
}}<label for="group">{{ $permission->ident }} - {{ $permission->description }}</label>
#endif
</div>
#endforeach
I've formatted it the best I can, so that it's easy to read. Basically I had a create.blade.php and edit.blade.php which both include the form partial, but each file handles the opening and closing of the form (model binding for edit, normal open for create), hence the if statement.
Unfortunately I couldn't find a better method to achieve this. I hope this helps you.
P.S: As a side note, I've actually written a tutorial about creating a robust and simple ACL with Laravel, I can link if you'd like.

Related

Update specific table field on another Table

I need to update specific one id / row on a separate field on another table. how is the logic to that? so far i have this pseudo code sql query.
table name: settings
current table: aircrafts
UPDATE settings SET description id = 4
i need to update id 4 on my database in database settings
how can i integrate this code into laravel syntax?
assuming i have this controller
public function editAirReg(Request $request, $id)
{
$descr = $request->input('descr_id');
DB::update('update settings set description = ,'$descr', where id = 4',[$name,$id]);
return redirect('/admin/aircrafts')->with('success', 'Settings Updated');
}
and also this view
{!! Form::open(['action' => 'Admin\AircraftsController#getdata', 'method' => 'POST']) !!}
<input type="hidden" class="form-control" name="settings" value="{{$aircraft->air_line}}">
{{Form::submit('BIND', ['class'=>'btn btn-primary btn-block btn-lg', 'name'=>'submit'])}}
{!! Form::close() !!}
First of all, getData() doesn't make sense if you're updating something in mysql. It should be called store() or save or whatever you want to call so that the function name is appropriate.
Let's change the form so that it can pass the id to the controller.
{ Form::open(array('action' => 'Admin\AircraftsController#getdata', $id)) }}
{{ Form::hidden('settings', $aircraft->air_line) }}
{{ Form::submit('Submit', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
What I did is that change your input to the laravel syntax. Also make sure you pass the id from form to controller. take a look at my example. look where I put $id field.
Now in the controller, this is what you do.
$setting = Setting::findOrFail($id); // you must have a model or you can use DB facade
$setting->description = $request->settings; //name that you called it in form
$setting->save();

User Submitted Posts Store function using Laravel

So in addition to my prior topic (thank you guys for helping) routes with compact
I am now facing troubles with my store function, I am getting the error : "Trying to get property of non-object.
This is my store function in my Controller
public function store(Request $request)
{
// validate the data
$this->validate($request, array(
'title' => 'required|max:255',
'body' => 'required'
));
// store in the database
$userpost = new Usp;
$userpost->title = $request->title;
$userpost->body = $request->body;
$userpost->save();
Session::flash('success', 'The blog post was successfully saved!');
return redirect()->route('admin.userposts.show', $userpost->id);
}
This is the view to create userpost(to make it more clear, p.s. the same form with different route ofcourse, works for my simple posts but not for my user submitted posts)
#extends('index')
#section('index-stylesheets')
{!! Html::style('css/parsley.css') !!}
#endsection
#section('content')
<h1>Create New User Post</h1>
<hr>
{!! Form::open(array('route' => 'admin.userposts.store', 'data-parsley-validate' => '')) !!}
{{ Form::label('title', 'Title:') }}
{{ Form::text('title', null, array('class' => 'form-control', 'required' => '', 'maxlength' => '255')) }}
{{ Form::label('body', "Post Body:") }}
{{ Form::textarea('body', null, array('class' => 'form-control', 'required' => '')) }}
{{ Form::submit('Create Post', array('class' => 'btn btn-success btn-lg btn-block', 'style' => 'margin-top: 20px;')) }}
{!! Form::close() !!}
#endsection
#section('index-scripts')
{!! Html::script('js/parsley.min.js') !!}
#endsection
Method of showing the post:
public function show($id)
{
$userpost = Usp::find($id);
return view('admin.userposts.show', compact('userpost'));
}
So the fact is that the problem was not the store method but the routes.
Route::get('/userposts/{id}', 'UserPostsController#show')->name('admin.userposts.show');
Route::get('/userposts/create', 'UserPostsController#create')->name('admin.userposts.create');
Route::post('/userposts/store', 'UserPostsController#store')->name('admin.userposts.store');
When registering the routes in that order, when laravel will iterate over your routes, it will first encounter the show one, and it will therefore take "create" as the id. Therefore, it will go into the show method and it won't find any post that matches, the post being null, you get the error.
So, there are two ways of fixing this.
The first one (the easiest, works in all cases, maybe not the best) is to put the create route before the show route.
The second one, the best in my opinion, is to add a condition to the id (doesn't work in the case of a slug). As the ids are only integers, you get :
Route::get('/userposts/{id}', 'UserPostsController#show')->name('admin.userposts.show')->where('id', '[0-9]+');
Therefore, create won't match the regular expression and it won't go in the show method.
For "resource creations" (storing in database), I wouldn't use a "field-by-field" method.
Instead, I'd do something like this :
$userpost = Usp::create($request->only('title', 'body'));
I feel this is more talkative.
But, it won't work, laravel protects* us against such things. To make it work, you have two options.
(The best option in my opinion)
In your model, add a protected variable called $fillable with all your columns that you allow to mass assign*. In this case you would put :
protected $fillable = ['name'];
(The option if you are sure of what are you doing)
In your model, you can say, hey, I know what I'm doing here, just let me do my stuff without guarding me. In this case you would put :
protected $guarded = [];
Notes :
$request->only('field1', ...) gives you an array of the fields that you want with the fields name as keys, in this case it gives you ['field1' => $request->field1]. In your case it will give you ['title' => $request->title, 'body' => $request->body].
Mass assignment is when you give an array to the model and it puts all attributes to the fields of the array. More informations here https://laravel.com/docs/5.4/eloquent#mass-assignment
When I mean laravel protects us against those things, it does't really protect us because it isn't a bad practice (instead, I find it more readable), but because it does allow you to make mistakes (for exemple, setting fields that don't exist).

Laravel 5 binding value in bootstrap-slider in edit/Patch

I'm implementing bootstrap-slider in my CRUD, I have implemented it successfully in Create, the problem is when I try to edit it,
I want to get the current value from the Model. Idk how to do this.
This is for PATCH.
<div class="form-group">
<h3 class='box-title text-info'>Percentage</h3>
{!! Form::input('text','percentage',null,['id'=>'ex8', 'data-slider-id'=>'ex1Slider', 'data-slider-min'=>'0', 'data-slider-max'=>'100', 'data-slider-step'=>'5', 'data-slider-value'=>'50']) !!}
</div>
In your form instead of creating a new form. You will bind the form to the model.
{!! Form::model('modelname', [options here] !!}
All the fields will math the model's property values.
Edit
Here is an example
You must used something like this to create a EDIT FORM
{{ Form::model($smartphones, ['method' => 'PATCH', 'url' => 'smartphones/'.$smartphones->id]) }}
You get by using $(your_model)['inputID']...You can use in "data-slider-value"... Something like this
{{ Form::input('text','mem_ram', null, ['id' => 'mem_ram', 'data-slider-value'=>$smartphones['mem_ram']]) }}

Laravel 5:Validation on update to model with relationship to user is throwing unique error

I was doing great so far until I ran into another problem with validation. I'm trying to update a user related table called socialLinks. The problem is every time I update, since it's a model backed form, the prefilled values in the form gets pass through validations and I get a 'has already been taken' error in return.
After doing a bunch of googling, I tried to pass userId through update, but i haven't had any success. I had this problem before but I was validating a column from User. Now I'm trying to validate a column from another table with a relationship with user and nothing I tried before works. Super Frustrating.
my form
{!! Form::model($user_links,['method' => 'PATCH', 'action'=> ['UserController#update_social']]) !!}
<div class='row form-group'>
<div class='col-md-2'>
{!! Form::label('facebook', 'Facebook Username') !!}
</div>
<div class='col-md-7'>
{!! Form::text('facebook', null,['class'=>'form-control']) !!}
</div>
</div>
<div class='row form-group'>
<div class='col-md-2'>
{!! Form::label('twitter', 'Twitter Username') !!}
</div>
<div class='col-md-7'>
{!! Form::text('twitter', null,['class'=>'form-control']) !!}
</div>
</div>
<div class='row form-group'>
<div class='col-md-2'>
{!! Form::label('reddit', 'Reddit Username') !!}
</div>
<div class='col-md-7'>
{!! Form::text('reddit', null,['class'=>'form-control']) !!}
</div>
</div>
<div class='row form-group'>
<div class='col-md-3'>
{!! Form::submit('Save Changes',['class'=>'btn btn-md btn-success']) !!}
{!! Form::close() !!}
routes
Route::get('/account/social','UserController#social');
Route::patch('/account/social','UserController#update_social');
and controllers
public function social(Request $request){
$user = $request->user();
$user_links= $request->user()->links;
return view('user.edit.social_connect',compact('user_links','user'));
}
public function update_social(Request $request){
$user = $request->user();
$validator=Validator::make($request->all(),[
'facebook' => 'unique:social_links,facebook,'.$user->id,
'twitter' => 'unique:social_links,twitter'.$user->id,
'reddit' => 'unique:social_links,reddit,'.$user->id,
'google' => 'unique:social_links,google,'.$user->id
]);
if ($validator->fails()){
var_dump($user->id);exit;
return Redirect::back()->withErrors($validator)->withInput();
}
$data=Input::all();
$links = $user->links;
if ($links == null){
$links = new SocialLinks();
$links->fill($data);
$links->user_id=$user->id;
$links->save();
}else{
$links->fill($data);
$links->save();
}
return Redirect::back()->with('message','Your profile has been updated');
}
Update put validation logic in controller
this is what worked for me
$user = $request->user();
$id = $user->id;
$validator=Validator::make($request->all(),[
'facebook' => 'unique:social_links,facebook,'.$id.',user_id',
'twitter' => 'unique:social_links,twitter,'.$id.',user_id',
'reddit' => 'unique:social_links,reddit,'.$id.',user_id',
'google' => 'unique:social_links,google,'.$id.',user_id',
]);
I honestly don't get why though. Why do we concatenate id to exclude it from being validated? the syntax makes no sense to me. Also $id comes from user object, and 'user_id' is from my social links table. Am I matching ids here? Somebody please show me the light ;(
To start: In general, extending the Laravel Request class and dependency injecting your extended class into your controller functions, although it can be done, is a bad idea. Read this to understand why (although it may not appear to be related at first read):
Laravel 5 / Codeception not routing correctly
Basically the problem is that if your validation class throws a perfectly legitimate validation exception, that exception has to be trapped by the Laravel router and not by the controller function. Essentially unless the validation passes your controller function never gets called, and so it can't trap the validation exception. This frequently results in either a 500 error or a redirect to a completely different page (which is why this screws up codeception tests amongst other unwanted side-effects).
So a better plan is to pass a Laravel Request object into your controller function and validate inside the function, rather than attempting to get Laravel to do it for you.
Once you resolve that issue, getting the validation code to handle the case where the $user does not exist should be easy. Some suggestions for your validation code to handle that validation (which should now be inside your controller function, or in a separate validator class called from your controller function):
Request probably doesn't contain a User object. It might contain a user_id variable which you can turn into a User object using User::find($user_id) or similar.
Check to ensure that $user is not null before attempting to work with $user->id or you'll get an error. If the $user_id passed in is empty or invalid then User::find($user_id) will return null. Check for this case and throw an exception first, before you continue to look at $userId or save any links.
I can't see exactly what you're doing in your form but if the above doesn't resolve your issues then post the form here and we can take another look.
You need to edit validation for updating, this is my example from one app :
public function rulesAdmin($id = NULL)
{
return [
'name' => 'required|min:5',
'username' => 'unique:users' . ($id ? ",username, $id" : ''),
];
}
on editing ->you pass from database $id, on saving new record -> $id is NULL.

NotFoundHttpException at new route Laravel 4

i see there are similar questions but dont find any clue of me problem.
I created a basic users system, to manage groups, permissions, users, etc. The basic routes like create, edit, delete, index are working.
Now im trying to add one more function to UserController, to manage the users groups in a simple view.
Route::group(array('prefix' => 'admin'), function()
{
Route::resource('groups', 'GroupController');
Route::resource('users', 'UserController');
});
The function in controller:
public function groups($id)
{
$user = Sentry::findUserByID($id);
$groups = $user->getGroups();
return View::make('users.show')
->with('groups', $groups);
}
And the users/groups.blade.php:
#extends('layouts.admin')
#section('content')
<header id="page-title">
<h1>User Groups</h1>
</header>
<!-- if there are creation errors, they will show here -->
{{ HTML::ul($errors->all()) }}
{{ Form::open(array('url' => 'admin/users/save_groups')) }}
<div class="form-group">
</div>
{{ Form::submit('Create!', array('class' => 'btn btn-primary')) }}
{{ Form::button('Cancel', array('class' => 'btn btn-danger')) }}
{{ Form::close() }}
#stop
I go to url "mysite/admin/users/2/groups", and im getting the NotFoundHttpException, i try many ways to make it works and dont know what is happening.
I assume it will works like "mysite/admin/users/2/edit", but if i test the show function, it only is "mysite/admin/users/2", dont need the show action to know is that function, maybe i missed something.
You have declared a route for "GroupsController". As per the documentation, this will only handle actions as defined in the table: "Actions Handled By Resource Controller"
Just by adding one more action it won't simply be extended by Laravel.
You should instead type:
Route::get('users/{id}/groups', 'UserController#groups');

Categories