How to properly pass data from PHP to JS - laravel

I'd like to store a Customer model in a JS variable as JSON. Here are the approaches I tried and the pitfalls I found in each of them:
{{ $customer }} makes the resulting code in <script> look like this: var customer = {"id":1, ... "}, failing with Uncaught SyntaxError: Unexpected token & error. Also, if the variable is null in PHP, then in JS it becomes var customer = ;, which breaks the code.
{!! $customer !}} stores the data properly var customer = {"id":101, ... }, but it suffers from the same problem as {{ }} above when the variable is null in PHP.
{!! json_encode($customers->toArray()) !!}; works for a collection, but not for a single model object -- in the latter case PHP would fail by trying to call toArray() on null. Also, {!! !!} are vulnerable to XSS attacks.
The one that did work for me was {!! $customer ?? 'undefined' !!}. It properly handles all cases, but it's haky and insecure. Another solution seems to be {!! json_encode($customer) !!} but again, it also suffers from security issues. I wonder if it can be simplified to just {{ }}, or maybe there is a better approach.
Thanks!

Well that's a little difficult I was trying that time ago, but the only thing that I did (is not the better approach) is this...
I asssigned the values into data tags example
<input type="hidden" data-customer="{{json_encode(custumer)}}">
Then I used javascript/JQuery to access to tha info in my script

try isset
#if(isset($custumer)){{ $custumer }}#endif

I'm using this package, which does the magic for you:
https://github.com/laracasts/PHP-Vars-To-Js-Transformer

Related

Blade view for rich text field on description tag

I'm using voyager in a laravel 7 shopping app for the description of all products.
I want to output the field for the description of the product
#section('description', {!! $item->description !!} )
and
for the facebook share = og:description" content="{!! $item->description !!}">
When I use {!! $item->description !!} in the body, no problem. But in the tag the output always read the p tag and all style form the description.
The weird thing is it's working find on localhost but not on the server. I tried various combination of solution with the same result. I feel there's a quick or maybe it's just not possible?
try html_entity_decode() ref link https://www.php.net/manual/en/function.html-entity-decode.php
{!! $item->description !!}
to
{!! html_entity_decode($item->description) !!} // it will render html
If you are using laravel 7/8 you can create a blade component then you can simple call
<x-editor :content="$description></x-editor>
check out this laravel docs
try this:
{{strip_tags(trim($item->description)}}

Need to go through 2 objects at the same time with VUEJS

I just want to throught POSTS and USERINFO at the same pace, in a way that in show the right user avatar for a given post
Objects
posts : {!! $posts !!},
userinfo : {!! $userinfo !!},
Template
< v-cloak v-for="post in posts">
<div v-bind:style="{ backgroundImage: 'url(' + post.picture + ')' }">
</div>
Dont know how... basicly...
The correct way (IMHO) is to provide the data to the template in a correct way, so the template just loops through the data the least amount of time.
To support that a computed value may be the easiest way to implement.
You can create a complex loop using js in you computed value, and then you reduce any complex logic in the template. This may also reduce the number of renders or re-computations needed if other parts of the component or template are changing.
other options are to update data.variable using a watch or from an api callback
I think you can add a property id to your user object.
And a property userId to your post object to avoid mistakes.
User has to be a prop of your element to be used into it

Convert foreach loop into array using laravel5

#foreach($users as $user)
$users[] = $user->name;
#endforeach
I want to get the output like this.
['X', 'Y', 'Z', 'C'];
Note: i need this because i have to use this in JavaScript function.
First of all, you can't "turn a foreach loop into an array", you would use that foreach loop to get an array as outcome. In this case I wouldn't go with a foreach approach, there are some methods that can help you cleaning out your code a bit.
You have two options depending on the type of the $users variable, pluck() or array_column():
// $users is a collection
json_encode($users->pluck('name'));
// $users is an array
json_encode(array_column($users, 'name'));
The json_encode() is highly recommended (as the comments pointed out) if you are going to use that output in your javascript. Now you can just send it in a respond and use it as a normal JSON.
In case you print the resulting variable using Blade, remember you need to use {!! !!}, otherwise, if you use {{ }} you would get unwanted scaped characters, since it uses htmlspecialchars() function under the hood.
Hope this helps you.
I recommend You should perform this action in your controller only, and then pass it to your view as
$userNames=implode(",",array_column($users,'name'));
return view('your_view',['userNames'=>$userNames]);
Then split it in your js as
var names="{!! $userNames!!}";
var names= names.split(",");
Collections will automatically be converted to json when you try to echo them.
The reason you're seeing " is because using {{ }} will automatically escape strings for your protection. You can prevent this by using {!! !!} instead.
Try something like this:
<script>
var data = '{!! $users->pluck('name') !!}';
console.log( JSON.parse(data));
</script>
Hope this helps!

Laravel 4 - Showing edit form with OLD data input as well as DB information

Im making a edit form for my app and i was wondering if someone could tell me how to get the data from the database into my text field.
I can locate the record i need to edit based on the users click, and i can display the information if i do the following:
value="{{ $letter->subject }}"
BUT, the problem im having is that when i run it through the validation and there is an error, it comes back with the database information instead of the OLD data.
So my questions is. Is there a way to serve up the database information first and then when it goes through the validatior, validate the information the user has edited?
Currently to validate the text field and bring the data back incase of error, im using
Input::old('subject')
Is there a parameter for that old bit that allows me to put in the DB data?
Cheers,
Hey you could validate and return ->withInput() and then in your actual form, check if there is Input::old() and display it, otherwise display from the db.
example:
<input type="text" name="subject"
value="{{ (Input::old('subject')) ? Input::old('subject') : $letter->subject }}">
Or you could go the other way and define the variable and do a regular if statement, instead of the ternary one! Up to you to decide what you want to use!
All you need is form model binding http://laravel.com/docs/html#form-model-binding:
{{ Form::model($letter, ['route' => ['letters.update', $letter->id], 'method' => 'put']) }}
// your fields like:
{{ Form::text('someName', null, ['class' => 'someHTMLclass' ...]) }}
// no default values like Input::old or $letter->something!
{{ Form::close() }}
This way you form will be populated by the $letter data (passed from the controller for example).
Now, if you have on your countroller:
// in case of invalid data
return Redirect::back()->withInput();
then on the redirect your form will be repopulated with input values first, not the original model data.
Make it more simple and clean
<input type="text" name="subject" value="{{ (Input::old('subject')) ?: $letter->subject }}">
I'm not sure for Laravel 4 but in Laravel 5, function old takes second param, default value if no old data in session.
Please check this answer Best practice to show old value

Laravel Pagination links not including other GET parameters

I am using Eloquent together with Laravel 4's Pagination class.
Problem: When there are some GET parameters in the URL, eg: http://site.example/users?gender=female&body=hot, the pagination links produced only contain the page parameter and nothing else.
Blade Template
{{ $users->link() }}
There's a ->append() function for this, but when we don't know how many of the GET parameters are there, how can we use append() to include the other GET parameters in the paginated links without a whole chunk of if code messing up our blade template?
I think you should use this code in Laravel version 5+.
Also this will work not only with parameter page but also with any other parameter(s):
$users->appends(request()->input())->links();
Personally, I try to avoid using Facades as much as I can. Using global helper functions is less code and much elegant.
UPDATE:
Do not use Input Facade as it is deprecated in Laravel v6+
EDIT: Connor's comment with Mehdi's answer are required to make this work. Thanks to both for their clarifications.
->appends() can accept an array as a parameter, you could pass Input::except('page'), that should do the trick.
Example:
return view('manage/users', [
'users' => $users->appends(Input::except('page'))
]);
You could use
->appends(request()->query())
Example in the Controller:
$users = User::search()->order()->with('type:id,name')
->paginate(30)
->appends(request()->query());
return view('users.index', compact('users'));
Example in the View:
{{ $users->appends(request()->query())->links() }}
Be aware of the Input::all() , it will Include the previous ?page= values again and again in each page you open !
for example if you are in ?page=1 and you open the next page, it will open ?page=1&page=2 So the last value page takes will be the page you see ! not the page you want to see
Solution : use Input::except(array('page'))
Laravel 7.x and above has added new method to paginator:
->withQueryString()
So you can use it like:
{{ $users->withQueryString()->links() }}
For laravel below 7.x use:
{{ $users->appends(request()->query())->links() }}
Not append() but appends()
So, right answer is:
{!! $records->appends(Input::except('page'))->links() !!}
LARAVEL 5
The view must contain something like:
{!! $myItems->appends(Input::except('page'))->render() !!}
Use this construction, to keep all input params but page
{!! $myItems->appends(Request::capture()->except('page'))->render() !!}
Why?
1) you strip down everything that added to request like that
$request->request->add(['variable' => 123]);
2) you don't need $request as input parameter for the function
3) you are excluding "page"
PS) and it works for Laravel 5.1
In Your controller after pagination add withQueryString() like below
$post = Post::paginate(10)->withQueryString();
Include This In Your View
Page
$users->appends(Input::except('page'))
for who one in laravel 5 or greater
in blade:
{{ $table->appends(['id' => $something ])->links() }}
you can get the passed item with
$passed_item=$request->id;
test it with
dd($passed_item);
you must get $something value
In Laravel 7.x you can use it like this:
{{ $results->withQueryString()->links() }}
Pass the page number for pagination as well. Some thing like this
$currentPg = Input::get('page') ? Input::get('page') : '1';
$boards = Cache::remember('boards' . $currentPg, 60, function() {
return WhatEverModel::paginate(15);
});
Many solution here mention using Input...
Input has been removed in Laravel 6, 7, 8
Use Request instead.
Here's the blade statement that worked in my Laravel 8 project:
{{$data->appends(Request::except('page'))->links()}}
Where $data is the PHP object containing the paginated data.
Thanks to Alexandre Danault who pointed this out in this comment.

Resources