packy

packy

Member Since 3 Years Ago

Coeur d’ Alene

Experience Points
27,500
Total
Experience

2,500 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
222
Lessons
Completed
Best Reply Awards
1
Best Reply
Awards
  • start-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-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-token Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer-token Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • lara-evanghelist 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 6
27,500 XP
Feb
18
1 week ago
Activity icon

Replied to Get "Grandparent" Relationship From Child

Never mind. I just ended-up walking up the chain. Not sure why I didnt do that in the first place?????

so to get the slug I just needed:

$this->productType->shopCategory->slug

Activity icon

Started a new Conversation Get "Grandparent" Relationship From Child

So I have been trying to figure this out for a while and I just kind find the right relationship, or am using it wrong. Basically I am trying to get the "Grandparent" relationship from the child. Right now I have 3 tables:

merchandises
-id
-product_type_id;
-name;
-description;
-slug;

product_types
-id
-shop_category_id;
-name;
-slug;

shop_categories
-id
-name;
-slug;

So on the Merchidese model I want to be able to get the shop_category slug. I thought the relationship would be

public function shopCategory()
    {
        return $this->hasOneThrough(ShopCategory::class, ProductType::class);
    }

but that assumes product_types has a merchandise_id which it doesnt.

Merchandise HasOne ProuductType that HasOne ShopCategory. So how do I get the ShopCategory from the Merchandise??

Feb
11
2 weeks ago
Activity icon

Replied to Getting E-Commerce Parcel Size

Thats @sti3bas . I will check that out

Activity icon

Started a new Conversation Getting E-Commerce Parcel Size

I am currently building an e-commerce solution for a company and having trouble wrapping my head around shipping costs. I am using Shippo and I can easily get rates, labels and really everything I need, the issue is not a technical one with their API. I am just curious how you find the Parcel size to get rates before we package it. Right now the systems works like any other: you click to checkout, we know whats in your cart, you fill out shipping destination and the API returns rates. To get the rates I need to provide the parcel weight and size. I can add all the weights of items but how do you figure a box size? If the item is 4X1X1 that is not the actual box size, just the item size. If we have multiple items how can a pick a box size? I assume most people just use the same box size for 1 item as the do 5 items.

Here is the Shippo tutorial I used:

https://m.dotdev.co/easily-handle-shipping-in-laravel-with-shippo-12055c903704

Here is what I need to pass Shippo to get rates for the user to select (Parcel is the final package to send):

$parcel = array(
    'length'=> '5',
    'width'=> '5',
    'height'=> '5',
    'distance_unit'=> 'in',
    'weight'=> '2',
    'mass_unit'=> 'lb',
);

$shipment = Shippo_Shipment::create( array(
    'address_from'=> $fromAddress,
    'address_to'=> $toAddress,
    'parcels'=> array($parcel),
    'async'=> false
    )
);
Feb
07
2 weeks ago
Activity icon

Replied to ECommerce Shipping Costs

Per their docs, I provide everything in parcel, including the parcel size and weight

Activity icon

Started a new Conversation ECommerce Shipping Costs

I am currently building an e-commerce solution for a company and having trouble wrapping my head around shipping costs. I am using Shippo and I can easily get rates, labels and really everything I need, the issue is not a technical one with their API. I am just curious how you find the Parcel size to get rates before we package it. Right now the systems works like any other: you click to checkout, we know whats in your cart, you fill out shipping destination and the API returns rates. To get the rates I need to provide the parcel weight and size. I can add all the weights of items but how do you figure a box size? If the item is 4X1X1 that is not the actual box size, just the item size. If we have multiple items how can a pick a box size? I assume most people just use the same box size for 1 item as the do 5 items.

Here is the Shippo tutorial I used:

https://m.dotdev.co/easily-handle-shipping-in-laravel-with-shippo-12055c903704

Here is what I need to pass Shippo to get rates for the user to select (Parcel is the final package to send):

$parcel = array(
    'length'=> '5',
    'width'=> '5',
    'height'=> '5',
    'distance_unit'=> 'in',
    'weight'=> '2',
    'mass_unit'=> 'lb',
);

$shipment = Shippo_Shipment::create( array(
    'address_from'=> $fromAddress,
    'address_to'=> $toAddress,
    'parcels'=> array($parcel),
    'async'=> false
    )
);
Jan
04
1 month ago
Activity icon

Started a new Conversation When To Use Vapor

I have been looking at Laravel Vapor and just trying to see if I should go that route with a new site. I want to try it but also don't want to go overboard if its not needed. I know the general answer is "to use it is case by case" which I agree and understand. I am just trying to see what are people's thresholds for when to switch to Vapor. If you site has over 10k users? If you are getting over X amount of request a minute on average? Can you add Vapor later fairly easy if you start on Forge?

The site is going to be a e-commerece store with a customer and wholeseller portal to place more orders easily. I think Forge would be fine but also worried about missing orders if the server is jacked. Also want an excuse to try Vapor

Dec
27
1 month ago
Activity icon

Replied to Series Suggestion: E-commerce App

Thanks for the link, I will take a look.

Activity icon

Started a new Conversation Series Suggestion: E-commerce App

I think a great series that a lot of people would use in everyday app building would be one on e-commerce. It could show how to setup Cashier with stripe for subscriptions (since that’s different now), single purchase with Stripe, setting up a shopping cart, shipping label with Shippo, etc. A lot of people would use this real world, practical tutorial to build apps to generate income. Would be a super big win for the community.

Dec
20
2 months ago
Activity icon

Commented on Building Data-Tables With Livewire

Anyone else having some buggyness with the perPage select action? It works the first 3 times I change it but after that it stops sending a request?

Dec
17
2 months ago
Activity icon

Awarded Best Reply on Larvel Cashier Not Storing Card Version 10.1

Thanks @kensmithzzz . I found a good article explaining the new setup finally (https://www.seismicpixels.com/creating-a-laravel-saas-framework-part-6/). Basically when I show my registration view I now create a new User and pass the intent there. I kept thinking the user had to be saved already, not just created. So if anyone else wants to do it:

Show the view

Registration Controller

public function show()
    {
        $user = new User;

        return view('auth.register', [
            'intent' => $user->createSetupIntent()
        ]);
    }

Pass the intent to my Vue component

<register-form stripe-key="{{ env('STRIPE_KEY') }}" stripe-intent="{{ $intent->client_secret }}">
            </register-form>

Add stripe elements to a div:

 mounted() {
        // Create a Stripe client.
        this.stripe = Stripe(this.stripeKey);

        // Create an instance of Elements.
        var elements = this.stripe.elements();

        var style = {
            base: {
                color: "#32325d",
                fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                fontSmoothing: "antialiased",
                fontSize: "16px",
                "::placeholder": {
                    color: "#aab7c4"
                }
            },
            invalid: {
                color: "#fa755a",
                iconColor: "#fa755a"
            }
        };

        // Create an instance of the card Element.
        this.card = elements.create("card", { style: style });

        // Add an instance of the card Element into the `card-element` <div>.
        this.card.mount("#card-element");
    },

process the data

pay() {
            this.isLoading = true;

            if (this.form.payment_method == "cc") {
                this.setupCard();
            } else {
                this.register();
            }
        },

        setupCard() {
            this.stripe
                .handleCardSetup(this.stripeIntent, this.card, {
                    payment_method_data: {
                        billing_details: { name: this.form.name }
                    }
                })
                .then(data => {
                    this.form.stripePayment = data.setupIntent.payment_method;
                    if (this.form.stripePayment) this.register();
                })
                .catch(error => {
                    this.isLoading = false;
                    console.log(error);
                });
        },

        register(setupIntent) {
            this.form
                .post("/register")
                .then(data => {
                    this.isLoading = false;
                    if (data.type == "success") {
                        this.$swal({
                            type: "success",
                            title: "Great...",
                            text: data.message,
                            toast: true,
                            position: "top-end",
                            showConfirmButton: false,
                            timer: 2000
                        });

                        setTimeout(() => {
                            window.location.replace(data.url);
                        }, 2000);
                    }
                })
                .catch(error => {
                    this.isLoading = false;
                });
        }

save the user

Register Controller

protected function create(request $request)
    {
        $request->validate([
            'name' => 'required',
            'email' => 'required|unique:users',
            'username' => 'required|alpha_dash|unique:users',
            'phone' => 'required',
            'city' => 'required',
            'state' => 'required',
            'password' => 'required|confirmed',
            'agree' => 'required',
        ]);

        $user = User::create([
            'username' => $request['username'],
            'name' => $request['name'],
            'email' => $request['email'],
            'phone' => $request['phone'],
            'city' => $request['city'],
            'state' => $request['state'],
            'password' => Hash::make($request['password']),
        ]);

        if ($request['subscription_type'] == 'premier' && $request['payment_method'] == 'cc') {

            $user->newSubscription('default',  env('STRIPE_PLAN_ID'))->create($request->input('stripePayment'), [
                'email' => $request['email'],
            ]);
        }



        if ($user) {
            $user->assignRole('subscriber');



            Auth::login($user);

            return response()->json([
                'type' => 'success',
                'message' => 'you are all set.',
                'url' => '/dashboard'
            ]);
        }
Activity icon

Replied to Larvel Cashier Not Storing Card Version 10.1

@kensmithzzz tested and confirmed to work. I wish the docs better showed how to do it on user registration and not to just a already registered user, makes it confusing. Any pull to updated the docs @jeffreyway

Activity icon

Replied to Larvel Cashier Not Storing Card Version 10.1

Thanks @kensmithzzz . I found a good article explaining the new setup finally (https://www.seismicpixels.com/creating-a-laravel-saas-framework-part-6/). Basically when I show my registration view I now create a new User and pass the intent there. I kept thinking the user had to be saved already, not just created. So if anyone else wants to do it:

Show the view

Registration Controller

public function show()
    {
        $user = new User;

        return view('auth.register', [
            'intent' => $user->createSetupIntent()
        ]);
    }

Pass the intent to my Vue component

<register-form stripe-key="{{ env('STRIPE_KEY') }}" stripe-intent="{{ $intent->client_secret }}">
            </register-form>

Add stripe elements to a div:

 mounted() {
        // Create a Stripe client.
        this.stripe = Stripe(this.stripeKey);

        // Create an instance of Elements.
        var elements = this.stripe.elements();

        var style = {
            base: {
                color: "#32325d",
                fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                fontSmoothing: "antialiased",
                fontSize: "16px",
                "::placeholder": {
                    color: "#aab7c4"
                }
            },
            invalid: {
                color: "#fa755a",
                iconColor: "#fa755a"
            }
        };

        // Create an instance of the card Element.
        this.card = elements.create("card", { style: style });

        // Add an instance of the card Element into the `card-element` <div>.
        this.card.mount("#card-element");
    },

process the data

pay() {
            this.isLoading = true;

            if (this.form.payment_method == "cc") {
                this.setupCard();
            } else {
                this.register();
            }
        },

        setupCard() {
            this.stripe
                .handleCardSetup(this.stripeIntent, this.card, {
                    payment_method_data: {
                        billing_details: { name: this.form.name }
                    }
                })
                .then(data => {
                    this.form.stripePayment = data.setupIntent.payment_method;
                    if (this.form.stripePayment) this.register();
                })
                .catch(error => {
                    this.isLoading = false;
                    console.log(error);
                });
        },

        register(setupIntent) {
            this.form
                .post("/register")
                .then(data => {
                    this.isLoading = false;
                    if (data.type == "success") {
                        this.$swal({
                            type: "success",
                            title: "Great...",
                            text: data.message,
                            toast: true,
                            position: "top-end",
                            showConfirmButton: false,
                            timer: 2000
                        });

                        setTimeout(() => {
                            window.location.replace(data.url);
                        }, 2000);
                    }
                })
                .catch(error => {
                    this.isLoading = false;
                });
        }

save the user

Register Controller

protected function create(request $request)
    {
        $request->validate([
            'name' => 'required',
            'email' => 'required|unique:users',
            'username' => 'required|alpha_dash|unique:users',
            'phone' => 'required',
            'city' => 'required',
            'state' => 'required',
            'password' => 'required|confirmed',
            'agree' => 'required',
        ]);

        $user = User::create([
            'username' => $request['username'],
            'name' => $request['name'],
            'email' => $request['email'],
            'phone' => $request['phone'],
            'city' => $request['city'],
            'state' => $request['state'],
            'password' => Hash::make($request['password']),
        ]);

        if ($request['subscription_type'] == 'premier' && $request['payment_method'] == 'cc') {

            $user->newSubscription('default',  env('STRIPE_PLAN_ID'))->create($request->input('stripePayment'), [
                'email' => $request['email'],
            ]);
        }



        if ($user) {
            $user->assignRole('subscriber');



            Auth::login($user);

            return response()->json([
                'type' => 'success',
                'message' => 'you are all set.',
                'url' => '/dashboard'
            ]);
        }
Activity icon

Started a new Conversation Larvel Cashier Not Storing Card Version 10.1

I am creating a new app using Cashier 10.1. In the past I would send a token from Stripe to the subscription function when registering a user with a subscription. Now it says it takes a Payment Method (id). I am registering a payment method with Stripe and passing that to my controller but it returns the error "This customer has no attached payment source". I read the docs but it only gives an example of how to add a subscription to a current user by passing to the view $user->createSetupIntent(). Below is the code for when a user registers:

Component

       pay() {
            this.isLoading = true;

            if (this.form.payment_method == "cc") {
                let that = this;
                this.stripe
                    .createPaymentMethod({
                        type: "card",
                        card: that.card
                    })
                    .then(result => {
                        this.form.stripePayment = result.paymentMethod.id;
                        this.register();
                    })
                    .catch(e => {
                        console.log(e);
                    });
            } else {
                this.register();
            }
        },

        register() {
            this.form
                .post("/register")
                .then(data => {
                    this.isLoading = false;
                    if (data.type == "success") {
                        this.$swal({
                            type: "success",
                            title: "Great...",
                            text: data.message,
                            toast: true,
                            position: "top-end",
                            showConfirmButton: false,
                            timer: 2000
                        });

                        setTimeout(() => {
                            // window.location.replace(data.url);
                        }, 2000);
                    }
                })
                .catch(error => {
                    this.isLoading = false;
                });
        }

RegisterController

protected function create(request $request)
    {
        $request->validate([
            'name' => 'required',
            'email' => 'required|unique:users',
            'username' => 'required|alpha_dash|unique:users',
            'phone' => 'required',
            'city' => 'required',
            'state' => 'required',
            'password' => 'required|confirmed',
            'agree' => 'required',
        ]);

        $user = User::create([
            'username' => $request['username'],
            'name' => $request['name'],
            'email' => $request['email'],
            'phone' => $request['phone'],
            'city' => $request['city'],
            'state' => $request['state'],
            'password' => Hash::make($request['password']),
        ]);

        if ($request['subscription_type'] == 'premier' && $request['payment_method'] == 'cc') {

            $user->newSubscription('default',  env('STRIPE_PLAN_ID'))->create($request->input('stripePayment'), [
                'email' => $request['email'],
            ]);
        }



        if ($user) {
            $user->assignRole('subscriber');



            Auth::login($user);

            return response()->json([
                'type' => 'success',
                'message' => 'you are all set.',
                'url' => '/dashboard'
            ]);
        }

I posted this on Stackoverflow as well and it was mentioned that Cashier no longer can create a subscription when you create a user. You have to create a user first, return a new view with that users createSetupIntent and then take the payment information. This seems like it creates a lot of room for the user to exit out before they created their subscription which will lead to some confusion if they signed up for a subscription thats paid for or not. Even this site takes the CC when you register, I would assume he uses Cashier.

Sep
30
4 months ago
Activity icon

Replied to Laracasts Search Buggy

@click. Oh I see. That was a while ago too, I would think the site update would have made some search updates as well but I guess not. Looks like I will just continue to use Google.

Activity icon

Replied to Laracasts Search Buggy

I understand that, but if Vapor is in all the titles you think if Laracasts found some, it would find them all?

Activity icon

Started a new Conversation Laracasts Search Buggy

Anyone else notice the search on the discussion board doesn't always pull up all the discussions?

Example: I am looking for discussions on Laravel Vapor so I search "Vapor". When I do there is only some older posts, non of which are about the correct vapor. I get the keyword Vapor is what triggered those results.

If I search Google for "Laracasts Vapor" there are 2 discussions that are about the Vapor I was looking for: https://laracasts.com/discuss/channels/laravel/vapor-taylor-otwell-presentation?page=1 and https://laracasts.com/discuss/channels/site-improvements/laravel-vapor-queue-worker-serverless.

Both of these discussion also have "Vapor" in their title so why didn't they show up in my search on Laracasts??

Sep
25
5 months ago
Activity icon

Started a new Conversation Webflow Animation In Laravel

Has anyone used Webflow to make scroll animations and then exported the code to use within an existing project? I usually dont like those "build your site" sites but after looking at Webflow, making scroll animations for "story telling" pages seems much easier than Scrollmagic. I still build mostly apps so would never use them to build a full project, but some pages like "home" and "how it works" would be great places to use scroll animations like:

https://www.reine-lungau.at/ http://the-goonies.webflow.io/

Just curious if anyone has done it.

Sep
21
5 months ago
Activity icon

Replied to Do You Need A Roles Package?

Thats my thought. Just wasnt sure if there was some special magic in the packages.

Activity icon

Started a new Conversation Do You Need A Roles Package?

I have always wondered this. In the last 5 apps I have done there are really only 2 roles: admin and subscriber. There are never any permissions since most of what you can do as a subscriber is determined by Cashier (your subscription). In this scenario, does it make sense to just add a role column to the users table? Seems like it would be better not to add in more relationships and packages if you dont need to.

Sep
13
5 months ago
Activity icon

Replied to Redirect Based On Refferer

Just found this: https://github.com/spatie/laravel-referer. Might have some potential

Activity icon

Replied to Redirect Based On Refferer

No not super ugly, but for marketing we want to use the main site address everywhere and then forward to a landing page if we want from the code side. More consistent and we are not locked into any set URL

Activity icon

Started a new Conversation Redirect Based On Refferer

Not sure if this should be in Laravel or Forge, but basically I was wondering if there is a way to identify the referrer of incoming traffic and redirect based on that. So lets say I have a link on Instagram: mysite.com. If you click that link from Instagram it redirects to a landing page. If you directly type in mysite.com it takes you to the home page. The point being, keeping the branding/marketing all the same on different platforms but redirect to specific use cases without making an ugly link like mysite.com/instagram-landing

Sep
12
5 months ago
Activity icon

Started a new Conversation Forge Down?

Anyone try and get on Forge today? I am getting a 502 Bad Gateway screen

Sep
11
5 months ago
Activity icon

Replied to Settings Global Helper

Not sure why that had an error but I just changed my helpers.php to:

<?php

use Spatie\Valuestore\Valuestore;

function settings($key)
{
    $settings = Valuestore::make(storage_path('app/settings.json'));

    return $settings->get($key);
}

Works for what I need it to

Activity icon

Started a new Conversation Settings Global Helper

I am following the guide here: https://laravel-news.com/global-application-settings but keep getting the error Target [App\Settings] is not instantiable. Not sure what is causing this. I have got it to work using directly in a controller like $settings = Valuestore::make(storage_path('app/settings.json')); but I need a global solution.

Settings.php

<?php

namespace App;

use Spatie\Valuestore\Valuestore;

class Settings extends Valuestore
{
    //
}

helpers.php

<?php



function settings($key = null, $default = null)
{
    if ($key === null) {
        return app(App\Settings::class);
    }

    return app(App\Settings::class)->get($key, $default);
}

in AppServiceProvider


 public function register()
    {
        $this->app->singleton(Settings::class, function () {
            return Settings::make(storage_path('app/settings.json'));
        });
    }

in View

{{ settings('facebook_url') }}

Aug
27
5 months ago
Activity icon

Started a new Conversation New Resource Based On Scope

Is there a way to create a resource and just use a scope to pull in the entries? Basically I want to have a Subscribers resource on the the side nav that basically just grabs all the Users with the role of subscriber. I know I could add a filter on the Users resource but it would be nice to have a resource with just subscribers with different metrics, options (i never create a subscriber on the backend), filters, ect.