ralphmorris

Experience

23,390

1 Best Reply Awards

  • Member Since 2 Years Ago
  • 198 Lessons Completed
  • 0 Favorites

1st September, 2018

ralphmorris started a new conversation Handling Failed One Of Charges With Cashier/spark • 2 weeks ago

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?

14th August, 2018

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

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 • 1 month ago

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 • 1 month ago

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 • 1 month ago

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!

26th July, 2018

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

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

9th June, 2018

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

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

3rd May, 2018

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

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 • 4 months ago

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 • 4 months ago

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!

30th April, 2018

ralphmorris started a new conversation Query Two Different Models And Merging With Pagination • 4 months ago

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

23rd April, 2018

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

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

16th April, 2018

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

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. • 5 months ago

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.

31st March, 2018

ralphmorris left a reply on Updating Multiple Rows Ignoring SetAttribute • 5 months ago

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

30th March, 2018

ralphmorris started a new conversation Updating Multiple Rows Ignoring SetAttribute • 5 months ago

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

13th March, 2018

ralphmorris left a reply on Order By Count This Month • 6 months ago

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 • 6 months ago

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

18th January, 2018

ralphmorris left a reply on Queues On Forge • 8 months ago

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

16th January, 2018

ralphmorris left a reply on Chart Js Multiple Chart On A Page. Filtering/Reloading Chart • 8 months ago

@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 • 8 months ago

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 • 8 months ago

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!

14th January, 2018

ralphmorris started a new conversation Queues On Forge • 8 months ago

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!

31st December, 2017

ralphmorris started a new conversation Scope Subscribed To Plan - Laravel Cashier • 8 months ago

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?

30th December, 2017

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 • 8 months ago

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 • 8 months ago

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 • 8 months ago

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 • 8 months ago

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 • 8 months ago

Do you have ssh access?

22nd December, 2017

ralphmorris left a reply on Send Form Cross-domain • 8 months ago

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 ? • 8 months ago

You could try this I think

return redirect('/transfer-request#complete')->with('message', 'Success!');

18th December, 2017

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

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!

13th December, 2017

ralphmorris left a reply on Send Notification 'exactly' 1 Hour After DateTime Field • 9 months ago

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 • 9 months ago

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? • 9 months ago

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 • 9 months ago

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? • 9 months ago

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 • 9 months ago

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.

1st November, 2017

ralphmorris left a reply on Export Table To CSV - Escaping Commas • 10 months ago

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);
    }

29th October, 2017

ralphmorris left a reply on Order By Tag Priority • 10 months ago

@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

25th October, 2017

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

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 • 10 months ago

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 • 10 months ago

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

22nd October, 2017

ralphmorris left a reply on Occasional TokenMismatch Error - Is That Normal? • 10 months ago

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!

21st October, 2017

ralphmorris started a new conversation Occasional TokenMismatch Error - Is That Normal? • 10 months ago

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

18th October, 2017

ralphmorris left a reply on Export Table To CSV - Escaping Commas • 11 months ago

Thanks both for your replies :)

I initially tried @Cronix's suggestion as it was closest to what I already had which worked well for the escaping of commas but when I tried it on some live data I discovered there were more characters that needed escaping. I then tried @robrogers3's suggestion and integrated it into my class. It worked great with all data I tested it with.

Here is the full code incase it helps anyone else in the future.

<?php

namespace App\Exporter;

class Exporter
{
    /**
     * Export any collection to CSV. All fields exported.
     * 
     * @param  Collection $collection
     * @return Response downloads CSV
     */
    public function exportToCsv($collection)
    {
        $f = fopen('php://memory', 'w+');
        
        $header = array_keys($collection->first()->toArray());

        fputcsv($f, $header);
        foreach ($collection as $thread)
            fputcsv($f, $thread->toArray());

        rewind($f);

        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="export.csv"',
        ];

        return \Response::make(stream_get_contents($f), 200, $headers);
    }
}

17th October, 2017

ralphmorris started a new conversation Export Table To CSV - Escaping Commas • 11 months ago

Hi there,

I wonder if anyone can help me.

I am working on creating an export to CSV function for any collection I pass to it.

I have created the following class.

<?php

namespace App\Exporter;

class Exporter
{
    
    public function exportToCsv($collection)
    {
        $first = $collection->first();

        $output = implode(", ", array_keys($first['attributes']))."\n";

        foreach ($collection as $row) 
        {
            $output .= implode(", ",$row['attributes'])."\n";
        }

        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="export.csv"',
        ];

        return \Response::make($output, 200, $headers);
    }
}

This works well if there are no commas, but one field on say the Users table contains a description where the user can easily enter commas. These commas are breaking the layout of my csv export. I know I need to escape the commas I think by wrapping each field in double quotes but can't figure out how to achieve this with the implode function.

Any help appreciated!

18th September, 2017

ralphmorris left a reply on Messaging System. Should Encrypt Messages In Db? • 1 year ago

Thanks @kobear for your advice.

The application is marketed at mostly self employed/small businesses selling their services.

I did end up adding the trait and writing a migration to update all the current messages just to be safe.

16th September, 2017

ralphmorris started a new conversation Scope Orderby Subscription Level - Cashier • 1 year ago

I have 3 subscription levels with Laravel Cashier and Stripe.

Free - no customer/subscription created. Pro Member - monthly subscription Pro Plus member - monthly subscription

I have been tasked with ordering Users by subscription like so.

Pro Plus Member - Priority 1 Pro Member - Priority 2 Free - Priority 3

The only idea I have is to have an integer 'order' field on the user model and create a global scope to order by this field.

But I am wondering if there is a tidier way that I can do the calculation based on the stripe_plan itself?

Stripe Plans Ids are as above:

Pro Plus Member Pro Member Free (no stripe plan created)

Thanks in advance

Ralph

2nd September, 2017

ralphmorris started a new conversation JOB_TOO_BIG: Job Data Exceeds Server-enforced Limit • 1 year ago

I have just added encryption to my messages model on the message field.

All is working well with standard size messages but when adding 1000 words as a bit of a stress test. I start to get JOB_TOO_BIG: job data exceeds server-enforced limit.

It is failing when I try to add a new message notification onto the Mail queue. I am using Pheanstalk.

I've just tested it again but removing the encryption and restoring the database. It still happens but it takes a few more large messages for it to overload the queue so I guess this issue was still here before encryption it's just the messages haven't been long enough to cause any issue. So my concern is that when I release the encryption on messages the message field will become larger and this may become an issue on production?

How can I ensure that I don't overload the queue?

After the queue has been overloaded, it seems to crash as even small messages get the same error after. However no more messages are sent with the Mail queue. I have to literally delete the rows that are too big from the database for the queue to begin working again. Is there another way to manage this?

Thanks

Edit Your Profile
Update

Want to change your profile photo? We pull from gravatar.com.