trevorpan

trevorpan

Member Since 1 Year Ago

Experience Points
51,920
Total
Experience

3,080 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
461
Lessons
Completed
Best Reply Awards
1
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 11
51,920 XP
Mar
13
2 weeks ago
Activity icon

Replied to WithoutSyncingToSearch() - Algolia - Laravel Media Library Thumbnail Image Indexing Issue

@sti3bas

What I'm doing is getting the path for the thumbnail and sending to algolia in the Job index. Algolia doesn't allow for two indexes to be searched in the way the DB does — with joins e.g..

So, what I was doing was delaying the index method on Job so Media could be stored then retrieving the string url so it could be sent to algolia under the one index Job (in this case).

Because I have the algolia-php package I believe that's why wait() allows the media to be stored before returning the index array.

I'm still not certain it will always work (in production) but at least in the few tests I've done it performs well. Does that help clarify? Are you able to do this to?

Activity icon

Replied to WithoutSyncingToSearch() - Algolia - Laravel Media Library Thumbnail Image Indexing Issue

@sti3bas actually, have implemented a queue since we last chatted..

Here's the wait() https://www.algolia.com/doc/api-reference/api-methods/wait-task/

I'm thinking that's why that method is available on my implementation. Not sure if it's a bulletproof use case, but I do know with certainty the $thumbUrl is sent to algolia, where before it was not pulling the url to send to the index.

Have you tried this out?

Activity icon

Replied to WithoutSyncingToSearch() - Algolia - Laravel Media Library Thumbnail Image Indexing Issue

Hi @sti3bas

I found this method wait() from a forum manager on Algolia and it allowed for the media to process, and by Joe, has sent the image path to algolia. I gave it a shot without using an image and your handy helper gave it the default image.

Is this too good to be true?

$thumbUrl = optional($this->getMedia('document')->first())->getUrl('thumbnail')->wait();

Activity icon

Replied to How To Structure A Console Command Handle() Method?

Hi @tippin - I can definitely see I need to work on refactoring! I picked up the course Refactoring to Collections - just haven't put in the time yet.

The only issue that came up is the update() is not Method Illuminate\Database\Eloquent\Collection::update does not exist.

So I just turned on the transaction again.

Big thank you!!

Mar
12
3 weeks ago
Activity icon

Replied to How To Structure A Console Command Handle() Method?

@tippin - you are extremely helpful. Spent the entire day working this out - not saying it's the best way but it works.

After getting too many emails/second type error on the first loops I watched the entire queue series at laracasts and got that issue solved..

Here's a sample email it spit out!!!

Your job has bidded: Phone number test

The low bid was 25,782.01 //dollars

The following bids were placed:

- 27,173.22 //dollars


- 25,782.01 //dollars


- 30,374.64 //dollars


- 89,640.66 //dollars

Pay for your order now //button

Thank you,
BidBird

Back to the original post and the handle()—is this too much logic to have here or is this kind of what you envisioned??

   /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $biddedJobs = SlugJob::where([
                ['deadline', '<=', Carbon::now('America/Los_Angeles')->toDateTimeString()],
                ['bidded', '=', 0]
            ])
            ->get();

        foreach ($biddedJobs as $biddedJob):

            $bids = $biddedJob->bids;
            $sortedHighBids = $bids->sortByDesc('bid');
            $sortedHighBids->pop();
//            dd($sortedHighBids);

            foreach ($sortedHighBids as $sortedHighBid):
                $highBidUser = $sortedHighBid->user;
//                dd($sortedHighBid);
                $highBidUser->notify(new SendJobBiddedLosingBiddersNotified($sortedHighBid));
//                dd('hi');
            endforeach;

        endforeach;

        foreach ($biddedJobs as $biddedJob):

            $bids = $biddedJob->bids;
            $lowBid = $bids->sortBy('bid');
            $lowBid->splice(1);
//            dd($lowBid);
//            dd($lowBid->first()->user);
            $winningBidder = $lowBid->first()->user;
//            dd($winningBidder);

            $winningBidder->notify(new SendJobBiddedWinningBidderNotified($biddedJob));

        endforeach;

        foreach ($biddedJobs as $biddedJob):

//            dd($biddedJob);

            $buyer = $biddedJob->first()->user;
            $buyer->notify(new SendJobBiddedBuyerNotified($biddedJob));

        endforeach;

        DB::transaction(function () {
            DB::table('jobs')->where([
                ['deadline', '<=', Carbon::now('America/Los_Angeles')->toDateTimeString()],
                ['bidded', '=', 0]
            ])
                ->update(['bidded' => 1]);
        });

    }
Mar
10
3 weeks ago
Activity icon

Replied to How To Structure A Console Command Handle() Method?

@tippin ok, very cool app you're working on. I gave the various tools a shot on your demo site `

Came back basically to the last refactor. I'm wondering if an event is the best tool for the job? The SlugJobs can be numerous, but each job also has many users who all need notification emails.

Notification::send($users, new SendJobBiddedLosingBiddersNotified($biddedJobs));

Would you scrap the event and swap the above line out in the command? Or use the event and fire this notification from the listener handle()?

Is it even possible to send a batch of users and SlugJobs to a notification facade? Or does that need a loop?

Just to get a better picture of what's happening: a deadline ends for bids, and I'd like to notify via a cron job the bidders and buyer who won, who lost, and the final price.

Kind of complicated...really appreciate your thoughts.

Activity icon

Replied to How To Structure A Console Command Handle() Method?

Hi @tippin Thank you so much. If you can share a sample I'd love that. This is the DeadlineExpired. I'm really in the weeds on this one!

class DeadlineExpired
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * The job instance.
     *
     * @var SlugJob $job
     */
    public $job;

    /**
     * Create a new event instance.
     *
     * @param SlugJob $job
     */
    public function __construct(SlugJob $job)
    {
            $this->job = $job;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}
Activity icon

Replied to How To Structure A Console Command Handle() Method?

I've tried to refactor this a bit more but am still unclear on the events and collections. I watched some of the videos related to this one on Laravel 6 series: https://laracasts.com/series/laravel-6-from-scratch/episodes/46

If handle() has a collection of objects, in this case $biddedJobs, is a foreach() the right way to process the events? I've heard foreach() with many posts can cause performance issues.

However, I found the listener __construct() did not like the collection and gave this error:

Argument 1 passed to App\Events\DeadlineExpired::__construct() must be an instance of App\SlugJob, instance of Illuminate\Database\Eloquent\Collection given,

https://laravel.com/docs/7.x/notifications#using-the-notification-facade This facade link above says that's the way to handle a collection - but I've read a post on laracasts stating having an event is good as you can always hook in more listeners.

Having a hard time knowing what's the best way forward ~

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $biddedJobs = SlugJob::where([
                ['deadline', '<=', Carbon::now('America/Los_Angeles')->toDateTimeString()],
                ['bidded', '=', 0]
            ])
            ->get();

        // foreach ($biddedJobs as $biddedJob):
            event(new DeadlineExpired($biddedJobs));
        //endforeach;

        DB::transaction(function () {
            DB::table('jobs')->where([
                ['deadline', '<=', Carbon::now('America/Los_Angeles')->toDateTimeString()],
                ['bidded', '=', 0]
            ])
                ->update(['bidded' => 1]);
        });

    }
Mar
07
3 weeks ago
Activity icon

Replied to How To Structure A Console Command Handle() Method?

thought about the error a little bit:

public function handle()
    {
        $biddedJobs = SlugJob::where('deadline', '<=', Carbon::now())
            ->where('bidded', 0)
            ->get();

        foreach ($biddedJobs as $biddedJob):

            DB::transaction(function () use ($biddedJob) {
                DB::table('jobs')
                    ->update(['bidded' => 1]);
            });

            event(new DeadlineExpired($biddedJob));

        endforeach;
    }

Is this acceptable for your projects? I just haven't seen enough real websites to know if it's proper. This does send out emails in test I just tried...

Activity icon

Started a new Conversation How To Structure A Console Command Handle() Method?

Goal: I'd like to know how you structure a console command to get some fairly complex code to generate events based on a cron job that runs every minute?

https://laracasts.com/discuss/channels/laravel/laravel-command-debugging

I took a look above - the command has a ton of logic but helped me structure this below. The laravel docs say to keep it light.

<?php

namespace App\Console\Commands;

use App\Events\DeadlineExpired;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class DeadlineHasPassed extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'email:deadlineHasPassed';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Send winning bid emails';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $biddedJobs = DB::table('jobs')
            ->where('deadline', '<=', Carbon::now())
            ->get();

//        dd($biddedJobs);
        foreach ($biddedJobs as $biddedJob):
            DB::transaction(function () use ($biddedJob) {

//                dd($biddedJob->id);

                DB::table('jobs')->where([
                    ['id', $biddedJob->id],
                    ['bidded', 0]
                ])->update(['bidded' => 1]);
            });

            event(new DeadlineExpired($biddedJob));

            return $biddedJob;

        endforeach;

    }
}

Would you tuck any of this logic in other files? I'm trying to learn what is necessary. This particular command generates an error:

Argument 1 passed to App\Events\DeadlineExpired::__construct() must be an instance of App\SlugJob, instance of stdClass given

The event is trying to get a SlugJob $job instance. When querying the DB above in jobs table I don't think it's pulling objects just some records.

Have it almost together - if you have any tips I'd appreciate your input. Thank you

Activity icon

Replied to Steps To Upgrade Laravel From 5.8 To 7.0

geez, @jlrdw I didn't know that.

this nesbot/carbon is driving me mad. I think I'll take it easy on laravel 7 and wait a bit.

It sure would be nice to run a command that says

if (you want to upgrade to laravel 7)
	update: such and such
then (upgrade laravel/framework to ^7.0)

Seems like there'd be something for that??

Activity icon

Replied to Steps To Upgrade Laravel From 5.8 To 7.0

Hi @jlrdw

how do you check the unique packages our apps have against the Laravel ^7.0 requirements?

I went through your guide, this https://www.youtube.com/watch?v=-5QcxlpyA7Y and have spent just shy of 8 hours today upgrading from 6-7.

Had to reset to the last git commit, as I'd sabotaged the vendor directory.

Most of errors today were like this:

 - Can only install one of: symfony/process[5.0.x-dev, 2.0.5].
Feb
29
1 month ago
Activity icon

Replied to Is $schedule->command()->when() The Best Way To Listen For A Deadline The Second It Ends?

killer..@snapey

Have retweeked the command to add the time check as you mentioned.

$schedule->command('email:deadlineHasPassed')->everyMinute()->when(function () {
            DB::table('jobs')
                ->where('deadline', '<=', Carbon::now())
                ->get();
                return true;
            })
            ->withoutOverlapping();

Worked on this a bit:

// \Console\Commands\DeadlineHasPassed.php
    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {

        $biddedJobs = DB::table('jobs')
            ->where('deadline', '<=', Carbon::now())
            ->get();

//        dd($biddedJobs);

// is this second check redundant??
        if ($biddedJobs === true) {
             DB::transaction(function ($biddedJobs) {
                    DB::table('jobs')->update(['bidded' => 1]);
            });

        foreach ($biddedJobs as $biddedJob) {
            event(new JobBidded($biddedJob));
        }
    }

Had talked with a guy on the MySQL forum about this 'bidded' column. He mentioned it's irrelevant as you can make the time check. However, you're right that in this case 'bidded' is a required column so we can check that jobs don't run again.

Was going through this post, but I'm not sure manually dialing this in is necessary. https://fideloper.com/laravel-database-transactions

Is it necessary to loop $biddedJob or will event fire for each job? I've tried this but the events are not firing yet. This is my first time on this aspect of laravel.. Thank you ~

Activity icon

Replied to Is $schedule->command()->when() The Best Way To Listen For A Deadline The Second It Ends?

Hi @snapey I apologize for not responding - did not see a laracasts notification in my email.

The deadline is set when someone makes a job post. So, say Saturday 11:30am is when they post and then add 2 weeks via carbon package, etc.

When the stored dateTime is reached I'd like to fire off the emails.

Already have this logic working with a vue component but it sent the deadlineHasPassed emails each time someone viewed a page. So that was not going to work.

Yes, it is the correct appoach to check for passing deadlines every minute (if that is how granular you need to be)

Does the above $schedule-> command require ->everyMinute()? or does ->when() continuously check? This use case is a little uncommon, I've found it's tough to find the exact answers.

Feb
23
1 month ago
Activity icon

Started a new Conversation Is $schedule->command()->when() The Best Way To Listen For A Deadline The Second It Ends?

I've been wracking my brain on how to fire an event when a predetermined deadline is met.

This recent post tried to fire the event when the deadline was met via a VueComponent. However this fires each time a user looks at a page. https://laracasts.com/discuss/channels/vue/every-page-load-calls-a-method-that-is-supposed-to-only-run-once

My goal is to have the deadline fire only once from the server side.

This post below is pretty interesting as it uses a @while blade directive, but I'm concerned that could fire each time a user loads the page like the VueComponent above. https://laracasts.com/discuss/channels/laravel/fetch-data-based-on-date-and-time

Is this approach below the right way?

  /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('email:deadlineHasPassed')->when(function () {
            DB::table('jobs')
                ->where('deadline', '<=', Carbon::now())
                ->get();
                return true;
            })
            ->withoutOverlapping();
    }

Thank you ~

Activity icon

Replied to WithoutSyncingToSearch() - Algolia - Laravel Media Library Thumbnail Image Indexing Issue

Hi there. That's awesome, I'll check that out today.

Not currently using a queue, just thought it might be something worth looking at.

Had another possible solution was to use MySQL views: https://stitcher.io/blog/eloquent-mysql-views

Maybe sending the data we need to a view and then indexing that model is a possibility. Have a post on the MySQL forum - a regular there said MySQL views can be updated, unlike the blog above says.

I'll let you know what ends up working! Thank you -

Feb
22
1 month ago
Activity icon

Replied to WithoutSyncingToSearch() - Algolia - Laravel Media Library Thumbnail Image Indexing Issue

Hi there @sti3bas

That's exactly what the goal is. Spent some time looking through Media model, actually had deleted the toSearchableArray(). So please pardon the confusion there. That was an initial attempt.

So pleased at what you've shared above. The optional image shows up just great and is indexed to Algolia.

However, the Spatie code returns null. I tried using self::getMedia etc but that returned null too.

Is the toSearchableArray() something that should be put to a queue to delay the function?

I'm thinking because the model may not be saved and presented with a view via a controller the getMedia line is not able to locate the path??

Thank you again, Trevor

Feb
21
1 month ago
Activity icon

Replied to WithoutSyncingToSearch() - Algolia - Laravel Media Library Thumbnail Image Indexing Issue

Hi thank you @sti3bas

Gave this a run and am getting this error still:

Too few arguments to function App\Job::App\{closure}(), 0 passed in /Users/trevorpan/code/bidbird/vendor/laravel/scout/src/Searchable.php on line 216 and exactly 1 expected

Now I'm thinking I'm not doing what needs to be done. The original goal withoutSyncingToSearch() was to find the job being stored in the form (prior to submitting to algolia) and then identify and attach it's path to the array which is sent as $imageUrl to algolia on the Job index not the Media index.

(not sure if you know that package but when using MediaLibary natively we can call $job->getMedia('document')->first()->getUrl('thumbnail'); and get the image in blade. But when sending it for index to algolia those relations are lost- which is why I tried concatenating things above in the image path)

The end goal is to be able to say something like this line in the Vue Jobs Search component

<img :hit="item" :src=“item.imageUrl” :hit="item" width=200 height=120   alt=""/>

This would be ideal as it only uses one algolia index Job.

Activity icon

Started a new Conversation WithoutSyncingToSearch() - Algolia - Laravel Media Library Thumbnail Image Indexing Issue

Hi,

Have been trying to figure out how use the Spatie MediaLibrary and Algolia VueInstantSearch. I've made a few posts on algolia's forum and have discovered we cannot have two models in the same index.

I wanted to see if Laravel's withoutSyncingToSearch() could accomplish this but am getting errors such as:

Symfony\Component\Debug\Exception\FatalThrowableError
Too few arguments to function Illuminate\Database\Eloquent\Model::asJson(), 0 passed in /Users/trevorpan/code/bidbird/app/Job.php on line 415 and exactly 1 expected 

Basically, I'm trying to stall the indexing, locate the job being saved and then insert it into the job index.

Before this approach, I was trying to use the two indexes Job.php and Media.php and concatenate them in the VueComponent such as:

<img :hit="item" attribute="model_id" :src=“'/storage/' + item.model_id + '/conversions/' + item.file_name” :hit="item" attribute="model_id" width=200 height=120   alt=""/>

The above image src is the MediaLibary path. However, it's not the way the package performs in php which is in the block below:

// Job model
/**
     * Get the indexable data array for the model.
     *
     * @return array
     */
    public function toSearchableArray()
    {

        $job = SlugJob::asJson()->get()->first(); 
        // ignition suggested the asJson() vs class()

        SlugJob::withoutSyncingToSearch(function ($job) {
            return $imageUrl = $job->getMedia('document')->first()->getUrl('thumbnail');
        });

        return [
...
...
...
            'imageUrl' => $imageUrl,
            'customRanking' => [
                'desc(deadline)'
            ]
        ];
    }

Can you see a way to achieve this goal?

Thank you - have been at this for months off and on. There's got to be a way... Trevor

Feb
16
1 month ago
Activity icon

Replied to Every Page Load Calls A Method That Is Supposed To Only Run Once

@mikemacdowell thank you for clarifying the JS issue I was facing.

Reread your reply and decided to watch this whole series in hopes of finding a technique https://laracasts.com/series/get-real-with-laravel-echo

Super cool stuff in that series but I didn't see:

You'd be better to have the time countdown on your server and the Event be executed at the point your server wants.

Do you know of a series on laracasts (or other resource) that covers your quote above?

Activity icon

Awarded Best Reply on Vue Components Are Not Working

not sure if this'll do it, but is necessary for my components to load properly

//above your new vue in app.js

const files = require.context('./', true, /\.vue$/i)
files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
Feb
14
1 month ago
Activity icon

Replied to Every Page Load Calls A Method That Is Supposed To Only Run Once

Hi thank you. @mikemacdowell

Maybe add a query string to the uri and check for it in the controller as a debug tool?

I'm not sure how to do the above. Do you know of a tutorial on that? This sounds like a great thing to have in my toolbox.

Just getting the component to update was a big challenge - especially the controller action updateBiddedStatus. I know telescope says the put method is used for [email protected].

I'll have to hunt around and see where it's referenced - however, it is only called when I load the page. (e.g. clicking a job page)

It seems to me like

this.$on('bidded', () => this.updateBiddedStatus());

needs to be limited to only ever firing once. Maybe instead of bidded there's another term used?

Activity icon

Started a new Conversation Every Page Load Calls A Method That Is Supposed To Only Run Once

Hi,

Was wondering if you could point out where this loads the updateBiddedStatus each time someone views the page.


    <div id="countdown">

        <slot :countdown="countdown">{{ until }}</slot>

        <div v-if="bidded" v-text="biddedText" v-bind:slug="slug">

        </div>

        <div v-else>
            <span>{{ remaining.days }} d, </span>
            <span>{{ remaining.hours }} h, </span>
            <span>{{ remaining.minutes }} m, </span>
            <span>{{ remaining.seconds }} s </span>
        </div>
    </div>

</template>


<script>

    import moment from 'moment';

    export default {

        props: {
            slug: '',
            until: String,
            biddedText: {
                default: 'This job has bidded.'
            },
        },

        data() {
            return {
                now: new Date(),
                countdown: '',
            }
        },

        created() {
            let interval = this.refreshEverySecond();

            this.$on('bidded', () => clearInterval(interval));
            this.$on('bidded', () => this.updateBiddedStatus());
        },

        computed: {
            bidded() {
                return this.remaining.total <= 0;
            },

            remaining() {
                let remaining = moment.duration(Date.parse(this.until) - this.now);

                if (remaining <= 0) {
                    this.$emit('bidded');
                }

                return {
                    total: remaining,
                    days: remaining.days(),
                    hours: remaining.hours(),
                    minutes: remaining.minutes(),
                    seconds: remaining.seconds()
                };
            },
        },

        methods: {

            refreshEverySecond() {
                return setInterval(() => {
                    this.now = new Date();
                }, 1000);
            },

            async updateBiddedStatus() {
                await window.axios.put(`/jobs/` + this.slug + `/updateBiddedStatus`);
            },
        }
    }
</script>

I added this condition in the following method but it seems to be called nonetheless as telescope says the DeadlineExpired event is fired and sends a mail. The goal is for the updateBiddedStatus to only run once - when the countdown timer gets to zero.

      public function updateBiddedStatus(Request $request, SlugJob $job)
        {
           // dd($job->complete);
            if ($job->complete === false) {
                DB::transaction(function () use($job) {

                    DB::table('jobs')
                        ->where([
                            ['id', $job->id],
                            ['bidded', '=', 0]
                        ])
                        ->update(array('bidded' => 1));
                });

                event(new DeadlineExpired($job));
            }
        }

Thank you ~

Jan
29
2 months ago
Activity icon

Replied to How To Create A Model And Payment With One Submit Button? (possibly Similar To A Shopping Cart And Payment Setup)

Has anyone made a shopping cart before?

Starting to think that may be the way to think about the problem.

Jan
28
2 months ago
Activity icon

Started a new Conversation How To Create A Model And Payment With One Submit Button? (possibly Similar To A Shopping Cart And Payment Setup)

// blade
                <form class="input-group" id="payment-form" action="/jobs/{{ $job->slug ?? '' }}/jobpostpayment" method="POST">

In this case, I'd like to have an offeror post a job and make a payment on the same page - at time of job (model) creation.

I've got another working charge the routes.web file is similar to this:

Route::post('jobs/{job}/jobpostpayment', '[email protected]');

However, as the job does not exist I tried using the ?? '' option to not crash the create page; this allows the page to render but fails with a 404 when hitting submit as the id has not yet been created.

Does this mean a two page form is in order? Is there a way to do it all on one page?

Have you created a temp_job table e.g. that sits in limbo until payment goes through? Then that's deleted and sent to the "real" jobs table for instance? Trying to get a strategy...

Jan
13
2 months ago
Activity icon

Replied to QR Code Alternatives

@bobbybouwmann you've got so many great tips.

It is pretty fancy but I think image in our apps matters a lot. I really like the laracasts videos widgets and recent improvements it just gives the site that polish..

The only thing I'm thinking is if you use a publicly available link or slug to generate the code someone could use your the qr api and 'copy' your code. Just a concern on scammers.

Maybe using a random generated number to create the code ??

Your last line - are you saying we can use the camera to scan a random number?

Jan
12
2 months ago
Activity icon

Started a new Conversation QR Code Alternatives

https://laracasts.com/discuss/channels/laravel/qr-code-generator https://laracasts.com/discuss/channels/laravel/qr-codes?page=1

I checked out the above posts. It appears even google deprecated their QR code api.

Is the main issue with using these the interpretation side?

The app I'm working on is kind of like ebay but it's construction materials so the buyer goes to the seller's business location to pick up their goods.

My goal is to generate a code of some sort (QR or otherwise) and when a person wins a bid a code is generated. When the buyer goes to pick up their construction materials the seller prints out a pdf with the code on it and the buyer uses their phone to verify the code through the laravel app.

The goal is to "verify" that the real seller is providing the goods and that the buyer has "accepted" them.

I could see just a random number generator working too but if you have any experience in this area I'd like to hear.

Activity icon

Awarded Best Reply on Using Axios.post To Update/trigger Database Transaction; Error: 0 Statements Were Executed

Spent a week reviewing js fundamentals and got this component to make the updates on the db table. For anyone who may come upon this later:

//Vuejs component
// use the v:bind=""
<template>
<div v-if="bidded" v-text="biddedText" v-bind:slug="slug">

...

</template>

...

// add an empty string on props:
slug: '',

...

created() {
    this.$on('bidded', () => this.updateBiddedStatus());
}

...

// I found this approach to work as I don't think creating an object was necessary as blade filled in the slug from the db.
async updateBiddedStatus() {
                await window.axios.put(`/jobs/` + this.slug + `/updateBiddedStatus`);
            },

In the blade file add:

<your component ... slug="{{ $job->slug }}"
Activity icon

Replied to Using Axios.post To Update/trigger Database Transaction; Error: 0 Statements Were Executed

Spent a week reviewing js fundamentals and got this component to make the updates on the db table. For anyone who may come upon this later:

//Vuejs component
// use the v:bind=""
<template>
<div v-if="bidded" v-text="biddedText" v-bind:slug="slug">

...

</template>

...

// add an empty string on props:
slug: '',

...

created() {
    this.$on('bidded', () => this.updateBiddedStatus());
}

...

// I found this approach to work as I don't think creating an object was necessary as blade filled in the slug from the db.
async updateBiddedStatus() {
                await window.axios.put(`/jobs/` + this.slug + `/updateBiddedStatus`);
            },

In the blade file add:

<your component ... slug="{{ $job->slug }}"
Jan
03
2 months ago
Activity icon

Replied to Using Axios.post To Update/trigger Database Transaction; Error: 0 Statements Were Executed

man, I keep getting this routing issue (from telescope):

PUT     /jobs/undefined/updateBiddedStatus  404     204ms   3s ago 
           updateBiddedStatus(job_id) {
                window.axios.put(`/jobs/${job_id}/updateBiddedStatus`).then(({ data }) => {
                    return data.job(job_id);
                });
            },

What is critical when you're sending a {job} from vue to a laravel route? Should a Vue single file component use props or the data()?

I feel like this is getting too complicated. It seems like all were trying to do is post the job_id to the route and the controller takes over??

Activity icon

Replied to Using Axios.post To Update/trigger Database Transaction; Error: 0 Statements Were Executed

Good morning, @spamhead2k gave that a shot - thank you.

Without the arrow the countdown timer does not keep updating; it just records the first second and stops. If you refresh it outputs that second.

So I tried without using the arrow on just this.updateBiddedStatus.

Could it have anything to do with the api routes? Just combing through that tutorial.

\routes\web.php
// Jobs
Route::resource('/jobs', 'JobsController', [
    'except' => ['updateBiddedStatus'] // is it necessary to except if it's a differently named method?
]);
Route::post('jobs/{job}/updateBiddedStatus', '[email protected]');

The other thought I have is is the jobs necessary ? I'm still pretty poor with js.

The good thing is that the job id does print in the jobId prop when you inspect. So I know it's calling the database in blade...

Jan
02
3 months ago
Activity icon

Started a new Conversation Using Axios.post To Update/trigger Database Transaction; Error: 0 Statements Were Executed

Hello ~

I'm modifying the countdown timer that was featured on laracasts. What I'd like to do is trigger this method on the controller:

        public function updateBiddedStatus($job)
        {
            DB::transaction(function () use($job) {

                DB::table('jobs')
                    ->where([
                        ['job_id', $job->id],
                        ['bidded', '=', 0]
                    ])
                    ->update(array('bidded' => 1));
            });

            event(new DeadlineExpired($job));

        }

Have used this tutorial: https://vuejsdevelopers.com/2018/02/05/vue-laravel-crud/ which has helped alot but it's not quite what I'm trying to do.

In blade, I call this Vue.component

    <div class="deadline">
            <h3>Deadline:</H3>
            <div class="countdown" id="countdown">
                <countdown until="{!! $job->deadline !!}" bidded-text="This job has bidded." job-id="{{ $job->id }}">
                    <template slot-scope="props">
                      <p v-text="props.until"></p>
                     </template>
                </countdown>
            </div>
            <div class="deadlineBackgroundBottom"></div>
    </div>
\Vue.component
<template>

    <div id="countdown">

        <slot :countdown="countdown">{{ until }}</slot>

        <div v-if="bidded" v-text="biddedText" v-bind:jobId="jobId">

        </div>

        <div v-else>
            <span>{{ remaining.days }} d, </span>
            <span>{{ remaining.hours }} h, </span>
            <span>{{ remaining.minutes }} m, </span>
            <span>{{ remaining.seconds }} s </span>
        </div>
    </div>

</template>


<script>

    import moment from 'moment';

    export default {

        props: {
            jobId: '',
            until: String,
            biddedText: {
                default: 'This job has bidded.'
            },

        },

        data() {
            return {
                now: new Date(),
                jobs: ''
            }
        },

        created() {
            let interval = this.refreshEverySecond();

            this.$on('bidded', () => clearInterval(interval));
            this.$on('bidded', () => this.updateBiddedStatus());
        },


        computed: {
            bidded() {
                return this.remaining.total <= 0;
            },

            remaining() {
                let remaining = moment.duration(Date.parse(this.until) - this.now);

                if (remaining <= 0) {
                    this.$emit('bidded');
                }

                return {
                    total: remaining,
                    days: remaining.days(),
                    hours: remaining.hours(),
                    minutes: remaining.minutes(),
                    seconds: remaining.seconds()
                };
            },
        },

        methods: {

            refreshEverySecond() {
                return setInterval(() => {
                    this.now = new Date();
                }, 1000);
            },

            updateBiddedStatus(jobId) {
                window.axios.post('/jobs/${job}/updateBiddedStatus').then(({ data }) => {
                    return data.jobs(jobId);
                });
            },
        }
    }
</script>

If you can see the error I'd really appreciate knowing. e.g. can you call (2) this.$on('bidded' ?

Dec
31
3 months ago
Activity icon

Replied to Can You Use {id} For Some Logic And {slug} For Others?

Hi @bugsysha ,

Came across one little gotcha, that I finally got working.

    /**
     * Store a newly created resource in storage.
     *
     * @param $job
     * @return Response
     */
    public function store(SlugJob $job)

When you dd($job) it gives an instance of App\SlugJob (the extended eloquent model), so when you get to the next logic in the store method it tries to insert slug_job_id in addition to job_id. This was messing with the orders and charges and all sorts of things.

The trick? So simple.

// Job.php model

    public function bidReserves()
    {
        return $this->hasMany(BidReserve::class, 'job_id');
    }

Just specify the foreign key - it throws out slug_job_id on the App\SlugJob instance and proceeds as it originally did.

Thank you again!

Dec
29
3 months ago
Activity icon

Replied to Upgrading To 6.0; Email Verification Route Change When Using Auth::routes(['verify' => True]);

Don't know how I missed it. Thank you @bobbybouwmann

really looking forward to your "Laravel Secrets"!

Dec
28
3 months ago
Activity icon

Replied to Tuning Argon2id Hash Options To Your Server

Hi @braunson ,

Thank you; I certainly will swap those out where they occur.

I was hoping to see if someone also "tunes" their argon2id hash options to their server. From what I gather, the first example enclosed in the OP is something you can use to "tune" your bcrypt hash algorithm to the unique constraints of your own server; you run that on the server and that script will give you a value to use for bycrpt rounds (I think).

It's not an area I know much about...there's only three posts I found on laracasts.com with argon2id. Not too much to go on yet.

Activity icon

Replied to Upgrading To 6.0; Email Verification Route Change When Using Auth::routes(['verify' => True]);

Ha! thank you @bobbybouwmann .

I wish the docs mentioned that; I can see the {hash} was added to the route after running composer update.

Forgot about the php artisan route:list command. Even still, how do you locate the file where the routes are stored? I'm using phpstorm.

Activity icon

Started a new Conversation Tuning Argon2id Hash Options To Your Server

If you read up on https://www.php.net/manual/en/function.password-hash.php you get this code, but it appears to reference the bcrypt hash (unless I'm wrong).

<?php
/**
 * This code will benchmark your server to determine how high of a cost you can
 * afford. You want to set the highest cost that you can without slowing down
 * you server too much. 8-10 is a good baseline, and more is good if your servers
 * are fast enough. The code below aims for ≤ 50 milliseconds stretching time,
 * which is a good baseline for systems handling interactive logins.
 */
$timeTarget = 0.05; // 50 milliseconds 

$cost = 8;
do {
    $cost++;
    $start = microtime(true);
    password_hash("test", PASSWORD_BCRYPT, ["cost" => $cost]);
    $end = microtime(true);
} while (($end - $start) < $timeTarget);

echo "Appropriate Cost Found: " . $cost;
?>

On that page a comment mentioned this: https://tools.ietf.org/html/draft-irtf-cfrg-argon2-06#section-9.4

9.4. Recommendations: The Argon2id variant with t=1 and maximum available memory is recommended as a default setting for all environments. This setting is secure against side-channel attacks and maximizes adversarial costs on dedicated bruteforce hardware.

It's not clear if t=1 is time or threads.

//using php7.4 allows use of Argon2id
/*
    |--------------------------------------------------------------------------
    | Argon Options
    |--------------------------------------------------------------------------
    |
    | Here you may specify the configuration options that should be used when
    | passwords are hashed using the Argon algorithm. These will allow you
    | to control the amount of time it takes to hash the given password.
    |
    */

    'argon2id' => [
        'memory' => 1024,
        'threads' => 2,
        'time' => 2,
    ],

Do you have any experience here? How do you tune the algorithm options to your server?

Dec
27
3 months ago
Activity icon

Started a new Conversation Upgrading To 6.0; Email Verification Route Change When Using Auth::routes(['verify' => True]);

https://laravel.com/docs/6.x/upgrade#email-verification-route-change

The route path for verifying emails has changed from /email/verify/{id} to /email/verify/{id}/{hash}.

When I view routes\web.php I don't see the routes to change.

I've been looking all over for the file to make this change. Do you know where it is? I used php artisan make:auth in the 5.8 laravel, and have now upgraded to 6.0.

//web.php
Auth::routes(['verify' => true]);

if you use command+F7 in phpstorm it shows these two classes; when you open them they don't have the email routes.

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;

Thank you, Trevor

Dec
24
3 months ago
Activity icon

Awarded Best Reply on Implementing A User Interface For Roles & Permissions

Hi @jlrdw , thank you for having a look here.

It was simpler than I thought - just removing required from $this->validate(request(), lifted that validation error as you first pointed out. The html5 required has been added to the html select elements for added browser validation.

After thinking about it for a while I recognized this controller is not storing the roles/permissions it's using the html selects to check against known roles/permissions and if that clears then the roles/permissions are attached using eloquent in the backend.

Do you, or anyone else, see any security flaws in this approach?

/**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->validate(request(), [
            'email' => 'string|email|max:255',
            'companyrole' => 'string|min:3',
            'companypermissions' => 'string|min:3',
        ]);

        $roleExists = Role::roleExists(request('companyrole'));
        $permissionExists = Permission::permissionExists(request('companypermissions'));

        if ($roleExists === true && $permissionExists === true) {

            $userExists = User::userExists(request('email'));
//            dd($userExists);
                if ($userExists) {

                    $companyHasAdministrator = Company::CompanyHasAdministratorRole(request('companyrole'));
    //                dd($companyHasAdministrator);
                    if ($companyHasAdministrator === false) {
//                        dd($userExists);
                        $role = Role::currentRole(request('companyrole'));
//                        dd($role);
                        $permission = Permission::currentPermission(request('companypermissions'));

                        $userExists->roles()->attach($role);
                        $role->givePermissionTo($permission);

                        flash('Thank you for adding roles and permissions.')->success();

                        return back();

                    } else {

                        flash('This company already has an administrator. Please select another role for that user.')->warning();

                        return back();
                    }

                } else {

                    flash('No one with that email exists. Would you please invite them in the Invitations Center below? After they accept you may add their roles and permissions.')->warning();

                    return back();

                }


        } else {

            flash('You have been reported to the FBI.')->warning();

            return back();
        }
Activity icon

Replied to Implementing A User Interface For Roles & Permissions

Hi @jlrdw , thank you for having a look here.

It was simpler than I thought - just removing required from $this->validate(request(), lifted that validation error as you first pointed out. The html5 required has been added to the html select elements for added browser validation.

After thinking about it for a while I recognized this controller is not storing the roles/permissions it's using the html selects to check against known roles/permissions and if that clears then the roles/permissions are attached using eloquent in the backend.

Do you, or anyone else, see any security flaws in this approach?

/**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->validate(request(), [
            'email' => 'string|email|max:255',
            'companyrole' => 'string|min:3',
            'companypermissions' => 'string|min:3',
        ]);

        $roleExists = Role::roleExists(request('companyrole'));
        $permissionExists = Permission::permissionExists(request('companypermissions'));

        if ($roleExists === true && $permissionExists === true) {

            $userExists = User::userExists(request('email'));
//            dd($userExists);
                if ($userExists) {

                    $companyHasAdministrator = Company::CompanyHasAdministratorRole(request('companyrole'));
    //                dd($companyHasAdministrator);
                    if ($companyHasAdministrator === false) {
//                        dd($userExists);
                        $role = Role::currentRole(request('companyrole'));
//                        dd($role);
                        $permission = Permission::currentPermission(request('companypermissions'));

                        $userExists->roles()->attach($role);
                        $role->givePermissionTo($permission);

                        flash('Thank you for adding roles and permissions.')->success();

                        return back();

                    } else {

                        flash('This company already has an administrator. Please select another role for that user.')->warning();

                        return back();
                    }

                } else {

                    flash('No one with that email exists. Would you please invite them in the Invitations Center below? After they accept you may add their roles and permissions.')->warning();

                    return back();

                }


        } else {

            flash('You have been reported to the FBI.')->warning();

            return back();
        }
Dec
23
3 months ago
Activity icon

Replied to Implementing A User Interface For Roles & Permissions

It's not a multi-tenant. I would like to have the user select various roles/permissions from the dashboard.

Imagine ::::: company => has a user => who has a role => who then has permissions

I almost wonder if a pivot table should be a model???

The below seems like it would sabotage the attach() method and not really be using eloquent to it's finest.

//Here's a psuedo code.
$roleId = request('companyrole')->id;

$role = RolePermission::create([
    'role_id' => $roleId,
    'user_id' => auth->user()->id,
    ]);

any thoughts? how to escape the validation error and still use selects

Activity icon

Replied to Implementing A User Interface For Roles & Permissions

Hi @jlrdw ,

Well, I don't know what to say. I'd like someone who creates an account to be able to "claim" their company.

e.g. perhaps an employee finds BidBird and "invites" their boss. The boss may be older and not hip to the jive.

The roles and permissions, as noted in the form, are for the company. e.g. for the company to add or remove employees at will. The app will not want to dictate that or get in between those considerations.

It's entirely possible html selects are a dumb way to do this, but my OP is "Implementing a user interface for Roles & Permissions". Would really appreciate any ideas towards that end....

Activity icon

Replied to Implementing A User Interface For Roles & Permissions

hi, yea I've checked out their package, no views accompany the package.

My goal is for a user to have the option of choosing roles / permissions via html selects. I've been cracking my head to get to this point, but lack the experience.

The code I have checks the tables to see if the roles/permissions even exist. The goal is to prevent users from manipulating the values in the browser. If I'm not mistaken, you want this control.

Then it checks if a user via an html input for email exists.

If a user exists it checks if an administrator exists for that company, as only one admin can be on a company. Then it assigns the roles/permissions that the user has selected to that email (this can be themselves or someone else). It's pretty custom, but as Jeffrey said he likes to control this aspect of his site vs. a package.

Anyone else have an idea on how to implement this?

Activity icon

Replied to Implementing A User Interface For Roles & Permissions

still having an issue with this implementation.

From what I gather on all ACL, Roles & Permissions videos on laracasts you want to have the roles/permissions defined in the roles and permissions tables. Using tinker this is quite easy to attach roles/permissions - like the videos.

Using a dashboard and an input box and html selects gives an error:

    The email field is required.
    The companyrole field is required.
    The companypermissions field is required.

It feels like after validation the controller wants to create an object - and gives the error. How would you make it possible to attach the roles without throwing this error?

Here's the controller:

/**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->validate(request(), [
            'email' => 'required|string|email|max:255',
            'companyrole' => 'required|string|min:3',
            'companypermissions' => 'required|string|min:3',
        ]);

        $roleExists = Role::roleExists(request('companyrole'));
        $permissionExists = Permission::permissionExists(request('companypermissions'));

        if ($roleExists === true && $permissionExists === true) {

//            $userEmailExists = User::userEmailExists(request('email'));
            $user = User::userExists(request('email'));

            if ($user) {

                $companyHasAdministrator = Role::CompanyHasCompanyAdministrator(request('companyrole'));

                if ($companyHasAdministrator === false) {

                    $role = request('companyrole');
                    $permission = request('companypermissions');

                    $user->roles()->attach($role);
                    $user->permissions()->attach($permission);

                    flash('Thank you for adding roles and permissions.')->success();

                    return back();

                } else {

                    flash('This company already has an administrator.')->warning();

                    return back();
                }

            } else {

                flash('No one with that email exists. Would you please invite them in the Invitations Center below? After they accept you may add their roles and permissions.')->warning();

                return back();

            }


        } else {

            flash('You have been reported to the FBI.')->warning();

            return back();
        }

    }
Activity icon

Replied to Can You Use {id} For Some Logic And {slug} For Others?

// Jobs route
Route::resource('/jobs', 'JobsController');

// Jobmedia route
Route::post('/jobs/media', '[email protected]')
  ->name('jobs.storeMedia');
    public function storeMedia(Request $request, Job $job)
    {
        $path = storage_path('medialibrary/temp/');

        if (!file_exists($path)) {
            mkdir($path, 0777, true);
        }

        $file = $request->file('file');

        $name = uniqid() . '_' . trim($file->getClientOriginalName());

        $file->move($path, $name);

        return response()->json([
            'name'          => $name,
            'original_name' => $file->getClientOriginalName(),
        ]);
    }

You're right again!

I can see this now, the addition of Job $job in this method was not required as it is governed by the public function store(Request $request, SlugJob $job). Is this an accurate assessment?

Have removed the Job $job from storeMedia to storeMedia(Request $request) as it originally was setup prior to implementing SlugJob. Also removed it from create().

Thank you for your expertise — Happy New Year, @bugsysha

Dec
22
3 months ago
Activity icon

Replied to Can You Use {id} For Some Logic And {slug} For Others?

On the jobs.create page there's a form with a file dropzone for uploading media - pdf, jpg, etc.. For some reason the not yet created $job->document was crashing the page giving this error: [document] was not a property on this collection.

Prior to implementing your solution with SlugJob the jobs.create page rendered just fine. After implementing - the page does not render, unless Job $job is type hinted in the controller.

It was strange to me, because the page is crashing before the form is submitted (when the jobs.create page is fetched) — but by putting an empty variable on the controller `public function create(Request $request, Job $job) it seems to prevent the crash.

Have you had experience where a not yet created variable causes a page to crash? I know this is related to our original post, as that's all I've been working on since it occurred. (I think future people may benefit by this gotcha being addressed - if possible)

Thank you again ~ @bugsysha

Dec
19
3 months ago
Activity icon

Replied to Can You Use {id} For Some Logic And {slug} For Others?

Have been messing around with this for a bit. You are a life - saver. Thank you ~ @bugsysha

Not sure how this was getting tripped up; it was crashing the page saying [document] was not a property on this collection.

      @if(isset($job) && $job->document)
        var files =
          {!! json_encode($job->document) !!}
        for (var i in files) {
          var file = files[i]
          this.options.addedfile.call(this, file)
          file.previewElement.classList.add('dz-complete')
          $('form').append('<input type="hidden" name="document[]" value="' + file.file_name + '">')
        }
      @endif

This is a section for a dropzone file uploader. In the create page all I had was this:

//get
    /**
     * Show the step 1 Form for creating a new product.
     *
     * @return \Illuminate\Http\Response
     */
    public function create(Request $request)
    {
        return view('jobs.create');
    }

// modified to
    /**
     * Show the step 1 Form for creating a new product.
     *
     * @return \Illuminate\Http\Response
     */
    public function create(Request $request, Job $job)
    {
        return view('jobs.create', compact('job', 'request'));
    }

After implementing {slug} and {job} it was not working with just Request $request. I had to add Job $job to the create method and pass it to the view.

Before the SlugJob that was not the case. It's strange to me, as the view doesn't really have a job, this is the page to create one..?

Dec
15
3 months ago
Activity icon

Replied to Can You Use {id} For Some Logic And {slug} For Others?

Thank you for hanging in on this, @bugsysha . I've found quite a few posts on the topic. Most notably this one: https://github.com/laravel/framework/pull/30471

That's a ways out though.

If I'm not mistaken the slug routes are needed to display the pages in this app, and the id's are needed to process charges and retrieve media. Not saying this is ideal but it's where the app's at at the moment.

Not sure why that would be a collection instance. Before the slug issue, I had quite a number of tests passing on this, where it was creating a model instance of BidReserve, Order, etc..storing the records.

// this action was changed from $job->id to:
<form id="payment-form" action="/jobs/{{ $job->slug }}/bidreserve" method="post">
    @csrf

...

    <button class="stripeButton">Bid Reserve</button>
</form>

Here's what I have in the BidReservesController.php

    /**
     * Store a newly created resource in storage.
     *
     * @param $job
     * @return Response
     * @throws ValidationException
     */
    public function store(Job $job)
    {
        $job = Job::Incomplete()
//            ->where('id', $job->id) // BUGSYSHA's added line 
//            ->orWhere('slug', $job->slug) // BUGSYSHA's added line 
            ->findOrFail($job);

  request()->validate([
            'amount' => 'required|numeric|min:1',
            'stripeToken' => 'required'
        ]);

        // Charging the bidder
        try {
            $bidReserve = $job->bidReserves()->create([
                'amount' => 500,
                'job_id' => $job->id,
            ]);

            $order = $bidReserve->complete($this->paymentGateway, request('stripeToken'), auth()->user()->id, $job, $bidReserve);

            return Route::redirect('jobs.show/{job->slug}')
                ->setStatusCode(201);
        } catch (PaymentFailedException $e) {

            return back()
                ->setStatusCode(422);

        }

I hope this helps out. If there's another snippet you need please let me know. I looked into the api, path()seems to be reserved for that exact function. Had played around with a slugPath() but it did not have any effect, and I was having a hard time figuring out where to call that - which is probably due to path() being reserved and I presume global...

Activity icon

Replied to Can You Use {id} For Some Logic And {slug} For Others?

Slug, slug, slug has slugged me.

I re-watched the below video, and have re-implemented this in the AppServiceProvider: https://laracasts.com/series/lets-build-a-forum-with-laravel/episodes/13

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        View::share('job', Job::all());
    }

It's giving an error here when doing a payment post, e.g.

select * from `jobs` where `slug` = '22' limit 1

or when switching:

select * from `jobs` where `bidded` = 0 and `jobs`.`id` = 'algolia-test' limit 1

I tried changing the calls from $job->id to $job->slug however it still gives errors such as: Method Illuminate\Database\Eloquent\Collection::bidReserves does not exist.

//Job.php model

    /**
     * Get a string path for the job
     *
     * @return string
     */
    public function path()
    {
//            return "/jobs/{$this->id}";

            return "/jobs/{$this->slug}";
    }

    /**
     * Get the route key for the model.
     *
     * @return string
     */
    public function getRouteKeyName(): string
    {
        return 'slug';
    }

If getRoutKeyName() is uncommented then the slug doesn't work.

I also added, as you mentioned, this to the JobsController

        $job = Job::where('id', $job->id)
            ->orWhere('slug', $job->slug)
            ->firstOrFail();

Below is a payment store function which attaches an order to the sale. One thing about slugs is that I didn't know to start using them immediately. A ton of logic is based on the $job->id.

Adding more difficulty, this app uses the Spatie Media-Library which bases the routing of media objects to the id. However, if in the browser a slug is present the media shows. So, I'm not sure if this is based on the View::share(). However, if you do a browser request such as bidbird.test/jobs/3 a 404 is returned. so I question if View::share() is working properly.

// BidReservesController.php
    /**
     * Store a newly created resource in storage.
     *
     * @param $job
     * @return Response
     * @throws ValidationException
     */
    public function store(Job $job)
    {
        $job = Job::Incomplete()
//            ->where('id', $job->id) // added line - may be removed
//            ->orWhere('slug', $job->slug) // added line - may be removed
            ->findOrFail($job);

It seems mostly to be a path() issue. I had even tried:

//Job.php model
 /**
     * Get a string path for the job
     *
     * @return string
     */
    public function path()
    {
        if ($this->id == 'job_id') {
            return "/jobs/{$this->id}";
        }
        elseif ($this->slug == 'job_slug'){
            return "/jobs/{$this->slug}";
        }

        //if ('job_id' == $this->id) {
        //    return "/jobs/{$this->id}";
        //}
        //elseif ('job_slug' == $this->slug){
        //    return "/jobs/{$this->slug}";
        //}
    }

but it was causing errors.

Do you have any more ideas? @bugsysha

Dec
14
3 months ago
Activity icon

Replied to Can You Use {id} For Some Logic And {slug} For Others?

Hi @bugsysha ,

I'm trying to implement this and I believe the {id} is being found, as the button I've got

<div class="jobsbutton">
        <a href="/jobs/{{ $job->id }}">
            <button type="button" class="btn btn-job">Details</button>
        </a>
    </div>

is finding the right number (in addition to using slug). However, no data is pulled from the database. So, basically it shows the right id but cannot locate the data.

However, the routes seem to be all jacked up.

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        View::share('job_id', '$job');
    }

in the routes.web file:

// Jobs
Route::resource('/jobs', 'JobsController', ['except' => ['show']]);
Route::get('/jobs/{slug}', '[email protected]');
Route::get('/jobs/{job}', '[email protected]');

How do you make both {slug} and {job} work in the routes file? Thank you ~