trevorpan

trevorpan

at BidBird, LLC

Member Since 2 Years Ago

Experience Points
60,110
Total
Experience

4,890 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
513
Lessons
Completed
Best Reply Awards
2
Best Reply
Awards
  • start your engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-in-session Created with Sketch.

    School In Session

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

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

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

  • subscriber Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • evangelist Created with Sketch.

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • chatty-cathy Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

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

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

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

Level 13
60,110 XP
Oct
24
6 days ago
Activity icon

Awarded Best Reply on ErrorException: Array To String Conversion Laravel Horizon

alright, it's hard to know exactly but when I restart nginx and restart server in forge these mysterious errors went away.

Long and short: restart nginx after upgrading php versions.

Activity icon

Replied to ErrorException: Array To String Conversion Laravel Horizon

alright, it's hard to know exactly but when I restart nginx and restart server in forge these mysterious errors went away.

Long and short: restart nginx after upgrading php versions.

Oct
17
1 week ago
Activity icon

Started a new Conversation ErrorException: Array To String Conversion Laravel Horizon

Not sure what's happening exactly, but it appears I've got a misconfiguration.

Error & line

Illuminate\Foundation\Bootstrap\HandleExceptions::handleError
vendor/laravel/horizon/src/QueueCommandString.php:53
...
$options->queue, $options->sleep, $options->timeout, $options->maxTries
...

config/horizon.php

    'environments' => [
        'production' => [
            'supervisor-1' => [
                'backoff' => [60, 120],
                'balance' => 'auto',
                'balanceMaxShift' => 3,
                'balanceCooldown' => 1,
                'connection' => 'redis',
                'delay' =>  10,
                'min_processes' => 1,
                'max_processes' => 10,
                'nice' => 5,
                'queue' => ['mail', 'notifications', 'listeners', 'default'], // this may be the line
                'timeout' => 40,
                'maxTries' => 3
            ],
        ],

Or possibly, the constructor is not necessary? Had run into some issues with the property..

typical listener configuration


//    public $queue = 'listeners';

    /**
     * Set the event listener queue configuration
     *
     * @return void
     */
    public function __construct()
    {
        $this->queue = 'listeners';
    }

If you have any ideas that'd be awesome there aren't many posts on internet about this exactly.

Oct
09
3 weeks ago
Activity icon

Replied to Can Envoyer And Mainentance Mode Prevent Zero Downtime When Upsizing Server?

Sorry, I have a hard time explaining these things. How's the above now?

Activity icon

Replied to Can Envoyer And Mainentance Mode Prevent Zero Downtime When Upsizing Server?

Again congratulations on #1 contributor! @snapey

Ok. I was thinking maybe making a clone, upsizing the clone and then re-assign the new ip to the clone and delete the original. But it seems like those kind of events have to have "some" downtime.

What are other common maintenance procedures requiring php artisan down?

e.g. if I do a new update, and all tests pass, envoyer folds that in nicely without a glitch - so there's no need for the down command.

Activity icon

Started a new Conversation Can Envoyer And Mainentance Mode Prevent Zero Downtime When Upsizing Server?

Had an interesting day yesterday.

Here are the steps I took. There was downtime.

  1. Made a backup of a linode.
  2. Learned you can put the server in maintenance mode by ssh'g into server and running php artisan down. Ok. Well, indeed the server went down and displayed a 503.
  3. I upgraded the server size/ram, etc.
  4. After the server was resized I first ran php artisan up.

The site did not return. It took a few hours w tech support, restarting mysql, nginx, etc.. (I wish that envoyer had a progress bar for the services, so you'd know when you can restart the next service. It would also be awesome to know what order to run things. I still am unclear on the order of things)

I was able to get the site back up and running when calling php artisan up again. This was after fiddling around with other services. It seems like perhaps one of the services was preventing up from executing. At any rate. Site is backup.

Can we upsize a server with zero downtime?

Oct
08
3 weeks ago
Activity icon

Replied to Object Storage Disk Not Changing From Public With Spatie/laravel-medialibary

Morning ~ @bobbybouwmann thank you ~

This is my custom script after envoyer's

Clone new release and Install composer dependencies

cd {{release}}

php artisan horizon:terminate

php artisan view:clear
php artisan event:clear
php artisan config:clear
php artisan cache:clear
php artisan route:clear

composer clearcache

composer dump-autoload

composer install --no-dev --no-scripts

php artisan scout:sync
php artisan scout:optimize

php artisan storage:link

then Activate New Release then my custom script to finish off

cd {{release}}

php artisan optimize --env="production"
php artisan migrate --force --env="production"
npm run production

php artisan event:cache
php artisan config:cache
php artisan route:cache

then Purge Old Releases

Could the storage:link call be overriding? (now that I"ve posted it here!)

Oct
07
3 weeks ago
Activity icon

Started a new Conversation Object Storage Disk Not Changing From Public With Spatie/laravel-medialibary

Hi,

Was wondering if you'd tried Linode's s3 compatible object storage? I have the public disk working fine which stores to the web server linode.

However, I'm trying change this setup to using object storage.

    'disks' => [

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],

        'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public/media'),
            'url' => '/storage/media',
            'visibility' => 'public',
        ],

        'buyer_objects' => [
            'driver' => 's3',
            'key' => env('LINODE_BUYER_KEY'),
            'secret' => env('LINODE_BUYER_SECRET'),
            'region' => env('LINODE_BUYER_DEFAULT_REGION'),
            'bucket' => env('LINODE_BUYER_BUCKET'),
            'url' => env('LINODE_BUYER_URL'),
            'endpoint' => env('LINODE_BUYER_ENDPOINT'),
        ],

Here's spatie's default setup:

// media-library.php v8
return [

    /*
     * The disk on which to store added files and derived images by default. Choose
     * one or more of the disks you've configured in config/filesystems.php.
     */
    'disk_name' => env('MEDIA_DISK',  'public'),

I'm not sure how you'd add one or more disks as env() only takes two arguments. Have added a MEDIA_DISK=buyer_objects to production .env

But it keeps storing to public disk. The model has been updated on these type of methods: ->useDisk('buyer_objects');

If you have any experience here that'd be awesome.

This was pretty helpful, but I'm missing something: https://stackoverflow.com/questions/61407039/laravel-use-linodes-storage-object-as-an-alternative-to-aws-s3

Thank you!

Sep
29
1 month ago
Activity icon

Awarded Best Reply on Typed Property Illuminate\Events\CallQueuedListener::$job Must Not Be Accessed Before Initialization. Php7.4.10, Laravel 8, Queues, Horizon

trait InteractsWithQueue
{
    /**
     * The underlying queue job instance.
     *
     * @var \Illuminate\Contracts\Queue\Job
     */
    public \App\Models\SlugJob $job;

After much headbanging I found the model was type hinted in the trait the vendor directory. It makes no sense as to how it got there, but there it is. I thought because the my app uses $job the framework somehow latched onto it during upgrading.

Remove the typehint \App\Models\model_name if you hit this error.

Activity icon

Replied to Typed Property Illuminate\Events\CallQueuedListener::$job Must Not Be Accessed Before Initialization. Php7.4.10, Laravel 8, Queues, Horizon

trait InteractsWithQueue
{
    /**
     * The underlying queue job instance.
     *
     * @var \Illuminate\Contracts\Queue\Job
     */
    public \App\Models\SlugJob $job;

After much headbanging I found the model was type hinted in the trait the vendor directory. It makes no sense as to how it got there, but there it is. I thought because the my app uses $job the framework somehow latched onto it during upgrading.

Remove the typehint \App\Models\model_name if you hit this error.

Sep
28
1 month ago
Activity icon

Replied to Typed Property Illuminate\Events\CallQueuedListener::$job Must Not Be Accessed Before Initialization. Php7.4.10, Laravel 8, Queues, Horizon

https://laracasts.com/discuss/channels/laravel/how-to-set-a-queue-inside-jobs

After reading the above, I commented out public string $connection; which is above the constructor.

I've tried using self::onConnection('listeners'); in the constructor which removes: Symfony\Component\ErrorHandler\Error\FatalError App\Listeners\SendPublicMessageNotification and Illuminate\Bus\Queueable define the same property ($connection) in the composition of App\Listeners\SendPublicMessageNotification. However, the definition differs and is considered incompatible. Class was composed

It comes back to the OP error: Error Typed property Illuminate\Events\CallQueuedListener::$job must not be accessed before initialization

Where is it being accessed?

What's the best way to fine tune our queue'd jobs?

Sep
27
1 month ago
Activity icon

Started a new Conversation Typed Property Illuminate\Events\CallQueuedListener::$job Must Not Be Accessed Before Initialization. Php7.4.10, Laravel 8, Queues, Horizon

Hi there,

Made the upgrade to Laravel 8. Have tests passing. Then I started working on my queue'd jobs.

In Laravel 7, $public properties did not cause issues with the queue or horizon. After the upgrade I merged in the new queue branch and got errors. I found this link https://github.com/laravel/nova-issues/issues/557#issuecomment-422963978 and decided to move the properties to the constructor, but that yields this error:

Error Typed property Illuminate\Events\CallQueuedListener::$job must not be accessed before initialization

class UsersMail extends Mailable implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    // when these below are uncommented they give errors

    // public $tries = 3; 
    // public $timeout = 40;
    // public $retryAfter = [60, 120];
    // public $delay = 10;
    // public $connection = 'redis';
    // public $queue = 'notifications';

    protected $biddedJob;


    /**
     * The user instance.
     *
     * @var  \Illuminate\Contracts\Auth\Authenticatable
     */
    public $user;

    /**
     * Create a new message instance.
     * Set the mail queue configuration
     *
     * @param \Illuminate\Contracts\Auth\Authenticatable  $user
     */
    public function __construct($user)
    {
        $this->user = $user;

        $this->connection = 'redis';
        $this->tries = 3;
        $this->retryUntil = 40;
        $this->backoff  = [60, 120];
        $this->delay = 10;
        $this->queue = 'mail';
    }

Here is my horizon setting:

    'environments' => [
        'production' => [
            'supervisor-1' => [
                'connection' => 'redis',
                'queue' => ['mail', 'notifications', 'listeners', 'default'],
                'balance' => 'auto',
                'min_processes' => 1,
                'max_processes' => 10,
                'balanceMaxShift' => 3,
                'balanceCooldown' => 1,
                'timeout' => 90,
                'tries' => 3,
                'nice' => 5
            ],
        ],

I found this nice post: https://stitcher.io/blog/typed-properties-in-php-74 but am still a bit unclear on how to properly set queue configurations given we have a horizon config.

My understanding is that horizon config sets the default, but the individual classes can override these settings as the app may require.

Is this proper?

    // here we initialize? It seems redundant to do this on each class, or is it better this way without inheritance? Or would you create many horizon configs, in this case 4 different config settings? e.g. ['mail', 'notifications', 'listeners', 'default'],

    public int $tries; 
    public int $timeout;
    public int $retryAfter;
    public int $delay;
    public string $connection;
    public string $queue;

    protected $biddedJob;


    /**
     * The user instance.
     *
     * @var  \Illuminate\Contracts\Auth\Authenticatable
     */
    public $user;

    /**
     * Create a new message instance.
     * Set the mail queue configuration
     *
     * @param \Illuminate\Contracts\Auth\Authenticatable  $user
     */
    public function __construct($user)
    {
        $this->user = $user;

        $this->connection = 'redis';
        $this->tries = 3;
        $this->retryUntil = 40;
        $this->backoff  = [60, 120];
        $this->delay = 10;
        $this->queue = 'mail';
    }
Sep
23
1 month ago
Activity icon

Replied to Add HasFactory Trait To Model::class() Vs. Each Model?

Hi @michaloravec appreciate your tip. Going through the l8 updates. Definitely pulled in composer require laravel/legacy-factories seems like a beast to update a big test suite!

Activity icon

Replied to Add HasFactory Trait To Model::class() Vs. Each Model?

On each new model?

I'm still trying to sort out, as a practice, when extra work is worth it - to make the code more clear. Or if it adds to much overhead...

Activity icon

Started a new Conversation Add HasFactory Trait To Model::class() Vs. Each Model?

If each model extends:

<?php

namespace App\Models;

...

class Order extends Model
{

Is it reasonable to just add it to the Model class?

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model as Eloquent;

class Model extends Eloquent
{
    use HasFactory;
    protected $guarded = [];
}
Aug
15
2 months ago
Activity icon

Replied to Package:discover --ansi Handling The Post-autoload-dump Event Returned With Error Code 1

hi, @simonangatia

Do you have telescope installed on your production app?

Aug
10
2 months ago
Activity icon

Replied to Getting The Policy Logic Of @can Right With Multiple States

Well THAT does not throw an error. Thumbs up @jlrdw !

Can't believe I get tripped up on such simple things. I thought a strict comparison === would need to have 3 = when in the negative.

Now, what about the switch statements you mentioned? Is what I sketched out up above what you had in mind?

Activity icon

Replied to Getting The Policy Logic Of @can Right With Multiple States

@jlrdw

I'm basing the logic on this: https://laravel.com/docs/7.x/authorization#policy-methods which uses === if I'm not mistaken one = would cause an error.

Because there's two types of users on the page, I would like all @can directives to be in the affirmative. First I gave this a shot: return $user->id !=== $job->user_id;

But that does not fly, so then I tried:

return  $user->id === User::all()->except($job->user_id);
Activity icon

Replied to Getting The Policy Logic Of @can Right With Multiple States

Nice, well it seems like removing @cannot and replacing it with @can did the trick.

The thing I still don't understand is why you can't do this in the policy: return $user->id !=== $job->user_id;

Activity icon

Replied to Getting The Policy Logic Of @can Right With Multiple States

It seems like a policy with blade directives can do the work of your scope?

	return  $user->id === User::all()->except($job->user_id);

Can you see why this would show the form to the $job->user_id?

Activity icon

Replied to PHPStorm Vue Syntax Highlighting

Might try updating to the latest - I'm at 2019.2.1. Vue.js is installed and shows the "V" logo.

Activity icon

Replied to Getting The Policy Logic Of @can Right With Multiple States

Hi @jlrdw thank you!

You know, that may be something to keep in mind. How have you handled the slug with admin/user? I'm concerned there'd be two pages for each post?

@can('buyBidReserve', $job)

    @switch($i)

        @case($hasPayedBidReserve === false)
            First case...
            @break

        @case($hasPlacedBid === false)
            Second case...
            @break

        @default
            Default case...

    @endswitch

@endcan

Is that kind of what you are thinking? Have never actually used a switch statement yet. Grabbed this from the docs and put in a few conditions

Activity icon

Replied to Stripe, Webhooks And SCA European Law Checkout Flow

@gabotronix

Not sure if you've ever used Stripe developers help forum?

https://webchat.freenode.net put in #stripe and they'll certainly help you

Afraid I can't help out too much on this topic.

Activity icon

Started a new Conversation Getting The Policy Logic Of @can Right With Multiple States

I've been a bit perplexed on writing good @can directives.

When one user can visit a page it's pretty easy.

However, this app has two types of users with about 6 different states revolving around an auction. So, pre-auction, after paying but not bidding, bidded - for one user. And pre-receiving bids, received bids but not paid, or not accepting any bids.

Right now, I'm achieving the states with @if blade directives inside the @can directives - I swear there's got to be a better way.

Each @can directive is basically straightforward but becomes messy when checking for the states, it causes oddly named things like @cannot('buyBidReserve', $job) - this works for the person posting the job.

When you read the blade file a person who bids the job - who actually can bid the job - it says @cannot.

So, I've tried to make everything affirmative. The below policy ends up showing the job poster i.e. $job->user_id the form that should only be seen by the other party.

/**
     * Determine whether the user can buy a bid reserve on the job.
     *
     * @param  \App\User  $user
     * @param  \App\SlugJob  $job
     * @return mixed
     */
    public function buyBidReserve(User $user, SlugJob $job)
    {
        return  $user->id === User::all()->except($job->user_id);
    }

I tried using the bang negatives in the policy but phpstorm does not care for that. e.g.

    return  $user->id === !$job->user_id;

Is this something that does not exist? Policy States?

Jul
28
3 months ago
Activity icon

Replied to Make Clickable List Group Item And Submit Value (for Questions And Answers)

Hi @snapey

Here's the final blade. Might look into markdown for quotes, @ , and other forum tools for the future. But having this $job->question->answer relationship allows each question to have the specific answer or answers. A little color change really helps to clarify, too.

Thanks again for helping to make this possible!


  <div class="container">
        <div class="row">
            <div class="col">
                <div class="col-lg-6 col-md-12 col-sm-12 ">

                    <h3>Bidder Questions:</h3>
                    <div class="list-group" id="list-tab" role="tablist">
                        @foreach ($jobQuestions->questions as $question)

                            <a class="list-group-item list-group-item-action m-2 border border-secondary rounded"
                               data-toggle="list"
                               href="#"
                               role="tab"
                               onclick="questionHandler({{ $question->id }});"
                            >
                                <strong>Bidder</strong>&nbsp;
                                <em>{{ $question->created_at->diffForHumans() }}</em>:
                                &nbsp;
                                <p style="white-space: pre-wrap">{{ $question->body }}</p>
                            </a>

                                @forelse ($question->answers as $answer) //these show up light blue 
                                    <a class="list-group-item list-group-item-action list-group-item-info m-2  border border-info rounded"
                                           data-toggle="list"
                                           href="#"
                                           role="tab"
                                           aria-controls="#"
                                    >
                                        <strong>Buyer</strong>&nbsp;
                                        <em>{{ $answer->created_at->diffForHumans() }}</em>:
                                        <p style="white-space: pre-wrap">{{ $answer->body }}</p>
                                    </a>
                                @empty

                                @endforelse

                    @endforeach
                    </div>
                </div>
            </div>
        </div>
    </div>
Activity icon

Replied to Make Clickable List Group Item And Submit Value (for Questions And Answers)

ahh ok. Yea, definitely don't need a million forms.

Have got to finish Wes Bos' js course. Just so much to know!

Thank you`

Jul
27
3 months ago
Activity icon

Replied to Make Clickable List Group Item And Submit Value (for Questions And Answers)

@snapey wins again!

I've added onclick="questionHandler({{ $question->id }});" and removed id= from this <a> element.

//reworked the js a good bit.
        function questionHandler(questionId) {

            // console.log(questionId);
            let answerForm = document.getElementById('answer-form');
            let hiddenInput = document.createElement('input');

            hiddenInput.setAttribute('type', 'hidden');
            hiddenInput.setAttribute('name', 'question_id'); //why does this have to be set in js, not html?
            hiddenInput.setAttribute('value', questionId);

            //console.log(hiddenInput);

            answerForm.appendChild(hiddenInput);
            //console.log(answerForm);

        }

Here's the reworked form:

<form method="POST" action="/jobs/{{ $job->slug }}/answers"
    name="answers"
    id="answer-form">
    @csrf

    <div class="form-group">
    <label for="ask-question" class="credit-label mt-4">Give your answer</label>
    <textarea name="body" id="ask-question"
        placeholder="Answer the bidder's question about this job -"
        class="form-control"
        cols="30"
        rows="6"
        spellcheck="true"
        required>
    </textarea>

    <input type="hidden"
        id="question_id"
        name="question_id" // why does this need to be set with js??
        value=""
    />
    </div>
        <button type="submit"
            class="btn btn-warning my-2"
        >
        Answer Question
    </button>
</form>

It was failing withquestion_id field is required before setting hiddenInput.setAttribute('name', 'question_id');.

So, this does not fill in missing html, it creates a new form? So html in this case is just a placeholder?

Activity icon

Replied to Make Clickable List Group Item And Submit Value (for Questions And Answers)

Hi @snapey

Making progress. Does the questionId need to increment in the @foreach loop? Each time I select questionId it retrieves the first one when printing to console.

Ended up trying {{ $loop->iteration }} but now let questionId = document.getElementById('questionId'); doesn't grab anything. Do you handle it like this?

let questionId = document.getElementById('questionId-*');

<a class="list-group-item list-group-item-action m-2 border border-secondary rounded"
    //id="questionId"
    id="questionId-{{ $loop->iteration }}"
    data-toggle="list"
    href="#" //does this need to increment?
    role="tab"
    onclick="questionHandler();" // this is necessary?
    value="{{ $question->id }}">

    <strong>Bidder</strong>&nbsp;
    <em>{{ $question->created_at->diffForHumans() }}</em>:
        &nbsp;
    <p style="white-space: pre-wrap">{{ $question->body }}</p>
</a>



// form
<form method="POST" action="/jobs/{{ $job->slug }}/answers" name="questions">
    @csrf

    <div class="form-group">
    <label for="ask-question" class="credit-label mt-4">Give your answer</label>
    <textarea name="body" id="ask-question"
        placeholder="Answer the bidder's question about this job -"
        class="form-control"
        cols="30"
        rows="6"
        spellcheck="true"
        required>
        </textarea>
            <input type="hidden"
                name="questionId"
                 value=""   //this should be empty to fill from questionHandler(), right?
            />
      </div>
      <button type="submit"
          class="btn btn-warning my-2"
       >
       Answer Question
       </button>
</form>
// js
        let questionId = document.getElementById('questionId');
        console.log(questionId); 

// console.log pulls up first element in list: <a id="questionId" class="list-group-item list-gro…order-secondary rounded" data-toggle="list" href="#" role="tab" onclick="questionId()" value="2">

        form.addEventListener('submit', function(event) {
            event.preventDefault();
            function questionHandler(result.questionId);
        });

        function questionHandler(questionId) {

            var hiddenInput = document.createElement('input');
            hiddenInput.setAttribute('type', 'hidden');
            hiddenInput.setAttribute('name', questionId);

            form.appendChild(hiddenInput);

            // Submit the form
            form.submit();
        }
Activity icon

Replied to Make Clickable List Group Item And Submit Value (for Questions And Answers)

ok, I didn't understand what the # was for in this: https://getbootstrap.com/docs/4.5/components/list-group/#links-and-buttons now the prevent default makes sense.

Thank you @snapey for the explanation - let me try and get this wired up!

Activity icon

Replied to Make Clickable List Group Item And Submit Value (for Questions And Answers)

Yes, there can be many questions. On selecting the id-what makes the question selectable? Is this an onclick event?

That’s what I meant by clickable list item in the post title. (questions are looped in a foreach and rendered on the page as list items)

Activity icon

Replied to Make Clickable List Group Item And Submit Value (for Questions And Answers)

Ha! o man. Thought this was well put. Sorry @snapey

Ok, so here's a screenshot: https://bidbird.co/questions.png

Basically, my thought is a buyer can click the question to respond to.

list-group-item-action active-light class from bootstrap seems to make it clickable. However, when the form is submittedquestionId gives an error question id is required.

So, clearly when the question

  • item is selected it's not passing the id to the form.

    I may not be going about the problem in the best way.

    // here's answer schema
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::create('answers', function (Blueprint $table) {
                $table->id();
                $table->unsignedBigInteger('user_id');
                $table->unsignedBigInteger('question_id');
                $table->foreign('question_id')->references('id')->on('questions');
                $table->unsignedBigInteger('job_id');
                $table->foreign('job_id')->references('id')->on('jobs');
                $table->text('body');
                $table->timestamps();
            });
        }
    

    Would you handle it differently?

  • Jul
    26
    3 months ago
    Activity icon

    Started a new Conversation Make Clickable List Group Item And Submit Value (for Questions And Answers)

    Hi,

    Have been working on the How to Build a Forum series.

    I have built a question form, which sends out emails, etc.

    Would like to add an answer form. This way the responder can tag a question and the answer renders beneath that question. e.g. sometimes many questions are asked and it's hard to see which question an answer is for which question.

    Using bootstrap, I've got the active class working. Which is nice for user experience. However, I'd like it to be clickable so a user can "answer" the question.

    <h3>Bidder Questions:</h3>
    @foreach ($jobQuestions->questions as $question)
    
    <div class="list-group" id="myList" role="tablist">
        <li class="list-group-item list-group-item-action active-light list-group-item-light m-2  border border-info rounded"
            data-toggle="list"
            id="questionId"
            role="tab"
            value="{{ $question->id }}">
            <strong>Buyer</strong>&nbsp;
            <em>{{ $question->created_at->diffForHumans() }}</em>:
            <p style="white-space: pre-wrap">{{ $question->body }}</p>
        </li>
    
    // goal is to render the answer here:
        <li>
           <p style="white-space: pre-wrap">{{ $question->answers->body }}</p>
        </li>
    
    </div>
    @endforeach
    

    Here is the form. I believe the goal is to select the id of the <li> item and submit it via a hidden input. Not sure if js is required or not.

     <div class="container">
                    <div class="row">
                        <div class="col-sm-6">
                            <form method="POST" action="/jobs/{{ $job->slug }}/answers"
                                  name="questions">
                                @csrf
    
                                <div class="form-group">
                                    <label for="ask-question" class="credit-label mt-4">Give your answer</label>
                                    <textarea name="body" id="ask-question"
                                          placeholder="Answer the bidder's question about this job -"
                                          class="form-control"
                                          cols="30"
                                          rows="6"
                                          spellcheck="true"
                                          required>
                                    </textarea>
                                    <input type="hidden"
                                           name="question"
                                           id="questionId"
                                           value=""
                                    />
                                </div>
                                <button type="submit"
                                        class="btn btn-warning my-2">
                                    Answer Question
                                </button>
                            </form>
                        </div>
                    </div>
                </div>
    

    These are somewhat similar to the threads / replies concept from laracasts series, except they are shown on a jobs page. So, job_id is the main model -> questions -> answers. At least i think that's the best model relationship approach to render the answers below the questions.

    Jul
    24
    3 months ago
    Activity icon

    Awarded Best Reply on "[email protected]"

    whoops - ha. ah man

    Had this on the listener: dd($event->question->user->email);

    Activity icon

    Replied to "[email protected]"

    whoops - ha. ah man

    Had this on the listener: dd($event->question->user->email);

    Activity icon

    Replied to "[email protected]"

    Tried out using make():

            $question = factory(Question::class)->make([
                'user_id' => $harry->id,
                'job_id' => $job->id,
            ]);
    

    Which returns the Question class as expected.

    App\Question {#2801
      ....
      #attributes: array:3 [
        "user_id" => 2
        "job_id" => 1
        "body" => "Iure quae distinctio et accusantium. Eos reiciendis nam dicta ut est aut quaerat. Ipsum veritatis voluptatem pariatur nihil. Vitae harum libero laudantium est."
      ]
    
    

    Is there a bug with create?

    Jul
    23
    3 months ago
    Activity icon

    Started a new Conversation "[email protected]"

    This has to be the most bizarre behavior I've ever seen. There's no dd() absolutely no reason this should spit out on the command line - but there it is: "shany74@example.org".

    class QuestionsAnswersTest extends TestCase
    {
        use RefreshDatabase;
    
        /** @test */
        public function a_user_can_view_questions()
        {
            $john = factory(User::class)->create([
                'firstname' => 'john',
            ]);
            $harry = factory(User::class)->create([
                'firstname' => 'harry'
            ]);
            $job = factory(SlugJob::class)->create([
                'user_id' => $john->id,
                'jobtitle' => 'Hardware job'
            ]);
    
    // this is where the email is returned
            $question = factory(Question::class)->create([
                'user_id' => $harry->id,
                'job_id' => $job->id,
            ]);
    
            $response = $this->get('/jobs/hardware-job');
            $response->assertSee($question->body);
        }
    
    <?php
    
    /** @var \Illuminate\Database\Eloquent\Factory $factory */
    
    use App\Question;
    use App\SlugJob;
    use App\User;
    use Faker\Generator as Faker;
    
    $factory->define(Question::class, function (Faker $faker) {
        return [
            'job_id' => function () {
                return factory(SlugJob::class)->create()->id;
            },
            'user_id' => function () {
                return factory(User::class)->create()->id;
            },
            'body' => $this->faker->paragraph,
        ];
    });
    

    Have you ever seen anything like this?

    Jul
    22
    3 months ago
    Activity icon

    Replied to How To Access Index-name .env Var With Algolia Process.env.MIX_VUE_APP_INDEX_NAME;

    @piljac1

    Thank you on the props - still need to watch more videos on vue and js.

    Man, I've been going back and forth on this for several days. It keeps saying undefined. Do .env variables need to be defined? I thought they were all considered strings.

    Is it better to use this way of inserting .env variables?

    const indexName = '{{ config('services.algolia.index') }}'; Couldn't get that syntax just right, but is that the better way vs. process.env etc?

    the line here does not seem to recognize indexName

    <template>
        <div class="container">
            <ais-instant-search
                :search-client="searchClient"
                :index-name="indexName"
            >
    
    Jul
    20
    3 months ago
    Activity icon

    Replied to How To Access Index-name .env Var With Algolia Process.env.MIX_VUE_APP_INDEX_NAME;

    @piljac1 thank you.

    yea, I've got watcher going. It's really confusing with all algolia api keys. I had the api key assigned to that index and was giving an invalid key name.

    Swapped that out but still not displaying the index: Error: The ``indexName`` option is required.

    I've checked php artisan env = local which is correct.

    and because that indexName isn't available it causes: [Vue warn]: Error in created hook: "TypeError: can't access property "addWidget", this.instantSearchInstance is undefined"

    Activity icon

    Started a new Conversation How To Access Index-name .env Var With Algolia Process.env.MIX_VUE_APP_INDEX_NAME;

    Hi,

    Have a frustratingundefined variable.

    In the .env file:

    MIX_VUE_APP_INDEX_NAME=testing_jobs
    

    in the vue component:

    <template>
        <div class="container">
            <ais-instant-search
                :search-client="searchClient"
               // index-name="{ indexName }" 
                :index-name="indexName" // have tried binding the var but still is undefined
    
            >
    ....
    
    
    <script>
        import algoliasearch from 'algoliasearch/lite';
        import 'instantsearch.css/themes/algolia-min.css';
    
        let indexName = process.env.MIX_VUE_APP_INDEX_NAME;
    
        export default {
            data() {
                return {
                    props: {
                        job: Object,
                        imageUrl: String,
                        // indexName: String // this did not work either, it expected string but got undefined
                    },
                    searchClient: algoliasearch(process.env.MIX_ALGOLIA_APP_ID, process.env.MIX_ALGOLIA_SEARCH),
                    indexName: process.env.MIX_VUE_APP_INDEX_NAME
                }
            }
        };
        console.log(indexName);
    

    I'm sure this is super easy, but I'm not sure why algoliasearch(process.env.MIX_ALGOLIA_APP_ID, process.env.MIX_ALGOLIA_SEARCH) works but not the indexName.

    Thank you `

    Jul
    12
    3 months ago
    Activity icon

    Started a new Conversation How To Access/display Js Countdown Timer On A Site With A Link In Markdown Email?

    Hi,

    Is it possible to access/display js countdown timer on a site with a link in markdown email?

    This post talks about the reasons why js is not embedded in an email... https://stackoverflow.com/questions/1088016/html-email-with-javascript

    I'd like to include the timer link from a page on the website so when a user is reading the mail there's some more urgency.

    // blade markdown 
    # Deadline to bid:
    {{ $url.'/#countdown' }}
    

    This only spits out the url - not the countdown timer...

    Jul
    05
    3 months ago
    Activity icon

    Replied to Maximum Execution Time Of 30 Seconds Exceeded. Spatie MediaLibrary

    Awesome @guybrush_threepwood thank you for the boost!

    the longer execution time of

    max_execution_time = 120
    
    max_input_time = 60
    

    Seems to work on local. You mentioned queueing the conversions. The local env had sync so that definitely caused some issues locally (for anyone else who finds this)

    // QUEUE_CONNECTION=sync
    QUEUE_CONNECTION=redis // at least to test locally with horizon - drastically sped the feeling of the site site "working" -- UX
    

    Took a bit to figure out how to edit that file policy.xml on the production server. While ssh'ing this command does the trick sudo nano /etc/ImageMagick-7/policy.xml

    But I also wanted to do it locally and came across this post. The command I picked up is identify -list policy Super helpful as it shows you everything on the command line.

    https://stackoverflow.com/questions/52703123/override-default-imagemagick-policy-xml

    And this is also a helpful site with other recipes: https://forgerecipes.com/recipes/215

    Activity icon

    Replied to Maximum Execution Time Of 30 Seconds Exceeded. Spatie MediaLibrary

    Hi @guybrush_threepwood

    In your experience, do you think the max_execution_time should exceed 30 seconds? I was concerned that something is not setup right.

    Just got this error and was about to dive into it:

    ImagickException
    attempt to perform an operation not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/408
    

    this is where they are right now:

    max_execution_time = 60
    
    max_input_time = 60
    
    Jul
    03
    3 months ago
    Activity icon

    Started a new Conversation Maximum Execution Time Of 30 Seconds Exceeded. Spatie MediaLibrary

    $this->numberOfPages = $this->imagick->getNumberImages();

    Has anyone run into this?

    Have laravel medialibrary installed. It works fine for single page files. However a four page 8.5MB (and a smaller 2.5MB of the same file) pdf throws this:

    Maximum execution time of 30 seconds exceeded or 502 Bad Gateway

    Single page files do not throw the error.

    spatie/laravel-medialibrary#1271 http://www.imagemagick.org/discourse-server/viewtopic.php?t=19087

    Tried out a ton possible issues, but the error always comes back to a method in vendor/spatie/pdf-to-image/src/Pdf.php file.

    Here's the versions I'm using:

    "spatie/laravel-medialibrary": "^7",
    "spatie/pdf-to-image": "2.0.1",
    

    Laravel 7 GPL Ghostscript 9.50 (2019-10-15)

    php.ini

    upload_max_filesize = 32M
    max_file_uploads = 20
    post_max_size = 128M
    memory_limit = 2048M
    extension="redis.so"
    extension="imagick.so"
    

    Laravel Valet 2.11.0 Can verify valet uses [email protected] Have verified the server is using [email protected] laravel/valet#728 (comment) (this was a big pain, and a great find)

    Have gone through all the possibilities I can find. Including this one: https://github.com/laravel/valet/issues/269#issuecomment-271928229 it adds:

    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;
    

    to valet.conf but I'm not seeing an improvement. restart valet many times after these tweaks

    Jun
    30
    4 months ago
    Activity icon

    Started a new Conversation A Guide To Deploying Production Artisan Commands

    | php artisan  | Runs | Notes |
    
    | scout:import |once| if rerun, existing records that were deleted will reappear |
    | schedule:run |once?| commands will not run without it |
    

    Would anyone like to contribute to this guide?

    I want to have a place to reference these deploy scripts. Got stumped many times on deploy. e.g. scout:import was run on each update. After deleting a record in the index it would reappear; I left it in the database for the record but don't necessarily want it in the search index. After numerous support emails with algolia I finally figured it out. So, if algolia itself wasn't privy to this nuance it seems like this guide would be really useful.

    On forge, I had a few support tickets about cron jobs not running and was told they should be running. But again without a guide it's hard to know that, as it's not the most obvious thing (at least to me).

    (also, not sure how to get a table to show as markdown on laracasts)

    Anyhow, if you have experience with a command please make a post and I'll fold it in here!

    Jun
    27
    4 months ago
    Activity icon

    Replied to How Do You Set Up A Truth Test Console Command To Run A Task In Production?

    @bugsysha thank you so much. I was at a complete loss as to why this was not going. Your return statement above was the most important. But I realized how badly everything else was setup.

    Truth Test Steps:

    1. Make sure statement returns true or false, as shown above
    2. Depending on whether the console command sends emails make sure constructors are set properly, and args implemented
    3. If dispatching a huge number of things you may not need an arg as shown here:
        /**
        * Execute the console command.
        *
        */
        public function handle()
        {
        SendDeadlineExpiredEmails::dispatch();
        }
    

    The above was really confusing, as the docs imply the use of args. But my case is a bit different as it loops through many jobs to email a bunch of users based on other conditions...

    1. In my case the queue job did not need type hints, as the handle() pulled special conditions and it was not an implied model like making a blog post or something.
    2. Make sure envoyer, or other deployment uses php artisan queue:restart
    3. AND most important be sure to include php artisan schedule:run

    Wow, thank you. This was a really complicated setup.

    Got the expected real emails on production server!!:

    Your job has bidded: George Washington's Lumber Job (sample) We are very sorry to report that no one placed a bid on your job.

    Activity icon

    Replied to How Do You Set Up A Truth Test Console Command To Run A Task In Production?

    Alright, your solution should have run but it has not. There are no logs @bugsysha .

    class DeadlineHasPassed extends Command
    {
        /**
         * The name and signature of the console command.
         *
         * @var string
         */
        protected $signature = 'email:deadlineHasPassed {biddedJobs}'; // should this be model name?
    
        /**
         * The console command description.
         *
         * @var string
         */
        protected $description = 'Send deadline expired emails';
    
        /**
         * Create a new command instance.
         *
         * @return void
         */
        public function __construct()
        {
            parent::__construct();
        }
    
        /**
         * Execute the console command.
         * @param SlugJob $biddedJobs
         */
        public function handle(SlugJob $biddedJobs)
        {
            SendDeadlineExpiredEmails::dispatch($biddedJobs);
        }
    }
    

    Well, this has to be it. If the truth test tests whether a condition exists does the console command require arguments? If so, would the user be the argument or the model SlugJob? I've tried both. Something seems to be amiss.

    I also verified the php artisan queue:restart is set in envoyer...

    Activity icon

    Replied to How Do You Set Up A Truth Test Console Command To Run A Task In Production?

    aahh. Ok let me give that a go.

    I had tried this but it did not work either.

            $schedule->command('email:deadlineHasPassed --force')
                ->everyMinute()
                    ->withoutOverlapping()
                        ->when(function () {
                           $biddedJobs = DB::table('jobs')
                                ->where([
                                    ['deadline', '<=', Carbon::now('America/Los_Angeles')->toDateTimeString()],
                                    ['bidded', '=', 0]
                                ])
                                ->exists();
                            return $biddedJobs;
                        });
    
    Activity icon

    Replied to How Do You Set Up A Truth Test Console Command To Run A Task In Production?

    @bugsysha yea, I had originally used the return. Here's the doc sample:

    $schedule->command('emails:send')->daily()->when(function () {
        return true;
    });
    

    So my code was like:

    protected function schedule(Schedule $schedule)
        {
           $schedule->command('email:deadlineHasPassed --force')
        ->everyMinute()
            ->when(function () {
                DB::table('jobs')
                    ->where([
                        ['deadline', '<=', Carbon::now('America/Los_Angeles')
                            ->toDateTimeString()],
                        ['bidded', '=', 0]
                    ])->get();
            })->withoutOverlapping();
    
    return true;
    

    I looked at that for a bit. It seemed like get() was the wrong call whereas exists() returns true or false. So it seems redundant to check for a truth and then explicitly return true as this could falsely return true.

    Am I wrong?

    Activity icon

    Started a new Conversation How Do You Set Up A Truth Test Console Command To Run A Task In Production?

    Recently, I made a post and was successfully able to write a test for this condition: https://laracasts.com/discuss/channels/testing/the-expected-notification-was-not-sent-using-cron-scheduled-command-phpunit

    However, now that it's in production the scheduler does not run when a job deadline passes. I've tried with --force and without.

    The docs mention a routes/console.php is needed for a closure. This truth test appears to be a closure, however in the docs https://laravel.com/docs/7.x/scheduling#schedule-frequency-options under Truth Test Constraints it makes no mention of the routes/console.php file???

    class Kernel extends ConsoleKernel
    {
        /**
         * The Artisan commands provided by your application.
         *
         * @var array
         */
        protected $commands = [
            Commands\DeadlineHasPassed::class,
            Commands\GenerateSitemap::class
        ];
    
        /**
         * Define the application's command schedule.
         *
         * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
         * @return void
         */
        protected function schedule(Schedule $schedule)
        {
           $schedule->command('email:deadlineHasPassed --force')
                ->everyMinute()->when(function () {
                DB::table('jobs')
                    ->where([
                        ['deadline', '<=', Carbon::now('America/Los_Angeles')
                            ->toDateTimeString()],
                        ['bidded', '=', 0]
                    ])->exists();
            })->withoutOverlapping();
    
    Jun
    26
    4 months ago
    Activity icon

    Replied to Phpunit: AssertArrayHasKey() - Undefined Index: Errors

    @fuhrn

    I appreciate your comment! So, I reworked the test:

        /** @test */
        public function an_order_is_not_created_if_payment_fails()
        {
            $this->withoutExceptionHandling();
            $joe = factory(User::class)->create();
            $job = factory(SlugJob::class)->create();
    
            $this->actingAs($joe)
                    ->payBidReserve($job, [
                        'price' => 500,
                        'quantity' => 1,
                        'stripeToken' => 'not-a-token',
                    ]);
    
    
            $this->response->assertStatus(422);
            $this->response->assertJsonValidationErrors(['stripeToken']); // this returns: Invalid JSON was returned from the route.
    
            $this->assertFalse($joe->hasOrderFor($joe->id));
        }
    

    I made some searches and found the answer from the man himself!

    https://github.com/laravel/framework/pull/28595#issuecomment-495251983

    The line $this->response->assertJsonValidationErrors(['stripeToken']); is redundant and not needed as 422 is asserted.

    Thank you - without your post I wouldn't have discovered this`