ralphmorris

ralphmorris

Member Since 2 Years Ago

Experience Points 23,560
Experience
Level
Lessons Completed 198
Lessons
Completed
Best Reply Awards 1
Best Answer
Awards
  • Start Your Engines Achievement

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • First Thousand Achievement

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • One Year Member Achievement

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • Two Year Member Achievement

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • Three Year Member Achievement

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • Four Year Member Achievement

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • Five Year Member Achievement

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • School In Session Achievement

    School In Session

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

  • Welcome To The Community Achievement

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • Full Time Learner Achievement

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • Pay It Forward Achievement

    Pay It Forward

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

  • Subscriber Achievement

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • Lifer Achievement

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • Laracasts Evangelist Achievement

    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 Achievement

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • Laracasts Veteran Achievement

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • Ten Thousand Strong Achievement

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • Laracasts Master Achievement

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • Laracasts Tutor Achievement

    Laracasts Tutor

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

  • Laracasts Sensei Achievement

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • Top 50 Achievement

    Top 50

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

05 Dec
1 week ago

ralphmorris left a reply on Dynamically Create Different Tables For Same Model?

Thanks @martinbean,

Thats what I currently have. A standard hasMany relationship between Site and Log. The logs table containing a site_id column.

Number of entries is the main concern yes, which is why I'm looking to separate it out. But as this is part of a saas app and a feature for users I wouldn't be able to use Papertrail.

I'm more looking for a solution in Laravel for separating out just this one table rather than full multi-tenancy.

ralphmorris started a new conversation Dynamically Create Different Tables For Same Model?

Hi everyone!

I have a Site model which hasMany Log. Currently there is one logs table however I'm looking at the possibility of separating out the different sites logs into different dynamically generated tables.

The ideal solution would be for users to sign up, create a new Site which and then dynamically creates a new 'logs' table associated with that Site. The Log table name would be something like site_1_logs.

I feel like it should be possible to override the setTable() method on the hasMany relationship dynamically but can't see way yet so wondering if anyone has here done this before? Are there any risks with this approach also? To me it feels like a simpler form of multi-tenancy.

Thanks!

Ralph

18 Oct
1 month ago

ralphmorris started a new conversation Trix Editor Uploading Image. After Page Refresh Getting "Unexpected End Of JSON Input"

I am using the Trix editor and have implemented uploading images as per their docs which works almost perfectly.

However when the page refreshes after saving I am getting "Unexpected end of JSON input" which then results in nothing being loaded into the trix editor field.

I can see that in the DB it is saved and contains data attributes with json inside containing trix information about the html tags. For instance.

<div><a href="http://d40qaqg3egdda.cloudfront.net/public/assets/19/sapiente-et-nisi-dolores-image.jpg"><strong><figure class="attachment attachment--preview" data-trix-attachment="{&quot;contentType&quot;:&quot;image&quot;,&quot;height&quot;:1280,&quot;url&quot;:&quot;http://d40qaqg3egdda.cloudfront.net/public/assets/19/sapiente-et-nisi-dolores-image.jpg&quot;,&quot;width&quot;:854}" data-trix-content-type="image" data-trix-attributes="{&quot;caption&quot;:&quot;Hey&quot;}"><img src="http://d40qaqg3egdda.cloudfront.net/public/assets/19/sapiente-et-nisi-dolores-image.jpg" width="854" height="1280"><figcaption class="attachment__caption attachment__caption--edited">Hey</figcaption></figure></strong></a></div>

It looks like the quotes are getting escaped but this is happening as I add the image via the trix editor not on the backend.

Would be very grateful if somebody can help!?

Ralph

04 Oct
2 months ago

ralphmorris started a new conversation Trix Editor Markup Changing After Save. Figcaption Markup Not Rendering Properly

I wonder if somebody else has experience this?

I am using the Trix editor and have implemented uploading images as per their docs which all works almost perfectly.

The only issue is if I add a caption it seems to work until the point I click save. When the page refreshes the caption is bumped below where it was and the 'Add a caption' message is back.

I'm also using the latest version of 'mews/purifier' for html validation.

$request->merge([
    'content' => Purifier::clean($request->content)
]);

Weirdly if I don't use the above and let it just save to the db I get the following JS error after the page refreshes.

VM5777:1 Uncaught SyntaxError: Unexpected end of JSON input
    at JSON.parse

This is what is saved to the db:

<div><a href="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg" data-trix-attachment="{&quot;contentType&quot;:&quot;image/jpeg&quot;,&quot;filename&quot;:&quot;carina.jpg&quot;,&quot;filesize&quot;:64581,&quot;height&quot;:960,&quot;href&quot;:&quot;http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg&quot;,&quot;url&quot;:&quot;http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg&quot;,&quot;width&quot;:638}" data-trix-content-type="image/jpeg" data-trix-attributes="{&quot;caption&quot;:&quot;this is my caption&quot;}"><figure class="attachment attachment--preview attachment--jpg"><img src="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg" width="638" height="960"><figcaption class="attachment__caption attachment__caption--edited">this is my caption</figcaption></figure></a></div>

If I use the HTML Purifier I get this saved to the db:

<div><a href="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg"></a><figure><a href="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg"><img src="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg" width="638" height="960" alt="some-post-image.jpg"><figcaption>this is my caption</figcaption></a></figure><a href="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg"></a></div>

This obviously is stripping out some trix data attributes which is why it doesn't render correctly? If I then don't change anything but just hit save it changes again and completely removes the figcaption tag.

<div><a href="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg"><strong></strong></a><figure><a href="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg"><strong><img src="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg" width="638" height="960" alt="some-post-image.jpg"></strong></a></figure><a href="http://d40gggg3egdda.cloudfront.net/public/assets/8/some-post-image.jpg"><strong></strong><strong>this is my caption</strong></a></div>

So in summary..!

  1. If I don't HTML Purify, when saving laravel still seems to do some sort of escaping and breaks the Trix editor on page refresh?
  2. If I HTML Purify, the markup changes. If I save again figcaption is completely removed.

Here is my purifier config. I found the below below also which talked about allowing for figcaption and trix data attributes in the validation but not sure if it is perfect yet?

https://github.com/stevebauman/purify/issues/7

<?php

return [
    'encoding'      => 'UTF-8',
    'finalize'      => true,
    'cachePath'     => storage_path('app/purifier'),
    'cacheFileMode' => 0755,
    'settings'      => [
        'default' => [
            'HTML.Doctype'             => 'HTML 4.01 Transitional',
            'HTML.Allowed'             => 'div,b,strong,i,em,u,a[href|title],ul,ol,li,p[style],br,span[style],img[width|height|alt|src],figure,figcaption',
            'CSS.AllowedProperties'    => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',
            'AutoFormat.AutoParagraph' => true,
            'AutoFormat.RemoveEmpty'   => true,
        ],
        'test'    => [
            'Attr.EnableID' => 'true',
        ],
        "youtube" => [
            "HTML.SafeIframe"      => 'true',
            "URI.SafeIframeRegexp" => "%^(http://|https://|//)(www.youtube.com/embed/|player.vimeo.com/video/)%",
        ],
        'custom_definition' => [
            'id'  => 'html5-definitions',
            'rev' => 1,
            'debug' => false,
            'elements' => [
                // http://developers.whatwg.org/sections.html
                // ['section', 'Block', 'Flow', 'Common'],
                // ['nav',     'Block', 'Flow', 'Common'],
                // ['article', 'Block', 'Flow', 'Common'],
                // ['aside',   'Block', 'Flow', 'Common'],
                // ['header',  'Block', 'Flow', 'Common'],
                // ['footer',  'Block', 'Flow', 'Common'],
                
                // Content model actually excludes several tags, not modelled here
                ['address', 'Block', 'Flow', 'Common'],
                ['hgroup', 'Block', 'Required: h1 | h2 | h3 | h4 | h5 | h6', 'Common'],
                
                // http://developers.whatwg.org/grouping-content.html
                ['figure', 'Inline', 'Inline', 'Common'],
                ['figcaption', 'Inline', 'Inline', 'Common'],
                
                // http://developers.whatwg.org/the-video-element.html#the-video-element
                ['video', 'Block', 'Optional: (source, Flow) | (Flow, source) | Flow', 'Common', [
                    'src' => 'URI',
                    'type' => 'Text',
                    'width' => 'Length',
                    'height' => 'Length',
                    'poster' => 'URI',
                    'preload' => 'Enum#auto,metadata,none',
                    'controls' => 'Bool',
                ]],
                ['source', 'Block', 'Flow', 'Common', [
                    'src' => 'URI',
                    'type' => 'Text',
                ]],

                // http://developers.whatwg.org/text-level-semantics.html
                ['s',    'Inline', 'Inline', 'Common'],
                ['var',  'Inline', 'Inline', 'Common'],
                ['sub',  'Inline', 'Inline', 'Common'],
                ['sup',  'Inline', 'Inline', 'Common'],
                ['mark', 'Inline', 'Inline', 'Common'],
                ['wbr',  'Inline', 'Empty', 'Core'],
                
                // http://developers.whatwg.org/edits.html
                ['ins', 'Block', 'Flow', 'Common', ['cite' => 'URI', 'datetime' => 'CDATA']],
                ['del', 'Block', 'Flow', 'Common', ['cite' => 'URI', 'datetime' => 'CDATA']],
            ],
            'attributes' => [
                ['iframe', 'allowfullscreen', 'Bool'],
                ['table', 'height', 'Text'],
                ['td', 'border', 'Text'],
                ['th', 'border', 'Text'],
                ['tr', 'width', 'Text'],
                ['tr', 'height', 'Text'],
                ['tr', 'border', 'Text'],
            ],
        ],
        'custom_attributes' => [
            ['a', 'target', 'Enum#_blank,_self,_target,_top'],
            ['figure', 'class', 'Text'],
            ['figcaption', 'class', 'Text'],
            ['figcaption', 'data-trix-placeholder', 'Text'],
        ],
        'custom_elements' => [
            ['u', 'Inline', 'Inline', 'Common'],
        ],
    ],

];

Thanks in advance!

26 Sep
2 months ago

ralphmorris left a reply on Laravel Queues Strange Log Error

@martyyy just wondering if you ever got to the bottom of this?

I have just got this.

Type error: Argument 1 passed to Illuminate\Queue\Jobs\Job::resolveAndFire() must be of the type array, null given
01 Sep
3 months ago

ralphmorris started a new conversation Handling Failed One Of Charges With Cashier/spark

I have subscriptions using Spark which works great.

However there a also one off payments which need to happen occasionally for certain user actions.

For this I am using the Cashier invoiceFor method as per the docs below to generate the charge and invoice.

$user->invoiceFor('One Time Fee', 500, [
    'description' => 'your invoice description here',
]);

However this notice from the docs has stumped me:

"The invoiceFor method will create a Stripe invoice which will retry failed billing attempts. If you do not want invoices to retry failed charges, you will need to close them using the Stripe API after the first failed charge."

If the charge fails an exception is thrown with the "Your card was declined" message which is fine. However how can I then find the Invoice ID for me then to retrieve and close as per the docs?

14 Aug
4 months ago

ralphmorris left a reply on Validating Current Team If User Were To Change Teams In A Different Tab

Thanks guys, for all your input.

@Cruorzy I believe you are correct although I think the Carbon::now() would need to be done on the original page load and put into the form so you could check whether the user had switched teams since loading the current page rather than in the store method.

Something like:

if (request()->page_original_loaded_timestamp < $user->last_team_change) {
    //throw error
}

ralphmorris left a reply on Validating Current Team If User Were To Change Teams In A Different Tab

Hi @Cruorzy , no worries. Yes that's what happens. But the user would likely think they are still on the old teams page when creating a post for example as the logo (or whatever) would be the original teams. Obviously if the user refreshed the page it would show the updated current teams logo so would be more obvious but I doubt a user would remember to do that.

ralphmorris left a reply on Validating Current Team If User Were To Change Teams In A Different Tab

Thanks @Cruorzy, I'm using policies in there to check if the user is part of the team, however this would always return true unless it was a malicious user trying to access a page belonging to a team they weren't on even if the current_team_id has changed as it is a difference relationship.

However I need to check the current_team_id matches the id that the user was currently on when they first loaded the page. The only thing I can think of is a team token in a hidden input but this feels a bit much for every single form.

For instance if I had a route of /posts, there is no team identifier in the url to check the current_team_id against, so it would just create the post against the current_team_id even if it has changed when the user was on another page. As opposed to /{team}/posts where you can validate the team. However this kind of defeats the point of the having the current_team_id.

Hope that makes sense.

ralphmorris started a new conversation Validating Current Team If User Were To Change Teams In A Different Tab

I've come across a scenario where users might change teams in another tab, but then come back to the original tab and create a post for instance. This would then be assigned the the wrong team accidentally if you were simply doing the below:

$post = auth()->user()->currentTeam->posts()->create($request->all());

What might be the best/most manageable way of validating that the user is still on the same team as when they first loaded the page for example? Some sort of team_token input in every single form? or something else?

Thanks!

26 Jul
4 months ago

ralphmorris started a new conversation Spark - Charge For Only Certain User Roles In A Team?

Hi there,

I am using the chargeTeamsPerMember method in my service provider but need to allow Team owners to invite guests to join their team for free. They would be a 'guest' user role that would have less permissions in the rest of the application.

Has anybody any experience implementing this?

Thanks :)

Ralph

09 Jun
6 months ago

ralphmorris started a new conversation Failed Job Delay - Queue Settings. New Field. Not Sure What It Is

Hey all,

I've updated my Queue config and upped my ttr to 60 seconds in my queue beanstalkd config.

I went into my Forge queue settings to change the Timeout field to 60 also but noticed a new field that I'm not sure what is does.

Failed Job Delay

What does this do/should I set it to?

Also noticed 'Rest Seconds When Empty' which I'm not sure if I remember, but it has a default of 10 which I assume is ok?

Thanks as always :)

Ralph

03 May
7 months ago

ralphmorris left a reply on Query With Conditional Logic In Relationship Has() Method Always Returning True

Hi @36864 ,

Thanks for your reply.

The only trouble is the $date is different for each job so I'm not sure how I can get to it from inside the whereHas?

ralphmorris started a new conversation Query With Conditional Logic In Relationship Has() Method Always Returning True

I have the following relationship set up to show me new applications compared to when a summary of new applications was last sent out..

    // Job Model

    public function applications()
    {
        return $this->belongsToMany('App\Professional', 'applications_pivot')
                    ->withPivot('message')
                    ->withTimestamps()
                    ->with('user.professional')
                    ->orderBy('message', 'desc');
    }

    public function newApplications()
    {
        if (!$this->last_summary_sent_out_at) 
        {
            $date = Carbon::now()->subDays(30);
        }
        else
        {
            $date = $this->last_summary_sent_out_at;
        }

        return $this->applications()->whereDate('applications_pivot.created_at', '>=', $date );
    }

This works well for instances like the below. Showing me only the applications that have been created since the last summary send out.

$job = \App\Job::findOrFail(1);

dd($job->newApplications);

However when I try to use the newApplications in the has() method it seems to return all jobs that have applications, not NEW applications.

$jobs = \App\Job::has('newApplications')->get();

This seems to have something todo with $this->last_summary_sent_out_at returning false in the query builder. This makes sense but not sure how to get what I want.

Any ideas? Let me know if this isn't clear enough.

Thanks!

Ralph

ralphmorris left a reply on Query Two Different Models And Merging With Pagination

Thanks very much for everyones input. Direct Enquiries were a separate table with no relationship to conversations. hence I was trying to Union them somehow. However following from your comments I realised there was no reason why a direct enquiry couldn't be a child of a conversation as a conversation already hasMany messages so I created a hasOne directEnquiry and now only need to query the one table.

Not sure who to mark as best answer but all good advice thank you!

30 Apr
7 months ago

ralphmorris started a new conversation Query Two Different Models And Merging With Pagination

I have two Models Conversation and DirectEnquiry that I would like to query together and show in the same list of results with pagination.

This is where I am at:

        $conversations = $user->conversations()
                                ->inbox($filters)
                                ->with('job')
                                ->paginate(20);

        $directEnquiries = $user->directEnquiries()->paginate(20);

        $conversations = $conversations->merge($directEnquiries)->sortBy(function($item) {
            
            return $item->updated_at;

        })->reverse();

This works fine until it hits the pagination method at the bottom of the view

{!! $conversations->links() !!}

I am getting the following error message:

ErrorException in Macroable.php line 74:
Method links does not exist.

I've tried playing with unions also but as these are two different models that won't work.

Any ideas?

Thanks!

Ralph

23 Apr
7 months ago

ralphmorris started a new conversation Storing An Email Address In Session Data - File Driver, Unencrypted

I have a contact form on a users profile that any visitor can fill out to send an enquiry. They then have to confirm they're email address/enquiry before the message gets sent to the user who's profile it is.

There is a chance that a visitor might want to contact a few other users via their profile contact form. I don't want to create an account for the visitor as I don't want to store the data for a one off enquiry but don't want the visitor to have to confirm their email address each time they submit an enquiry.

I have thought of two options:

  1. Store the email they confirm in a session variable so that if they send a second enquiry I simply check to see if they have already confirmed the email address.

  2. Simply lookup in the db to see if that email already exists in the enquiries table where it would be stored for a short while.

With option 1, I am using the file session driver, encryption set to false. Is this an issue if I were to be storing an email address?

With option 2, I guess the only thing would be that once that email address has been confirmed any body could submit an enquiry with that email address which would automatically be confirmed. But the likelihood of that is minimal.

What would anybody suggest?

Thanks!

Ralph

16 Apr
7 months ago

ralphmorris left a reply on Input Field Unable To Edit Or Made Changes In Sweet Alert

I think for Sweet alert you need to create the inputs in a slightly different way.

Example:

swal({
  content: {
    element: "input",
    attributes: {
      placeholder: "Type your password",
      type: "password",
    },
  },
});

See here: https://sweetalert.js.org/docs/

ralphmorris left a reply on I Have A Bit Of Issues On My Laravel Project, My Jobs Run With Wrong Code.

Do you by any chance have multiple queues running on the one server? For instance staging and production? If so you'd want to configure them to have different queue names.

31 Mar
8 months ago

ralphmorris left a reply on Updating Multiple Rows Ignoring SetAttribute

Thanks @Snapey - ended up encrypting the string first as you said.

30 Mar
8 months ago

ralphmorris started a new conversation Updating Multiple Rows Ignoring SetAttribute

I'm using L5.2 and on deletion of a user am removing the content of the users messages but keeping the rows in the db so as not to ruin the thread for other users.

I am using the following trait to encrypt/decrypt the message field which works well.

<?php

namespace App\Traits;

use Crypt;

trait EncryptableTrait
{
    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);

        if (in_array($key, $this->encryptable)) {
            $value = Crypt::decrypt($value);
        }

        return $value;
    }

    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->encryptable)) {
            $value = Crypt::encrypt($value);
        }

        return parent::setAttribute($key, $value);
    }
}

When updating each row separately inside a foreach loop the new string gets encrypted perfectly as per normal.

foreach ($this->messages as $message) 
{
        $message->update(['message' => 'This content is no longer available.']);
}

However there could be many messages that the user might have sent and so would rather update them all in one query. I tried the below however it skips the setAttribute.

$this->messages()->update(['message' => 'This content is no longer available.']);

Is that expected behaviour? I'd like to keep the encrypting/decrypting only in the EncryptableTrait rather than wrap "This content is no longer available" in the encrypt method if possible.

Thanks!

Ralph

13 Mar
9 months ago

ralphmorris left a reply on Order By Count This Month

Hi @bashy

Thanks for your reply.

Typically, an idea came to me just after posting this question and think I've got it working now!

I created a new relationship with the added thisMonth query scope.

    public function referralsThisMonth()
    {
        return $this->referrals()->thisMonth('referral_activated');
    }

And then modified the controller method as follows:

    public function getTopReferrersThisMonth()
    {
        return User::has('referralsThisMonth')
                    ->withCount('referralsThisMonth')
                    ->orderBy('referrals_this_month_count', 'desc')
                    ->take(3)
                    ->get();
    }

ralphmorris started a new conversation Order By Count This Month

Hi there,

I have a referral system where users can refer other users.

Relationships

    public function referredBy()
    {
        return $this->belongsTo('App\User', 'referred_by');
    }

    public function referrals()
    {
        return $this->hasMany('App\User', 'referred_by');
    }

There is also a 'referral_activated' dateTime field which gets set once the user is confirmed which is the point when the referrer gets their reward.

In our admin interface I am trying to get the top 3 referrers this month and order them by their referrals count that month.

My code so far.

    // Controller
    public function topReferrersThisMonth()
    {
        return User::whereHas('referrals', function ($query) {
                        $query->thisMonth('referral_activated');
                    })
                    ->withCount('referrals')
                    ->orderBy('referrals_count', 'desc')
                    ->take(3)
                    ->get();
    }

    // Model
    public function scopeThisMonth($query, $field = 'created_at')
    {
        return $query
            ->whereDate($field, '>=', Carbon::now()->startOfMonth())
            ->whereDate($field, '<=', Carbon::now()->endOfMonth());
    }

This almost does what I want apart from it is ordering by the total count, not the count this month. Can anyone point me in the right direction?

Thanks :)

Ralph

18 Jan
10 months ago

ralphmorris left a reply on Queues On Forge

Thanks @bobbybouwmann for your reply. It was really helpful.

Can I just double check question 1 though? If I set the ttr in my config/queue.php to 10, do I then need to set my Timeout config to 10 also? Or does the timeout need to be larger?

I updated my forge queues to have more workers and all has been fine for a few days sending quite a few emails until just now i've had this:

Pheanstalk\Exception\ServerException: Cannot delete job 16309: NOT_FOUND 

I think this is because I still had no Timeout set in Forge, but did have the ttr set to 10 in my config. Does that sound right?

My app sent out about 40 emails and I had 3 of those exceptions. From looking at my mail logs, I can see a few of the emails look like they got sent twice.

Thanks again

16 Jan
10 months ago

ralphmorris left a reply on Chart Js Multiple Chart On A Page. Filtering/Reloading Chart

@ejdelmonico Yeah, I'm thinking about bringing vue into it as have been keen to start playing with it anyway. But the app has been live for a little while now and there's not much more development that's planned yet so might feel like overkill to bring it in so late?

Correct, all 4 charts work perfectly until I filter. The filter works fine too for the last chart that is created. It's just getting multiple filters working with the same code.

ralphmorris left a reply on Chart Js Multiple Chart On A Page. Filtering/Reloading Chart

Thanks @ejdelmonico,

It definitely is something to do with that.

Essentially I am initialising 4 charts on the page, the second one is currently the only with a filter but need to add it to all of them.

What I've noticed is that if I initialise the one with the filter last it works fine, but if I initialise another chart after this one, the performanceChart.chart variable is changed to the latest instance of the chart. So I am losing the instance of the chart as it is I guess being overridden.

I thought the way it worked was that each object call would have its own scope somehow but it seems that calling performanceChart.init($('#mysecondid')); a second time overwrites the performanceChart.chart variable instance.

Does anyone know how I can get around/fix this?

ralphmorris started a new conversation Chart Js Multiple Chart On A Page. Filtering/Reloading Chart

I've got the following code which has worked well with multiple charts on one page until now when I have tried to add some range options which then reloads the chart.

Code:

var performanceChart = {

    chart: '',

    type: '',

    datasetValue: [],

    target: '',

    init: function(target, type) {

        performanceChart.type = type || 'bar';
        
        performanceChart.target = target;

        performanceChart.datasetValue = performanceChart.prepareDataset();
        
        performanceChart.createChart();

        performanceChart.onChange();

    },

    prepareDataset: function() {

        var label = performanceChart.target.attr('data-label');
        var data = JSON.parse(performanceChart.target.attr('data-data'));

        var datasetValue = [];

        datasetValue[0] = {
            label: label,
            data: data,
            backgroundColor: 'rgba(168, 212, 210, .6)',
            borderColor: 'rgba(168, 212, 210, 1)',
            borderWidth: 1
        }

        if (performanceChart.target.attr('data-label-2')) {

            var label2 = performanceChart.target.attr('data-label-2');
            var data2 = JSON.parse(performanceChart.target.attr('data-data-2'));

            datasetValue[1] = {
                label: label2,
                data: data2,
                backgroundColor: 'rgba(215, 190, 126, .6)',
                borderColor: 'rgb(215, 190, 126)',
                borderWidth: 1
            }

        }

        return datasetValue;

    },

    createChart: function() {

        performanceChart.chart = new Chart(performanceChart.target, {
            type: performanceChart.type,
            data: {
                labels: JSON.parse(performanceChart.target.attr('data-MonthLabels')),
                datasets: performanceChart.datasetValue
            },
            options: {
                maintainAspectRatio: false,
                responsive: true,
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero:true,
                            min: 0,
                            // autoSkip: true,
                            maxTicksLimit: 6,
                            // stepSize: 1
                            callback: function(value, index, values) {
                                if (Math.floor(value) === value) {
                                    return value;
                                }
                            }
                        }
                    }]
                },
            }
        });

    },

    onChange: function() {

        performanceChart.target.closest('.js-chart-container').find('.select2').change(function() {

            performanceChart.loadData($(this).closest('form'));

        });

    },

    loadData: function(form) {

        $.ajax({
            type: "POST",
            url: form.attr('action'),
            data: form.serialize(),
            success: function(result) {

                performanceChart.target.attr("data-monthLabels", JSON.stringify(result.monthLabels));
                performanceChart.target.attr("data-data", JSON.stringify(result.count));

                performanceChart.chart.destroy();

                var datasetValue = performanceChart.prepareDataset();

                performanceChart.createChart(datasetValue);
                
            },
            error: function(data){

                var errors = data.responseJSON;

                console.log(errors);
                
                return false;
            },
        });

    },

};

I can then call it multiple time with:

performanceChart.init($('#myfirstid'));
performanceChart.init($('#mysecondid'));

I am trying to store the variables in global variables inside the object like performanceChart.chart for instance. But when I try updating the first chart it ends up reloading the last chart.

I think I need to somehow scope this but not sure how.

Forgive me I'm still working on my js skills.

Thanks!

14 Jan
11 months ago

ralphmorris started a new conversation Queues On Forge

2 quick questions on if anyone can clear this up for me?

  1. Should the Maximum Seconds per job in the Forge settings match the TTR in my config/queue.php? I currently have a limit of 10 in my TTR config but 0 (No timeout) in Forge. I'm not sure if these are related? I see other people are setting to 90, so is my 10 a little low. I am mainly just queue mail.

  2. Are 'Processes' in Forge the equivalent of logging in in the terminal with two different tabs and running php artisan queue:listen twice on the same site? Probably a stupid question but have anyone to ask!

Thanks!

31 Dec
11 months ago

ralphmorris started a new conversation Scope Subscribed To Plan - Laravel Cashier

I have written this query scope to filter users that are subscribed to a particular plan in Laravel Cashier.

    /**
     * Scope subscribed to given plan
     * 
     * @param  $query builder
     * @param  $plan string/array
     * @return builder
     */
    public function scopeWhereSubscribedToPlan($query, $plan)
    {
        return $query
            ->active()
            ->whereHas('subscriptions', function ($s) use ($plan) {
                $s->whereNested(function ($t) use ($plan) {
                    $t->whereIn('stripe_plan', (array) $plan)
                        ->whereNull('ends_at')
                        ->orWhere('ends_at', '>', Carbon::now())
                        ->orWhereNotNull('trial_ends_at')
                        ->where('trial_ends_at', '>', Carbon::today());
                });
            });
    }

However I have noticed if the if the ends_at column is is not null and has a date in the future, it ignores the whereIn clause and shows users in the wrong plan.

Where am I going wrong?

30 Dec
11 months ago

ralphmorris left a reply on Updated Homestead To Latest - L5.2, Need Php7.0, Command Line Still Using Php7.2 - ErrorException: Count(): Parameter Must Be An Array Or An Object That Implements Countable

Ah finally got it. I had to move my homestead.yaml back to the .homestead folder as it's now using the older version again.

I have php7.0 back!

2.20am here. I can now go to bed...

ralphmorris left a reply on Updated Homestead To Latest - L5.2, Need Php7.0, Command Line Still Using Php7.2 - ErrorException: Count(): Parameter Must Be An Array Or An Object That Implements Countable

Hi @shez1983 - yeah I've been following the docs here:

https://laravel.com/docs/5.4/homestead#old-versions

But it still says 7.2 when I run php -v

Steps I've taken:

Top of my homestead.yaml I've added the version

---
box: laravel/homestead
version: 0.6.0
ip: "192.168.10.10"
memory: 2048
cpus: 4
provider: virtualbox

vagrant destroy --force

vagrant box add laravel/homestead --box-version 0.6.0

Reset the Homestead repo to this commit for php7.0

https://github.com/laravel/homestead/releases/tag/v3.1.0

git reset --hard 7924ab4

But then after running vagrant up, ssh'ing in and running php -v it still says php 7.2.0-1

Am I missing something? I thought this was going to fix it.

ralphmorris started a new conversation Updated Homestead To Latest - L5.2, Need Php7.0, Command Line Still Using Php7.2 - ErrorException: Count(): Parameter Must Be An Array Or An Object That Implements Countable

I've updated my Laravel Homestead to the latest version where I can now control the php versions of each dev site.

I have added the php: "7.0" to my yaml however this doesn't effect the command line php version. I can see in the docs that I can do something like php7.0 artisan ... but I need phpunit to run php7 also but is running 7.2 and so am getting this error.

ErrorException: count(): Parameter must be an array or an object that implements Countable

How can I get round this? Do I have to use an older version of homestead? Or update my app to L5.5? Though I could update my app quite yet.

Thanks

ralphmorris left a reply on Hospital Management

Something like this on your Bed model perhaps?

    public function assignPatient($id)
    {
        $this->patient_id = $id;
        $this->save();
    }

ralphmorris left a reply on Shared Hosting Run Php Artisan Command

Do you have ssh access?

22 Dec
11 months ago

ralphmorris left a reply on Send Form Cross-domain

You could disable CSRF for only this specific route but then create your own middleware where you could do your own validation/check the referrer etc?

Just an idea.

ralphmorris left a reply on How To Navigate To Next Form In Next Tab After Saving Current Form ?

You could try this I think

return redirect('/transfer-request#complete')->with('message', 'Success!');
18 Dec
11 months ago

ralphmorris started a new conversation Phpunit Really Slow With Mysql. Tried Sqlite. Throws Null Errors On Migration/saving

Completely new to testing.

My production db is on MariaDB and locally I'm using MySQL on Homestead.

I've written a few very basic tests following tutorials to get started, connecting to a local mysql db.

However have noticed that to run these tests it literally takes 45 seconds. I've read that sqlite is a lot faster but is 45 seconds still normal for tests with mysql?

These are my tests. Some of them are probably a bit stupid but I'm learning ;)


use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class PagesTest extends TestCase
{
    /** @test */
    function browse_main_pages_to_artist_profile()
    {
        $this->visit('/')
            ->see('The smarter way to book hair and makeup artists for your wedding day.')
            ->click('Inspiration Board')
            ->see('Need some inspiration?')
            ->click('Browse Artists')
            ->see('Search for')
            ->select('berkshire', 'location')
            ->press('SEARCH')
            ->see('Artists In Berkshire')
            ->click('VIEW PROFILE')
            ->see('Contact Artist');
    }

    /** @test */
    function footer_pages()
    {
        $this->visit('/')
            ->click('SIGN UP')
            ->see('Request availability')
            ->click('LOGIN')
            ->see('Login')
            ->click('FAQs')
            ->see('FAQs')
            ->click('JOIN US')
            ->see('Artist Registration')
            ->click('OUR MISSION')
            ->see('Our Mission')
            ->click('TERMS OF USE')
            ->see('Terms of Use')
            ->click('PRIVACY POLICY')
            ->see('Privacy Policy')
            ->click('COOKIE POLICY')
            ->see('Use of Cookies')
            ->click('CONTACT US')
            ->see('Contact us');
    }
}

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\User;

class ProfessionalRegistrationTest extends TestCase
{
    /** @test */
    function a_user_fills_out_the_application_form_and_gets_a_success_message()
    {
        $email = str_random(10) . '@test-professional.com';

        $this->visit('/professional-registration')
            ->type('Ralph', 'first_name')
            ->type('Morr', 'last_name')
            ->type($email, 'email')
            ->type($email, 'email_confirmation')
            ->type('Ralphs Business name', 'business_name')
            ->type('qqqqqqQ1', 'password')
            ->type('qqqqqqQ1', 'password_confirmation')
            ->select('1', 'insurance')
            ->select('1', 'services')
            ->type('Example postal code', 'postal_code')
            ->type('some town', 'town')
            ->type('Hampshire', 'county')
            ->select('1', 'locations')
            ->type('5', 'years_experience')
            ->type('www.google.com', 'website')
            ->type('ralphyinsta', 'instagram_username')
            ->check('accept_terms')
            ->press('Sign Up')
            ->see('Email confirmation sent!');
    }

    /** @test */
    function a_professional_confirms_their_email_address()
    {
        $user = User::orderBy('created_at', 'desc')->first();

        $this->visit(route('professional.registration.confirm', $user->confirmation_code))
            ->see('Thanks for confirming!');
    }
}

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\User;

class BrideSignUpTest extends TestCase
{
    /** @test */
    function a_bride_fills_out_the_enquiry_form_on_the_home_page()
    {
        $email = str_random(10) . '@test-bride.com';

        $input = [
            'first_name'                        => 'Lucy',
            'last_name'                         => 'Bradd',
            'email'                             => $email,
            'email_confirmation'                => $email,
            'client[job][wedding_date]'         => '25-12-2020',
            'client[job][location_id]'          => '3',
            'client[job][bride_makeup]'         => 1,
            'client[job][bride_hair]'           => 1,
            'client[job][bridesmaids_makeup]'   => 1,
            'client[job][bridesmaids_hair]'     => 1,
            'client[job][mothers_of_hair]'      => 0,
            'client[job][mothers_of_makeup]'    => 0,
            'client[job][flower_girls_makeup]'  => 0,
            'client[job][flower_girls_hair]'    => 0
        ];

        $this->visit('/')
            ->submitForm('Send now!', $input)
            ->see('Set your password!');
    }

    /** @test */
    function a_bride_then_confirms_their_email_address()
    {
        $user = User::orderBy('created_at', 'desc')->first();

        $this->visit(route('client-dashboard.confirm', $user->confirmation_code))
            ->see('Your enquiry has been sent!');
    }
}

One thing I've also noticed is that emails are getting sent out when I run the test even though I don't have my queue worker running locally when running the tests which is kinda cool! But probably slowing down things?

Lastly, I tried using sqlite for test but got loads of errors with the migrations to do with making all fields nullable when adding to an existing table. I added nullable to get around this but then got syntax errors on the below method even this works fine with mysql. Just wondering if maintaining two database types is going to be more of a pain than it's worth?

    {
        $slug = str_slug($slug, '-');

        $count = Professional::whereRaw("slug RLIKE '^{$slug}(-[0-9]+)?$'")->count();

        return $count ? "{$slug}-{$count}" : $slug;
    }```


Appreciate any advice!
13 Dec
1 year ago

ralphmorris left a reply on Send Notification 'exactly' 1 Hour After DateTime Field

Awesome. That is exactly what I want thanks.

Out of interest do you know what the limit might be of Beanstalkd/Redis? Just for future.

ralphmorris left a reply on Send Notification 'exactly' 1 Hour After DateTime Field

Thanks for your responses.

I didn't know about about the delay method. Sounds awesome.

I see this as a note: "The Amazon SQS queue service has a maximum delay time of 15 minutes.".

Does the delay method work with Beanstalkd? As that is what I am currently using.

ralphmorris left a reply on Eloquent API Resources - Nested Relationship?

You could add the id of the School to your students table? Then create another relationship.

ralphmorris started a new conversation Send Notification 'exactly' 1 Hour After DateTime Field

I have a Job model which has a last_sent_out_at field which stores a timestamp of the last time a notification was sent. ry I have created an artisan command which I could call every minute which would query the Job model by that last_sent_out_at and send the notification if found as per the below.

        $jobs = Job::whereDate('last_sent_out_at', '=', Carbon::now()->subHour(1)->format('Y-m-d H'))->get();

        foreach ($jobs as $job) 
        {
            $job->sendNotification();
        }

However:

a) This seems like a lot of db calls for one simple occasional task. Can anyone suggest a better way?

b) the $jobs var is constantly returning 0 when I dd($jobs->count()) even when I run date in the terminal, quickly add the correct minute 1 hour ago and run the command.

Thanks

ralphmorris left a reply on 'Return Ajax' Printing The Code?

Try returning your array with something like.

return response()->json(['success'=>1, 'msg'=> trans('app.payment_received_msg'), 'response' => $this->payment_success_html()]);

https://laravel.com/docs/5.5/responses#json-responses

ralphmorris left a reply on How Do You Get The Updated_at Date For Only Certain Fields

Try adding another dateTime field where you would store the timestamp of when you updated your specific information?

I'd probably leave the actual updated_at field as it can sometimes come in handy down the line.

01 Nov
1 year ago

ralphmorris left a reply on Export Table To CSV - Escaping Commas

Just trying to add the ability to remove certain keys from the exported csv, like 'id' etc.

I've tried adding the following line at the top of the above method.

$collection = $collection->forget($collection->first()->notExportable);

But has it has no effect?

On my model I have for example:

    public $notExportable = [
        'id',
        'some_other_protected_field'
    ];

My controller:

    public function exportToCsv(UserFilters $filters)
    {
        $users = User::filter($filters)->new()->get();

        $exporter = new Exporter;

        return $exporter->exportToCsv($users);
    }
29 Oct
1 year ago

ralphmorris left a reply on Order By Tag Priority

@tisuchi I have the longitude and latitude of the users on a separate professionals table which is where I am storing all their profile information. I'm unsure how I can order the users by the lng and lat of their values on the professional table.

These are my relationships:

Location Model

    public function users()
    {
        return $this->belongsToMany('App\User');
    }

User Model

    public function professional()
    {
        return $this->hasOne('App\Professional');
    }

My query currently is:

        $professionalUsers = $location->users()->active();

        $professionalUsers->has('portfolio');

        $professionalUsers = $professionalUsers->paginate(20);

To add the orderBy nearest longitude and latitude login I want to add something like:

        $professionalUsers = $location->users()->active();

        $professionalUsers->has('portfolio');

        // Example location. Hardcoded for now.
        $lat = '50.842991';
        $lng = '50.842991';

        $professionalUsers = $professionalUsers
        ->orderBy(\DB::raw('ABS(lat - '.(float)$lat.') + ABS(lng - '.(float)$lng.')'),'ASC' )
        ->paginate(20);

But this is looking for lat and lng columns on the users table.

I found that orderBy line here:

https://stackoverflow.com/questions/28601607/laravel-orderby-calculated-value

I think I need to do a join but not sure where/how?

Thanks

25 Oct
1 year ago

ralphmorris started a new conversation Beanstalkd Error - Job 4058 NOT_FOUND: Does Not Exist Or Is Not Reserved By Client / Queue/Forge Tip

Hi,

I've just had a notification from Sentry on my new app. A new post has just been sent out and so about 42 emails were added to the queue.

The error is:

Beanstalkd Error - Job 4058 NOT_FOUND: does not exist or is not reserved by client

I have found a few forum discussions suggesting to up the ttr. Mine is currently set to only 10 in my config/queue.php which I'm discovering sounds very low?

I can see in the mailgun logs one temporary failed message: "Service closing transmission channel - command timeout" which I guess might be where the response from mailgun took too long and so hit the ttr?

I think there might also be a slight issue with my Forge config not matching my config/queue.php - does the timeout section have to match the ttr?

In my config/queue.php I have:

        'beanstalkd' => [
            'driver' => 'beanstalkd',
            'host' => 'localhost',
            'queue' => env('QUEUE_NAME'),
            'ttr' => 10,
        ],

And in my Forge settings I have one queue set up as the following:

Connection: beanstalkd Queue: queue-production Timeout: 0 Processes: 1 Tries: 3 Daemon: No

Can someone just confirm that my set up looks ok and suggest a more appropriate ttr/timeout in Forge?

Thanks

ralphmorris left a reply on Order By Tag Priority

Hi @tisuchi

Sorry I should have mentioned. The Locations are UK counties that a user can choose to cover or not.

Some users may only want to cover one county while others might choose to cover 10.

However they may still want to prioritise certain counties over others.

There's likely to be some restriction as to how many counties a user can cover based on subscription level in the future.

Thanks

ralphmorris started a new conversation Order By Tag Priority

Hi,

I have a many to many relationship between Users and Locations so that users can tag themselves to certain locations they want to show up in.

I need to somehow order the results by the priority of their tag (Location). I am imagining making my select2 drag and drop sortable so that they can put preferred locations higher up to be prioritised more. However how this could be implemented on the server side I am not sure.

Possibly by adding an integer field to the users_locations table?

Does anyone have any idea how I could do this? And then be able to order the Users on the frontend?

I hope this is clear. It's confusing me a little!

Thanks

Ralph

22 Oct
1 year ago

ralphmorris left a reply on Occasional TokenMismatch Error - Is That Normal?

Thanks guys for your responses. Congrats @Snapey on the 1000 best answers!

@ejdelmonico - Just to double check. My forms all contain the _token hidden input and all I'm doing is serialising the form with something like:

        $.ajax({
            type: "POST",
            url: $('form').attr('action'),
            data: $('form').serialize(),

So the token is inside with the form data.

In parts where I am sending an ajax request without the use of a form I use

        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });

@Snapey - would you mind expanding on why the CSRF isn't needed on the login form? One of the forms is located on the homepage so it's very possible that the user has left and come back later. The other is the login page so this would be possible also. The third is a logged in profile page where they can add/update bits of info.

Thanks!

21 Oct
1 year ago

ralphmorris started a new conversation Occasional TokenMismatch Error - Is That Normal?

Hi,

I launched my first Laravel app about 4 months ago with Laravel 5.2, Forge & Digital Ocean. All is going well so far but have noticed Sentry has flagged the TokenMismatch error 5 times since October 3rd. We have 225 users so far, approx 1000 users a month, average duration on the site is 5 mins.

It looks like 3 separate occasions though in 3 different parts of the site. I haven't found any issue when using those sections myself.

3rd Oct - Creating a resource. The user does not have to be logged in but has an account created after creating the resource. Many users have since created the same resource just fine.

10 Oct - 3 errors on the same user action. Update another resource with ajax. I have tested this but all seems to work fine for me. The user must be logged in to get to this page.

21 Oct - postLogin method when logging in.

I have read other posts where the TokenMismatch error is happening multiple times a day. Is it normal to get a few of these errors here and there?

Thanks!

Ralph