nolros

nolros

Member Since 5 Years Ago

Experience Points 86,560
Experience Level 18

3,440 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed 376
Lessons
Completed
Best Reply Awards 28
Best Reply
Awards
  • Start Your Engines Achievement

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • First Thousand Achievement

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • One Year Member Achievement

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • Two Year Member Achievement

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • Three Year Member Achievement

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • Four Year Member Achievement

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • Five Year Member Achievement

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • School In Session Achievement

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • Welcome To The Community Achievement

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • Full Time Learner Achievement

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • Pay It Forward Achievement

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • Subscriber Achievement

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • Lifer Achievement

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • Laracasts Evangelist Achievement

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • Chatty Cathy Achievement

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • Laracasts Veteran Achievement

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • Ten Thousand Strong Achievement

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • Laracasts Master Achievement

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • Laracasts Tutor Achievement

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • Laracasts Sensei Achievement

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • Top 50 Achievement

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

18 Mar
3 months ago

nolros started a new conversation Webpack.mix First Render Config

Anyone have a best practice or ideally an example for compiling for first paint (Critical Rendering Path) i.e. I would like to compile the core JS and Sass. So that I can minimize initial JS and CSS file size and load. Then defer / async block load the majority of JavaScript and CSS. The purpose is obviously for PageSpeed.

I could just use Webpack vanilla, but wondering if there is a Laravel best practice example.

As a plus if anyone has examples of defer loading third-party scripts like Google Analytics, Facebook API, Twitter, etc. I could write a wrapper, but that almost always goes sideways when an update occurs.

19 Feb
4 months ago

nolros started a new conversation VueJS Render Static HTML

This seems like an obvious or simple ANSWER, but I cannot seem to find an answer. How do I dynamically import a HTML FILE into a Vue component? NOT a template, but lets say I have an article-.html file that I want to pull in dynamically e.g. on click of post abstract show the above mentioned html file. In Laravel it would @include(‘path’) or AngularJS it would be ng-include(‘path)

05 Jan
5 months ago

nolros left a reply on How To Submit A Vue Component In Laravel Blade?

Code would look like this:

BLADE

        <section>

                <editor-by-vue
            :id="{!! $question->id !!}"
                        :editcontent="{!! $question->body !!}">
                </editor-by-vue>

            </section>

VUE

<template>
    <form action="/question/{{ $question->id }}" 
            name="editor"
              @submit.prevent="onSubmit"
              method="post">
        <label for="title">Description</label>
        <vue-editor
                v-model="content"
                :editorToolbar="customToolbar">
        </vue-editor>
        <button  type="submit">Publish</button>
    </form>
</template>


<script>
    import { VueEditor } from 'vue2-editor';

    export default {
        props: [
        'editcontent',
        'id
    ],
        components: {
            VueEditor
        },
        mounted() {
            this.content = this.editcontent;
        },
        data() {
            return {
                content: '',
                customToolbar: [
                    ['bold', 'italic', 'underline'],
                    [{ 'list': 'ordered'}, { 'list': 'bullet' }],
                    ['image', 'code-block']
                ]
            }
        }

        methods: {

            onSubmit: function () {
                var url = '/question/' + this.id;

                axios.post(url, this.content)
                    .then(response => {

                    })
                    .catch(error => {
                    });

            },
        },
    }
</script>


nolros left a reply on How To Determine If Multiple Records' Are More Than A Value Then Count?

@patricksj assuming they are all in the results table you could do this

     $paperIds = [1,2,3];
        $min = 50;
        $max = 95;
        

    // $count will give you count & $results will be the collection 

        $count = count($results = DB::table('results')
            ->whereIn('paper_id', $paperIds)
            ->whereBetween('mark', [1, [$min, $max]])
            ->get());

nolros left a reply on Dynamically Import And Render HTML Documents

@JLRDW - @jlrdw yes I can do it via php but I was looking for an elegant Vue solution. I think the right answer is Vue Directive combined with Vue async https://vuejs.org/v2/guide/components-dynamic-async.html. The issue with php and Vue is that Vue like most JS libraries doesn't work well with dynamic DOM manipulation so you need to compile / render and everything should be promise based to give Vue time to sync the changes. AngularJS solved this with directives and even then it was cycle intensive $digest() $apply(),, $watch()

Vue doesn't seem to have a clean solution. I'm noticing that Vue struggles with some of the earlier DOM issues that AngularJS struggled with. It has issues SEO, dynamic DOM compile / render, etc. However in the absence of AngularJS Vue is the next best solution because ANgular and Laravel is an overkill and frankly not a good fit.

nolros left a reply on How To Change Values Of A Prop If Components Are Produced Via Blade For Loop?

@ANDREASB - Here is the working code

Blade

         <section>

                <followable-icon 
                        title="title: Remove from list"
                        icon="icon:minus-circle; ratio: 0.8"
                        :question-id="{!! $question->id !!}"
                        followable="bookmark"
                        :is-followable=true>
                ></followable-icon >
      

            </section>

Vue

<template>
    <div style="width: 100px; height: 100px; background: red;">
        <a href="#"
           :data-uk-tooltip="title"
           class="uk-icon-link"
           :data-uk-icon="icon"
           @click="toogleFollowable()">Click
        </a>
    </div>
</template>


<script>
    export default {

        props: {
            title: {
                type: String,
                required: true
            },
            icon: {
                type: String,
                required: true
            },
            questionId: {
                type: Number,
                required: true
            },
            followable: {
                type: String,
                required: true
            },
            isFollowable: {
                type: Boolean,
                required: true
            },
        },
        data: function () {
            return {
                active:{}
            }
        },
        methods: {

            toogleFollowable: function (event) {
                var url = '/question/toogleFollowable/' + this.followable+ '/' + this.questionId;

                axios.post(url)
                    .then(response => {
                        this.toogleFollowableUIChanges(event)
                    })
                    .catch(error => {
                        this.error = error;
                    });

            },

            toogleFollowableUIChanges: function (event) {
                switch(this.isFollowable ){
                    case "true":
                        this.icon = "icon:plus-circle; ratio: 0.8";
                        this.isFollowable = "false";
                        break;
                    case "false":
                        this.icon = "icon:minus-circle; ratio: 0.8";
                        this.isFollowable = "true";
                        break;
                }
            },
        },

    }
</script>


03 Jan
5 months ago

nolros left a reply on Eager Loading With Where Clause Not Working As Expected

You hav a single relation "belongsTo" so if there is a relationship lets say on if it will get the team for you i.e. dd($league->team->toArray()); should show you a team if the relationship is working and the records exist. The query for team name would be redundant as there is only one team per league as you've setup the relationship. However I suspect there are meany teams in the league and as such you should have

public function team()
{
    return $this->hasMany(Team::class);
}

in which case you could have something like this

class League extends Model {

    public function teams()
    {
        return $this->hasMany(Team::class);
    }


}

class LeagueController extends Controller
{
    protected $league;

    public function __construct(League $league)
    {
        $this->league = $league;
    }

    public function getTeamOfLeague($league, Team $team)
    {
//      OPTION 1 returns league with team
        $leagueInstanceWithTeam =  $this->league->where('name',$league)->with(['teams' => function($q) use ($team) {
            $q->where('name', '=', $team->name);
        }])->first();

//      OPTION 2: returns $league instance with teams relations collection
        $team = ($league = $this->league->where('name',$league)->with(['teams'])->first())
                    ->teams
                    ->where('name', $team->name)->first();
        
//      OPTION 3: same as 2 with collection filter, map or foreach
        if ($league = $this->league->where('name',$league)->with(['teams'])->first() ) {
            $team = $league->teams->where('name', $team->name)->first();

            $leagueWithTeam = $league->teams->filter(function ($t) use ($team) {
                return $t.name === $team.name;
            });
            
            // OR 

            $teamWithNoLeague = $league->teams->map(function ($t) use ($team) {
                return $t.name === $team.name;
            });

        }
        
        //OR 
      
//      Other options DB::raw() - join OR collection custom macros e.g. $league->teamOfLeague() ... other
    }
}

nolros left a reply on How To Change Values Of A Prop If Components Are Produced Via Blade For Loop?

example to help you

<!--BLADE FOREACH-->
<ul id="product__card"
    class="product__cards--container list-reset">
    @if(count($category->products))

        @foreach($category->products as $product)
        <product-card
                id="{!! $product->id!!}"
                name="{!! $product->name!!}"
                image-url="{!! $product->image_url!!}"
                dimensions="{!! $product->dimensions!!}"
                projects="{!! $product->projects!!}">
        </product-card>

        @endforeach
    @endif
</ul>




<template>
    <div class="product__card--item">
            <div class="product__card-image--container">
                <img class="product__card-image"
                     itemprop="url"
                     :src="imageUrl"
                     alt="">
            </div>
            <p class="product__card-title">{{name}}</p>
        <div id="product__card-info">
            <ul>
                <li class="product__card-info">
                    <h3 class="text-center">{{dimensions}}</h3>
                    <p class="text-center">dimensions</p>
                </li>
            </ul>
        </div>
    </div>
</template>


<script>
    export default {
        props: {
            id: {
                type: String,
                required: true
            },
            name: {
                type: String,
                required: true
            },
            imageUrl: {
                type: String,
                required: true
            },
            dimensions: {
                type: String,
                required: true
            },
            projects: {
                type: String,
                required: true
            },
        },
        data: function () {
            return {
                active:{}
            }
        },
        methods: {

            tester: function () {
                console.error("click tester");

            }
        }
    }
</script>

nolros left a reply on How To Change Values Of A Prop If Components Are Produced Via Blade For Loop?

You declaring props, but not binding them with :

  1. try this
           <followable-icon 
                        :title="'title: Remove from list" 
                        :icon="icon:minus-circle; ratio: 0.8"
                        :question-id="{!! $question->id!!}" 
                        :followable="bookmark"
                        :is-followable=true>
                    
                </followable-icon>
  1. remove this you've already have them set in props - vue will complain i.e. this.icon will work fine
    data: function () {
      return {
        icon: this.icon,
        questionId: this.questionId,
        followable: this.followable,
        isFollowable: this.isFollowable,
        
      }
    },

nolros left a reply on Return Items Separated Out By Date

You could try something like this, but unsure if you are saving anything.

        $latest = Site::query()
            ->with('upvotes')
            ->where([
                ['is_approved', '=', 2],
                ['is_featured', '=', 1],
            ])->orderBy('created_at', 'DESC')
            ->get()
            ->map(function ($sites) {
                $sites->groupBy(function ($s, $k) {
                    return $s->created_at->toDateString();
                });
                return $sites;
            });

nolros left a reply on How To Update Multiple Forms

I wouldn't recommend this approach, but as long as the forms are contained in a single scope they will all use a single model. You will handle the post outside of the forms with a generic post

please note I have not tested any of this i.e. just conceptual

<template>
    <div> // NOTE: this is in one scope
        <form v-for="(form,index) in forms">
            <input :v-model="model[form.input]"
                   type="{{form.input}}" 
                   id="{{form.input}}">
        </form>
        <button @click="submitForms"></button>
    </div>
</template>

<script>
    export default {
        name: "Example",
        data: function () {
            return {
                htmlDocuments: [
                    {
                        id:1,
                        form: "form-one",
                        input: text
                    },
                    {
                        id:2,
                        form: "form-two",
                        input: email
                    },
                    {
                        id:3,
                        form: "form-three",
                        input: password

                    },
                ],
                model: {
                    email:"",
                    name: "",
                    url: ""
                },
                active:{}

            }
        },
        methods: {
            submitForms: function () {
                const url = '/api/post';

                return new Promise((resolve, reject) => {
                    axios[.post(url, this.model)
                        .then(response => {
                            resolve(response.data);
                        })
                        .catch(error => {
                            reject(error.response.data);
                        });
                });
                
            },
        }

    }
</script>

nolros started a new conversation Hoe To Import And Render N Number Of HTML Documents

What is the best option to import and render a list html documents / templates that are NOT Vue components

Options:

  1. 'import htmlFile from htmlFile.html' ... the problem is this doesn't work with dynamic list of files i.e. n number of html files
  2. Vue render() function
  3. vue-router but that really works for nav / tabs, etc but in the face of lets say blog posts where all I'm looking do is import and render html then it is not idea

Example in AngularJS the ng-include

<li ng-repeat="item in list">
    <div ng-include="item.source_url'"></div>
</li>

Example HTML Documents

<!--/templates/example-1.html-->
<div>
    <p>Nothing special</p>
</div>

<!--/templates/example-2.html-->
<div>
    @include("php-file-example")
    <p>Php and HTML</p>

</div>

<!--/templates/example-3.html-->
<div>
    <p :text="somevar"></p>
</div>
<!--ExampleComponent-->
<template>
    <ul>
        <li v-for="(document,index) in htmlDocuments">
            <!--Import and render html document-->
        </li>
    </ul>
</template>

<script>
    export default {
        name: "Example",
        data: function () {
            return {
                htmlDocuments: [
                    {
                        id:1,
                        source_url: "/templates/example-1.html"
                    },
                    {
                        id:2,
                        source_url: "/templates/example-3.html"
                    },
                    {
                        id:3,
                        source_url: "/templates/example-3.html"
                    },
                ]

            }
        },


    }
</script>
27 Dec
5 months ago

nolros left a reply on Validation Exception Into A JSON Response

Sorry to be clear. I’m saying that I found the exception handler code in 5.5. release note which works great and as such asking the question as to why it is not included in the current 5.7 build i.e. you still need to add it to the exception handler.

I was getting "message: The given data was invalid" error on standard Vue axios data submission i.e. name and body input text fields.

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ContactForm extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name'      => 'required',
            "body"      => 'required'
        ];
    }

}

Controller example:

public function postContactUs(ContactForm $request)
{
    return ['message' => 'Project Created!'];
}

26 Dec
5 months ago

nolros started a new conversation Validation Exception Into A JSON Response

Any idea why this nugget in 5.5 release notes is not automatically added to the 5.7 install App\Exceptions\Handler class?

without it I kept getting "message: The given data was invalid" on any given Vue AJAX submission

    /**
     * Convert a validation exception into a JSON response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Validation\ValidationException  $exception
     * @return \Illuminate\Http\JsonResponse
     */
    protected function invalidJson($request, ValidationException $exception)
    {
        return response()->json($exception->errors(), $exception->status);
    }
28 Sep
8 months ago

nolros left a reply on Display Same Data On 2 Routes (and Same View) While Keeping DRY

@robot98 you are looking for authorization https://laravel.com/docs/5.7/authorization where you set create policies and authorize users against those policies

26 Sep
8 months ago

nolros left a reply on Select Statement Where $request->input() Laravel 5.5

I think you have named the input it agency_id and not id. Try this -


$agencyarchives = Agencyarchive::select('*')
                        ->where('agency_id', $request->input('agency_id'))
                        ->get();


29 May
1 year ago

nolros left a reply on How Do I Search Records Within The Eager Loaded Data?

@yansusanto here you go

    public function Blog($title, $firstName, $lastName)
    {

        return Blog::where('title', 'LIKE', '%' . $title . '%')
            ->with(['user', function ($q) use ($firstName, $lastName) {
                $q->where('first_name', $firstName);
                $q->where('last_name', $lastName);
            }])
            ->latest()
            ->paginate(10);
    }
        

nolros left a reply on 404 Not Found In Views Subfolders

@henrylemmon do you have a route for "tasks" in your routes file and do you have a view associated with that route? Suggest you post code for people to review.

nolros left a reply on ReflectionException (-1) Class App\policies\RolePolicy Does Not Exist

@ljlizarraga

have you declared it in the AuthServiceProvider?


<?php

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        //
    }
}

nolros left a reply on Get All Collections With BelongsToMany Relation

@rzme

        User::where("id",1)
            ->with('roles', function($q) {
                $q->orderBy('name');
            })->get();

nolros started a new conversation Import My App Init Vue File

Is the best approach in Vue to import my own init (app or main or whatever you want to call it )

init.vue

<template>
    <div>
        <p>stuff</p>>
    </div>
</template>

<script>

    export default {

    };

</script>

app.js

require('./bootstrap');

window.Vue = require('vue');

import init from './init.vue'

const app = new Vue({
    el: '#app',
    render: h => h(init)
});
28 May
1 year ago

nolros left a reply on GET Request $request->getContent() Is Empty

@MrFiliper if I recall you get it as follows:

// no function just key
$var =  $request->key 

nolros left a reply on Jquery .text Vs .html

@behnampmdg3 why escape to \n if already in JS. Keep

Example:

https://codepen.io/matrixme/pen/XYrqOy

HTML

<textarea cols="30" rows="10" id="input"></textarea>
<p><button id="sanitize">Sanitize</button></p>
<p id="output"></p>

JS

(function($) {
    $.sanitize = function(input) {
        var output = input.replace(/<script[^>]*?>.*?<\/script>/gi, '').
                     replace(/<((?!br))[\/\!]*?[^<>]*?>/gi, '').
                     replace(/<style[^>]*?>.*?<\/style>/gi, '').
                     replace(/<![\s\S]*?--[ \t\n\r]*>/gi, '');
        return output;
    };
})(jQuery);


$(function() {
    $('#sanitize').click(function() {
        var $input = $('#input').val();
        $('#output').html($.sanitize($input));
    });

});

nolros left a reply on Jquery .text Vs .html

@behnampmdg3 unsure if you looking 2 way binding or sanitize.

  1. sanitize will stop script tags or any html tags
// HTML
<textarea cols="30" rows="10" id="input"></textarea>
<p><button id="sanitize">Sanitize</button></p>
<p id="output"></p>


JS
(function($) {
    $.sanitize = function(input) {
        var output = input.replace(/<script[^>]*?>.*?<\/script>/gi, '').
                     replace(/<[\/\!]*?[^<>]*?>/gi, '').
                     replace(/<style[^>]*?>.*?<\/style>/gi, '').
                     replace(/<![\s\S]*?--[ \t\n\r]*>/gi, '');
        return output;
    };
})(jQuery);

$(function() {
    $('#sanitize').click(function() {
        var $input = $('#input').val();
        $('#output').text($.sanitize($input));
    });

});

  1. one way binding (jQuery kindof)
//HTML

<p>Type something:</p>
<textarea></textarea>
<p>You typed:</p>
<div id="data"></div>


// JS
var textarea=$("textarea");
var data=$("#data");

textarea.keypress(function() {
    data.text(textarea.val());
});

You can combine the two so you have two sanitized and two way binding

  1. two way binding JS vanilla

// HTML
<input type=text id="myText1">
<span type=text id="myDomElement"></span>


function Binding(b) {
    _this = this
    this.elementBindings = []
    this.value = b.object[b.property]
    this.valueGetter = function(){
        return _this.value;
    }
    this.valueSetter = function(val){
        _this.value = val
        for (var i = 0; i < _this.elementBindings.length; i++) {
            var binding=_this.elementBindings[i]
            binding.element[binding.attribute] = val
        }
    }
    this.addBinding = function(element, attribute, event){
        var binding = {
            element: element,
            attribute: attribute
        }
        if (event){
            element.addEventListener(event, function(event){
                _this.valueSetter(element[attribute]);
            })
            binding.event = event
        }       
        this.elementBindings.push(binding)
        element[attribute] = _this.value
        return _this
    }

    Object.defineProperty(b.object, b.property, {
        get: this.valueGetter,
        set: this.valueSetter
    }); 

    b.object[b.property] = this.value;
}

var obj = {a:123}
var myInputElement1 = document.getElementById("myText1")
var myDOMElement = document.getElementById("myDomElement")

new Binding({
    object: obj,
    property: "a"
})
.addBinding(myInputElement1, "value", "keyup")

.addBinding(myDOMElement, "innerHTML")

obj.a = "Nolan";

nolros left a reply on Eloquent - Timestamps In Pivot Tables

@JarekTkaczyk how are doing sir ? Been a long time. Couldn't you write something like this ? Rough concept have not run or tested it, but wonder if this could be made to work?

class AppServiceProvider
{
    public function boot()
    {

         /**
         * we pass it instance or just date and return new date
         */ 
         Carbon::macro('dateFormater', function ($instance) {
            $dt = Carbon::parse($instance->created_at); 
            
            if (!isset($self) && isset($this)) {
                $self = $this;
            }
  
            return  $dt->format('m-d');
        });


        /**
         * we pass builder callback
         */ 
        Builder::macro('myAppTags', function($callback) {
   
            if (count(call_user_func($callback->bindTo($this)))) {
                foreach ($variable as $key => $value) {
                    variable[$key]['new_date'] = Carbon::macro('dateFormater')
                }
            }
            return $this;
        });

       /**
         * Start here. 
         */ 
        SomeModel::myAppTags(function () {
            return $this->belongsToMany('Tag')->withTimestamps();
        });

    }
}

nolros left a reply on A Way To Store Site Settings In Laravel

@chori.av 4 Options, are as follows:

Option 1. traditional method would be settings DB a "settings" table with columns for each setting (doesn't scale well and would definitely NOT recommend)

id: is_business: boolean has_fax: boolean server: ...

Option 2. DB with 2 tables:

Table 1. setting_prop (options) e.g. is business or has business related to business, but you might have settings like, has_fax, is_local, etc.

id: 3 prop_key: is_business prop_value: true

id: 4 prop_key: is_business prop_value: false

Unlike #1 ... you have to search for the key and then read values e.g. (where->("prop_key","is_business")->get()) => in our case we get 2 records back

Table 3: user to setting property relationship (pivot table) - user_id , setting_prop_id e.g. user 1 has selected is_business as false

Option 2. (My preferred method) json string stored in SQL 5.7 json column or < SQL 5.7 text column. In this case you are parsing the json string to set and get values. So more code than DB approach. Very flexible as you can adjust as you need. Could encrypt string if there is sensitive data contained. Also works great with multi-language as you can create your own language file to support all languages. So each admin will have a record / row. Columns:

id: int settings: json / text timestamp: timestamp

Option 3. if performance is key you could store as bits. That does require more coding and easy t get confused. Unless you have a large app and high transactions wouldn't recommend.

26 May
1 year ago

nolros left a reply on Are There Any Security Concerns About Updating The Page This Way?

@Snapey not to labor the point but I disagree. If the client is a hacker and you open a door then your backend is also vulnerable. I can could inject DB. If I dont sanitize then I could inject something like into input field [Gotach](Javascript&#58this;alert(1#&#41)). and I now start from there onwards. I think client is as important as server. My 2 cents fwiw

nolros left a reply on $this->request->get() Doesn't Work Inside FormRequest

@LorienDarenya as @Snapey said your extending FormRequest which extends Request so all you need is $this->get() as $this === request() in this class

nolros left a reply on Are There Any Security Concerns About Updating The Page This Way?

@Cronix why do you say no as a matter of interest? Given that there is no safe or sanitized html? Example, "sender" var could be changed to inject something in the HTML, for example, if update_text is updated to DB you can inject SQL crap. AngularjS for example wont be happy with that and will require some sort of bind-unsafe-html directive or $sce, etc. A I missing something?

nolros left a reply on AngularJS - Factory Array From Controller

@jcmargentina

The User API could be extracted to UserServices and ApiServices, but if I were actually writing an app I would build an APIProvider. If I were building a large app I would break it into Ap provideri, Http Endpoints, request service, url resolver, etc. services. However, to simplify here is an example

I have not tested or run the code, but here is how I would do it

  1. Blade example
<div class="article__col column--50"
     ng-controller="UserController as UserCtrl">
    <ul>
        <li ng-click="UserCtrl.setActive(user,$event)"
            ng-repeat="user in UserCtrl.data.users.data track by user.id">
                <p ng-bind="user.first_name"></p>
        </li>
    </ul>
</div>
  1. AngularJS example.
(function () {
    'use strict';


    UsersApi.$inject = ['$http', "$q", "_ROUTES", "$window"];
    function UsersApi($http,$q, _ROUTES, $window) {
        var service = this,
            token = $window.localStorage["_token"] || defaultValue;

        /**
         * API Resource instance. Needed if grow API to include http endpoints etc.
         */
        function Resource(resource) {
            this.resource = resource;
        }

        /**
         * api service as you will need api.get, api.save, etc
         */
        let api = function apiService(resource) {
            return new Resource(resource);
        };

        /**
         * Get on a given url
         *
         * @param url
         * @param params
         */
        api.get = function apiGet(url, params) {
            return http({
                method: 'GET',
                url: url,
                params: params // check for params
            });
        };

        function isOK(response) {
            function isErrData(data) {
                return data && data._status && data._status === 'ERR';
            }
            return response.status >= 200 && response.status < 300 && !isErrData(response.data);
        }


        /**
         * Call $http once url is resolved
         */
        function http(config) {
            return $q.when(config.url)
                .then(function(url) {
                    config.url = url;
                    return $http(config);
                }).then(function(response) {
                    return isOK(response) ? response.data : $q.reject(response);
                });
        }

        function hasUserRoute(url) {
            // can do further validation regex or string etc
            return (angular.isUndefined(url) ?_ROUTES.USERS : url) + token;
        }

        /**
         *Get all users of api url
         */
        service._getUsers = function (url, params = {}) {
            return api.get(hasUserRoute(url), params)
                .then(function (result) {
                    return result;
                });
        };

        return {
            getUsers: function (url, params) {
                return service._getUsers(url, params);
            }

        }
    }

    UserController.$inject = ['$scope','UsersApi'];
    function UserController($scope,UsersApi) {
        let vm = this,
  
            getAllUsers = function () {
                UsersApi
                    .getUsers()
                    .then(function (results) {
                        // you would do data and error validation here as well. For brevity sake ill let you handle
            // this is now used in blade or html
                        vm.data = {
                            users: results,
                        };
                    });
            };



        vm.$onInit = function () {
         // note: not good practice because there is no url or params being passed but just an example. The right way would be based on a method you would resolve url to a server and return the url to pass through to http method, but lets use as example

            getAllUsers();
        };
    }


    angular.module('myapp')
        .factory('UsersApi', UsersApi)
        .controller('UserController', UserController)
        .constant("_ROUTES", {
            USERS: 'http://localhost:8000/api/user/list?token=',
        })

})();

nolros left a reply on Best Strategy To Model This?

@jcmargentina

Note: i would think you dont really need school / store, etc. as you could just have organization and use some field to indicate it is a school , etc use organization_properties model / table to create dynamic properties that way it scales to any org type.

Here are some options to explore:

Option 1: use SQL join

Option 2: use hasManyThrough .

class Organization extends Model
{
    public function roles()
    {
        return $this->hasManyThrough(
            'App\Roles',
            'App\User',
            'organization_id', // Foreign key on users table...
            'user_id', // Foreign key on roles table...
            'id', // Local key on organization table...
            'id' // Local key on users table...
        );
    }

    public function schools()
    {
    return $this->hasMany('App\School');
    }

    public function stores()
    {
    return $this->hasMany('App\Store');
    }

}

class School extends Model
{
    public function organizations()
    {
       // foreign key organization_id
    return $this->belongsTo('App\Organization')
    }
}

class Store extends Model
{
    public function organizations()
    {
       // foreign key organization_id
    return $this->belongsTo('App\Organization')
    }
}

Option 3: Polymorphic

Relationship between roles and user and roles and org ... this has potential issues but workable

class Roles extends Model
{
    public function roleable()
    {
        return $this->morphTo();
    }
}

class User extends Model
{
    public function role()
    {
        return $this->morphMany('App\Role', 'roleable');
    }
}

class Organization extends Model
{
    public function role()
    {
        return $this->morphMany('App\Role', 'roleable');
    }
}
04 Feb
1 year ago

nolros left a reply on How To Get Random Array

if you re attempting to get random model / table data you could do something like this:


         $user = User::orderBy(\DB::raw('RAND()'))->first();

nolros left a reply on How Does Laravel Check Login Info With Database?

Im not sure what you asking? Have you made auth? Migrated databased? if youv'e run php artisan auth:make then laravel will use app\http\controller\auth\LoginController as the controller and trait AuthenticatesUsers on that controller does most of the work

nolros left a reply on Logout Gives Methodnotallowedexception

  1. Do a php artisan route:list to see if you have conflicts
  2. is the logout redirect sending you to a route with a conflicting method. In the LoginController you have trait called AuthenticatesUsers with the method below that will redirect you somewhere. Do you have a default or alt route?
    /**
     * Log the user out of the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function logout(Request $request)
    {
        $this->guard()->logout();

        $request->session()->invalidate();

        return redirect('/');
    }
03 Feb
1 year ago

nolros started a new conversation L5.5 Bind Model & Service In Service Provider

My service provider below ProductsServiceProvider works. I register a service class UrlService(…) and then inject the UrlService along with a Product Model into a repository ProductRepository(…). Both are bound to interfaces.

My questions:

  1. Should the UrlService be bound to an interface? a. Is it best practice to still bind a service to an interface or should I just register the actual class as a service and inject the UrlService::class i.e. no bound interface?

  2. As the UrlService is dynamic service that will provide different data based on unique url / uri it should be a singleton? $app->singletion('service', ...); // binds a service in the IoC. Or should I $app->bind('service', ...);?

  3. As im injecting both a Product model and the UrlService into a Product Repository should repository also be a singleton given it’s a service type class and again should I bind it an interface?

namespace Providers;

        use Illuminate\Support\ServiceProvider;
        use Products\Models\Product;
        use Products\ProductRepository;
        use Products\ProductInterface;
        use Resources\UrlService;
        use Resources\UrlInterface;


        class ProductsServiceProvider extends ServiceProvider
        {

            /**
             * Indicates if loading of the provider is deferred.
             *
             * @var bool
             */
            protected $defer = true;

            /**
             * Bootstrap the application services.
             *
             * @return void
             */
            public function boot()
            {
                //
            }

            /**
             * Register the application services.
             *
             * @return void
             */
            public function register()
            {
                $this->registerUrlService();
                $this->registerSolutionRepository();
            }

            /**
             * Register a url service 
             */
            protected function registerUrlService()
            {
                $this->app->singletion(UrlInterface::class, function ($app) {
                    return new UrlService($app['request'], config('models.url-configl') );
                });
            }

            /**
             * register a product repository and inject products and url service
             */
            protected function registerProductRepository()
            {
                $this->app->singletion(ProductInterface::class, function($app) {

                    $solution = $this->app->make(Product::class);
                    $urlService = $this->app->make(UrlInterface::class);

                    return new ProductRepository($solution, $urlService );
                });
            }

        }

01 Oct
1 year ago

nolros left a reply on Page Load In Laravel Quite Slow

Also if you really looking for performance you might look at lumen which is for a lack of better term - Laravel lite.

nolros left a reply on A Real Example Of Angular 4, Laravel 5.5 And Elixir

@IsaacBen thanks for reply. I used Angular 1.x exclusively with Laravel and although both MVC frameworks there were many scenarios where complemented each other well. The problem AJS4 is that is very much an overlap of Laravel, but skilling up on Vue or React is a pain. I can get the two to work together it just is not clean therefore wondering if there are any solid examples.

30 Sep
1 year ago

nolros started a new conversation A Real Example Of Angular 4, Laravel 5.5 And Elixir

Anyone have a real example of Laravel 5.5, Angular 4 and Elixir working together. All the examples I’ve seen install all typescript config files into root. Some use NPM and some use gulp. It is just ugly. Even when I get it to install into storage it copies all npm modules into storage. Im sure there are ways to config it so the two work together? There must be a best practice out there to get the two to work together?

If not I’m going to have to move to Vue or React which blows.

Sidenote: I even bought the Angular 4 and Laravel 5 book. What a piece of crap. Don’t waste a cent.

29 Apr
2 years ago

nolros left a reply on Eloquent's Join

@Sreadon here is your answer:

  1. Migration creates

       Schema::create('items', function(Blueprint $table) {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->unsignedInteger('post_id')->unique()->index();
            $table->string('name', 100);
            $table->string('category', 100);
            $table->timestamps();
        });

        Schema::create('item_details', function(Blueprint $table) {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->unsignedInteger('item_id')->unique()->index();
            $table->text('description');
            $table->timestamps();
        });

        Schema::create('item_games', function(Blueprint $table) {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->unsignedInteger('item_id')->unique()->index();
            $table->text('description');
            $table->timestamps();
        });

  1. Model and controller example

2.1. Use Singular naming convention when creating models as each model instance will be a single item e.g. Item, itemDetail. DB tables would be plural as it contains many items

2.2. ->hasOne and ->belongsTo will Define a one-to-one or many relationship and as such will return a single instance so again name them accordingly.


    class HomeController extends Controller
    {
        /**
         * @var Item
         */
        private $item;
    
        /**
         * HomeController constructor.
         * @param Item $item
         */
        public function __construct(Item $item)
        {
            $this->item = $item;
        }
    
        /**
         * @return $this|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
         */
        public function index()
        {
            if ($item = $this->item->getItem(1) ) {
               return view('itemView')->with(['item' => $item]);
            }
    
            return view('itemErrorView');
    
        }
    }
    
    class Item extends Model
    {
        /**
         * @var string
         */
        protected $table = 'items';
    
        /**
         * @var string
         */
        protected $primaryKey = 'id';
    
        /**
         * @return \Illuminate\Database\Eloquent\Relations\HasOne
         */
        public function itemDetail()
        {
            return $this->hasOne(ItemsDetail::class);
        }
    
        /**
         * @return \Illuminate\Database\Eloquent\Relations\HasMany
         */
        public function games()
        {
            return $this->hasMany(ItemGame::class);
        }
    
        /**
         * @param $id
         * @return mixed
         */
        public function getItem($id)
        {
            return $this
                ->where('item_id', $id)
                ->with(['itemDetail', 'games'])
                ->first();
        }
    
    }
    
    
    
    class ItemDetail extends Model
    {
        /**
         * @var string
         */
        protected $table = 'item_details';
    
        /**
         * @var string
         */
        protected $primaryKey = 'id';
    
        /**
         * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
         */


nolros left a reply on Issues When Cloning A Project From Github

@CHRIS1904 sounds like your migration table is corrupt or you have drop issue with settings. Im assuming this is not production? If so you could do the following:

1. php artisan migrate:reset
    If it wont allow you to reset because of the  settings table then

    2. delete the migration table then run  
    php artisan migrate:install 

    3. if this works then I tend 
     3.1  php artisan migrate:reset (rollback all)
     3.2 delete migration table again
     3.3 composer dumpautoload
     3.4 php artisan config:clear
     3.5 php artisan migrate:install (btw php artisan migrate will create teh DB if it doesnt exist but I prefer to go through the steps)
     3.6 php artisan migrate

    4. If the problem persists then you have an issue in one of your migrations in which case fix and repeat the above until problem resolved

nolros left a reply on Laravel 5.4 Routing And Anchor Tags

use this syntax in view blade / HTML


     <a href="{!! url()->current() !!}">Current path</a>
OR
     <a href="{!! url()->full() !!}">Full path</a>
OR
     <a href="{!! url('books/news') !!}">Relative path</a>
OR
     <a href="{!! url('/books/news') !!}">Relative to root path</a>



27 Apr
2 years ago

nolros left a reply on Trying To Get Property Of Non-object (View: /var/www/html/pet/resources/views/backend/product/product-library.blade.php)

@Ahmedjalal try the following :

      public function index() 
      { 

            $products = Product::with('categories', 'colors' , 'sizes', 'materials', 'fantasias')->get(); 

            return view('backend.product.product-library')->with(['products' => $products]); 
      }


nolros left a reply on Laravel, Blade & AngularJS For The Win

@amol in AJS 1.x you need to set the start and end symbols so as not to conflict with blade suffix. Example in my root js file I'll insert the following

    angular.module('app', modules)
        .config(function ($interpolateProvider) {
            $interpolateProvider.startSymbol('{[{');
            $interpolateProvider.endSymbol('}]}');
        })

then this will work

     @if(true)

          {[{ Hello }]}

      @endif 
25 Apr
2 years ago

nolros started a new conversation HELP NEEDED: Complex Query Help

All,

I appreciate any guidance. I’ve create a basic CMS system with 3 tiers of DOM objects that are stored in a nested set table (Baum Nested Sets) . The nested sets table is called ‘blocks’. The reason for 3 levels versus n levels is because of the issue below.

I’m using the query below, which works, but it is messy and obviously limited to 3 tiers versus supporting an nth type model using the true power of nested sets. I’m sure experienced people have done this before and can help me structure a query that allows for a more effective / efficient query. I’ll be fine maintaining a 3 level model, but would be great to know how to do this in a n level type approach.

        $getPage = $this->page
            ->where('slug', $this->presentationPage)
            ->with(['theme','layout.blocks' => function($query) {
                $query->with(['cssTemplate', 'blocks' => function($query) {
                    $query->with(['images','menus.images','cssTemplate','template', 'documents.contentBodies','quotes','blocks' =>  function($query) {
                        $query->with(['images','cssTemplate','template', 'documents.contentBodies']);
                    }]);
                }]);
            }])
            ->first();

ADDITIONAL DETAIL

Here is the controller, migration and model to help provide additional detail:

<?php
            
            use Presentations\models\Presentation;
            use CMS\models\Page;
            use Illuminate\Http\Request;
            
            
            class example
            {
                /**
                 * @var string
                 */
                private $presentationPage = 'presentation-page';
            
                /**
                 * @var Page
                 */
                private $page;
            
                /**
                 * @var Presentation
                 */
                private $presentation;
            
                /**
                 * example constructor.
                 * @param Page $page
                 * @param Presentation $presentation
                 */
                public function __construct(Page $page, Presentation $presentation)
                {
                    $this->page = $page;
                    $this->presentation = $presentation;
                }
            
                /**
                 * @param Request $request
                 */
                public function showPresentation(Request $request)
                {
                    $getPage = $this->page
                        ->where('slug', $this->presentationPage)
                        ->with(['theme','layout.blocks' => function($query) {
                            $query->with(['cssTemplate', 'blocks' => function($query) {
                                $query->with(['images','menus.images','cssTemplate','template', 'documents.contentBodies','quotes','blocks' =>  function($query) {
                                    $query->with(['images','cssTemplate','template', 'documents.contentBodies']);
                                }]);
                            }]);
                        }])
                        ->first();
            
                    return view('presentation.main')->with(['page'=>$getPage]);
                }
            }
            
            
            class CreateDocumentsTable extends Migration
            {
                /**
                 * Run the migrations.
                 *
                 * @return void
                 */
                public function up()
                {
                    Schema::create('blocks', function(Blueprint $table) {
                        $table->increments('id');
                        $table->integer('parent_id')->nullable()->index();
                        $table->integer('lft')->nullable()->index();
                        $table->integer('rgt')->nullable()->index();
                        $table->integer('depth')->nullable();
                        $table->string('name', 100);
                        $table->string('slug')->index();
                        $table->unsignedSmallInteger('block_type')->nullable();
                        $table->unsignedInteger('css_template_id')->nullable()->index();
                        $table->foreign('css_template_id')->references('id')->on('css_templates');
                        $table->unsignedInteger('template_id')->nullable()->index();
                        $table->foreign('template_id')->references('id')->on('templates');
                        $table->unsignedSmallInteger('ordering')->nullable();
                        $table->timestamps();
                    });
            
                }
            
            }
            
            class Block extends Node
            {
                use UuidTrait, CSSTrait;
            
                /**
                 * @var
                 */
                private $css;
            
                private $currentDocument;
                private $currentImage;
                private $currentQuote;
            
                /**
                 * @var array
                 */
                private $columnEnums = ['block_type' => CMSBlockTypeEnum::class, 'block_depth'=> CMSBlockDepthEnum::class, 'block_element' => CMSBlockElementEnum::class];
            
                /**
                 * The database table used by the model.
                 *
                 * @var string
                 */
                protected $table = 'blocks';
            
                /**
                 * The attributes that should be hidden for arrays.
                 *
                 * @var array
                 */
                protected $hidden = ['uuid','blockable_id','blockable_type', 'pivot'];
            //
            //    protected $guarded = array('id', 'parent_id', 'lidx', 'ridx', 'nesting');
            
            
                /**
                 * @var string
                 */
                protected $primaryKey = 'id';
            
                /**
                 * The attributes that are mass assignable.
                 *
                 * @var array
                 */
                protected $fillable = [
                    'name',
                    'description',
                    'uuid',
                    'hierarchy_node',
                    'block_type',
                    'block_element',
                    'block_depth',
                    'ordering',
                    'width',
                    'depth',
                    'padding',
                    'margin',
                    'columns',
                    'css_class',
                    'blockable_id',
                    'blockable_type'
                ];
            
            
                /**
                 * NOTE removed code for brevity sake
                 */
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\MorphMany
                 */
                public function contents()
                {
                    return $this->morphMany(ContentNode::class, 'contentable');
                }
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\MorphMany
                 */
                public function menus()
                {
                    return $this->morphMany(Menu::class, 'menuable');
                }
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\HasMany
                 */
                public function childrenBlocks()
                {
                    return $this->hasMany(Block::class, 'parent_id', 'id');
                }
            
                /**
                 * @return mixed
                 */
                public function allBlocks()
                {
                    return $this->childrenBlocks()->with('allBlocks');
                }
            
                /**
                 * @return mixed
                 */
                public function blocks()
                {
                    return $this->children();
                }
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
                 */
                public function cssTemplate()
                {
                    return $this->belongsTo(CSSTemplate::class, 'css_template_id', 'id');
                }
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\MorphOne
                 */
                public function survey()
                {
                    return $this->morphOne(Survey::class, 'surveyable');
                }
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
                 */
                public function template()
                {
                    return $this->belongsTo(Template::class, 'template_id', 'id');
                }
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
                 */
                public function images()
                {
                    return $this->belongsToMany(Image::class, 'block_image');
                }
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\HasOne
                 */
                public function product()
                {
                    return $this->hasOne(Product::class, 'block_id', 'id');
                }
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
                 */
                public function quotes()
                {
                    return $this->belongsToMany(Quote::class, 'block_quote');
                }
            
                /**
                 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
                 */
                public function documents()
                {
                    return $this->belongsToMany(ContentNode::class, 'block_content_node');
                }
            
            }

30 Jan
2 years ago

nolros left a reply on Store Model With Empty Date Fields Coming From Forms.

@rocordial

  1. when you create the DB I assume you are using timestamps():

public function up() { Schema::create('messages', function(Blueprint $table) { $table->engine = 'InnoDB'; $table->increments('id'); $table->string('name'); $table->string('email')->index(); $table->timestamps(); }); }

  1. protected $dates = [...]; in model

  2. Here is an example of a date helper:

<?php
    namespace Infrastructure\Services;


    use Carbon\Carbon;

    class DateTimeHelper
    {

        /**
         * Subtract twp dates from one another and then render to human readable format
         *
         * @param   Carbon $startDate
         * @param   Carbon $endDate
         * @return  string
         */
        public function dateDifferenceToHuman(Carbon $endDate, $startDate = null)
        {
            if (is_null($startDate))
            {
                $startDate = Carbon::now();
            }

            return ($endDate->diff($startDate)->days < 1)
                ? 'today'
                : $endDate->diffForHumans($startDate);
        }

        /**
         * Format a timestamp to a date
         *
         * @param $timeStamp
         * @return bool|string
         */
        public function dateFormat($timeStamp)
        {
            return date('Y-m-d h:i:s', $timeStamp);
        }

        /**
         * Create carbon date from timestamp e.g. file getCTime
         *
         * @param $timeStamp
         * @return static
         */
        public function createFromTimestamp($timeStamp)
        {
            return Carbon::createFromTimestamp($timeStamp);
        }



        /**
         * Subtract number of days from a timestamp
         *
         * @param $timestamp
         * @param $days
         * @return static
         */
        public function subDays($timestamp, $days)
        {
            return Carbon::createFromTimestamp($timestamp)->subDays($days);
        }

        /**
         * Timestamp to string for storage
         *
         * @param $timeStamp
         * @return string
         */
        public function createFromTimestampToStr($timeStamp)
        {
            Carbon::parse( $timeStamp)->toFormattedDateString();

            return Carbon::createFromTimestamp($timeStamp)->toDateTimeString();

        }



        /**
         * Get a Carbon timestamp and get difference from 2nd date, now can be any date
         *
         * @param $carbonNow
         * @param $carbonDate
         * @return mixed
         */
        public function daysDiff($startDate, $endDate)
        {
            return Carbon::parse($endDate)->diff(Carbon::parse($startDate))->days;
        }

        /**
         * Get a Carbon timestamp and get difference from 2nd date in human format, now can be any date
         *
         * @param $carbonNow
         * @param $carbonDate
         * @return mixed
         */
        public function daysDiffForHumans($startDate, $endDate)
        {
            return Carbon::parse($endDate)->diffForHumans(Carbon::parse($startDate));
        }



    }

  1. Example of Carbon date query

                   Analytics::whereIn('category', $this->analyticDefinitionCategories)
                                ->where('analyticable_type', QuestionOption::class)
                                ->with([
                                        'months' => function($query) {
                                            $query->where('start_date', ">=", Carbon::now()->subMonth(2)->endOfMonth())
                                                ->where('end_date', "<=", Carbon::now()->addMonth(1)->startOfMonth());
                                        }])
                                    ->get() ) 

nolros left a reply on Need Some Advice On Saving A Ajax Form Data Into L5

@vincej the data is coming through as a string because your sterilizing the data. You can grab it using PHP server commands encode to JSON, but you don't need to do that. ->get() is looking for JSON and not finding it.

So I suggest try just passing the JSON data versus serializing i.e. pass as JS object or array.

'''

var formData = $("form");

'''

nolros left a reply on Undefined Variable: Products

You need to pass the variable in the controller to the view.

'''

  public function showProduct()
    {
        $product = ["name"=>"iPhone","price"=>"$100"];

        return view('products.main')->with('product', $product);

    }

'''