Recursing nested array in blade template - laravel

I am attempting to loop out a menu in Laravel.
I am passing the nested array to the main blade template categories-management.blade.php.
View::make('categories-management')->with('categories', $categories);
Where $categories is
array (size=3)
'Business Resources' =>
array (size=7)
'Operations' =>
array (size=4)
'resource_type_id' => int 1
27 =>
array (size=3)
'id' => int 27
'name' => string 'Design & Development' (length=20)
'children' =>
array (size=2)
... truncated ...
I am then kicking of the menu inside of categories-management.blade.php with this:
#include('/includes/category-menu-item', array('categories', $categories))
Inside includes/category-menu-item I have the following loop:
#if(is_array($categories))
<ul>
#foreach($categories as $key => $value)
<li>
#if(!is_numeric($key))
<p>{{$key}}</p>
#include('/admin/includes/category-menu-item', array('categories', $value))
#else
<button data-category-id="{{$value->id}}">{{$value->name}}</button>
#include('/admin/includes/category-menu-item', array('categories', $value->children))
#endif
</li>
#endforeach
</ul>
#endif
This is still obviously incomplete but I already have issues where the template never gets past the first layer and prints out:
Business Resources
Business Resources
Business Resources
Business Resources
... etc ...
How do I get Laravel to recognise the new array value? Or is there a better method for this?

Your #include statements are not correct. The data passed to view need to be an associated array, you have passed an array with numeric keys. You have to change from array('categories', $value) into array('categories' => $value):
#if(is_array($categories))
<ul>
#foreach($categories as $key => $value)
<li>
#if(!is_numeric($key))
<p>{{$key}}</p>
#include('/admin/includes/category-menu-item', array('categories' => $value))
#else
<button data-category-id="{{$value->id}}">{{$value->name}}</button>
#include('/admin/includes/category-menu-item', array('categories' => $value->children))
#endif
</li>
#endforeach
</ul>
#endif

Related

Laravel 5.5 Validation errors are not displaying in case form validation fails

I am trying to display form errors in case form validation fails. Everything works fine and form is validated correctly but it does not display form errors in view. Every time an empty array is returned as errors.
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class HomeController extends Controller
{
public function storeProjectDetails(Request $request)
{
$messages = [
'title.required' => 'Please enter trip title',
'title.max' => 'Only 254 characters are allowed as trip title',
'startDate.required' => 'Please enter trip start date',
'startDate.date' => 'Only date formats are allowed as start date',
'endDate.required' => 'Please enter trip end date',
'endDate.date' => 'Only date formats are allowed as end date',
];
$this->validate($request,[
'title' => 'required|string|max:254',
'startDate' => 'required|date',
'endDate' => 'required|date',
]);
}
}
View:
print_r($errors->all());
used this
#if($errors->has())
#foreach ($errors->all() as $error)
<div>{{ $error }}</div>
#endforeach
#endif
First you need to check for errors using an if condition then you need to print the errors using a loop as given below
#if ($errors->any())
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#endif
In your case, you are missing to return the errors array in your controller. Try the validation check given below.
$this->validate($request,[
'title' => 'required|string|max:254',
'startDate' => 'required|date',
'endDate' => 'required|date',
], $messages);
You are building the messages array in a wrong format, it should look like this:
$messages = [
'required' => 'Please enter :attribute',
'date' => 'Only date formats are allowed as :attribute',
...
];

Displaying form elements obtained from database

I have a questions table which has a variety of questions of different input types. The format in my seeder is like so
DB::table('questions')->insert([
'name' => 'name',
'type' => 'text',
'text' => 'Name',
]);
DB::table('questions')->insert([
'name' => 'title',
'type' => 'select',
'text' => 'Title',
'values' => serialize(['Mr', 'Mrs', 'Ms']),
'class' => 'selectpicker'
]);
So you can see the above I have one text input and one select, which has serialized list of values. Now within my controller I get the Questions and pass it to my view.
Within my view, I am doing something like the following
#foreach($questions as $q)
<div class="col-xs-12">
<input type="{{ $q["type"] }}"
class="form-control {{ $q["class"] }}"
id="{{ $q["name"] }}"
name="questions[{{ $q["id"] }}]"
>
</div>
#endforeach
Where I am having difficulty is with the select inputs. How would I go about displaying my selects along with their options (values)?
Thanks
To create a list you can check the type of $q in your foreach. The code inside your loop would look like this:
#if( $q['type'] === 'select' )
<select name="questions[{{ $q['id'] }}]">
#foreach( unserialize($q['values']) as $v )
<option value="{{ $v }}">{{ $v }}</option>
#endforeach
</select>
#endif

Laravel blade, recursive view with php translated to blade

I have this recursive view with php, which is plain wrong so I have to translate this to blade, for recursive call for a view.
My php recursive code in (comments.blade.php):
<?php
tree($Comments, 0, 0);
$var = -1;
function tree($Comments, $parent_id = 0, $level=0, $c=0) {
global $var;
foreach($Comments as $Comment) {
if($Comment['parent_id'] == $parent_id) {
If ($level > $var) $var++; else {
for ($i = $var-$level+1; $i>0; $i--) { if ($c < 0) echo '</div> </div>'; else $c--; };
$var=$level;
};
echo '<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="..." alt="...">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">Media heading</h4>';
tree($Comments, $Comment['id'], $level+1,$c);
}
};
};
?>
And that's what I am looking for(in comments.blade.php:
<div>
#include('recursive', ['comments' => $comments, 'parent_id' => 0, 'level' => 0, 'c' => 0])
</div>
The thing is I don't know how to translate all that variables in first snippet of code into blade, so to create Recursive.blade.php:
Edit 1:
Guys please help me, I worked 2 days on this damn algorithm and I am stuck once again in a problem even bigger then it was 2 days ago :(
For some people that doesn't understand why I am sticking with that code is because that code above is the algorithm for making the threaded comments like that on reddit, in the algorithm there is 2x echo, and a media class echo.
If i put 2x after the media class on 2 comments in a row, the next one comment will create with first one, comments with same parent_id, this means they are childs that belong to the same comment(parent before them), If the 2x div are not put then this means the next one comment after first is the child of the first and so on. This is my algorithm, i am doing this to translate to blade because I have some cheeky votes buttons which uses routes that i will integrate into recursive design, that's why i want to be translate to blade, but i don't know how. :(
Why would you call the recursively for generating the view, you can make an file name comment.blade.php and run a loop inside main blade file which will include the comment.blade.php and pass the comment object or array and then the comment.blade.php file will user the properties of that $comment object or array.
For example:
$Comments = [
[
'body' => 'First comment',
'name' => 'First Commentator'
],
[
'body' => 'Second comment',
'name' => 'Second Commentator'
],
[
'body' => 'Third comment',
'name' => 'Third Commentator'
],
[
'body' => 'Fourth comment',
'name' => 'Fourth Commentator'
],
[
'body' => 'Fifth comment',
'name' => 'Fifth Commentator'
],
[
'body' => 'Sixth comment',
'name' => 'Sixth Commentator'
],
];
and in your main blade file that can be index.blade.php or any other
#foreach($Comments as $Comment)
#include('comment',['comment'=>$comment])
#endforeach
comment.blade.php file would have
<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="..." alt="...">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">Media heading</h4>
</div>
</div>
There is a automatic tool for get this job done. check out PHP2Blade
you can convert multiple files to blade syntax by runnig this command.
php php2blade <files directory> <optional output directory>

Laravel : I am trying to pass a variable from view to controller but it returns null

This is My View code When i am executing the application it only returns me NULL value, basically my $office_category is not being passed, i need the office category to query the database
<div class="box-body">
{{ Form::open(['route' => 'office.index','class' => 'form-horizontal office-form']) }}
<div class="form-body">
<div class="form-group">
<div class="col-md-3">
{{ Form::select('office_category', [
null=>'Please Select',
'Software' => 'Software',
'Computer Hardware' => 'Computer Hardware',
'Survey Instruments' => 'Survey Instruments',
'Office Equipments' => 'Office Equipments'
], isset($office_category) ? $office_category : '', ['class' => 'form-control input-xlarge select2me', 'placeholder' => 'Project Type', 'id' => 'office_category'] ) }}
</div>
{{ Form::hidden('office_category', $office_category) }}
{{ Form::submit('Search Equipment',['class' => 'btn green']) }}
</div>
</div>
{{ Form::close() }}
My Controller Code: I want the Office category thats it
Class OfficeController extends BaseController{
public function index(){
$office_category = Input::get('office_category');
if($office_category=='')
$offices = Office::orderBy('office_category', 'asc')
->get();
else
$offices = Office::where('office_category','=',$office_category)
->get();
$assets = ['table','datepicker'];
$users = User::where('client_id','=','')
->orderBy('name','asc')
->lists('name','username');
return View::make('office.index',[
'office_category' => $office_category,
'offices' => $offices,
'users' => $users,
'assets' => $assets
]);
}
Where am i going wrong please help.
You have a hidden field directly after your select that has the same name as the select. The value of this hidden field (empty) is what is getting sent to the server.
Delete this line:
{{ Form::hidden('office_category', $office_category) }}
Or rename this hidden field.
By default Form::open creates a POST request and your index method on Controller are expecting a GET request.
You need to add a new route on routes.php to match this POST request.
Route::post('index', 'OfficeController#index');
Or if you don't mind, you can set index to listen any kind of request:
Route::any('index', 'OfficeController#index');
In most of the case, above answer will solve your problem. If not, you can inspect your web request from browser and confirm value in $office_category variable.

In Laravel what is the best method to save or store data in database

For usual Form like the following form I use the following technique to save data into database.
// Controller
public function store()
{
$validator = Validator::make($data = Input::all(), Person::$rules);
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
Person::create($data);
return Redirect::route('admin.person.index');
}
But in my this form there is an file input field where user can upload multiple files at a time. and I want to store the files name into database i,e
image-1, image-2, image-3 like this. I am trying to use image intervention package to handle image files. But in that case what would my code to store data into database.
// Form
{{ Form::open(array('route' => array('admin.index.store'), 'method' => 'post', 'files' => true)) }}
<li>
{{ Form::label('name', 'Index Name') }}
{{ Form::text('name', null, array( 'class' => 'form-control input-sm', 'placeholder' => 'Name' )) }}
{{ $errors->first('name', '<p class="error">:message</p>' ) }}
</li>
<li>
{{ Form::label('phone_number', 'Phone Number') }}
{{ Form::text('phone_number', null, array( 'class' => 'form-control input-sm', 'placeholder' => 'Phone Number' )) }}
{{ $errors->first('phone_number', '<p class="error">:message</p>' ) }}
</li>
<li>
{{ Form::label('image', 'Profile Picture') }}
{{ Form::file('files[]', array('id' => 'files', 'multiple' => true)); }}
</li>
{{ Form::close() }}
Person::create($data); this wont fly.
You have to parse Input from forms, remove Files, process files separatelly and then update filepath with
//code to get $dataWithoutfiles;
$person = Person::create($dataWithoutFiles);
//code to save files to local
$person->file1 = 'path1';
// 2,3,4, etc.
$person->save();

Resources