piljac1

piljac1

Full stack web developer at Tollé

Member Since 6 Months Ago

Mascouche

Experience Points
21,050
Total
Experience

3,950 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
19
Lessons
Completed
Best Reply Awards
31
Best Reply
Awards
  • start your engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-in-session Created with Sketch.

    School In Session

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

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

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

  • subscriber Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • evangelist Created with Sketch.

    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 Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

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

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

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

Level 5
21,050 XP
Mar
31
2 days ago
Activity icon

Replied to How To Get Each Value Of A Looped Data In Javascript

So if I understood correctly, you're saying that if you console log this.id in your click event, it always outputs 1 ?

Activity icon

Replied to Vue Component Not Showing Up In Resources/js/components

You can find the component(s) related to the NPM package in the node_modules folder under the package name.

If you want to import it in one of your own components, just follow the package's documentation :

<template>
  <vue-slider v-model="value" />
</template>

<script>
  import VueSlider from 'vue-slider-component'
  import 'vue-slider-component/theme/antd.css'

  export default {
    components: {
      VueSlider
    },
    data () {
      return {
        value: 0
      }
    }
  }
</script>

Also, components can be in whatever folder, but it is recommended to put them in resources/js/components. I'd also suggest to create subfolders within the components folder to group your components.

Mar
29
4 days ago
Activity icon

Replied to Authorizing / Checking Several Parent Models

You should look at policies.

Your show method in your policy would look like this (untested). It basically would check if the hierarchy is correct as you were testing :

public function show(User $user, Domain $domain, Article $article, Note $note)
{
    return $user->whereHas('domains', function(Builder $query) {
        return $query->where('id', $domain->id)->whereHas('articles', function(Builder $query) {
            return $query->where('id', $article->id)->whereHas('notes', function(Builder $query) {
                return $query->where('id', $note->id);
            });
        });
    })
    ->get()
    ->isNotEmpty();
}

And then at the top of your show function in your controller, you can apply the policy like (the authenticated user is passed by default, don't pass it as a parameter) :

$this->authorize('show', [$domain, $article, $note]);

P.S. For the policy to work, please follow the policy link at the top of my reply, because I didn't write down the entire setup steps

Mar
28
5 days ago
Activity icon

Replied to Progressbar Type And Animated Didnt Work To Change

Well if it is the based on Bootstrap (didn't check but it sounds like it does), the animated class only animates stripes and not the actual left to right progress. You need to explicitly change the width of the progress bar for it to work.

<progressbar
  :style="{ width: `${progress}%` }"
  :now="progress"
  type="danger"
  striped
  animated
/>
Mar
26
1 week ago
Activity icon

Replied to Fix My Ugly Code! Using Assets!

{{ asset("storage/product/{$product->img}") }}
Activity icon

Awarded Best Reply on One Valet Linked Website Encounters A 404 While Others Don't

Nevermind I messed up big time. Didn't realize Joomla's community maintained .gitignore is aimed towards components development, which means it ignores many vital files for an entire Joomla website to work on its own, including the root index.php, which explains why it was working on my local machine because I had all those files.

Well... shit happens lol.

Activity icon

Replied to One Valet Linked Website Encounters A 404 While Others Don't

Nevermind I messed up big time. Didn't realize Joomla's community maintained .gitignore is aimed towards components development, which means it ignores many vital files for an entire Joomla website to work on its own, including the root index.php, which explains why it was working on my local machine because I had all those files.

Well... shit happens lol.

Activity icon

Started a new Conversation One Valet Linked Website Encounters A 404 While Others Don't

Hi guys, I had a big head-scratcher today while trying to help a collegue out. We inherited a Joomla based website lately and today, I've been in charge of gitting the project and elaborate a doc on how to setup the project locally, because it's pretty much the first Joomla base web site that we have to work on.

I've been successfully able to set a local instance on my machine, but my collegue encountered an issue, which I think is purely valet related. I assume that because I've been able to link the website folder without any issues on my side, but it has been another story on her side.

Despite having multiple working valet linked projects of all types (Laravel, Wordpress, framework-less, etc.), she wasn't able to create a working link with this new website folder (which is in the same parent folder as her other websites). She encountered a 404 - Not found error.

I've tried to debug it for an hour and a half trying to avoid purging her .valet folder so she doesn't lose all of her already existing and working links, but without any luck.

I've tried unlinking and re-linking, valet park in the non-working website directory, restart valet, restart all brew services, reboot the computer, uninstalling Valet and re-installing it... Nothing works !

My next step would be to purge the .valet and /usr/local/bin/valet folders, but I'm wondering if I forgot a debug step before proceeding to this solution.

Mar
25
1 week ago
Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

No problem, I'll wait for my beer ;)

Let me know if you have other questions.

Mar
24
1 week ago
Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

Well if both stages and products (which I think you now refer to as options) are both in the products table, you won't need a polymorphic many to many. Orderables would be need if your structure was like the following.

products

  • id
  • name
  • etc.

stages

  • id
  • name
  • etc.

orderables

  • order_id
  • orderable_type - App\Product or App\Stage
  • orderable_id
  • etc. (if needed)

orders

  • id
  • user_id
  • etc.

In your case, if your options (what you used to call products) and stages need different columns, you could do:

options

  • id
  • name
  • etc.

stages

  • id
  • name
  • etc.

products

  • id
  • productable_type - App\Option or App\Stage
  • productable_id
  • etc. (if needed)

order_product

  • order_id
  • product_id
  • etc. (if needed)

orders

  • id
  • user_id
  • etc.

Both of these solutions would work for the same use case. But which solution is "the best" is a matter of personal preference in my opinion. Again, these solutions would only be useful in your case if options and stages do not use exactly the same columns (or could need different columns in the future).

Activity icon

Awarded Best Reply on How To Make CKEditor To Be RTL Direction.

What version of CKEditor are you using ? Because since CKEditor 5, you can specify a language in your options such as language: 'ar', which would set the language to Arabic and since it is a RTL language, the UI and content will be RTL.

If you want your UI and content to have a different language, you can specify it like this

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        language: {
            // The UI will be English.
            ui: 'en',

            // But the content will be edited in Arabic.
            content: 'ar'
        }
    } )
    .then( editor => {
        window.editor = editor;
    } )
    .catch( err => {
        console.error( err.stack );
    } );
Activity icon

Replied to How To Make CKEditor To Be RTL Direction.

What version of CKEditor are you using ? Because since CKEditor 5, you can specify a language in your options such as language: 'ar', which would set the language to Arabic and since it is a RTL language, the UI and content will be RTL.

If you want your UI and content to have a different language, you can specify it like this

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        language: {
            // The UI will be English.
            ui: 'en',

            // But the content will be edited in Arabic.
            content: 'ar'
        }
    } )
    .then( editor => {
        window.editor = editor;
    } )
    .catch( err => {
        console.error( err.stack );
    } );
Activity icon

Replied to How To Add Product Color In Right Way

You really need to elaborate. Your issue and expected result is incomprehensible.

Mar
23
1 week ago
Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

Well if that works for your use case, there's no need for an orderables table. I don't see an issue with the structure except if your options and stages don't have the exact same fields. If there are unused fields for options and unused fields for stages, I would probably separate them in two tables that could have a one to one polymorphic relationship with the products table. Else, you could omit the products table and use many to many polymorphic relations with an orderables table instead of a order_product table.

Also, as a tip, it is considered bad practice to prefix a column with its table name (singular). product_name, should be name, product_category should be category (except if your category is a foreign key, in which case it should be category_id), etc.

Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

Well if you could post your database structure as of now, that would help me answer these questions. We've come a long way since your initial post, so it's hard for me to conceive in my head.

Activity icon

Replied to Json Mutator And Special Characters

But is it causing problems when you decode ? Because unicode characters are escaped by default with json_encode, but when decoding, you should get your special characters back. Else you can pass JSON_UNESCAPED_UNICODE as a second parameter to json_encode to keep unicode characters unescaped.

json_encode($array, JSON_UNESCAPED_UNICODE);
Mar
22
1 week ago
Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

You want to use the withPivot function on your relations to retrieve extra column values from the intermediate table (your price, quantity, etc.).

The below example is for a polymorphic many to many relationship (if you converge to an orderables table instead of an order_product and order_stage table).

class Order extends Model
{
    public function products()
    {
        return $this->morphedByMany('App\Product', 'orderable')->withPivot(['price', 'quantity']);
    }

    public function stages()
    {
        return $this->morphedByMany('App\Stage', 'orderable')->withPivot(['price', 'quantity']);
    }
}
class Product extends Model
{
    public function orders()
    {
        return $this->morphToMany('App\Order', 'orderable')->withPivot(['price', 'quantity']);
    }
}
class Stage extends Model
{
    public function orders()
    {
        return $this->morphToMany('App\Order', 'orderable')->withPivot(['price', 'quantity']);
    }
}

After implementing with pivot, you can use the following logic in your total cost attribute Unfortunately, there's currently no way that I know of to benefit from the same non-explicit behavior as polymoprhic one to one or one to many relationships to get all orderables instead of retrieving posts and stages separately. There are work arounds, but I'll keep it simple.

class Order extends Model
{
    public function getTotalCostAttribute()
    {
        $total = 0;

        // Total price of products related to the order
        $total += $this->products->sum(function($product) {
            return $product->pivot->price;
        });

        // Total price of stages related to the order
        $total += $this->stages->sum(function($stage) {
           return $stage->pivot->price;
        });

        return $total;
    }
}

And then to use an attribute, you can either use the camel case or snake case (snake case is the preferred form) form of what's between "get" and "Attribute" in your function name.

// Camel case
$total = $order->totalCost;

// Snake case ** THIS SYNTAX IS PREFERRED**
$total = $order->total_cost;
Mar
21
1 week ago
Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

The attach method can receive multiple types and numbers of arguments and there's one that suits your needs. Currently, you're attaching an array of IDs, but it is also possible to add extra info to that pivot table.

For convenience, attach and detach also accept arrays of IDs as input:

$user = App\User::find(1);

$user->roles()->detach([1, 2, 3]);

$user->roles()->attach([
   1 => ['expires' => $expires],
   2 => ['expires' => $expires]
]);

The third example here is what you need. To achieve this format, you can, firstly, retrieve all your products matching your option_id array. Then you can use the collection mapWithKeys function to format your collection properly and finally the all function extracts the underlying array represented by the collection.

$products = Product::whereIn('id', $request->option_id)->get();

$products = $products->mapWithKeys(function($product) {
    return [$product->id => ['price' => $product->product_sale]];
})->all();

$order->products()->attach($products);
Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

And if you want to be able to issue multiple invoices and keep track of each ones, your invoice_items (that should be renamed to invoiceables in your current context) would replicate the orderablesat the time the invoice was issued. But maybe you don't need to keep track of multiple invoices. In that case you could get rid of your invoiceables table and then your invoices would be based on you orderables (through the order relationship)

Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

Yes you're right. Your order_product and order_stage should become a singular orderables table which would contain your order_id, an orderable_type (App\Product or App\Stage) and an orderable_id (product_id or stage_id). You would also store the price/quantity (and maybe more necessary fields such as taxes) of the orderable item in the orderables table.

Mar
20
1 week ago
Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

Storing calculated values in the database goes against the database normalization process, which was set in part to reduce data redundancy. Since it is possible to calculate your invoice total with your invoice items, it would be redundant to have a calculated column. Omitting a calculated column also ensures that if invoice items are added after the initial calculation, or somehow, an admin modifies the value of an invoice item, the total value will still be correct without additional processing to update your total value in your invoice table.

To define an attribute, you can follow @pom directives, except that you need to have "get" in your attribute function name to get it to work.

public function getTotalCostAttribute()
{
	// Calculate and return total invoice cost
}
Activity icon

Awarded Best Reply on Display Original Values In Edit Form For Checkbox And Select

Oh ! Try this then. The old function accepts a second parameter which is the fallback value if the old value isn't set.

P.S. For the select example, I'm using the optional helper because I don't know if a book can have no associated language in your database.

For selects

<div class="form-group">
    <label for="language_id">Sprache:</label>
    <select name="language_id" class="form-control @error('language_id') is-invalid @enderror">
        <option value="">-- {{ __('Spache auswählen') }} --</option>
        @foreach ($languages as $language)
            <option value="{{ $language->id }}"{{ old('language_id', optional($book->language)->id) == $language->id ? ' selected' : '' }}>{{ $language->name }}</option>
        @endforeach
    </select>
    @error('language_id')
        <div class="alert alert-danger">{{ $message }}</div>
    @enderror
</div>

For checkbox arrays

@php
    // Instead of doing this logic here, I suggest you create an attribute which does the following logic
    $genreIds = $book->genres()->pluck('id')->all();
@endphp
<div class="form-group">
    <label for="genres">Genre(s):</label>
    @foreach($genres as $genre)
        <input type="checkbox" name="genres[]" value="{{ $genre->id }}"{{ is_array(old('genres', $genreIds)) && in_array($genre->id, old('genres', $genreIds)) ? ' checked' : '' }}>{{ $genre->name }}
    @endforeach
    @error('genre_id')
        <div class="alert alert-danger">{{ $message }}</div>
    @enderror
</div>
Mar
19
2 weeks ago
Activity icon

Replied to Vue Terminology

If you wanna pay a small amount for a really great and extensive course, I really recommend this one.

Maximilian is an excellent teacher. I've learned Vue.js with his course and I started following the React course as well as the React Native course.

Activity icon

Replied to Provider Switch

Never had to implement something like this (we're using Stripe only), but my approach would probably be to create a trait with a function calling the function of the specific provider. So lets say the function is called processPayment, it could receive all your necessary elements as parameters (including the provider) and then it would pass these to the appropriate function. Here I'm returning values from functions that are called, but it's not necessary if you have nothing to return.

/**
 * Process the payment using the specified provider.
 *
 * @param  string  $provider  Name of the provider
 * @param  mixed  $paramX  Whatever it is
 * @param  mixed  $paramY  Whatever it is
 * @param  mixed  $paramZ  Whatever it is
 * @return mixed Whatever you want to return
 */
public function processPayment(string $provider, $paramX, $paramY, $paramZ)
{
    $method = 'process' . Str::studly($provider) . 'Payment';

    if (method_exists($this, $method)) {
        return $this->{$method}($paramX, $paramY, $paramZ);
    }

    return $this->invalidProvider();
}

/**
 * Process the payment using the PayPal provider.
 *
 * @param  mixed  $paramX  Whatever it is
 * @param  mixed  $paramY  Whatever it is
 * @param  mixed  $paramZ  Whatever it is
 * @return mixed Whatever you want to return
 */
public function processPaypalPayment($paramX, $paramY, $paramZ)
{
    // Your logic    

    return $whatever;
}


/**
 * Process the payment using the Square provider.
 *
 * @param  mixed  $paramX  Whatever it is
 * @param  mixed  $paramY  Whatever it is
 * @param  mixed  $paramZ  Whatever it is
 * @return mixed Whatever you want to return
 */
public function processSquarePayment($paramX, $paramY, $paramZ)
{
    // Your logic    

    return $whatever;
}

/**
 * Process the payment using the Stripe provider.
 *
 * @param  mixed  $paramX  Whatever it is
 * @param  mixed  $paramY  Whatever it is
 * @param  mixed  $paramZ  Whatever it is
 * @return mixed Whatever you want to return
 */
public function processStripePayment($paramX, $paramY, $paramZ)
{
    // Your logic    

    return $whatever;
}


/**
 * Do whatever if the provider is invalid.
 *
 * @return mixed Whatever you want to return
 */
public function invalidProvider()
{
    // Your logic    

    return $whatever;
}
Activity icon

Replied to I Want To Disable My Button If A Form Field Value Is Empty.

It's important to note that if you want something dynamic (disable the button if the user empties the field and enable it when the user has typed something in the field), you'll need JavaScript. It cannot be done in HTML/Blade/PHP.

Activity icon

Replied to Display Original Values In Edit Form For Checkbox And Select

Oh ! Try this then. The old function accepts a second parameter which is the fallback value if the old value isn't set.

P.S. For the select example, I'm using the optional helper because I don't know if a book can have no associated language in your database.

For selects

<div class="form-group">
    <label for="language_id">Sprache:</label>
    <select name="language_id" class="form-control @error('language_id') is-invalid @enderror">
        <option value="">-- {{ __('Spache auswählen') }} --</option>
        @foreach ($languages as $language)
            <option value="{{ $language->id }}"{{ old('language_id', optional($book->language)->id) == $language->id ? ' selected' : '' }}>{{ $language->name }}</option>
        @endforeach
    </select>
    @error('language_id')
        <div class="alert alert-danger">{{ $message }}</div>
    @enderror
</div>

For checkbox arrays

@php
    // Instead of doing this logic here, I suggest you create an attribute which does the following logic
    $genreIds = $book->genres()->pluck('id')->all();
@endphp
<div class="form-group">
    <label for="genres">Genre(s):</label>
    @foreach($genres as $genre)
        <input type="checkbox" name="genres[]" value="{{ $genre->id }}"{{ is_array(old('genres', $genreIds)) && in_array($genre->id, old('genres', $genreIds)) ? ' checked' : '' }}>{{ $genre->name }}
    @endforeach
    @error('genre_id')
        <div class="alert alert-danger">{{ $message }}</div>
    @enderror
</div>
Activity icon

Replied to Invoices Via Pivot Table Or Separate Table?

I'm not sure that I understand your concern about the invoice_items table correctly, but I'm guessing you're looking for a polymorphic many to many relation using a MorphPivot.

As for your second question (pending to complete), I would not have an invoice total column in your invoices table, because it would be information duplication (you can already, like you said yourself, add up the monetary value of each invoice items). I would instead add an attribute in your Invoice model that would manage this calculation.

Mar
18
2 weeks ago
Activity icon

Replied to Display Original Values In Edit Form For Checkbox And Select

For selects

<div class="form-group">
    <label for="language_id">Sprache:</label>
    <select name="language_id" class="form-control @error('language_id') is-invalid @enderror">
        <option value="">-- {{ __('Spache auswählen') }} --</option>
        @foreach ($languages as $language)
            <option value="{{ $language->id }}"{{ old('language_id') == $language->id ? ' selected' : '' }}>{{ $language->name }}</option>
        @endforeach
    </select>
    @error('language_id')
        <div class="alert alert-danger">{{ $message }}</div>
    @enderror
</div>

For checkbox arrays

<div class="form-group">
    <label for="genres">Genre(s):</label>
    @foreach($genres as $genre)
        <input type="checkbox" name="genres[]" value="{{ $genre->id }}"{{ is_array(old('genres')) && in_array($genre->id, old('genres')) ? ' checked' : '' }}>{{ $genre->name }}
    @endforeach
    @error('genre_id')
        <div class="alert alert-danger">{{ $message }}</div>
    @enderror
</div>
Mar
17
2 weeks ago
Activity icon

Replied to Best For Writing Code: US English Keyboard Or French Keyboard?

It's a matter of preference. I'm used to the French Canadian layout so it feels weird when switching to US English. There's simply no such thing as "the best".

Activity icon

Replied to 'v-for' With 'v-if' Vuejs/laravel

In your View Model, create add a key named computed (like you did with methods) and define your computed property like a method. Computed properties don't accept parameters though.

computed: {
  filteredBooks() {
    return Object.values(Books).filter(Book => Stock.book_id === Book.id);
  }
}

You can then use this property like a data element.

<td
  v-for="Book in filteredBooks"
  :value="Book.id"
  :key="Book.id"
>
  {{ Book.name }}
</td>
Activity icon

Replied to 'v-for' With 'v-if' Vuejs/laravel

However, your filtering logic should be in a computed property to keep your HTML syntax clean.

Activity icon

Replied to 'v-for' With 'v-if' Vuejs/laravel

You need to convert your object to an Array to be able to filter it.

Try Object.values which should work if your Object is built like I think it is (if your Object keys don't matter, else you could use Object.entries but you will need to modify your code a bit)

<td
  v-for="Book in Object.values(Books).filter(Book => Stock.book_id === Book.id)"
  :value="Book.id"
  :key="Book.id"
>
  {{ Book.name }}
</td>
Activity icon

Replied to Laravel Without Eloquent

The query builder is basically a PDO wrapper. So I can't say it is drastically better, but it can facilitate easy queries and most importantly, it works with any database engine (so no refactoring if you change your DB engine). For complex queries, I agree that it can be a pain in the a**, but it is possible to make it work. Just be sure to use bindings if you're using raw SQL to avoid injection (but you probably know that if you come from a PDO background).

Activity icon

Replied to 'v-for' With 'v-if' Vuejs/laravel

Is Books an Array or an Object?

Mar
15
2 weeks ago
Activity icon

Replied to How To Show Categories Video?

Your videos are associated to the category IDs 39 and 40. You're accessing category ID 43, which has no video. Am I missing something ?

Mar
11
3 weeks ago
Activity icon

Awarded Best Reply on Need To Test For Duplicate Slugs

Yes (even though I'm not a fan of faker in unit tests like I said). But you would have to change $post by $post2 in your assertion.

Activity icon

Replied to Need To Test For Duplicate Slugs

Yes (even though I'm not a fan of faker in unit tests like I said). But you would have to change $post by $post2 in your assertion.

Activity icon

Awarded Best Reply on Function Not Defined

There are two ways to accomplish what you're trying to achieve with your bundled Webpack JS.

First Method

The first method, which is the recommended way, would be to add library and libraryTarget to your Webpack export settings:

mix.webpackConfig({
  output: {
    library: 'libraryName',
    libraryTarget: 'umd',
    umdNamedDefine: true, // optional
    globalObject: 'this' // optional
  }
})

library is, of course, your library name, libraryTarget is the type of library output you will get. You have multiple options, but the most common are var (available when loading a script within a script tag) and umd, which is compatible with every support forms (ES6, AMD, CommonJS and var). umdNamedDefine is only pertinent when using umd target and AMD syntax, but AMD syntax isn't common anymore so... As for globalObject, it is once again only required (if I remember correctly) when the library target is umd. It represents the global object to bind to and by default is is 'window', which causes issues with umd.

Then, at the bottom of your JS file(s), you'll need to export functions that you want to make available:

const yourFunction = function () {
  // ...
}

module.exports = {
  yourFunction
}

And to finish, to use it in your HTML/PHP file:

libraryName.yourFunction()

Second method

The second method is the simple solution. You simply need to bind your function to the window:

// In your JS file
window.myFunction = function() {
  // ...
}
// In your HTML/PHP file
window.myFunction()
Activity icon

Replied to Need To Test For Duplicate Slugs

It's also important to note that unit tests should test your code (validation of the store route in your case) and not pre-built functionalities such as the database unique constraint or the factory implementation (except if you want to test that your factories are still up to date as you grow and add column to the model).

Activity icon

Replied to Need To Test For Duplicate Slugs

For this kind of test you need to avoid using factory to know what to expect (in case you encounter a bug one day).

  1. Create a post with manual data
  2. Create an array containing key/values representing your columnName/value pairs in your post model. Make sure these values differ from the first post, except for the slug (so it is easy to distinguish).
  3. Call your store route and pass your array to it.
  4. Assert that the second post wasn't inserted

That would be the simple way, but you could also replace the 4th step by retrieving the count of the posts having the specified slug and assert that the count is 1

Activity icon

Replied to Function Not Defined

There are two ways to accomplish what you're trying to achieve with your bundled Webpack JS.

First Method

The first method, which is the recommended way, would be to add library and libraryTarget to your Webpack export settings:

mix.webpackConfig({
  output: {
    library: 'libraryName',
    libraryTarget: 'umd',
    umdNamedDefine: true, // optional
    globalObject: 'this' // optional
  }
})

library is, of course, your library name, libraryTarget is the type of library output you will get. You have multiple options, but the most common are var (available when loading a script within a script tag) and umd, which is compatible with every support forms (ES6, AMD, CommonJS and var). umdNamedDefine is only pertinent when using umd target and AMD syntax, but AMD syntax isn't common anymore so... As for globalObject, it is once again only required (if I remember correctly) when the library target is umd. It represents the global object to bind to and by default is is 'window', which causes issues with umd.

Then, at the bottom of your JS file(s), you'll need to export functions that you want to make available:

const yourFunction = function () {
  // ...
}

module.exports = {
  yourFunction
}

And to finish, to use it in your HTML/PHP file:

libraryName.yourFunction()

Second method

The second method is the simple solution. You simply need to bind your function to the window:

// In your JS file
window.myFunction = function() {
  // ...
}
// In your HTML/PHP file
window.myFunction()
Mar
09
3 weeks ago
Activity icon

Replied to How Can I Have A Select In Nova That Lets Me Store JSON In The Database?

I don't know the sequence since I never used the $dispatchEvents way. The easiest way would be to call the dd function in both to determine in which order they're executed.

Activity icon

Awarded Best Reply on Custom Blade Directives

I started a new project to try and get your Blade directive to work, and this seems to work perfectly.

// In view

// It also works with Auth::user()
@hasPermission(auth()->user(), 'view_bookings')
    Yes !
@endif
// In AppServiceProvider.php

Blade::directive('hasPermission', function ($expression) {
    list($user, $permission) = explode(', ', $expression);

    return "<?php if (in_array($permission, ($user)->permissions ?? [])): ?>";
});

Two things :

  • I added a null coalescing operator so an empty array will be used if the user is null
  • IMPORTANT : Do not forget to run php artisan view:clear after changing your Blade directive's code

You could also add a little touch to be less restrictive regarding the exact formatting of your parameters. With the current code, you will receive an error if there's no space or more than 1 space between your comma and your second parameter. To resolve the issue, you could explode the comma only and use trim to remove the excess spaces.

Blade::directive('hasPermission', function ($expression) {
    list($user, $permission) = explode(',', $expression);
    $user = trim($user);
    $permission = trim($permission);

    return "<?php if (in_array($permission, ($user)->permissions ?? [])): ?>";
});
Activity icon

Replied to How Can I Have A Select In Nova That Lets Me Store JSON In The Database?

For sure it would need to be a Nova specific one to avoid that processing on the front-end, but will the two observers collide ? Well not on the front-end since you're registering one of the two in Nova's service provider only. But about Nova itself, I'd need to test it, because I never had that situation happen. As a side question, is your already in place observer required to run in Nova also ?

Activity icon

Replied to Custom Blade Directives

@snapey Doh ! Thank you for noticing. Edited my answer (tested and working).