trevorpan

trevorpan

Member Since 1 Year Ago

Experience Points
39,700
Total
Experience

300 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
368
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 8
39,700 XP
21 Sep
1 day ago

trevorpan left a reply on 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.

17 Sep
5 days ago

trevorpan left a reply on 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?

16 Sep
6 days ago

trevorpan left a reply on 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
15 Sep
1 week ago

trevorpan left a reply on Pivot Tables And Markdown Mailables - Accessing The Data

Well, after thinking about this for most of the afternoon I remembered the eloquent relationships.

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.question-asked')
                    ->with([
                        'jobJobtitle' => $this->question->job->jobtitle,
                        'question' => $this->question
                    ]);
    }

So, removing one model from the constructor allowed the job to be accessed via the$question. While this works, is it hacky?

Is this a solid solution?

Thank you for any ideas.

trevorpan left a reply on Pivot Tables And Markdown Mailables - Accessing The Data

Hi, thank you! @sergiu17 here is how it is now

class SendQuestionAskedNotification implements ShouldQueue
{

    /**
     * Handle the event.
     *
     * @param  Job  $job
     * @param  QuestionAsked  $event
     * @return void
     */
    public function handle(QuestionAsked $event)
    {
        //
        Mail::to($event->question->user->email)->send(
            new QuestionAskedMail($event->question)
        );
    }

After adding the $job like this:

    /**
     * Handle the event.
     *
     * @param  Job  $job
     * @param  QuestionAsked  $event
     * @return void
     */
    public function handle(QuestionAsked $event, Job $job)
    {
        //
        Mail::to($event->question->user->email)->send(
            new QuestionAskedMail($event->question, $job)
        );
    }
Too few arguments to function App\Listeners\SendQuestionAskedNotification::handle(), 1 passed and exactly 2 expected

Tried wrapping it in an array, too. Been at this one for a bit...

Gave this a go...https://stackoverflow.com/questions/46453381/laravel-mail-multiple-variables

Same thing. My line looks like:

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.question-asked', ['job' => $this->job, 'question' => $this->question]);
    }

Tried adding a ->with() here. no dice.

    public function build()
    {
        return $this->markdown('emails.question-asked')
                    ->with([
                        'jobJobtitle' => $this->job->jobtitle,
                        'question' => $this->question
                    ]);
    }

trevorpan started a new conversation Pivot Tables And Markdown Mailables - Accessing The Data

The docs: https://laravel.com/docs/5.8/mail#view-data state any public variable will be made available in the markdown mail. In this case, a question is like a comment on a post.

I'm receiving an error:

Too few arguments to function App\Mail\QuestionAskedMail::__construct(), 1 passed in /Users/trevorpan/code/bidbird/app/Listeners/SendQuestionAskedNotification.php on line 33 and exactly 2 expected

Am I doing something wrong that would not allow the constructor to execute?

<?php

namespace App\Mail;

use App\Job;
use App\Question;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;

class QuestionAskedMail extends Mailable
{
    use Queueable, SerializesModels;

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

    /**
     * The question instance.
     *
     * @var Question
     */
    public $question;


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

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.question-asked');
    }
}
14 Sep
1 week ago

trevorpan left a reply on Event Listener Tries To Find "old" File Name After Renaming

shoot, after all those things: https://stackoverflow.com/questions/25237415/php-artisan-migratereset-failed-to-open-stream-no-such-file-or-directory

composer dump-autoload allowed me to get past this issue.

Why does that command work but the config:clear and cache:clear don't?

trevorpan started a new conversation Event Listener Tries To Find "old" File Name After Renaming

/app/Listeners/__SendQuestionAskedNotification.php): failed to open stream: No such file or directory

This has got me stumped.

I temporarily renamed the file to suppress errors and now it's trying to find the "old" name which was prefixed __SendQuestionAskedNotification.php

the Question model uses the proper event dispatch. I've searched the whole directory for that prefix, nothing shows up.

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

tried this: https://laracasts.com/discuss/channels/laravel/laravel-failed-to-open-stream-no-such-file-in-directory-1

php artisan config:clear and php artisan cache:clear it still yields the same error. I even remade an new SendQuestionAskedNotification.php listener, and the same error occurs.

13 Sep
1 week ago

trevorpan started a new conversation Can You Suggest A Proper Response At Endpoint For Stripe Charges?

Hi,

Have been working on this payment gateway for some time, and finally have it working!!!

However, when the payment goes through, the website goes away and this is the response I'm getting (on a black screen).

user_id 1
confirmation_number "84HLU8UAZ4SJTUA5DULZMHUE"
amount  500
card_last_four  "4242"

The controller:

   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' => 500,
                'job_id' => $jobId,
            ]);

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

            DB::transaction(function () use($order) {
                DB::table('bidreserves')->update(['order_id' => $order->id]);
            });

            Mail::to($order->user->email)->send(new OrderConfirmationMail($order));

            return response()->json($order, 201);
//            return view('jobs.jobfull', compact('order', 'job', 201));

        } catch (PaymentFailedException $e) {
            return response()->json([], 422);
//            return view('jobs.jobfull', compact([], 'job', 422));
        }

I feel like it should return back() to the jobs page, but what I tried above seems to interfere with the JobsController.

//form
<div class="bidReserve">

<form id="payment-form" action="/jobs/{{ $job->id }}/bidreserve" method="post">
    @csrf
     <input type="hidden" id="amount" name="amount" value="500">
//<input type="hidden" name="stripeToken" value=""/>
      <label for="card-element">
//Credit or debit card
      </label>
       <div id="card-element">
// A Stripe Element will be inserted here.//id="card-element" &ndash;&gt;--}}
        </div>

// &lt;!&ndash; Used to display form errors. &ndash;&gt;--}}
        <div id="card-errors" role="alert"></div>

         <button>Bid Reserve</button>
          </form>
 </div>
01 Sep
3 weeks ago

trevorpan left a reply on Using Array_unique() And Array_merge() Consecutively

@jlrdw there's a haboob going on here in Phx right now. Can't imagine a hurricane.

I was thinking some more though, perhaps consuming outside api's with json data, or web scraped data could use the array_unique() and then if a site needed it to be indexed? the array_merge() could be used. Anyhow, I'll keep thinking...

trevorpan left a reply on Using Array_unique() And Array_merge() Consecutively

Thank you much @jlrdw Starting to get a little bit more comfortable with coding!

what you say @cronix ?

trevorpan left a reply on Using Array_unique() And Array_merge() Consecutively

Alright! That's pretty neat. Is that for the pet site you shared a while back?

In that case though, the routes don't necessarily have to be consecutively indexed?

Can you think of any situations where the array_unique() and array_merge would be required consecutively? e.g. the out of order keys somehow messes up the data set?

trevorpan left a reply on Using Array_unique() And Array_merge() Consecutively

@jlrdw

It may just be the magic of seeing that array parsed then ordered that caught my eye. Seems like the two could be used consecutively for a particular purpose that I'm unaware of now, but could keep an eye out for.

With your example, if I understand what happens if the roles or admin are not_matched? I guess, what happens if the empty routes array is like:

null = Route3
key1 = Route2
key3 = Route1

If the controller tries to serve key1 does it error, as route2 is not what is expected? In your example what work is array_merge() doing?

trevorpan started a new conversation Using Array_unique() And Array_merge() Consecutively

I subscribe to the laravel/framework github channel and saw this post the other day.

https://github.com/laravel/framework/pull/29778

The array_merge() seemed like a really cool function to use in reordering / resetting keys. Today, I was playing around with array_unique() and had the idea to combine the two and essentially cut through the fluff and get the data lined up in an orderly way.

This post is just for fun. But do you see any use cases for these two consecutive functions in every day web work? Perhaps data science? Other applications?

$test = array_unique([1,1,1,2,3,4,5,4,7,]);
dd($test);
PHPUnit 7.5.13 by Sebastian Bergmann and contributors.

W.....array:6 [
  0 => 1
  3 => 2
  4 => 3
  5 => 4
  6 => 5
  8 => 7
]
dd(array_merge($test));
PHPUnit 7.5.13 by Sebastian Bergmann and contributors.

W.....array:6 [
  0 => 1
  1 => 2
  2 => 3
  3 => 4
  4 => 5
  5 => 7
]
28 Aug
3 weeks ago

trevorpan left a reply on Phpunit: AssertArrayHasKey() - Undefined Index: Errors

Well, after removing the helper function and testing it direct the test passes:

    //     /** @test */
    function an_order_is_not_created_if_payment_fails()
    {
        $this->withoutExceptionHandling();
        $user = factory(User::class)->create();
        $job = factory(Job::class)->create();

        $this->actingAs($user);

        $this->payBidReserve($job, [
            // 'email' => '[email protected]',
            'bidreserve' => 500,
            // 'payment_token' => 'invalid-payment-token'
            'payment_token' => $this->paymentGateway->getValidTestToken()
        ]);
        // dd($job->bidReserves);
        $this->response->assertStatus(422);
        // dd($this->decodeResponseJson());
        // dd($this->decodeResponseJson()['errors']);
        // $this->assertValidationError('payment_token');
        // $this->response->assertSessionHasErrors();
        // dd($job->orders);
        $this->assertFalse($job->hasOrderFor($user->id));
    }

Above you can see I have tried with 'invalid-payment-token' (which passes) and then with the $this->paymentGateway->getValidTestToken() (which fails).

So, at least the functionality of the test is asserted!

dd($job->orders); returns (which is great):

Trevors-Mac-mini:bidbird trevorpan$ ./vendor/bin/phpunit
PHPUnit 7.5.13 by Sebastian Bergmann and contributors.

W............Illuminate\Database\Eloquent\Collection^ {#4464
  #items: []
}

However, I'm still unsure of how to "set" the keys with assertArrayHasKey() which is what this OP was all about. If anyone knows how to solve that, I'd love to hear.

Thank you much.

trevorpan left a reply on Phpunit: AssertArrayHasKey() - Undefined Index: Errors

good morning @kevinbui ,

I'm heavily basing this on the Test Driven Laravel course, as that example is pretty close to what I'm trying to build, and like the idea of cleaning up the tests with custom methods Adam Wathan uses.

However, I really like that nothing works perfectly from that example and gives me all these errors - so I can learn more!

I gave your call a shot in the test; not sure why this happens, but sometimes response is available in the various tests I'm making - sometimes not. Usually putting $this->response->assertSessionHasErrors(); makes it available.

That call in the test yields:

There was 1 failure:

1) Tests\Feature\PayBidReservesTest::an_order_is_not_created_if_payment_fails
Session is missing expected key [errors].
Failed asserting that false is true.

I wish I knew how to specify the keys.

Found this Jeffrey Way pdf online looking for this error, his assertArrayHasKey section is real straight forward, I reversed the variable and key like his example, just to see if that did anything. nope.

Here's the link, a little old, but still really helpful.

http://baboon.ir/uploads/2015/07/laravel-testing-decoded-by-jeffrey-way.pdf

trevorpan left a reply on Phpunit: AssertArrayHasKey() - Undefined Index: Errors

Hi @ftiersch ,

I gave that a shot in assertValidationError($field) above assertArrayHasKey() and it returns:

Trevors-Mac-mini:bidbird trevorpan$ ./vendor/bin/phpunit 
PHPUnit 7.5.13 by Sebastian Bergmann and contributors.

W............[]

Empty array.

Same when I place dd($this->decodeResponseJson(); in the test.

When adding the dd($this->decodeResponseJson()['errors']); it yields:

ErrorException: Undefined index: errors

My understanding is that the errors should trigger with the validation requirements, right? like below here

// Controller
    public function store($jobId)
    {
        $job = Job::incomplete()->findOrFail($jobId);
  
        $this->validate(request(), [
            'bidreserve' => ['required', 'integer', 'min:1'],
            'payment_token' => ['required']
        ]);
....

Thank you!

27 Aug
3 weeks ago

trevorpan started a new conversation Phpunit: AssertArrayHasKey() - Undefined Index: Errors

Trying to test for a bad payment token, and have purposely given a bad value. It returns Undefined index: errors how do you define this index?

From what I can read here it's set up properly (below in my code) https://phpunit.readthedocs.io/en/8.3/assertions.html?highlight=assertArrayHasKey

    private function assertValidationError($field)
    {
        $this->response->assertStatus(422);
        $this->assertArrayHasKey($field, $this->decodeResponseJson()['errors']);
    }
    /** @test */
    function an_order_is_not_created_if_payment_fails()
    {
        // $this->withoutExceptionHandling();
        $user = factory(User::class)->create();
        $job = factory(Job::class)->create();

        $this->actingAs($user);

        $this->payBidReserve($job, [
            'email' => '[email protected]',
            'bidreserve' => 500,
            'payment_token' => 'invalid-payment-token'
        ]);

        $this->assertValidationError('payment_token');
        $this->assertFalse($job->hasOrderFor('[email protected]'));
    }
24 Aug
4 weeks ago

trevorpan started a new conversation Feedback: On A Functioning Orders Test

good afternoon ~

Have been working on this test for quite some time. I think I have it whipped! But want to see if anyone sees any flaws.

I found a few basic orders product_order product type posts and restructured my tables based on these. https://dba.stackexchange.com/questions/135054/mysql-what-to-store-in-orders-or-product-order https://laracasts.com/discuss/channels/eloquent/eloquent-relationship-for-order-order-items-and-products?page=1

In this case I have a orders bidreserves (like product_order) and jobs tables.

One issue I had creating a bid reserve was inserting the order_id which is necessarily created afterwards. Today, I used my first DB::transaction. I used a (order_id)->nullable(); column to allow for this. (this is one area I'd like to know if this is the best way to do it)

The other question: is the store method the right place to have a conditional for BidReserveExists()? I thought a custom @can blade directive might be a way to handle that. But am unsure if it's necessary to test for that in addition to a blade directive, or if one test for that condition is adequate?

Thank you ~

 public function store($jobId)
    {
        $job = Job::incomplete()->findOrFail($jobId);
        // dd(auth()->user()->BidReserveExists($jobId));
        // if (auth()->user()->BidReserveExists($jobId)) {
        //     return "You have already placed a bid reserve for this job.";
        // }
  
        $this->validate(request(), [
            'bidreserve' => ['required', 'integer', 'min:1'],
            'payment_token' => ['required'],
        ]);
 
        // Charging the bidder
        try {
            $bidReserve = $job->bidReserves()->create([
                'bidreserve' => 500,
                'job_id' => $jobId,
            ]);

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

            DB::transaction(function () use($order) {
                DB::table('bidreserves')->update(['order_id' => $order->id]);

                // DB::table('posts')->delete();
            });

            return response()->json($order, 201);
 
        } catch (PaymentFailedException $e) {

            return response()->json([], 422);
        } 
    }
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('bidreserve');
            $table->timestamps();
        });
    }
    /** @test */
    public function an_authenticated_bidder_can_pay_bidreserve_fee()
    {
        $this->withoutExceptionHandling();

        $user = factory(User::class)->create();
        $job = factory(Job::class)->create();
        $this->actingAs($user);
        $this->payBidReserve($job, [
            'bidreserve' => 500,
            'payment_token' => $this->paymentGateway->getValidTestToken()
        ]);

        $this->response->assertStatus(201);
        $this->assertCount(1, $job->bidReserves);
        // dd($job->orders);

        // Make sure customer was charged correct amount
        $this->assertEquals(500, $this->paymentGateway->totalCharges());

        // Make sure order exists for customer  
        $this->assertTrue($job->hasOrderFor($user->id));
    }

here's a dd($job);

      0 => App\BidReserve^ {#2798
                    -bidReserve: null
                    -email: null
                    +table: "bidreserves"
                    #attributes: array:6 [
                      "id" => "1"
                      "job_id" => "1"
                      "order_id" => "1"
                      "bidreserve" => "500"
                      "created_at" => "2019-08-24 18:51:01"
                      "updated_at" => "2019-08-24 18:51:01"
                    ]

    0 => App\Order^ {#2764
      #connection: "sqlite_testing"
      #table: "orders"
      #attributes: array:7 [
        "id" => "1"
        "user_id" => "1"
        "confirmation_number" => "KVS3PGCW9CKBN58PAZGR45D6"
        "amount" => "500"
        "card_last_four" => "4242"
        "created_at" => "2019-08-24 18:51:01"
        "updated_at" => "2019-08-24 18:51:01"
21 Aug
1 month ago

trevorpan left a reply on Access $variable Property In Test Method

@bobbybouwmann

I saw you hit 1,800 "Best Answers" on twitter. Congratulations!

ok, I noticed above I had $bidderEmail = $user->email; commented out. After uncommenting / rerunning and dd($bidderEmail) it returns: "[email protected]" - as expected.

Must have been exhausted and not paying attention last night. Although the $user->email worked after restarting the machine. Must have been stuck in memory or something. Will clear the cache more often.

20 Aug
1 month ago

trevorpan started a new conversation Access $variable Property In Test Method

Have been working on this test for a while with help from a previous post.

I'm really happy to get the paymentGateway working after a few days by myself without posting. That was a tough thing to get passing.

Hit a snag here, it's so close but thought someone more experienced can help out.

I know it's a very basic thing, but I've tried using some techniques here: https://www.php.net/manual/en/sdo.sample.getset.php and my favorite error was this one! ErrorException: Indirect modification of overloaded property App\User::$email has no effect

/** @test */
    public function an_authenticated_bidder_can_pay_bidreserve_fee()
    {
        $this->withoutExceptionHandling();

        $user = factory(User::class)->create();
        $job = factory(Job::class)->create();

        $this->actingAs($user);
        // dd($user->email);
        $this->payBidReserve($job, [
            'email' => $user->email,
            'bidreserve' => 500,
            'payment_token' => $this->paymentGateway->getValidTestToken()
        ]);
        // dd($this->paymentGateway->getValidTestToken()); 
                
        // dd($this->response);
        $this->response->assertStatus(201);
        $this->assertCount(1, $job->bidReserves);

        // Make sure customer was charged correct amount
        $this->assertEquals(500, $this->paymentGateway->totalCharges());
    // dd($job);

        // Make sure order exists for customer   
        $bidderEmail = $user->email;  
        // dd($bidderEmail);
        // dd($user->email);  $company->departments[0]

        $order = $job->ordersFor($bidderEmail)->first();
        dd($order);
        $this->assertEquals($user->email, $order->email);
        // dd($order);
        // dd($job->bidReserves);
    }

The $user->email property reliably spits out a faker email such as ... "[email protected]" However, when it's placed as an argument for ordersFor() it returns null. If as shown above I get the property put in a variable it returns ErrorException: Undefined variable: bidderEmail.

Why is that?

//Job.php
    public function ordersFor($bidderEmail)
    {
        return $this->orders()->where('email', $bidderEmail)->get();
    }

thank you ~

13 Aug
1 month ago

trevorpan left a reply on FindOrFail($jobId); Returns 404 But Test Creates $job

Hi,

You are correct! Missed the spelling. Also, I misstated, you are right on the functions being functions not methods. Still getting the hang of everything.

With the hardcoded $5.00 charge, I think it'll be like that until the site gets popular and needs other options (if it gets popular).

Thank you for the tips`

Now on to the Stripe stuff & all that jazz.

Trevors-Mac-mini:bidbird trevorpan$ ./vendor/bin/phpunit
PHPUnit 7.5.13 by Sebastian Bergmann and contributors.

...........                                                       11 / 11 (100%)

Time: 913 ms, Memory: 28.00 MB

OK (11 tests, 20 assertions)

trevorpan left a reply on FindOrFail($jobId); Returns 404 But Test Creates $job

ok, you have some great points! I have not started the exception portion just yet in the controller. Trying to go TDD all the way.

here's the revised BidReservesController

    public function store($jobId)
    {
        $job = Job::incomplete()->findOrFail($jobId);

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

    // Previous code
        // $bidreserve = BidReserve::create([
        //     'bidreserve' => 500,
        //     'job_id' => request($job->id),
        //     'user_id' => auth()->user()->id
        //     ]);

        $bidReserve = auth()->user()->bidReserves()->create([
            'bidreserve' => 500,
            'job_id' => $jobId
        ]);
        
        // Charging the customer
        $this->paymentGateway->charge(request('bidreserve'), request('payment_token'));

  
        return response()->json($bidReserve, 201);
    }

I believe that's what you meant about using the auth()->user() (above).

There is an existing bidReserves() relation in the job and user models

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

In a sense the bidreserves table is like an orders table, not sure if that's the best method/approach. Kind of the plan is you place a bidreserve, this gives you the authority to make a bid later in the auction - the goal is transparency so the other bidders see "hey, there's 6 bidders - should bid this one?"

If the bidder wins they get a final charge, if the bidder loses they only pay the bidreserve. I haven't decided on the best place to send an order email.

Gave the test a reboot:

class PayBidReservesTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        $this->paymentGateway = new FakePaymentGateway;
        $this->app->instance(PaymentGateway::class, $this->paymentGateway);
        Event::fake();
    }

    private function payBidReserve($job, $params)
    {
        $this->response = $this->json('POST', "/jobs/{$job->id}/bidreserve", $params);
    // I thought keeping the params in the test as opposed to this method made it more reusable, is that a valid assumption?
    }

/** @test */
    public function a_bidder_can_pay_reserve_fee()
    {
        $this->withoutExceptionHandling();

        $user = factory(User::class)->create();
        $job = factory(Job::class)->create();

        $this->actingAs($user); //was not able to get that to work on the method, it said $user was an undefined variable

        $this->payBidReserve($job, [
            'bidreserve' => 500,
            'payment_token' => $this->paymentGateway->getValidTestToken()
        ]);

        $this->response->assertStatus(201);

        // $this->assertCount(1, $job->bidreserve);

       $this->assertEquals(500, $this->paymentGateway->totalCharges());
    }
}

the assertCount() line yielded:

There was 1 error:

1) Tests\Feature\PayBidReservesTest::a_bidder_can_pay_reserve_fee
PHPUnit\Framework\Exception: Argument #2 (No Value) of PHPUnit\Framework\Assert::assertCount() must be a countable or iterable

After commenting out the above line the suite passed - sweet!

Trevors-Mac-mini:bidbird trevorpan$ ./vendor/bin/phpunit
PHPUnit 7.5.13 by Sebastian Bergmann and contributors.

...........                                                       11 / 11 (100%)

Time: 872 ms, Memory: 28.00 MB

OK (11 tests, 19 assertions)
12 Aug
1 month ago

trevorpan left a reply on FindOrFail($jobId); Returns 404 But Test Creates $job

Hi, thank you @takdw , I've commented out factory(User/Job::class)->make() which causes:

Time: 1.04 seconds, Memory: 28.00 MB

There was 1 error:

1) Tests\Feature\PayBidReservesTest::a_bidder_can_pay_reserve_fee
ErrorException: Undefined variable: user

/Users/trevorpan/code/bidbird/tests/Feature/PayBidReservesTest.php:65

and am unclear how you pass the job/user property from $bidreserve to payBidReserve method. (still learning this stuff) not sure why the user is not available from the bidreserve factory; this is why the factory(User/Job::class)->make() lines were in there...

    //belongsTo
    public function user() //$job->user
    {
        return $this->belongsTo(User::class);
    }


    public function job()
    {
        return $this->belongsTo(Job::class);
    }

The model does have the proper relations, from what I know. Although, I'm unclear if you need to use App\User; etc in models.

trevorpan started a new conversation FindOrFail($jobId); Returns 404 But Test Creates $job

error: Symfony\Component\HttpKernel\Exception\NotFoundHttpException: POST http://bidbird.test/jobs//bidreserve

As you can see above, the $job->id is not found.

class BidReservesController extends Controller
{
    private $paymentGateway;

    public function __construct(PaymentGateway $paymentGateway)
    {
        $this->middleware('auth');
        $this->paymentGateway = $paymentGateway;
    }

....

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

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

        dd($job);

        // dd($this->request);
        $this->validate(request(), [
            'bidreserve' => 'required|integer' 
        ]);

        $bidreserve = BidReserve::create([
            'bidreserve' => 500,
            'job_id' => request($job->id),
            'user_id' => auth()->user()->id
            ]);
        
        // Charging the customer
        $this->paymentGateway->charge(request('bidreserve'), request('payment_token'));

        // dd($job);

        return response()->json([], 201);

        return view('jobs.show', compact('bidreserve', 'job'));
    }
<?php

namespace Tests\Feature;

use App\BidReserve;
use App\Job;
use App\User;
use App\Billing\FakePaymentGateway;
use App\Billing\PaymentGateway;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;


class PayBidReservesTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        $this->paymentGateway = new FakePaymentGateway;
        $this->app->instance(PaymentGateway::class, $this->paymentGateway);
        Event::fake();
    }

    private function payBidReserve($job, $params)
    {
        $this->response = $this->json('POST', "/jobs/{$job->id}/bidreserve", $params);
    }


    /**
     * A basic feature test example.
     *
     * @return void
     */

    /** @test */
    public function a_bidder_can_pay_reserve_fee()
    {
        $this->withoutExceptionHandling();
        Event::fake();

        $job = factory(Job::class)->make();
        $user = factory(User::class)->make();
        $bidreserve = factory(BidReserve::class)->create();

        // dd($job);

        // dd($this->paymentGateway);
        // $this->actingAs($user);

        // dd($user);

        $this->actingAs($user)->payBidReserve($job, [
            'bidreserve' => 500,
            'user_id' => $user->id,
            'job_id' => $job->id,
            'payment_token' => $this->paymentGateway->getValidTestToken()
        ]);

     
        $this->response->assertStatus(201);
    }
}
<?php

/* @var $factory \Illuminate\Database\Eloquent\Factory */

use App\BidReserve;
use App\Job;
use App\User;
use Faker\Generator as Faker;

$factory->define(BidReserve::class, function (Faker $faker) {
    return [
        'user_id' => function() {
                return factory(User::class)->create()->id;
            },
        'job_id' => function() {
            return factory(Job::class)->create()->id;
        },
        'bidreserve' => 500,
        // 'job_id' => $this->faker->numberBetween(1, 10),
        // 'user_id' => $this->faker->numberBetween(1, 100),
    
    ];
});

Ok, when I dd($job); at the test it gives:

#attributes: array:11 [
    "jobtitle" => "Sequi veniam quia explicabo omnis quidem."
    "body" => "Qui veritatis quia sunt id distinctio soluta fugit. Temporibus ut aliquid veniam alias. Debitis optio maxime non a quos. Velit voluptatem dicta placeat quia possimus. Ex delectus debitis voluptas aperiam."
    "deadline" => "2019-09-10 01:16:36"
    "user_id" => 1
    "projectaddress" => "354 Rolfson Skyway Suite 563"
    "city" => "New Heavenchester"
    "state" => "Indiana"
    "zipcode" => "78306"
    "biddertype" => "consectetur"
    "job" => "eveniet"
    "subjob" => "cumque"
  ]

as expected.

when dd($bidreserve); it gives:

#attributes: array:6 [
    "user_id" => 2
    "job_id" => 1
    "bidreserve" => 500
    "updated_at" => "2019-08-13 01:17:32"
    "created_at" => "2019-08-13 01:17:32"
    "id" => 1
  ]
  #original: array:6 [
    "user_id" => 2
    "job_id" => 1
    "bidreserve" => 500
    "updated_at" => "2019-08-13 01:17:32"
    "created_at" => "2019-08-13 01:17:32"
    "id" => 1
  ]
//routes.web
Route::post('/jobs/{job}/bidreserve', '[email protected]')->name('bidreserve');

I have a few questions: if you create job_id and user_id in the BidReserveFactory is it proper to use make() in the test vs. create()?

Is that why there are two users?

But still perplexed why the $job->id is not available when it hits the controller.... thank you ~

25 Jul
1 month ago

trevorpan left a reply on Suggestions On Test: A_logged_in_user_can_view_an_individual_job()

Made a refactor, after realizing while the test passed the deadline was not truly returning a dateTime(). (for anyone coming to this later)

Also the line return (factory(User::class)->id); gave an error: ErrorException: Undefined property: Illuminate\Database\Eloquent\FactoryBuilder::$id so I added ->create()->id which seemed to fix it.

However I was puzzled why user_id said 2. Well, I commented out the creation of the user in the test and bam! user_id = 1 when dd$job);

Feel like I'm finally getting somewhere.

$factory->define(App\Job::class, function (Faker $faker) {

    $deadline = $this->faker->numberBetween(1, 10);

    return [
            'jobtitle' => $this->faker->sentence,
            'body' => $this->faker->paragraph,
            'deadline' => function () use ($deadline) {
                return Carbon::now()
                    ->addWeeks($deadline)
                    ->toDateTimeString();
            },
            'user_id' => function() {
                return (factory(User::class)->create()->id);
            },
            'projectaddress' => $this->faker->streetAddress,
            'city' => $this->faker->city,
            'state' => $this->faker->state,
            'zipcode' => $this->faker->postcode,
            'biddertype' => $this->faker->word,
            'job' => $this->faker->word,
            'subjob' => $this->faker->word
        ];
    });
    /** @test */
    public function a_logged_in_user_can_view_an_individual_job()
    {
        // $this->withoutExceptionHandling();
        Event::fake();
        //$user = (factory(User::class)->create());
        $job = (factory(Job::class)->create());

        // dd($job);

        $response = $this->actingAs($user)->get('/jobs/'.$job->id);

        $response->assertStatus(200)
            ->assertSee($job->jobtitle)
            ->assertSee($job->deadline);   
    }
24 Jul
1 month ago

trevorpan left a reply on Suggestions On Test: A_logged_in_user_can_view_an_individual_job()

@talinon

Mad genius!

My man, so happy got this thing to go. Modified your suggestion slightly to include the carbon() in the factory with afterMaking() which neatly takes the dateTime() stuff out of the test! The user->id bit was key.

Thank you. This is a mighty step forward.

  /** @test */
    public function a_logged_in_user_can_view_an_individual_job()
    {
        Event::fake();
        $user = (factory(User::class)->create());
        $job = (factory(Job::class)->create([
        'user_id' => $user->id
        ]));

        $response = $this->actingAs($user)->get('/jobs/'.$job->id);

        $response->assertStatus(200)
            ->assertSee($job->jobtitle)
            ->assertSee($job->deadline);      
    }
<?php

use Carbon\Carbon;
use Faker\Generator as Faker;

$factory->define(App\Job::class, function (Faker $faker) {
    return [
            'jobtitle' => $this->faker->sentence,
            'body' => $this->faker->paragraph,
            'deadline' => $this->faker->numberBetween(1, 10),
            // 'deadline' => Carbon::now()->addWeeks(rand(1,5)),
            'user_id' => $this->faker->numberBetween(1, 1000),
            'projectaddress' => $this->faker->streetAddress,
            'city' => $this->faker->city,
            'state' => $this->faker->state,
            'zipcode' => $this->faker->postcode,
            'biddertype' => $this->faker->word,
            'job' => $this->faker->word,
            'subjob' => $this->faker->word
        ];
    });


$factory->afterMaking(App\Job::class, function ($job) {
            return [ Carbon::now()
                    ->addWeeks($job['deadline'])
                    ->toDateTimeString()
                ];
});
Trevors-Mac-mini:bidbird trevorpan$ ./vendor/bin/phpunit
PHPUnit 7.5.13 by Sebastian Bergmann and contributors.

.........                                                           9 / 9 (100%)

Time: 1.09 seconds, Memory: 26.00 MB

OK (9 tests, 16 assertions)
Trevors-Mac-mini:bidbird trevorpan$ 
23 Jul
1 month ago

trevorpan left a reply on Suggestions On Test: A_logged_in_user_can_view_an_individual_job()

ahh cool. I wonder if modifying the factory($job) in the test is what alters the object and throws that error?

I gave this line a shot in the test:

$job = (factory(Job::class)->create([
            'deadline' => Carbon::now()
            ->addWeeks(3)
        ]));

dd($job); gives the below:

  #original: array:14 [
   // "jobtitle" => "Voluptatem ut enim rem tenetur."
    //"body" => "Sit similique qui quidem illo est. A aliquid in est aut et quis."
    "deadline" => Carbon\Carbon @1565752597^ {#2471}
   // "user_id" => 683
    //"projectaddress" => "16725 Marty Pine"
    //"city" => "Blairberg"
   // "state" => "Idaho"
    //"zipcode" => "99226"
   // "biddertype" => "quia"
   // "job" => "ipsum"
   // "subjob" => "deleniti"
    //"updated_at" => "2019-07-24 03:16:37"
  //  "created_at" => "2019-07-24 03:16:37"
    //"id" => 1
  ]

After removing dd:

Time: 3.88 seconds, Memory: 30.00 MB

There was 1 failure:

1) Tests\Feature\ViewPostedJobsTest::a_logged_in_user_can_view_an_individual_job
Expected status code 200 but received 500.
Failed asserting that false is true.

/Users/trevorpan/code/bidbird/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:150
/Users/trevorpan/code/bidbird/tests/Feature/ViewPostedJobsTest.php:60

I also tried the without the carbon in the test, just the factory as you wrote - it has a similar 500 error.

Was looking further into factories https://laravel.com/docs/5.8/database-testing#writing-factories , and started sketching out a closure but it's all jacked up...

Do you thing the $factory->afterMaking(App\Job::class, function ($job) {... approach should include the deadline?

Again, super big thank you!

trevorpan left a reply on Suggestions On Test: A_logged_in_user_can_view_an_individual_job()

Hi @talinon

alright, thank you.

I dd($basejob); you are right!

  #original: array:14 [
    "jobtitle" => "Labore inventore consequatur iusto tempora sunt."
    "body" => "Quibusdam atque aliquid error minima quis. Rerum et laboriosam voluptatem magnam distinctio voluptatem. Possimus et facilis rem deserunt nihil nihil necessitatibus. Magnam laboriosam sed qui porro praesentium ut."
    "deadline" => 5
    "user_id" => 933
    "projectaddress" => "87635 Harvey Terrace Apt. 386"
    "city" => "Queenfurt"
    "state" => "New Hampshire"
    "zipcode" => "69084"
    "biddertype" => "incidunt"
    "job" => "sunt"
    "subjob" => "hic"
    "updated_at" => "2019-07-24 02:08:37"
    "created_at" => "2019-07-24 02:08:37"
    "id" => 1

Thisdeadlinepiece of code has been really tricky for me (multiple times trying to get it right on laracasts, now with tests it's trouble again); here the faker gives an integer but does not convert it to a dateTime() this what I was trying to do with $basejob variable. Is this a case for array_merge()?

. When i comment out dd($basejob); it errors out:

There was 1 error:

1) Tests\Feature\ViewPostedJobsTest::a_logged_in_user_can_view_an_individual_job
ErrorException: Trying to get property of non-object

/Users/trevorpan/code/bidbird/tests/Feature/ViewPostedJobsTest.php:74 
((the $response = $this->be($user)->get('/jobs/'.$job->id); line))

That's always a pain. I can see it's an array from the dd but am unclear if this should be an object or an array of objects?

trevorpan left a reply on Suggestions On Test: A_logged_in_user_can_view_an_individual_job()

After looking at this, it seems like the deadline should really be handled in the factory.

Having a bit of a time with the closure...

<?php

use Carbon\Carbon;
use Faker\Generator as Faker;

$deadline = $this->faker->numberBetween(1, 10);

$factory->define(App\Job::class, function (Faker $faker, $deadline) {
    return [
            'jobtitle' => $this->faker->sentence,
            'body' => $this->faker->paragraph,
            // 'deadline' => $this->faker->numberBetween(1, 10),
            'deadline' => function () use ($deadline) {
                return Carbon::now()
                    ->addWeeks($deadline)
                    ->toDateTimeString();
            },
            'user_id' => $this->faker->numberBetween(1, 1000),
            'projectaddress' => $this->faker->streetAddress,
            'city' => $this->faker->city,
            'state' => $this->faker->state,
            'zipcode' => $this->faker->postcode,
            'biddertype' => $this->faker->word,
            'job' => $this->faker->word,
            'subjob' => $this->faker->word
    ];
});

The dd($job); in the test does not throw an error, but I can see the deadline does not addWeeks(). It seems to have added a day though!

  #attributes: array:11 [
    "jobtitle" => "Doloribus quisquam rerum quia rerum aut sint."
    "body" => "Ullam recusandae odit quisquam ut minus harum ex. Delectus voluptas atque aut et vel mollitia quibusdam."
    "deadline" => "2019-07-24 01:44:06"
    "user_id" => 948
    "projectaddress" => "5826 Antonietta Shores"
    "city" => "South Clementine"
    "state" => "Oklahoma"
    "zipcode" => "17962"
    "biddertype" => "est"
    "job" => "suscipit"
    "subjob" => "quia"

trevorpan started a new conversation Suggestions On Test: A_logged_in_user_can_view_an_individual_job()

Wondering if this is getting all the important assertions? Basically, the concept is there are jobs on a "blog" type page or 3 paginated results. If a user clicks details then they are required to either login (that test passes) or they are allowed to see the results.

The deadline attribute requires some footwork (taking integer, as weeks, from html select), but otherwise the factory spins up a fake job. Maybe the whole procedure should happen in the factory?

The only other question I had was on the RefreshDatabase trait. I read in the docs you should use DatabaseMigrations does that affect this make() or is it more appropriate to use create().

<?php

namespace Tests\Feature;

use Mockery;
use Session;

use App\Job;
use App\User;
use Carbon\Carbon;
use Tests\TestCase;
use Illuminate\Http\Request;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Support\Facades\Event;

class ViewPostedJobsTest extends TestCase
{
    use WithFaker, DatabaseMigrations;

    /** @test */
    public function a_logged_in_user_can_view_an_individual_job()
    {
        $this->withoutExceptionHandling();
        Event::fake();
        $user = (factory(User::class)->create());
        $basejob = (factory(Job::class)->make());

        $job = Carbon::now()
            ->addWeeks($basejob['deadline'])
            ->toDateTimeString();

        dd($job);  

        $response = $this->be($user)->get('/jobs/'.$job->id);

        $response->assertStatus(200);  
    }
}

Response from dd$job);

PHPUnit 7.5.13 by Sebastian Bergmann and contributors.

........"2019-09-03 23:58:13"

The conversion ends up stripping the job attributes.

<?php

use Faker\Generator as Faker;


$factory->define(App\Job::class, function (Faker $faker) {
    return [
            'jobtitle' => $this->faker->sentence,
            'body' => $this->faker->paragraph,
            'deadline' => $this->faker->numberBetween(1, 10),
            'user_id' => $this->faker->numberBetween(1, 1000),
            'projectaddress' => $this->faker->streetAddress,
            'city' => $this->faker->city,
            'state' => $this->faker->state,
            'zipcode' => $this->faker->postcode,
            'biddertype' => $this->faker->word,
            'job' => $this->faker->word,
            'subjob' => $this->faker->word
    ];
});
15 Jul
2 months ago

trevorpan left a reply on Forge: Script For Adding Column To Production Database Table

@dalma

Thank you, the next thing I need to go through is the new testing server series of laracasts to test out that stuff.

Going to read up on all those scripts some more. Appreciated!

trevorpan left a reply on Forge: Script For Adding Column To Production Database Table

@wilk_randall

Ok, it's one of those things - just want to be SURE that nothing screws up. It seems like eventually some really cool things could be done with the forge script, just getting my feet wet. Thank you!

trevorpan started a new conversation Forge: Script For Adding Column To Production Database Table

Was reading this post below and feel I have a good understanding of the process of creating a new migration which then adds a column to an existing table. I know I'll have to test the nullable or default values for previous users, e.g. to ensure there are no errors.

https://laracasts.com/discuss/channels/laravel/what-is-the-typical-process-to-add-a-field-to-a-production-database-without-loosing-existing-data

This doc: https://laravel.com/docs/5.8/migrations#columns states you need to add this dependency composer require doctrine/dbal. I've done that locally.

When I get ready to push this to production does the below script cover this dbal?

It seems like a yes, as it's in the composer.json which would be pushed to master, but it's not something I want to get wrong.

cd /home/forge/bidbird.co
git pull origin master
composer install --no-interaction --prefer-dist --optimize-autoloader
php artisan config:cache -q --no-interaction
php artisan route:cache
npm run production
echo "" | sudo -S service php7.1-fpm reload

if [ -f artisan ]
then
    php artisan migrate --force
fi

Thank you for any tips..

28 Jun
2 months ago

trevorpan left a reply on After Updating To Vue 2.6.10 Components Not Rendering

@BOBBYBOUWMANN - ok cool I'll get that straightened out.

Yea, I've seen a number of videos using cdn, and then read a random article somewhere else or visit a package and it has an npm script. So, as a beginner a number of things are catawompus!

Going to look at the stripe.component a little more closely - that may be part of the problem.

trevorpan left a reply on After Updating To Vue 2.6.10 Components Not Rendering

@BOBBYBOUWMANN - Alright! Just got that cleaned up. Every tip is appreciated. Slowly making progress. Thank you.

I researched a bit <scoped slots> as the countdown timer uses them; I thought possibly that was causing an issue.

However the vue.js notes say this has been deprecated but not removed. So I don't think that's contributing to the non-rendered components.

https://vuejs.org/v2/guide/components-slots.html

Wondering if referencing cdn's cause a conflict? Would you delete the duplicates below? Do you use one method over the other? What's your pro-tip?

//master.blade.php
<script src="https://js.stripe.com/v3/"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="{{ asset('js/vendor.js') }}"></script>
<script src="{{ asset('js/app.js') }}"></script>

trevorpan left a reply on After Updating To Vue 2.6.10 Components Not Rendering

@BOBBYBOUWMANN - Hi, thank you. Not sure how the vue-loaders was added in both places; I don't generally manually do this. It is best to allow the npm scripts handle these?

How do you know which dependency is the proper place for a package?

When I'm working locally I run the npm run dev then npm run watch. Can that change the package.json file around?

trevorpan started a new conversation After Updating To Vue 2.6.10 Components Not Rendering

Hi,

I've been trying to figure out all morning why these components are no longer rendering.

Here's a few things I've done composer update npm install

There were a few dependencies that needed updating, and I did that. I can't find any missing dependencies for the portal-vue. I've gone back through the megamenu, and modal videos on laracasts to try and see if something's amiss.

The Vue developer add-in in Chrome does not register any components. The package.json shows:

"devDependencies": {
    ...
    "vue": "^2.6.10",
        "vue-loader": "^15.6.1",
        "vue-loaders": "^2.0.0",
        "vue-template-compiler": "^2.6.10",
        "vueify": "^9.4.1",
    ...
},
    "dependencies": {
    ...
        "portal-vue": "^2.1.5",
        "vue-axios": "^2.1.4",
        "vue-loaders": "^2.0.0"
    }

Here's the app.js file. Any ideas of what's going on?

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

import Vue from 'vue';

import SponsorModal from './plugins/sponsormodal/SponsorModal';

import PortalVue from 'portal-vue';
import axios from 'axios';
import VueAxios from 'vue-axios';
import jquery from 'jquery';

import Countdown from './components/Countdown';
import LocationDropdown from './components/LocationDropdown';
import ReserveBid from './components/ReserveBid';


window.Vue = Vue;
window.Vue = require('vue');
window.$ = jquery;
window.jquery = jquery;

Vue.component('countdown', Countdown);
Vue.component('locationdropdown', LocationDropdown);
Vue.component('reservebid', ReserveBid);
 
Vue.use(VueAxios, axios);
Vue.use(PortalVue);
Vue.use(SponsorModal);

require('./bootstrap');

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */
const compiler = require('vue-template-compiler');
const files = require.context('./', true, /\.vue$/i)
files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))

const app = new Vue({
    el: '#app'
});

Usage: Vue.config.devtools = true;
16 Jun
3 months ago

trevorpan started a new conversation New Stripe: After Paying, How To Route For /success Or /cancel Views?

Hello ~

Have been working through the Accept Payments video series. On April 16, 2019 Stripe introduced a newer version of checkout.

The store() method below is straight from stripe's upgrade docs. https://stripe.com/docs/payments/checkout/migration#client-products

EDIT: Is the success page, and cancel page supposed to be routed from the Vue component?

I think the process is: 1. create a session. 2. Vue component goes to stripe server 3. returns to success or cancel?

class ReservesController extends Controller
{
    
    public function success()
    {
        return view('payments.success'); 
    }

    public function cancel()
    {
        return view('payments.cancel'); 
    }

    public function store()
    {

        $session = \Stripe\Checkout\Session::create([
          'payment_method_types' => ['card'],
          'line_items' => [[
            'name' => 'Bid Reserve Fee',
            'description' => ' Bid Reserve Fee',
            'amount' => 500,
            'currency' => 'usd',
            'quantity' => 1,
          ]],
          'success_url' => 'https://bidbird.co/success',
          'cancel_url' => 'https://bidbird.co/cancel',
        ]);

        
            return view('jobs.jobfull', compact('session')); 
            //return back();  ???
    }
}
//ReserveBid.vue
<template>
    <form action="/reserve" method="POST">
      <label for="card-element">
              Place a  reserve to bid this job. 
            </label>
        
        <button id="checkout-button">Pay Bid Reserve</button>
    </form>
</template>

<script src="https://js.stripe.com/v3/"></script>

<script>

var stripe = Stripe('pk_test_............');

stripe.redirectToCheckout({
  items: [
    // Replace with the ID of your SKU
    {sku: 'sku_.......', quantity: 1}
  ],
  successUrl: 'https://bidbird.co/success',
  cancelUrl: 'https://bidbird.co/cancel',
  billingAddressCollection: 'required',
}).then(function (result) {
  // If `redirectToCheckout` fails due to a browser or network
  // error, display the localized error message to your customer
  // using `result.error.message`.
});
</script>
//web.php

//reserve payments
Route::get('/success', '[email protected]');
Route::get('/cancel', '[email protected]');
Route::post('/jobs/{job}/reserve', '[email protected]');
04 Jun
3 months ago

trevorpan started a new conversation Modal:hover Issue With Multiple Reused Components

Hi,

https://laracasts.com/series/practical-vue-components/episodes/4

This is a sweet video and technique if you haven't watched it yet.

Have managed to get the SponsorModal.vue working fine. I'm using it for sponsor logos on the homepage. The idea is to popup a modal for paying sponsors - they can have a homepage away from home.

Because there's multiple logos (10) when you hover over one logo area, say sponsor6 it hovers fine (changes to light blue from a light grey gradient) but after the modal pops up the hovered logo sponsor6 area goes away, and the first logo sponsor1 shows the hover. This is confusing to a user.

I think this is because that's the first instance of the vue component which renders on the page. All 10 logos use the same component.

Any ideas?

//blade - just a few divs to test

<div class="homepage">

    <div class="sponsorleft">

        <div class="sponsor1">

             Interested in promoting <a href="#sponsor-modal"><b>Your Logo</b></a>?

            <sponsormodal name="sponsor-modal"></sponsormodal>

        </div>

        <div class="sponsor2">

             Interested in promoting <a href="#sponsor-modal"><b>Your Logo</b></a>?

            <sponsormodal name="sponsor-modal"></sponsormodal>

        </div>

Text here....

    <div class="sponsorright">

        <div class="sponsor6">

             Interested in promoting <a href="#sponsor-modal"><b>Your Logo</b></a>?

            <sponsormodal name="sponsor-modal"></sponsormodal>

        </div>

        <div class="sponsor7">

             Interested in promoting <a href="#sponsor-modal"><b>Your Logo</b></a>?

            <sponsormodal name="sponsor-modal"></sponsormodal>

        </div>
</div>
</div>
//app.css

// Sponsors left

.sponsorleft {
  grid-row: 1 / 8;
  grid-column: 1 / 2;
  display: grid;
  grid-template-rows: repeat(5, 150px);
  grid-row-gap: 10px;
  // background: blue;
}

.sponsor1 {
  grid-row: 1 / 2;
  grid-column: 1 / 2;
  text-align: center;
  padding-top: 35px;
  background: linear-gradient(180deg, #eee 0, #e9e9e9);
  border-radius: 50%;
}

.sponsor1:hover {
  background: lightblue;
}

.sponsor2 {
  grid-row: 2 / 3;
  grid-column: 1 / 2;
  text-align: center;
  padding-top: 35px;
  background: linear-gradient(180deg, #eee 0, #e9e9e9);
  border-radius: 50%;
}

.sponsor2:hover {
  background: lightblue;
}

//Sponsors right

.sponsorright {
  display: grid;
  grid-row: 1 / 8;
  grid-column: 8 / 9;
  display: grid;
  grid-template-rows: repeat(5, 150px);
  grid-row-gap: 10px;
  // background: red;
}

.sponsor6 {
  grid-row: 1 / 2;
  grid-column: 3 / 4;
  text-align: center;
  padding-top: 35px;
  background: linear-gradient(180deg, #eee 0, #e9e9e9);
  border-radius: 50%;
}

.sponsor6:hover {
  background: lightblue;
}

.sponsor7 {
  grid-row: 2 / 3;
  grid-column: 3 / 4;
  text-align: center;
  padding-top: 35px;
  background: linear-gradient(180deg, #eee 0, #e9e9e9);
  border-radius: 50%;
}

.sponsor7:hover {
  background: lightblue;
}
//SponsorModal.vue
<template>
    <div :id="name" class="overlay">

        <a href="#" class="sponsor"></a>

        <div class="modal">

            <slot>
              
                <div class="sponsorheading">
                    <b>Sponsorships Available</b>
                </div>

                <div class="sponsormodal-left-text1">
                    text heading
                </div>

                <div class="sponsormodal-center-text1">
                    
                    text
                </div>

                <div class="sponsormodal-left-text2">
                    text heading
                </div>

                <div class="sponsormodal-center-text2">
                        text
                        
                        <br><br>

                        text

                        <br><br>

                        text
                  
                </div>
            </slot>

            <a href="#" class="close"><span style='font-size:40px;'>&times;</span></a>
        </div>

    </div>

</template>

<script>
    export default {
        props: ['name']
    }
</script>

<style>
    .overlay {
        visibility: hidden;
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        background: rgba(0, 0, 0, .4);
        transition: opacity 3s;
        opacity: 0;
    }

    .overlay:target {
        visibility: visible;
        opacity: 1;
    }

    .modal {
        position: relative;
        width: 1000px;
        height: 750px;
        max-width: 80%;
        background: white;
        border-radius: 4px;
        padding: 10px 20px;
        box-shadow: 0 5px 10px rgba(36, 37, 38, 0.08);
    }

    .modal .close {
        position: absolute;
        top: 20px;
        right: 20px;
        color: grey;
        text-decoration: none;
    }

    .overlay .sponsor {
        position: absolute;
        width: 100%;
        height: 100%;
    }

</style>
31 May
3 months ago

trevorpan left a reply on How To Hook Additional Pagination Symbols Into Paginator

@JLRDW - Hi - thank you, I found this: https://laracasts.com/discuss/channels/guides/paginator-another-episode that helped on the <a href , kept trying different routes that would give 404.

<div class="leftarrow"> 
    <a href="{{ $jobs->previousPageUrl() }}">❰</a>
</div> 

<div class="rightarrow">
                          <a href="{{ $jobs->nextPageUrl() }}">❱</a>    
</div>

@snapey , thank you for the link. I'd read those before but didn't understand them. I kept thinking $results - what $results, but now understand it's the $jobs the controller is passing..

moving ahead! Thank you

trevorpan started a new conversation How To Hook Additional Pagination Symbols Into Paginator

Hi ~

I've found a number of posts on how to customize the out of the box pagination but want to see if you have created additional symbols for pagination.

The goal is to leave the basic ❰ 1 2 3 ❱ the bottom of page results but have the below symbols roughly mid page.

Have you done this?

<div class="leftarrow">❰</div> 
<div class="rightarrow">❱</div>

Thank you `

23 May
3 months ago

trevorpan left a reply on States, Cities, Zip Codes And Counties Database Tables (best Table Design For Populating Dropdowns)

@TRAY2 - Ok, thank you very much. I tend to have a orderly desire for all the records to be sequential but am going to have to let go!

trevorpan left a reply on States, Cities, Zip Codes And Counties Database Tables (best Table Design For Populating Dropdowns)

@TRAY2 - Ok, I think I have it.

class CreateStatesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('states', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('state');
        });
    }
class CreateCitiesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cities', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('city'); 
            $table->unsignedBigInteger('state_id');
            $table->foreign('state_id')->references('id')->on('states');
            $table->timestamps();
        });
    }
class CreateCountiesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('counties', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('county');
            $table->timestamps();
        });
    }
class CreateZipCodesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('zipcodes', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedMediumInteger('zipcode')->length(5);
            $table->timestamps();
        });
    }
class CreateCityCountyPivotTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
        Schema::create('city_county', function(Blueprint $table)
        {
            $table->primary(['city_id', 'county_id']);
            $table->unsignedBigInteger('city_id')->unsigned()->index();
            $table->foreign('city_id')->references('id')->on('cities');
            $table->unsignedBigInteger('county_id')->unsigned()->index();
            $table->foreign('county_id')->references('id')->on('counties');
        });
    }

apologies on the formatting, I wish these code blocks would allow wrapping or overflow

class CreateCityZipcodePivotTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('city_zipcode', function (Blueprint $table) {
            $table->primary(['city_id', 'zipcode_id']);
            $table->unsignedBigInteger('city_id')->unsigned()->index();
            $table->foreign('city_id')->references('id')->on('cities');
            $table->unsignedBigInteger('zipcode_id')->unsigned()->index();
            $table->foreign('zipcode_id')->references('id')->on('zipcodes');
        });
    }
class CreateStateZipcodePivotTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('state_zipcode', function (Blueprint $table) {
            $table->primary(['state_id', 'zipcode_id']);
            $table->unsignedBigInteger('state_id')->unsigned()->index();
            $table->foreign('state_id')->references('id')->on('states');
            $table->unsignedBigInteger('zipcode_id')->unsigned()->index();
            $table->foreign('zipcode_id')->references('id')->on('zipcodes');
        });
    }

Here, I believe the model ZipCode belongsToMany states. Does that seem right, as zipcodes cross state lines? Or is hasmany states more appropriate?

class ZipCode extends Model
{
    protected $fillable = ['zipcode'];
    
    // belongsToMany
    public function state() 
    {
        return $this->belongsToMany(State::class);
    }


    // hasMany

    public function cities()
    {
        return $this->hasMany(City::class);
    }

    public function counties()
    {
        return $this->hasMany(County::class);
    }
}
class State extends Model
{
   
    protected $fillable = ['state'];


    // hasMany
    public function cities()
    {
        return $this->hasMany(City::class);
    }

    public function zipcodes()
    {
        return $this->hasMany(ZipCode::class);
    }

    public function counties()
    {
        return $this->hasMany(County::class);
    }
}
class City extends Model
{
    protected $fillable = ['city'];

    // belongsTo
    public function state()
    {
        return $this->belongsTo(State::class);
    }


    // hasMany
    public function counties()
    {
        return $this->hasMany(County::class);
    }

    public function zipcodes() 
    {
        return $this->hasMany(ZipCode::class);
    }

}

Putting in the data will be a nightmare, I can now see why @gn0rt0n offered up a package.

Does having zipcodes out of sorting order matter much? e.g. AZ is in the 85000 range. Should that data be placed in the database sequentially? Thank you `

22 May
4 months ago

trevorpan left a reply on States, Cities, Zip Codes And Counties Database Tables (best Table Design For Populating Dropdowns)

so after solving the above I find this:

Apache Junction is a city in Maricopa and Pinal counties in the state of Arizona.

Does this suggest having a counties table with a many to many with cities and a belongsTo with state? Or would you store two values in the county column? This stuff is tedious.

trevorpan left a reply on States, Cities, Zip Codes And Counties Database Tables (best Table Design For Populating Dropdowns)

@TRAY2 - if I'm not mistaken seeding is for testing? Are you suggesting that's a way to populate these via the command line on the production server?

below is the path to solution..

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class State extends Model
{
   
    protected $fillable = ['state'];

    // hasMany

    public function cities() //$job->user
    {
        return $this->hasMany(City::class);
    }
}
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class City extends Model
{
    protected $fillable = ['city', 'county', 'zipcode'];

    // belongsTo

    public function state() //$job->user
    {
        return $this->belongsTo(State::class);
    }
}
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCitiesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cities', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('city');
            $table->string('county');
            $table->unsignedMediumInteger('zipcode')->length(5);
            $table->string('statecode')->length(2);
            $table->timestamps();
            $table->engine = 'InnoDB';
        });
    }
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateStatesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('states', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('state');
            $table->string('statecode')->length(2);
            $table->foreign('statecode')->references('statecode')->on('cities');
            $table->timestamps();
            $table->engine = 'InnoDB';
        });
    }

After trying for quite a while, I found the column types need to be the same. See the string did not allow, as one of the columns needed to increment or something like that (can't remember exactly)

https://coderwall.com/p/o73fbq/creating-foreign-key-in-laravel-migrations

in Laravel 5.8+bigIncrements must align with unsignedBigInteger(). this was a real pain, but: https://stackoverflow.com/questions/55745137/general-error-1215-cannot-add-foreign-key-constraint-laravel-5-mysql/55746533#55746533

Another thing that sucked was the time of the migration, in this case I had to change the states migration a second prior to cities otherwise it wouldn't be found!

$table->engine = 'InnoDB'; some posts I found said you needed to declare this, but the solution below does not require it.

Following is the solution that allowed migrations. Now that this worked, does it appear to you the foreign key is set up properly?

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateStatesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('states', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('state');
            $table->timestamps();
        });
    }
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCitiesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cities', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('city');
            $table->string('county');
            $table->unsignedMediumInteger('zipcode')->length(5);
            $table->unsignedBigInteger('statecode');
            $table->foreign('statecode')->references('id')->on('states');
            $table->timestamps();
        });
    }

trevorpan left a reply on States, Cities, Zip Codes And Counties Database Tables (best Table Design For Populating Dropdowns)

@TRAY2 - ok, I'll give that a shot and post the results. Since these tables are static, other than a new zipcode every now and then, would each state have a sql file? I guess that would be a mysql source /file command? Have/How do you do that on a production server?

trevorpan left a reply on States, Cities, Zip Codes And Counties Database Tables (best Table Design For Populating Dropdowns)

@GN0RT0N - Hi, ok cool I just checked that one out. Thank you`

Also looked into the post office and UPS api but felt they were a bit much for me to handle now.

My site is quite a ways away from needing other countries; it's not a learning process for the sake of learning, but to get AZ working. All about the minimum viable product . . . in entrepreneur parlance.

Just wanting to populate like this: https://www.youtube.com/watch?v=c7-HkztGahM

trevorpan started a new conversation States, Cities, Zip Codes And Counties Database Tables (best Table Design For Populating Dropdowns)

Hi there`

Have been working on a filter bar with html selects and came across the idea of dynamically populated dropdowns.

I've sketched out a number of ideas on how to structure the tables. It seems like a states table makes sense, not worried about countries yet, and right now I've got a ArizonaCitiesTable. I thought this would help against duplicate city names like Las Vegas, NM and Las Vegas (well of course Nevada!):

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateArizonaCitiesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('arizona_cities', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('city');
            $table->string('county');
            $table->unsignedMediumInteger('zipcode')->length(5);
            $table->timestamps();
        });
    }

Does this seem legit, or would you break out zipcodes, county?

These values then populate a jobs table.

And one other deal, with this kind of setup, do you have to create a sql file to upload on the production server to populate the values?

Thank you`

16 May
4 months ago

trevorpan left a reply on Put Search Filter Buttons Into Session And Return Results

@SNAPEY - Alright, cool. This should be enough to get this thing figured out. Thank you very much `