trevorpan

trevorpan

Member Since 1 Year Ago

Experience Points
43,740
Total
Experience

1,260 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
398
Lessons
Completed
Best Reply Awards
0
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 9
43,740 XP
Dec
08
1 day ago
Activity icon

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

Hi thank you @bugsysha ,

Have implemented this in the job.php

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

Does the below conform to your approach?

<?php

namespace App;

use App\Job;

class SlugJob extends Job
{
    protected $table = 'jobs';

    /**
     * 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';
    }

}

The issue facing now are these variables in the JobsController.php

public function show(SlugJob $job)
    {
        $downloads = $job->getMedia('document');

        $hasPayedBidReserve =
            auth()->user()
            ->bidReserves()
            ->where('job_id', $job->id)
            ->exists();

        $hasPlacedBid =
            auth()->user()
                ->bids()
                ->where('job_id', $job->id)
                ->exists();

        return view('jobs.show', compact('job', 'downloads', 'hasPayedBidReserve', 'hasPlacedBid'));
    }

'downloads', 'hasPayedBidReserve', 'hasPlacedBid' are dependent on the $jobId whereas job can use the slug. This is something i've wrestled withif you want several items to show on the page it seems like several controllers can make that happen.

In this case, if I move 'downloads', 'hasPayedBidReserve', 'hasPlacedBid' logic to the [email protected] they don't render. I'm guessing this is because the JobsController is the workhorse for showing the page?

Activity icon

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

Thank you, @tykus . I missed that article in the newsletter.

It's my first site, so unfortunately have a lot of balls down the field only to have someone (implicit-model-binding) intercept!!!

Activity icon

Started a new Conversation Can You Use {id} For Some Logic And {slug} For Others?

Have just implemented slugs via the Laracasts videos and they work nicelyexcept for existing logic that uses {id}.

One example is the payment gateway:

http://bidbird.test/jobs//bidreserve

As you can see above the id is missing for the job.

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

//BidReservesController.php
    /**
     * Store a newly created resource in storage.
     *
     * @param $jobId
     * @return Response
     * @throws ValidationException
     */
    public function store($jobId)
    {
        $job = Job::Incomplete()->findOrFail($jobId);
...
//other logic

Can you use {id} for some logic and {slug} for others? Otherwise, it seems a tremendous amount of work needs to be done to fix this.

Dec
06
3 days ago
Activity icon

Started a new Conversation How To Assign An Algolia Media Path Using Spatie's Laravel-Media Package?

I've watched the laracasts videos on algolia and have managed to get the front end search functionality working.

The HasMedia trait has been added to the model I'm indexing. All the appropriate columns have been sent to the toSearchableArray(). However, I'm at a loss how to get the image associated with a post to display.

Am using vue component for the search functionality and have added this:

<img src=“{hit.imgUrl}” title=“{hit.name}” width=120 height=200 />

The above is based on algolia's examples. How exactly is this accomplished?

the toSearchableArray() doesn't make sense to include a url, as no one would search for a media object....

just gave this a shot to no avail.

<img src=“/ . '{{ {hit.objectID}->getMedia('document')->first()->getUrl('thumbnail') }}' ” title=“{hit.name}” width=120 height=200 />
Dec
01
1 week ago
Activity icon

Replied to Help With $this->actingAs($user)->post(...);

@sergiu17 I'm amazed you've watched 1,521 videos. One thousand, five-hundred and twenty-one videos!

Thought I was doin' ok at at 396...

Thank you ~

Activity icon

Replied to Help With $this->actingAs($user)->post(...);

that's simply amazing @sergiu17 ; I'm always over complicating things.

Route::post('/dashboard/companies', '[email protected]'); so, that's where all the magic comes from?

Activity icon

Replied to Help With $this->actingAs($user)->post(...);

hi, thank you.

tried that, your solution works! $this->get('dashboard') ->assertSee('BidBird');

When I try the $company->companyname it gives: ErrorException: Undefined variable: company This is without the temporary $company.

So, when we state a post route does the test know we're creating a company simply from the Routes/web.php?

Is it necessary to test with the company factory in scenarios like this?

Activity icon

Started a new Conversation Help With $this->actingAs($user)->post(...);

Alright, very close, but I find if I create a factory (with faker data) that handles all the fields the array second argument gets upset. A number of my other tests pass with the array data, but I'm not sure what's wrong with this scenario...

Really, there's no need to pass the second argument as the factory is creating everything, but I don't know how to handle that. I believe I have to use the post() in order for the database to store a company name, e.g. That's why the test failsfrom what I gather.

/** @test */
    public function user_can_add_a_company_to_their_profile()
    {
//        $this->withoutExceptionHandling();
        $user = factory(User::class)->create();
        $company = factory(Company::class)->create();

        $companyname = [
        'companyname' => 'BidBird'
        ];
//        dd($company->companyname);
//        $this->actingAs($user)
//            ->post('/dashboard/companies', $companyname);

        $this->actingAs($user)
            ->post('/dashboard/companies', [
                'companyname' => 'BidBird'
            ]);
//            ->assertRedirect('/dashboard')
//            ->assertStatus(200);

        $response = $this->get('/dashboard');
        $response->assertStatus(200);
        $response->assertViewIs('dashboard');
//        dd($company->companyname);
        $response->assertSee($company->companyname);
    }

gives the error: fails to assert .... </body>\n \n </html>\n ' contains "accusamus". so, clearly, $companyname is not posting. The faker accusamus is making it to the end.

When a test requires a post how to you $this->actingAs($user) ->post(...);

Thank you for any tips ~

Nov
29
1 week ago
Activity icon

Replied to Method `unique` Not Found In Illuminate\Support\Fluent

Great post, thank you.

Here's an interesting line to remember foreign key couple unicity.

In this case, I'm picturing users will work for a construction outfit and a few years later may go somewhere else/get fired, so I believe the many-to-many is ok.

Could also provide an opportunity for "power bidders" who after so many successful bids can be promoted to help other contractors, as a consultant, etc...Their profile could list the other companies they bidded for...

We'll see. I get lost in creative-land.

Thank you again!

Nov
28
1 week ago
Activity icon

Replied to Method `unique` Not Found In Illuminate\Support\Fluent

I'm telling you @drgreen so many little nuances. And you only find them in the trenches!!

Curious, on a pivot table are autoincrement id's necessary? In this particular case I don't believe it would make sense for a person to have multiple records with the company.

Primary Key is a unique key identifier for the row/record. So, you don't need to specify it to be unique as the primary itself is unique.

Does the Primary Key approach prevent duplicate rows?

Or does this just boil down to preference?

...

spent some more time here EDIT

The Primary Key does prevent duplicate entry:

Duplicate entry '20-2' for key 'PRIMARY'

Activity icon

Started a new Conversation Method `unique` Not Found In Illuminate\Support\Fluent

https://laracasts.com/series/laravel-6-from-scratch/episodes/31

Just watched the new vid above, and am looking again at a pivot table I created a while ago:

// My original approach
            $table->primary(['company_id', 'user_id']);

// the new video recommends this (in this scenario):
            $table->unique(['company_id', 'user_id']);
// I tried this:
    $table->primary(['company_id', 'user_id'])->unique();

but it yields this error in phpstorm Method 'unique' not found in Illuminate\Support\Fluent

What is the best solution for having a unique pivot relationship? Is the primary key designation useless in this scenario?

Nov
27
1 week ago
Activity icon

Replied to Implementing A User Interface For Roles & Permissions

Ok, so a form like:

//form code
<div class="form-group">
            
// backend code checks for email
    <input type="email" placeholder="email"> 

    <label for="companyrole">Company Role</label>
    <select class="form-control" id="companyrole">
        <option value="CEO">CEO</option>
        <option value="Employee">Employee</option>
    </select>

    <label for="companypermissions">Company Permissions</label>
    <select class="form-control" id="companypermissions">
        <option value="Can view all financials">Can view all financials</option>
        <option value="Can bid">Can bid</option>
    </select>

    <button id="submit" type="submit">Add role/permissions</button>-
</div>

In this case above, the check on email...it seems like the person should have to accept if their email isn't from the same domain?

Activity icon

Replied to Implementing A User Interface For Roles & Permissions

sorry I missed your post, @jlrdw

Mainly, I'm interested in the user interface. e.g. what's it look like to add a role, permission?

Activity icon

Started a new Conversation Implementing A User Interface For Roles & Permissions

https://laracasts.com/series/whats-new-in-laravel-5-1/episodes/16

I've got a decent handle on creating the tables, etc. However, how have you solved this issue?

The goal on the dashboard is for an admin to be able to add a user to a role/permission. e.g. on this site a company owner may want to have 3 employees be able to bid on jobs. I want the owner to have control; if a user is fired or leaves the company the owner/admin can delete their roles/permission on that company without the website admin from having to do all this tedious work.

If a user is a member of the site does the admin type an email and then this is saved to the roles/permissions table? Then do you display these company users to the company admin? Like a looped list.

The dashboard currently has an invitation form which allows an existing user to invite others (there's a method which checks if an email already exists); it seems like this should stay vanilla and then only someone who is a user can be added for Roles & Permissions.

Trying to wrap my head around this problem.

Nov
18
3 weeks ago
Activity icon

Replied to Footer Contact Form

good morning @cronix

Ahh, never saw the first url part before. I've used the name() plenty of times. Great tip.

Thank you!

Nov
17
3 weeks ago
Activity icon

Replied to Footer Contact Form

@snapey

Route::post('contact', ['url' => 'contact', 'uses' => '[email protected]'])->name('contact.post');

Why is this working?

Does the ['url' => 'contact' .. line act as a wildcard for any page on the site?

Just implemented this on my own site, and it's fab.

Nov
16
3 weeks ago
Activity icon

Replied to 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))
Activity icon

Replied to Why Is Link To Page Section /#footer Not Linking?

A friend suggested a doing a javascript function to make it scroll smooth. I saw a few examples on stack that seemed a bit lengthy.

html, body {
...
scroll-behavior: smooth;
...
}

That did a pretty nice job, for just one line.

Nov
15
3 weeks ago
Activity icon

Replied to Why Is Link To Page Section /#footer Not Linking?

@snapey does it again!!!

Thank you, this was actually hard to search for.

Activity icon

Started a new Conversation Why Is Link To Page Section /#footer Not Linking?

The laravel.com site allows you to link to sections of the docs. I'd like to implement that exact feature.

// link on navbar

        <div class="email">
            <a href="#footer" >Contact Us</a>
        </div>
// footer.blade.php

    <div class="contactinfo">
        <a href="#footer"><h2>Contact BidBird</h2></a>
...
    </div>

Trying the above but nothing goes. I saw a post here on laracasts that mentioned bootstrap can get in the way of this, but had no further explanation.

Nov
09
1 month ago
Activity icon

Replied to Upgrading From 5.7: UnsignedbigInteger And Migrations

haha, 4B users, that'd be nice!!

It's the first column I grabbed. At the moment, I can't remember which column it was specifically but that integer no longer worked properly, maybe it was a foreign key reference or something like that.

Thank you, just wanted to check with someone about data integrity before I made that change.

Activity icon

Started a new Conversation Upgrading From 5.7: UnsignedbigInteger And Migrations

$table->unsignedInteger('user_id'); to $table->unsignedBigInteger('user_id');

https://laravel.com/docs/5.8/migrations#modifying-columns this has a warning:

Only the following column types can be "changed": bigInteger, binary, boolean, date, dateTime, dateTimeTz, decimal, integer, json, longText, mediumText, smallInteger, string, text, time, unsignedBigInteger, unsignedInteger and unsignedSmallInteger.

so is this how you'd do the above?

    $table->unsignedInteger('user_id', unsignedBigInteger)->change();
});

Will this lose the existing 'user_id' records?

Nov
02
1 month ago
Activity icon

Replied to {{ $loop->iteration }} As 'A' In Blade

That's pretty awesome. If it hits 26 bidders, I'll be happy to fix that bug!!

But I did go deeper in, and see @nakov could be used here. Both approaches are somewhat limitedmanually adding up to a 100 keys e.g. is not what I was hoping for.

Using PHP's A++ would be ideal.

So, I took a look at this file:

<?php

namespace Illuminate\View\Concerns;

use Countable;
use Illuminate\Support\Arr;

trait ManagesLoops
{
    /**
     * The stack of in-progress loops.
     *
     * @var array
     */
    protected $loopsStack = [];

    /**
     * Add new loop to the stack.
     *
     * @param  \Countable|array  $data
     * @return void
     */
    public function addLoop($data)
    {
        $length = is_array($data) || $data instanceof Countable ? count($data) : null;

        $parent = Arr::last($this->loopsStack);

        $this->loopsStack[] = [
           //'iteration' => 0,
           //'index' => 0,
            'letter' => 'A',
           //'remaining' => $length ?? null,
           // 'count' => $length,
           //'first' => true,
           //'last' => isset($length) ? $length == 1 : null,
           //'odd' => false,
           //'even' => true,
           //'depth' => count($this->loopsStack) + 1,
           //'parent' => $parent ? (object) $parent : null,
        ];
    }

    /**
     * Increment the top loop's indices.
     *
     * @return void
     */
    public function incrementLoopIndices()
    {
        $loop = $this->loopsStack[$index = count($this->loopsStack) - 1];

        $this->loopsStack[$index] = array_merge($this->loopsStack[$index], [
            //'iteration' => $loop['iteration'] + 1,
            'letter' => $loop['iteration'] + 1,
            //'index' => $loop['iteration'],
            //'first' => $loop['iteration'] == 0,
            //'odd' => ! $loop['odd'],
            //'even' => ! $loop['even'],
            //'remaining' => isset($loop['count']) ? $loop['remaining'] - 1 : null,
            //'last' => isset($loop['count']) ? $loop['iteration'] == $loop['count'] - 1 : null,
        ]);
    }

    /**
     * Pop a loop from the top of the loop stack.
     *
     * @return void
     */
    public function popLoop()
    {
        array_pop($this->loopsStack);
    }

    /**
     * Get an instance of the last loop in the stack.
     *
     * @return \stdClass|null
     */
    public function getLastLoop()
    {
        if ($last = Arr::last($this->loopsStack)) {
            return (object) $last;
        }
    }

    /**
     * Get the entire loop stack.
     *
     * @return array
     */
    public function getLoopStack()
    {
        return $this->loopsStack;
    }
}

It gives this error: A non-numeric value encountered I was thinking if we can get the index to increment as a String it'd be worth putting in a PR on github.

Here's the latest one I saw: https://github.com/laravel/framework/pull/27883/commits/c443c83c11a3ba93867e7fa0a2b31af026032a59

Wouldn't {{ $loop->letter }} be awesome?

Activity icon

Replied to {{ $loop->iteration }} As 'A' In Blade

Yea, I was going through that and wanted to increment 1 as 'A', 2 as 'B', etc.

From what I know loops start at e.g. $variable[0]

Have been trying this afternoon to loop variables and then display them as Bidder A, Bidder B, Bidder C, etc. The $loop->iteration was so clean in blade, it'd be neat if there was an increment on string version.

Activity icon

Started a new Conversation {{ $loop->iteration }} As 'A' In Blade

If you wanted to achieve this in a blade file how would you do it?

{{ $loop->iteration['A'] }}
Oct
29
1 month ago
Activity icon

Replied to __construct() Must Be Of The Type Int, Array Given (html Number To Integer)

ok @octoquad your notes on the redirect were right. I found the index showed a loop and it returns to a paginated collection of jobs, not exactly what I was hoping for.

The jobfull gave: Route [jobs.jobfull] not defined. In this case jobfull is the "blowup or detail" page of a job. I think this is the right way to do this, essentially a collection of jobs to look at snippets, thumbnails and then go to a detail or jobfull page...

So, then I tried this:

return redirect(route('jobs.show', $job->id));

That solved the issue, without using back();

@snapey I'll be sure to not use a return view on page data (e.g. adding a bid to a job).

Thank you both for helping on this. So happy laracasts is here.

Activity icon

Replied to __construct() Must Be Of The Type Int, Array Given (html Number To Integer)

@snapey I know! I wish there was a 50/50 solution.

Decided to leave the added (int) for good measure, but what lifted the error had to do with the redirect (which you noted in general). The error is a bit misleading, as I thought it was about converting the number to int.

Do you know why return back(); fixes this?

Oct
27
1 month ago
Activity icon

Replied to __construct() Must Be Of The Type Int, Array Given (html Number To Integer)

whoops, well here's what the issue was::::

return redirect('jobs.jobfull', compact('bid'));

after another search, this led me on a better track: https://laracasts.com/discuss/channels/laravel/symfony-component-debug-exception-fatalthrowableerror-e-recoverable-error-argument-2-passed-to-symfonycomponenthttpfoundationredirectresponse-construct-must-be-of-the-type-int-array-given-called-in-cxampphtdocskeyvendorlaravelframeworksrcilluminaterouting?page=1

So, I left the type $casts to integer on the model.

    public function store(Job $job)
    {
        $this->validate(request(), [
            'bid' => 'required|integer|min:2'
        ]);

        // add bid to job
        $bid = auth()->user()->bids()->create([
            'bid' => (int) request('bid'),
            'job_id' => $job->id
            ]);

        return back();
    }
Activity icon

Started a new Conversation __construct() Must Be Of The Type Int, Array Given (html Number To Integer)

Have been trying to get a html <input type="number" to be stored as an integer. (for money stored as cents)

https://laracasts.com/discuss/channels/laravel/how-to-convert-my-input-to-integer this post shows a number of techniques. I tried type casting in the model.

/**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'bid' => 'integer',
    ];

This generates the array given error. However, when it's commented out, the error still persists.

Argument 2 passed to Symfony\Component\HttpFoundation\RedirectResponse::__construct() must be of the type int, array given

here's the full error, I found a post on github about trust proxies, but the version I have includes that (5.8). protected $headers = Request::HEADER_X_FORWARDED_ALL;

I gave this below a shot, but it too gives the error.

 public function store(Job $job)
    {
        $this->validate(request(), [
            'bid' => 'required|integer|min:2'
        ]);

        $bid = (int) request('bid');

        // add bid to job
        $bid = auth()->user()->bids()->create([
            'bid' => $bid,
            'job_id' => $job->id
            ]);
...

It seems like such a basic thing but I must have something out of skew.

How have you solved this?

Oct
25
1 month ago
Activity icon

Replied to Spatie Medialibrary: How To Show 1st Thumbnail For Each $job. (3 Jobs In Collection)

ah yea, I see that returns the collection, whereas hasMedia() returns the bool. I found pulling the $job from the $thumbnails collection is not allowed. Method Illuminate\Database\Eloquent\Collection::getUrl

<img class="fda" src="{{ $thumbnails->first()->getUrl('thumbnail') }}">

It seems like the loop in the blade is most effective way to pull the $job from the collection. Is that true? got to be a cleaner way...

I think the major issue is the paginated $jobs??

Activity icon

Replied to Spatie Medialibrary: How To Show 1st Thumbnail For Each $job. (3 Jobs In Collection)

ahh... this works:

@if ($job->hasMedia('document'))
    <img class="jobthumbnail" src="{{ $job->getMedia('document')->first()->getUrl('thumbnail') }}">
@else
    <em>Sorry, this job does not have any pics. Check out details for more info.</em>
@endif

But is this the most elegant solution?

Activity icon

Replied to Spatie Medialibrary: How To Show 1st Thumbnail For Each $job. (3 Jobs In Collection)

@sinnbeck yea, that one returns:

Method Illuminate\Database\Eloquent\Collection::getMedia does not exist.

https://github.com/spatie/laravel-medialibrary/issues/1531

Even tried tagging the ->getMedia('thumbnail'); on the pagination, but it's not available on the collection.

I've given this some thought, if the index.blade loops $jobs as $job then something like this should work in the blade, right? .. but it doesn't

@if ($job->hasMedia('thumbnail'))
    <img class="jobthumbnail" src="{{ $job->first()->getUrl('thumbnail') }}">
@else
    <em>Sorry, this job does not have any pics. Check out details for more info.</em>
@endif
Activity icon

Replied to Spatie Medialibrary: How To Show 1st Thumbnail For Each $job. (3 Jobs In Collection)

Thank you, @sinnbeck Have given this a shot. It returns bool.

Collection {#625 ▼
  #items: array:3 [▼
    0 => true
    1 => true
    2 => true
  ]
}

It seems like the view needs to pluck or slice a member of the collection ... researching that now.

Oct
24
1 month ago
Activity icon

Started a new Conversation Spatie Medialibrary: How To Show 1st Thumbnail For Each $job. (3 Jobs In Collection)

Hi, pleased to say I've implemented the Spatie media library and it's working well.

However, I've noticed on the jobs.index page where there are 3 paginated jobs the first thumbnail in the collection shows upnot the thumbnail for each job.

//controller
index() {
...

        $jobs = Job::bidded($request->bidded)
            ->state($request->state)
            ->city($request->city)
            ->biddertype($request->biddertype)
            ->job($request->job)
            ->subjob($request->subjob)
            ->paginate(3)
            ->appends([
                   'bidded' => request('bidded'),
                   'state' => request('state'),
                   'city' => request('city'),
                   'biddertype' => request('biddertype'),
                   'job' => request('job'),
                   'subjob' => request('subjob')
            ]);

...
// $jobs has an array of 3 jobs, as expected
    $thumbnails = $jobs->hasMedia('document');

    return view('jobs.index', compact('jobs', 'thumbnails'))
}

The $thumbnails variable outputs: Illuminate\Database\Eloquent\Collection::hasMedia does not exist.

Is this because eloquent returns a collection, and hasMedia() returns a collection? The hasmediatrait has been installed on job, etc.

In the index view:

        @if ($jobs->count() > 0)
            @foreach ($jobs as $job) 
                    @include ('jobs.job')
                @endforeach
         @else
...
//jobs.job view (is like a preview page of jobs)

    <div class="jobthumbnail">
        @if ($thumbnails->count() > 0)
                <img class="jobthumbnail" src="{{ $thumbnails->first()->getUrl('thumbnail') }}">
        @else
            <em>Sorry, this job does not have any pics. Check out details for more info.</em>
        @endif
    </div>

I understand what's basically going on, $thumbnails has asked for the 1st 'thumbnail' for the 1st job in the collection of 3 and repeats it for each job.

How do you distinguish in the loop $jobs[0], $jobs[1], $jobs[2]

Oct
19
1 month ago
Activity icon

Replied to How Do You Instantiate Variables In An Event Based Markdown Mail?

ok, thank you. That's one area I'm still foggy on. $this

dd($job) in the complete() method; gives 8 so the id of the current bidder (in the local dev context). No bueno.

I realized, the complete method was missing $user!

you are amazing. Thank you again! Going to update a few of these posts which are related to this...nightmare I've been having.

Oct
18
1 month ago
Activity icon

Replied to How Do You Instantiate Variables In An Event Based Markdown Mail?

Hi @snapey , getting back to this. Got 44 tests together, but this one is not passing, still.

I've been trying to figure out the way to make the setup in the controller available in the complete() method. Can you simply add more arguments? Like so? Maybe I'm missing something.

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

The $job->id gives this error: Trying to get property 'id' of non-object. So this seems like the job is not being passed.

    public function complete($paymentGateway, $stripeToken, $job, $bidReserve)
    {
        $charge = $paymentGateway->charge($this->bidReserveAmount(), $stripeToken);
        $orderSetup = Order::forBidReserves($this->job->bidReserves(), $this->userId(), $charge);

        $order = DB::transaction(function () use($orderSetup, $job, $bidReserve) {

                    DB::table('bidreserves')
                        ->where([
                            ['job_id', $job->id],
                            ['created_at', $bidReserve->created_at]
                        ])
                        ->update(array('order_id' => $orderSetup->id));
                });

        return $order;
    }
Oct
14
1 month ago
Activity icon

Replied to AssertContains() Url: Testing Best Practice

@bobbybouwmann , thank you. Never thought of using a regex!

finally feel like i'm getting to the finer parts of programming.. instead of just basic functionality.

phpunit was upset, so adding double quotes allowed this to pass . vs. single quotes. $url = "http://bidbird.test/invitations/{$mail->invitation->invitation_code}";

Oct
12
1 month ago
Activity icon

Started a new Conversation AssertContains() Url: Testing Best Practice

Hi,

Have a test for emails that works. However, before I added the string url I was getting this error: Failed asserting that 'TESTCODE1234' contains "http://bidbird.test/invitations/TESTCODE1234".

How would you improve the url comparison for elegance?

/** @test
     *
     */
    public function email_contains_a_link_to_accept_the_invitation()
    {
test stuff...
            $this->assertContains(url('/invitations/TESTCODE1234'), "http://bidbird.test/invitations/{$mail->invitation->invitation_code}");
            
            return true;
        });
    }
Activity icon

Replied to How Do You Instantiate Variables In An Event Based Markdown Mail?

Ok, well, at least I got this far! @snapey

here's the bidreserve->complete():

// as posted...
    public function complete($paymentGateway, $stripeToken)
    {
        $charge = $paymentGateway->charge($this->bidReserveAmount(), $stripeToken);

        return Order::forBidReserves($this->job->bidReserves(), $this->userId(), $charge);
    }

I'd like the controller to say something like $order = $bidReserve->complete($this->paymentGateway, request('stripeToken'), auth()->user()->id)->updateBidReservesTable();

Would you recommend that type of approach? I'm not sure how to get those variables which are setup in the controller into this method...

// BidReserve.php
...
    public function updateBidReservesTable()
    {
        DB::transaction(function () use($order, $job, $bidReserve) {

            DB::table('bidreserves')
                ->where([
                    ['job_id', $job->id],
                    ['created_at', $bidReserve->created_at]
                ])
                ->update(array('order_id' => $order->id));
        });

    }

gave the above a shot, but it seems like the $job, $bidReserve should be available via the container somehow.

    public function complete($paymentGateway, $stripeToken)
    {
        $charge = $paymentGateway->charge($this->bidReserveAmount(), $stripeToken);
        $orderSetup = Order::forBidReserves($this->job->bidReserves(), $this->userId(), $charge);

        $order = DB::transaction(function () use($orderSetup, $this->job, $this->bidReserve) {

                    DB::table('bidreserves')
                        ->where([
                            ['job_id', $job->id],
                            ['created_at', $bidReserve->created_at]
                        ])
                        ->update(array('order_id' => $order->id));
                });

        return $order;
    }

The above isn't working but I feel it may be a bit better (overall) than the previous approach.

Oct
11
1 month ago
Activity icon

Replied to How Do You Instantiate Variables In An Event Based Markdown Mail?

@snapey

Sorry, just saw you responded.

Yea, that's the bidreserve. All I can think is that the update does not occur in time for the mailable to catch it and utilize the relationship.

How would you delay the update so the mailable can use it? Can't update the bidreserve till the order is created...

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store($jobId)
    {

        $job = Job::Incomplete()->findOrFail($jobId);

        $this->validate(request(), [
            'amount' => ['required', 'integer', 'min:1'],
            'stripeToken' => ['required']
        ]);

        // Charging the customer
        try {
            $bidReserve = $job->bidReserves()->create([
                'amount' => request('amount'),
                'job_id' => $jobId,
            ]);

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

            DB::transaction(function () use($order, $job, $bidReserve) {

                DB::table('bidreserves')
                    ->where([
                        ['job_id', $job->id],
                        ['created_at', $bidReserve->created_at]
                    ])
                    ->update(array('order_id' => $order->id));
            });

            return back()
                ->setStatusCode(201);

        } catch (PaymentFailedException $e) {

            return back()
                ->setStatusCode(422);
        }
    }
Oct
06
2 months ago
Activity icon

Replied to How Do You Instantiate Variables In An Event Based Markdown Mail?

Hi @snapey

My test keeps saying: ErrorException: Trying to get property of non-object

This mailable action only fails if trying to access data through the pivot table. e.g. dd($order->bidReserve->job->jobtitle);

id  job_id order_id amount    created_at                 updated_at
333   3     NULL    500       2019-10-06 21:08:34       2019-10-06 21:08:34

If it's changed to dd($order); It gives the proper data in my test:

  #original: array:7 [
    "amount" => 500
    "user_id" => 1
    "confirmation_number" => "ORDERCONFIRMATION1234"
    "card_last_four" => "1234"
    "updated_at" => "2019-10-07 01:03:55"
    "created_at" => "2019-10-07 01:03:55"
    "id" => 1
  ]

I've tried all your concepts above, even with hasOneThrough, hasManyThrough to no avail.

It seems like the pivot table bidreserves is causing issues. Is it a naming issue? e.g. it's not jobs_orders There is this in the BidReserve model: public $table = "bidreserves";

Basically, the orders table tallies amount and is linked to a user. The BidReserves table has the order_id. Should these relations be hasMany? to utilize pivot tables?

This is in the docs: return $this->belongsToMany('App\Role')->withPivot('column1', 'column2'); was not sure if this applies to this situation.

Any ideas?

Oct
02
2 months ago
Activity icon

Replied to How Do You Instantiate Variables In An Event Based Markdown Mail?

@snapey

After much trial and error I've settled on using OrderPlaced event as I think it more accurately describes what happened. A BidReserve or a Bid make up orders. So I think having a Bid or BidReserve event is not really accurate.

Does that seem legit?

So, I've finally come across a major issue, which your quote explains

Model created --> Event fires --> Listener catches --> mailable generated

My issue is not instantiating variables for a markdown mail but accessing a pivot table from the order.

class CreateOrdersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->string('confirmation_number');
            $table->integer('amount');
            $table->string('card_last_four');
            $table->timestamps();
        });
    }
class CreateBidReservesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('bidreserves', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('job_id');
            $table->unsignedBigInteger('order_id')->nullable();
            $table->foreign('job_id')->references('id')->on('jobs');
            $table->bigInteger('amount');
            $table->timestamps();
        });
    }

It seems like $order->bidReserve->job->jobtitle would work, but it does not. It gives: Trying to get property 'job' of non-object

I gave this a go in the Order.php model. Where's this going wrong?

    public function bidReserve()
    {
        return $this->belongsTo(BidReserve::class)->wherePivot('job_id', 'order_id');
    }
Sep
29
2 months ago
Activity icon

Started a new Conversation Best Way To Send An Order Mailable

From many examples I have found on the web, it's best to use the user_id in an orders table and utilize a pivot table. e.g. for the contents of the order itself.

If you have events in your app, say JobPosted, BidReservePlaced these two fire an event that is associated with an order, money is charged, and hopefully a mailable sent to document the order.

How would you structure the order mailable? There are many possible items that could be in an order.

class CreateOrdersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->string('confirmation_number');
            $table->integer('amount');
            $table->string('card_last_four');
            $table->timestamps();
        });
    }

Below is a pivot table.

class CreateBidReservesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('bidreserves', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('job_id');
            $table->unsignedBigInteger('order_id')->nullable();
            $table->foreign('job_id')->references('id')->on('jobs');
            $table->bigInteger('amount');
            $table->timestamps();
        });
    }

Should the order have many events dispatched? Or should only Job or BidReserve have the dispatch?

in short, who should tell whom what to do?

class Order extends Model
{
....
    protected $dispatchesEvents = [
        'created' => BidReservePlaced::class
    ];

    protected $dispatchesEvents = [
        'created' => JobPosted::class
    ];
....

I'm basing this strategy on the video: https://laracasts.com/series/laravel-from-scratch-2018/episodes/32

another thought I've had is to send the order mail in the controller, after a successful charge.

Sep
24
2 months ago
Activity icon

Replied to How Do You Instantiate Variables In An Event Based Markdown Mail?

@snapey

Yea, that's partly why it's been so frustrating.

The docs say here using the with() method you can assign e.g. $jobTitle. At least, how I read it and then it's available in the view. Order is available and effective, passes the the tests, etc, if I comment out the job.

https://laravel.com/docs/5.8/mail#view-data

Isn't the constructor for instantiating? when you say nothing else what would you do in a situation like that?

Activity icon

Replied to How Do You Instantiate Variables In An Event Based Markdown Mail?

@snapey

Ahh man. Criminy. So, just add the public properties in the event!

Do you personally add them in both places (event and mailable)? I was referring to the docs where it's shown in the mailable with no reference to the event itself.

Do you find that confusing?

Activity icon

Replied to How Do You Instantiate Variables In An Event Based Markdown Mail?

good morning, thank you for checking this out. Just been driving me crazy...

here's the error:

Too few arguments to function App\Listeners\SendOrderPlacedNotification::handle(), 1 passed and exactly 2 expected
//event
class OrderPlaced
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * The order instance.
     *
     * @var Order $order
     */
    public $order;


    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }
class OrderPlacedMail extends Mailable
{
    use Queueable, SerializesModels;


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

    /**
     * The order instance.
     *
     * @var Order $order
     */
    public $order;

    /**
     * Create a new message instance.
     *
     * @param Job $job
     * @param object $order
     * @return void
     */
    public function __construct($order, $job)
    {
        $this->order = $order;
        $this->job = $job;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.order-confirmation-email')
                    ->subject("Your BidBird Order")
                    ->with([
                        'jobTitle' => $this->job->jobtitle,
                        'orderConfirmation_number' => $this->order->confirmation_number
                    ]);

    }
class SendOrderPlacedNotification implements ShouldQueue
{

    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //

    }

    /**
     * Handle the event.
     *
     * @param Job $jobTitle
     * @param  object  $event
     * @return void
     */
    public function handle(OrderPlaced $event, $jobTitle)
    {
        Mail::to($event->order->user->email)->send(
            new OrderPlacedMail($event->order, $jobTitle)
        );
    }
class Order extends Model
{
    // private $job;
    //    private $confirmation_number;
    protected $guarded = [];

    protected $dispatchesEvents = [
        'created' => OrderPlaced::class
    ];


    // belongsTo

    public function job()
    {
        return $this->belongsTo(Job::class);
    }
Sep
23
2 months ago
Activity icon

Started a new Conversation How Do You Instantiate Variables In An Event Based Markdown Mail?

Hi,

I've been banging up against a wall.

When reviewing this section of the docs: https://laravel.com/docs/5.8/mail#view-data

It appears you can import the class, set a public property, call $this->order = $order and voila! now you have the event based order available in the markdown mail.

https://laracasts.com/series/laravel-from-scratch-2018/episodes/32 That video shows a great technique of tucking the mail::to function in the notificationhandle().

however, no matter what I do, if I try to add job to the mailable (in addition to $order) I get these errors saying in the notification handle(), we expected 2 but got 1.

job is not a column in the orders table, it holds the user_id which then goes to a pivot table with job_id, order_id.

Thank you ~

Sep
21
2 months ago
Activity icon

Replied to Pivot Tables And Markdown Mailables - Accessing The Data

Do event based mailables only allow for the model event? This seems like it's much harder than it probably is. https://laracasts.com/series/laravel-from-scratch-2018/episodes/32 this video only made available one model in the mailable.

    public function build()
    {
        return $this->markdown('emails.order-confirmation-email')
                    ->subject("Your BidBird Order")
                    ->with([
                        'jobTitle' => $this->order->user->job->jobtitle,
            // 'jobTitle' => $this->order->pivot->job->jobtitle,
                        'orderConfirmation_number' => $this->order->confirmation_number
                    ]);

The orders table only has the user_id, the other table has the job_id, order_id pivot relationship.

The goal is simply to show $job-jobtitle in the header of the $order mail.

Sep
17
2 months ago
Activity icon

Replied to Pivot Tables And Markdown Mailables - Accessing The Data

Hi anyone, I've found a few more posts, but this d... thing won't go. https://github.com/laravel/framework/issues/18597 https://laracasts.com/discuss/channels/laravel/use-variables-inside-the-markdown-mailables

Right now, this is how the few files look. How do you make the $job available?

// Here's the mail component, I've added the addition $job->jobtitle variable (not sure if it should just be $job, //but it does not seem to matter, as it fails on the handle() method of the notification
@component('mail::message', ['job' => $job->jobtitle])
# Order confirmation: {{ $job->jobtitle }}

We appreciate your interest in this job posting.

@component('mail::button', ['url' => '/orders/' . $order->id . '/' . $order->confirmation_number])
View job now
@endcomponent

Thank you,<br>
{{ config('app.name') }}
@endcomponent
Too few arguments to function App\Listeners\SendOrderPlacedNotification::handle(), 1 passed and exactly 2 expected
    /**
     * Handle the event.
     *
     * @param Job $job
     * @param  object  $event
     * @return void
     */
    public function handle(OrderPlaced $event, $job)
    {
        //
//            dd($event);
//        $job = array('job' => $job);
        Mail::to($event->order->user->email)->send(
            new OrderPlacedMail($event->order, $job)
        );
    }

dd($event); does give me the order but job never is made available:

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


    /**
     * The order instance.
     *
     * @var Order $order
     */
    public $order;

    /**
     * Create a new message instance.
     *
     * @param Job $job
     * @param Order $order
     * @return void
     */
    public function __construct($order, $job)
    {
        $this->order = $order;
        $this->job = $job->toArray();
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.order-confirmation-email')
            ->subject("Your BidBird Order")
            ->with([
                'job' => $this->job,
                'orderConfirmation_number' => $this->order->confirmation_number
            ]);

It seems like I've tried just about every variation. But $job never makes it to the handle method.

Is it possible to include two models on a markdown mail?

Sep
16
2 months ago
Activity icon

Replied to Pivot Tables And Markdown Mailables - Accessing The Data

The other day (above) I was able to access $this->question->job->jobtitle. It seems like this is two levels deep, and was able to access the both models.

However, in this code for a different email, it goes three levels deep and I'm unable to access the job->jobtitle. I'm baffled why the constructor does not allow for multiple models. Is this controller issue? https://laravel.com/docs/5.8/mail#sending-mail I read, that a public $variable in the mailable class makes it available in the markdown mail.

How do you pass multiple models to a markdown mail?

@component('mail::message')
# Order confirmation: {{ $order->user->bidreserve->job->jobtitle }}

We appreciate your order for this job posting.

@component('mail::button', ['url' => '/orders/' . $order->id . '/' . $order->confirmation_number])
View job now
@endcomponent

Thank you,<br>
{{ config('app.name') }}
@endcomponent