haakym

Experience

27,710

2 Best Reply Awards

  • Member Since 2 Years Ago
  • 393 Lessons Completed
  • 1 Favorite

6th July, 2017

haakym left a reply on Unknown Error: Cannot Find Chrome Binary Using Laravel Dusk And Valet • 1 month ago

The error messages states:

... cannot find Chrome binary ...

Do you have Google Chrome installed?

6th June, 2017

haakym left a reply on Guidance On Contributing To Laravel • 2 months ago

@Flugg

Ah, okay thanks! Sorry wasn't super clear to me.

Thanks for the encouragement!

5th June, 2017

haakym started a new conversation Guidance On Contributing To Laravel • 2 months ago

I would like to contribute to the Laravel framework. I started by browsing the issues on github and found this issue: https://github.com/laravel/framework/issues/19445.

The Laravel documentation states:

To encourage active collaboration, Laravel strongly encourages pull requests, not just bug reports. "Bug reports" may also be sent in the form of a pull request containing a failing test.

https://laravel.com/docs/5.4/contributions#bug-reports

As most issues are above my understanding, I thought I'd start off small and try to write a failing test for the aforementioned issue. Perhaps that wasn't very helpful? However, I thought that if I don't try I won't learn anything.

I made a PR to the 5.4 branch with the failing test which was subsequently closed: https://github.com/laravel/framework/pull/19460.

and I now have a couple of questions about contributing that I would hope somebody could answer...

How and where would one submit a bug report in the form of a PR/failing test, is it meant to go on a different branch?

The response I got after submitting the PR with the failing test suggested that I should be submitting a fix in the PR and not just a failing test. I assume they meant the fix and a passing test as I couldn't understand how you could have a failing test accompanied with a fix? Have I misunderstood the feedback I got on the PR or/and the context of the text I quoted above from the docs contribution guide, in which case please explain to me what I have misunderstood.

Any guidance on this would be greatly appreciated, thank you!

28th March, 2017

haakym left a reply on Async Await In Vue Component Compiling With Laravel Mix • 4 months ago

Right, so I'm using the async/await wrong, nothing to do with Mix as far as I'm aware.

haakym started a new conversation Async Await In Vue Component Compiling With Laravel Mix • 4 months ago

Hi everyone.

I've written the following methods in a .vue component utilising async/await on an axios post request call. However, when running the code it doesn't appear the async/await stuff is working as some of the variables that get set using it return undefined until the end of the execution of the code. I've stripped the code down to what I think are the important parts, happy to show more if needed.

resources/assets/js/components/PrintTicketDashboard.vue

printTicket() {
    let ticketInfo = this.saveTicket() // <-- async method is invoked here, see below
    
    let zplCommand = this.buildZplCommand()
    
    let printJob = this.printZpl(zplCommand)
},

async saveTicket() {
    const response = await axios.post('/tickets/store', {
        'department_id': this.ticket.department.id,
        'student_id': this.ticket.student.id,
        'ticket_data': JSON.stringify(this.ticket)
    })
    
    const createdAt = new Date(response.data.created_at)
        
    this.ticket.sequenceNumber = response.data.sequence_number
    this.ticket.dateTime = `${createdAt.getHours()}:${createdAt.getMinutes()} ${createdAt.getDate()}/${createdAt.getMonth() + 1}/${createdAt.getYear()}`
    /*
        ^--- these props are accessed in buildZplCommand() and printZpl() invoked in method above but return undefined until end of execution
    */
},

I'm using laravel mix to compile my assets and was under the impression the mix.js() method will compile any ES2015 (such as async/await) as mentioned here https://laravel.com/docs/5.4/mix#working-with-scripts.

I've tried mix.babel() instead but got some errors that I couldn't make sense of, perhaps I need a babel.rc file?

app.js

Vue.component('print-ticket-dashboard', require('./components/PrintTicketDashboard.vue'));

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

webpack.mix.js

const { mix } = require('laravel-mix');

mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css')
   .browserSync('ticket.dev')
   .disableNotifications();

Any ideas on what I might be doing wrong here?

17th March, 2017

haakym left a reply on Laravel Mix Windows Npm Error • 5 months ago

@rik13 Thank you!

10th March, 2017

haakym left a reply on Showing Request Validation Errors When Submitting Form By Ajax • 5 months ago

Hi @pjfl

If your endpoint is not understanding that it's an ajax request it may be returning a redirect back with the errors instead of a failed response back with the errors as json.

You might be best creating your own question with the code you're using.

6th March, 2017

haakym started a new conversation Braintree Setting Amount And Avoiding Rounding Errors • 5 months ago

I am creating a web app using PHP/Laravel and Braintree for payments. I am using the Braintree dropin.

A simplified flow of the web app:

  1. User uploads a file and selects a service from dropdown, submits form
  2. User is shown quote/price which is calculated by taking the uploaded file's word count * selected service
  3. User selects payment via Braintree drop-in, submits form to pay
  4. Web app fires Braintree_Transaction::sale()
  5. User is shown success page

Charging the customer

Regarding the above, I would like to get some advice on best practice for setting the amount in the Braintree_Transaction::sale() method call in step 4.

In the Braintree PHP example on github the amount used in the Braintree_Transaction::sale() method call is taken from a text input in the form, this can be edited by the user, I assume for example purposes.

In my web app flow described above, after step 1, would I be correct to set the quote/price of the selected service in the session then show this value from the session to the user in step 2 and finally pass the value from the session as the amount to Braintree_Transaction::sale()? Or is there a different recommended approach to take? My main concern is charging the customer the correct amount.

Avoiding rounding errors

As the quote/price is calculated in PHP by taking the uploaded file's word count and multiplying it with the service a customer has selected this will at times involve floating point numbers. E.g. Word count is 1000, selected service is proof-reading which is x1.5, so quote would be 1500 => £15.00.

If my memory serves me correctly Stripe represents, for example, one pound (£) in pennies `10. This is nice as it helps avoid rounding errors. Braintree on the other hand I believe expects one pound (£) to be represented with the decimal point `1..

What would be my best approach to avoid any rounding errors in such a scenario?

Thanks for any suggestions and please ask for more details if required I've tried to make this as brief and general as possible.

1st March, 2017

haakym left a reply on Add Watermark/stamp To PDF With Preview • 5 months ago

Hi @sorcjc

Yes, my working solution (although a bit hacky) was to use Mozilla's pdf.js and a JS drag and drop library as a preview in the browser. Then send the data over to the server and use FPDF or FPDI (I forget which one) to perform creation of the stamped documents.

What are you trying to do exactly? Would love to help if I can.

26th January, 2017

haakym left a reply on Preparing The Database Before A Test For A Model With Many Dependencies, Is There A Better Way? • 6 months ago

For anyone interested, I have made an SO question with an answer to use \Schema::disableForeignKeyConstraints(); which works. See here:

http://stackoverflow.com/questions/41802499/laravel-preparing-the-database-before-a-test-for-a-model-with-many-dependencies

Please note my comment under this answer:

although this achieves what I originally asked in my question, i.e. "Is there a more simple approach where I only create the model that is under test" - is this considered "bad practice" at all? I know with testing and programming, in general, there is not always a right way to do something but I'm just wondering if there are any implications that I should consider before taking on this approach throughout my whole test suite?

Any guidance would be greatly appreciated. Thanks!

20th January, 2017

haakym started a new conversation Preparing The Database Before A Test For A Model With Many Dependencies, Is There A Better Way? • 6 months ago

I am writing a test for a page that performs updates, the test simply checks that one of the model's attributes hasn't changed prior to submitting the form in order to prevent two users from updating the model if they had it both open in their browser at the same time.

The test requires the use of a model in my Laravel web app: App\Models\Application and I am using factories to create some fake data for this model. The test simply checks that one of the model's attributes hasn't changed prior to submitting the update form that will change it.

The Application model has many belongsTo relationships, which in turn requires for the related model to exist prior to the creation of the Application model. For example, the Application model has a belongsTo relationship with Applicant, so I need to create an Applicant model with a factory prior to creating an Application and an Applicant also has belongsTo relationships with User, which I also need to create before ... you get the idea.

So this has left me wondering if I am taking the wrong approach? Is there a more simple approach where I can simply create the model that is under test?

Thanks for any advice.

29th September, 2016

haakym left a reply on Using Vue.js In Laravel 5.3 • 10 months ago

Did you solve this? I am facing the same question...

@Raido

There's a response to my question here if you're interested: http://stackoverflow.com/questions/39708680/using-vue-js-in-laravel-5-3

27th September, 2016

haakym left a reply on Using Vue.js In Laravel 5.3 • 10 months ago

I'm going to repeat the question again as based on some of the answers it seems as I didn't get my point across. Hope this makes things clearer.

In Laravel projects prior to 5.3 I've utilised Vue.js using the script tag like this:

<script type="text/javascript" src="../js/vue.js"></script>

I would then create a Vue instance specific for that page like this:

<script>
    new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue.js!'
      }
    });
</script>

and then bind it to the relevant div#id in my HTML.

Now, in Laravel 5.3 Vue.js comes bundled and I am fully aware that I can use components as described in the docs, however, my question is if I want to create a Vue.js instance like I just mentioned, i.e. where I create a Vue.js instance strictly for a given page (not a component) how do I do it?

Do I set it up like I used to by importing the vue.js library in a script tag firstly or can I use generated app.js?

Am I not supposed to do it, should I be creating components for everything?

For me, it doesn't make sense to make a component for something I am only using once - I thought the purpose of components was that they are reusable. As mentioned in the Vue.js docs:

Components are one of the most powerful features of Vue.js. They help you extend basic HTML elements to encapsulate reusable code.

Any advice would be appreciated, thanks!

haakym left a reply on Using Vue.js In Laravel 5.3 • 10 months ago

@ejdelmonico Thanks for your reply. So are you saying that all interactions with Vue.js should be via components?

26th September, 2016

haakym left a reply on How To "DRY Up" My Tests Set Up • 10 months ago

@ohffs

Haha, at least you're honest!

Thanks for your insights and advice, very helpful! I think I'll probably reach for traits once I get a few more tests knocked out and can begin getting an idea of how I can structure the setup more wisely.

haakym left a reply on How To "DRY Up" My Tests Set Up • 10 months ago

@ohffs Thanks for your reply.

I think that's a good approach to take. How would you go about pulling in the global setup when you need to utilise it?

I like the method name you chose for delete shred() - haha!

haakym started a new conversation Using Vue.js In Laravel 5.3 • 10 months ago

In previous Laravel projects, I've dropped Vue.js into a page and created a Vue instance specific for that page. Something like this at the bottom of my page:

<div id="app">
    @{{ message }}
</div>
...
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.27/vue.js"></script>
<script>
        new Vue({
          el: '#app',
          data: {
            message: 'Hello Vue.js!'
          }
        });
    </script>

Now in Laravel 5.3 Vue.js comes bundled up with it and I have got a slight grasp on how I can create components which I can then drop into a page. However, I am struggling to understand how I can create a Vue.js instance like the aforementioned, i.e. where I just need to drop a vue instance into a page instead of creating a whole component.

Can I utilise Vue that gets incorporated into app.js when running gulp or do I need to pull in Vue as I did before with the script tag?

Thanks!

haakym left a reply on Vou-Router • 10 months ago

@LJ90

I maybe should mention that the vue-devtools in my chrome browser do not appear in the browser (and I have absolutely no idea why), so I cannot check for errors.

I have had this issue before when I'm using minified vue vue.min.js - try using it when it's not minified and see if that works.

haakym left a reply on How To "DRY Up" My Tests Set Up • 10 months ago

@ohffs I haven't actually. I'll be sure to check it out, thank you.

@ifpingram Thanks for your response. You really addressed my concerns there!

Perhaps my question should have been, should I be DRYing up my test setup - not how. I think I had the idea that a particular approach may have tackled the issues you mentioned more effectively. For now, I think I'll leave my tests alone and see how things pan out once I've written some more tests. Thanks again.

haakym started a new conversation How To "DRY Up" My Tests Set Up • 10 months ago

Hey everyone. I'm trying to practice a little TDD after watching Adam Wathan's videos at Laracon etc. I've got about three test classes so far and I seem to be doing a lot of setup that involves adding data to the DB that's required for the test. I would like to know what would be the best approach to clearing up such repetitive code from my tests and to further utilise this as my number of tests increase.

Some of the methods from my tests with similar setup flow looks like this:

  1. create a user(s)
  2. create a department the user(s) belongs to
  3. create a resource related to the user(s)

AuthenticationTest.php

/** @test */
public function user_is_logged_in()
{
    $user = factory(User::class)->make([
        'username' => 'jsmith',
        // ... some data
    ]);

    $department = factory(Department::class)->create(['name' => 'IT Department']);
    
    $department->users()->save($user);

    // sets $_SERVER['REMOTE_USER'] variable via SSPI
    $this->setRemoteUser($user->username); 

    $this->visit('/')
        ->assertEquals($user->username, Auth::user()->username);
}

AccountTest.php

/** @test */
public function user_can_view_their_account()
{
    $user = factory(User::class)->make([
        // ... some data
    ]);

    $department = factory(Department::class)->create(['name' => 'IT Department']);
    
    $department->users()->save($user);

    $employeeDetails = factory(EmployeeDetail::class)->make([
        // ... some data
    ]);
    
    $user->employeeDetails()->save($employeeDetails);

    Auth::login($user);
    
    $this->visit('/account')
         ->see($user->name)
         ->see($user->department->name)
         ->see($user->employeeDetails->start_date->format('d-m-Y'))
         ->see($user->employeeDetails->employee_type);
}

UserEmployeeRequestTest.php

/** @test */
public function user_can_view_their_requests()
{
    $employee = factory(User::class)->make([
        // ... some data
    ]);

    $manager = factory(User::class)->make([
        // ... some data
    ]);

    $department = factory(Department::class)->create(['name' => 'IT Department']);
    
    $department->users()->save($employee);
    $department->users()->save($manager);

    $employeeRequest = factory(EmployeeRequest::class)->make([
        // ... some data
        'manager' => $manager->id,
    ]);
    
    $employee->employeeRequests()->save($employeeRequest);

    Auth::login($employee);
    
    $this->visit('/employee/employee-requests')
        ->see(/* data from employee request */);;
}

So, as far as I'm aware, I have some of the following options:

  1. Extract the setup to a method on a base class
  2. Extract to a trait(s)
  3. Extract to a setUp() method on the class and call parent::setUp()

I'd appreciate any recommended ways to clear up the repetitive code while keeping it flexible enough to scale as I write more tests that may require different or more set up data. Thanks!

22nd September, 2016

haakym left a reply on Submitting Form In Vue.js With Ajax • 10 months ago

@sorcjc What does your console say - any errors?

22nd July, 2016

haakym started a new conversation Add Watermark/stamp To PDF With Preview • 1 year ago

In an application I'm building the admin users are currently downloading a PDF file then manually adding 3 image files as a stamp/watermark then re-uploading that PDF.

If at all possible, I would like to add this functionality to the web application. The functionality I'm looking for would allow the user to view the PDF in the webpage and decide where the stamp is placed using up/down, left/right buttons then once decided they could place the stamp in the desired location onto the PDF and add another if needed. The reason for this is because sometimes the stamp may not be visible if added to the same place each time due to content in the PDF.

So far I've looked at FDPF which I've used before to merge two PDF files together - I'm guessing this would help me achieve the watermark part, but how could I go about doing the preview part?

Any ideas or suggestions are welcome. I'm not restricted to PHP, any reasonable solution in PHP, JS or a script that could run in a Laravel application would be fine.

Thanks!

23rd May, 2016

9th May, 2016

haakym left a reply on Correct Approach To Creating Record Then Immediately Adding One-to-one Relation • 1 year ago

I'm trying this code:

$applicant = Applicant::create($this->applicantDataFromRequest($request));

$application = new Application([
    'status'           => 'pending',
    'reference_number' => $request->get('passport_number'),
    'organisation_id'  => $request->get('organisation'),
    'qualification_id' => $request->get('qualification') ?: null,
]);

$applicant->application()->save($application);

dd('done');

And still getting the same error:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`attestation`.`applications`, CONSTRAINT `applications_applicant_id_foreign` FOREIGN KEY (`applicant_id`) REFERENCES `applications` (`id`) ON DELETE CASCADE) (SQL: insert into `applications` (`status`, `reference_number`, `organisation_id`, `qualification_id`, `applicant_id`, `updated_at`, `created_at`) values (pending, 5730970933C7B, 24, 1, 22, 2016-05-09 14:56:25, 2016-05-09 14:56:25))

haakym left a reply on Correct Approach To Creating Record Then Immediately Adding One-to-one Relation • 1 year ago

@pmall

Thanks, I updated the question from:

$application = $applicant->applications()->create([
    // data
]);

to:

$application = $applicant->application()->create([
    // data
]);

haakym left a reply on Correct Approach To Creating Record Then Immediately Adding One-to-one Relation • 1 year ago

@desaijay123 so I would need to pass it a new instance rather than array in that case:

$application = new Application([
    // data
]);

$application = $applicant->application()->save($application);

haakym left a reply on Correct Approach To Creating Record Then Immediately Adding One-to-one Relation • 1 year ago

@pmall

Sorry! It's a one-to-one relation. Corrected the question.

haakym started a new conversation Correct Approach To Creating Record Then Immediately Adding One-to-many Relation • 1 year ago

I've got the following eloquent models and relations set up:

Applicant

class Applicant {
    public function application()
    {
        return $this->hasOne(Application::class);
    }
}

Application

class Application {
    public function applicant()
    {
        return $this->belongsTo(Applicant::class);
    }
}

I simply want to create a new applicant then add a new application for the applicant just created:

$applicant = Applicant::create([
    // data
]);

$application = $applicant->applications()->create([
    // data
]);

However, when running this code I receive the following error:

SQLSTATE[23000]: Integrity constraint violation: 
1452 Cannot add or update a child row: a foreign key constraint fails (
    `attestation`.`applications`, CONSTRAINT `applications_applicant_id_foreign` 
    FOREIGN KEY (`applicant_id`) REFERENCES `applications` (`id`) ON DELETE CASCADE
)
(SQL: insert into `applications` (
    `status`,
    `reference_number`,
    `organisation_id`,
    `qualification_id`,
    `applicant_id`,
    `updated_at`,
    `created_at`
) values (
    pending,
    573066CE59BFE,
    24,
    1,
    12, // <------ applicant_id, i.e. the foreign key!
    2016-05-09 11:30:38,
    2016-05-09 11:30:38
))

As I understand, the error is occuring because I'm passing it a foreign key that doesn't exist in the database. So I was wondering what is happening here with the first call to the DB that I make to create the applicant:

$applicant = Applicant::create([
    // data
]);

Is it not written to the DB before the second statement that creates the application:

$application = $applicant->applications()->create([
    // data
]);

... and thus causing the integrity constraint violation? Because if I dd($applicant) immediately after creating it or dd(Applicant::find($applicant->id)) I get the record and I can also view it in the DB.

I've found that prior to re-factoring my code when I was calling create() to add a new record then building up a new application line by line and using save(), I didn't encounter this issue. So I'm curious to know how both calls differ (if they do) and what would be the correct way to approach such a scenario as I thought it was something very simple with eloquent which I've done many times before. Any advice would be most appreciated, thanks!

3rd May, 2016

haakym left a reply on Testing A Form, Dropdown Issues Where Dropdown Is Populated Via Vuejs • 1 year ago

Great, thanks for the suggestion @ohffs I will check out the video and see if its manageable.

Jeffrey Way did mention the following on an AMA on hashnode last month:

One pain point for me at the moment would relate to testing code that requires JavaScript. Right now, we have a great API in place for integration testing...but, once you introduce JavaScript, it gets a little tricky. I'm hoping that someone will PR a Selenium driver that allows us to use the exact same API we currently have, but leverage Selenium behind the scenes.

https://hashnode.com/ama/with-jeffrey-way-cimd458uo01bwtg53yed55n8n#cimdltl9l01eltg53in0oaiqk

Here's hoping it gets implemented.

haakym left a reply on Question On Book: PHP Objects, Patterns, And Practice • 1 year ago

@robgeorgeuk Looks like there is something in the works! No idea when it will be completed though?

Just signed a contract to write PHP Objects Patterns and Practice Edition 5 - should be a fun one!

https://twitter.com/getInstance_mz/status/685193564368814085

haakym left a reply on Question On Book: PHP Objects, Patterns, And Practice • 1 year ago

Thanks a lot for the suggestions guys!

25th April, 2016

haakym started a new conversation Question On Book: PHP Objects, Patterns, And Practice • 1 year ago

Hey everyone,

At the following link https://laracasts.com/recommended-reading the book "PHP Objects, Patterns, and Practice 4th ed. 2013 Edition" by Matt Zandstra is recommended.

I wanted to purchase the book on kindle, but as the book was published in 2013 I was curious to know whether a large part of the content would be outdated or not, or if there's a newer version in the works that I should wait for.

Any advice on this or recommendations for other books would be appreciated.

Thank you!

20th March, 2016

haakym started a new conversation Testing A Form, Dropdown Issues Where Dropdown Is Populated Via Vuejs • 1 year ago

I'm writing a small test for a form and I'm getting errors when running phpunit. It gets stuck because it can't see any options in one of the dropdown boxes named organisation which is populated by vuejs. The dropdown in question is populated with a list of json values loaded when the page first loads up and is further filtered by the first dropdown list in the form, namely academic_certificate.

Here's my view/blade file with the dropdown:

<select name="organisation" id="" class="form-control" {{-- required="required" --}} v-model="organisation">
    <option value="">Select</option>
    <option v-for="organisation in organisations | filterBy application_type in 'organisation_types'">
        @{{ organisation.name }}
    </option>
</select>

Here's my test:

/** @test */
public function verified_user_can_create_academic_certificate_application()
{
    $faker = Faker::create();

    $user = factory(App\Models\User::class)->create();
    $applicant = Role::where('name', 'applicant')->firstOrFail();
    $user->roles()->attach($applicant->id);
    
    $this->actingAs($user)
        ->visit('/applicant/application/create')
        ->select('academic_certificate', 'application_type')
        ->type($faker->firstNameMale, 'first_names')
        ->type($faker->lastName, 'last_name')
         // fill out rest of form ...
        /****************************************
            here's where it gets an error!
        ****************************************/
        ->select('Some organisation', 'organisation')   
        ->select('1', 'qualification')
        ->type('IT', 'speciality')
        ->type('2002', 'year_of_award')
        ->press('Submit')
        ->see('complete');
}

The test:

$ vendor/bin/phpunit
PHPUnit 4.8.23 by Sebastian Bergmann and contributors.

E.FF

Time: 7.15 seconds, Memory: 37.00Mb

There was 1 error:

1) ApplicationTest::verified_user_can_create_academic_certificate_application
InvalidArgumentException: Input "organisation" cannot take "Some organisation" as a value (possible values: ,
                                                {{ organisation.name }}
                                            ).

C:\wamp\www\attestation\vendor\symfony\dom-crawler\Field\ChoiceFormField.php:140
C:\wamp\www\attestation\vendor\symfony\dom-crawler\FormFieldRegistry.php:128
C:\wamp\www\attestation\vendor\symfony\dom-crawler\Form.php:77
C:\wamp\www\attestation\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:808
C:\wamp\www\attestation\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:788
C:\wamp\www\attestation\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:775
C:\wamp\www\attestation\tests\acceptance\applicant\ApplicationTest.php:55

Any help would be really appreciated, I'm trying to get to grips with testing and would hate to get stuck here! Thank you.

14th March, 2016

haakym left a reply on Generating A Unique ID/Code For Resource • 1 year ago

@premsaurav

No, not really. The main reason I was asking the question is that firstly I was wondering if there are any issues with the methods that I have considered, i.e. uniqid() and if there's a better way that others may have used in their projects.

haakym started a new conversation Generating A Unique ID/Code For Resource • 1 year ago

Apologies if this has already been addressed on the fourms, wasn't entirely sure what to search for.

I'm developing an application where a user submits an Application. Each Application needs to have a unique ID or code which will primarily be used by the user and the system admins in order to identify an particular Application.

My question is what would be the best way to generate this ID/code in PHP? I have the following considerations for the ID/code:

  1. It has to be unique
  2. It can't be too long (if the applicant phones up we don't him reading a 30/40 digit number over the phone)

I've considered using uniqid() or uniqid(rand()) which generates a unique string of 13 and 23 characters respectively. From my searching around I've also seen UUID been mentioned but didn't feel it was right for my use case.

Any suggestions or guidance on this would be appreciated.

Thank you!

26th February, 2016

haakym left a reply on Dynamic Eloquent Relationship • 1 year ago

Many thanks @harryg and @pmall

I've implemented some of the suggestions you made and the structure although I think I could do a bit more refining the database is looking a lot better now! The adam wathan video was quite useful too.

Thanks again for your helpful advice.

haakym started a new conversation Working A Large Number Of Tasks Into A Queue • 1 year ago

I'm building a web application using Laravel 5 that creates links to the web application that when visited show a form for a student's progress report. These links are sent by the web application to an email of a contact at the institution the student attends in order for them to complete the progress report accessed by the link in the email.

The problem I face is when creating and sending links. I have some code which works fine with a couple of hundred students, however in real world use the application would be potentially creating and sending 3000 or so links at one time. The code I've written simply can't handle such a large number and the application crashes.

Although I'm more than welcome to other suggestions, I believe the answer to the problem is utilising queues. I have already used queues when sending email, but I would like to work some other parts of the code into queues but I'm a bit unsure how to do this!

Brief database schema

Student hasMany Link

Student hasMany InstitutionContact (limited to two by my application)

Link hasMany InstitutionContact (limited to two by my application)

Email manyToMany Link

What I am trying to accomplish

  • Get all the Student's that require a new Link

  • Create a Link for each Student

  • Assign the Student's current InstitutionContacts to the Link's InstitutionContact

  • Loop through all the newly created Links in order to group them together by shared InstitutionContacts - this is so an email is not sent per link (thus possibly sending too many emails to the same address), rather links should be grouped together by the same email/contact and sent together where applicable

  • Loop through all the Links grouped by email/contact and:

    1. Send an email including the Link's info to the designated InstitutionContact's email address
    2. Write a copy of the Email to the database
    3. Join the Email created in the former step to the Link(s) that were sent in it

So the main challenge I'm facing is performing the aforementioned task with a large dataset. I have already considered creating and sending a Link one by one via a queue, however this wouldn't allow me to group all the Links together by contact/email. As the task wouldn't be performed regularly I would be open to consider performing the task as it is already with an increase in memory and time for the process, however I didn't have much success when attempting this using set_time_limit(0); and ini_set('memory_limit','1056M'); before sending any links.

Any help would be really appreciated, thank you if you read this far!

Code

app\Http\Controllers\LinkController.php

public function storeAndSendMass(Request $request)
{
    $this->validate($request, [
        'student_id' => 'required|array',
        'subject'    => 'required|max:255',
        'body'       => 'required|max:5000',
    ]);

    $studentIds = $request->get('student_id');
    $subject    = $request->get('subject');
    $body       = $request->get('body');
    
    $students = $this->student
        ->with('institutionContacts')
        ->whereIn('id', $studentIds)
        ->where('is_active', 1)
        ->get();

    // create link, see Link.php below for method
    $newLinks = $this->link->createActiveLink($students);

    // send link to student's contact(s), see LinkEmailer.php below for method
    $this->linkEmailer->send($newLinks, ['subject' => $subject, 'body' => $body], 'mass');

    // return
    return response()->json([
        'message' => 'Creating and sending links'
    ]);
}

app\Models\Link.php

public function createActiveLink($students)
{
    $links = [];

    foreach ($students as $student) {
        $newLink = $this->create([
            'token'          => $student->id, // automatically hashed
            'status'         => 'active',
            'sacb_refno'     => $student->sacb_refno,
            'course_title'   => $student->course_title,
            'university_id'  => $student->university_id,
            'student_id'     => $student->id,
            'institution_id' => $student->institution_id,
            'course_id'      => $student->course_id,
        ]);

        // $newLink->save();

        $studentContacts = $student->institutionContacts;

        if ($studentContacts) {

            foreach ($studentContacts as $studentContact) {
                
                $newLink->contacts()->create([
                    'type'                   => $studentContact->pivot->type,
                    'institution_contact_id' => $studentContact->pivot->institution_contact_id/*,
                    'link_id'                => $linkId,*/
                ]);

                $newLink->save();
            }

        }

        $links[] = $newLink->load('student');
    }

    return $links;
}

app\Emails\LinkEmailer.php

namespace App\Emails;

use App\Emails\EmailComposer;

class LinkEmailer
{
    protected $emailComposer;

    public function __construct(EmailComposer $emailComposer)
    {
        $this->emailComposer = $emailComposer;
    }

    public function send($links, $emailDetails, $emailType)
    {        
        $contactsAndLinks = $this->arrangeContactsToLinks($links);

        foreach ($contactsAndLinks as $linksAndContact) {
            
            $emailData = array_merge($linksAndContact, $emailDetails);
            
            // send/queue email
            \Mail::queue('emails/queued/reports', $emailData, function ($message) use ($emailData) {
                $message
                    ->to($emailData['email'], $emailData['formal_name'])
                    ->subject($emailData['subject']);
            });
            
            // compose email message, returns text of the email
            $emailMessage = $this->emailComposer->composeMessage($emailData);

            // // create Email
            $email = \App\Models\Email::create([
                'to'      => $emailData['email'],
                'from'    => 'report@domain.org',
                'subject' => $emailData['subject'],
                'body'    => $emailMessage,
                'type'    => $emailType,
                'user'    => $_SERVER['REMOTE_USER']
            ]);

            foreach ($linksAndContact['links'] as $link) {
                $link->emails()->attach($email->id);
            }
        }
    }

    // group links by contact
    public function arrangeContactsToLinks($links)
    {
        $contactsForLinks = [];
        $assigned         = false;
        $match            = false;
        
        foreach ($links as $link) { // 1, n

            if ($link->contacts) {

                foreach ($link->contacts as $contact) { // 1, 2
                    
                    if ($contactsForLinks) {
                        
                        $assigned = false;

                        foreach ($contactsForLinks as $key => $contactLink) { // n
                            // assign links to existing email in array
                            if ($contactLink['email'] === $contact->institutionContact->email) {
                                $match = false;

                                // check link hasn't already been included
                                foreach ($contactsForLinks[$key]['links'] as $assignedLink) {
                                    if ($assignedLink === $link) {
                                        $match = true;
                                    }
                                }

                                // if there was no match add to list of links
                                if (!$match) {
                                    $contactsForLinks[$key]['links'][] = $link->load('student');
                                    $assigned = true;
                                    break;
                                }
                            }
                        }

                        if (!$assigned) {
                            $contactsForLinks[] = [
                                'email'                 => $contact->institutionContact->email,
                                'formal_name'           => $contact->institutionContact->formal_name,
                                'requires_id'           => $contact->institutionContact->institution->requires_id,
                                'requires_course_title' => $contact->institutionContact->institution->requires_course_title,
                                'links'                 => [$link->load('student')],
                            ];
                        }
                    } else {
                        $contactsForLinks[] = [
                            'email'                 => $contact->institutionContact->email,
                            'formal_name'           => $contact->institutionContact->formal_name,
                            'requires_id'           => $contact->institutionContact->institution->requires_id,
                            'requires_course_title' => $contact->institutionContact->institution->requires_course_title,
                            'links'                 => [$link->load('student')],
                        ];
                    }
                }
            }
        }

        return $contactsForLinks;
    }
}

25th February, 2016

haakym left a reply on How To Run Queue:work Correctly? • 1 year ago

Ahhhh man I feel silly! I'm pretty sure I'd checked the database before and found the jobs still in there but it seems to be firing them off just fine now I've double checked.

Also, that's really useful to know that queue:work doesn't give the same feedback as queue:listen.

Thanks so so much for your help Jeroen! Really appreciate it!

haakym started a new conversation How To Run Queue:work Correctly? • 1 year ago

I've got a system that will potentially send up to 1000s of emails at once. I decided to use Laravel's queue functionality opting for the inbuilt database queue.

I can happily fire off jobs using artisan queue:listen and was wondering if I can save resources after reading that I can run artisan queue:work --daemon. However whenever I run artisan queue:work --daemon nothing happens? queue:listen on the other hand seems to work just fine. Do I need to run queue:listen alongside queue:work?

As I understand from this post: https://laracasts.com/discuss/channels/general-discussion/queue-worker-vs-daemon-queue-worker

queue:listen fires queue:work so a bit unsure why it isn't working to begin with?

Any help would be appreciated, thanks!

22nd January, 2016

haakym left a reply on How Do I Check If The User Is Logged In From A View? • 1 year ago

Pretty sure it must be the same. From the docs:

Determining If The Current User Is Authenticated

To determine if the user is already logged into your application, you may use the check method on the Auth facade, which will return true if the user is authenticated:

if (Auth::check()) {
    // The user is logged in...
}

However, you may use middleware to verify that the user is authenticated before allowing the user access to certain routes / controllers.

https://laravel.com/docs/5.2/authentication#retrieving-the-authenticated-user

6th January, 2016

haakym left a reply on Dynamic Eloquent Relationship • 1 year ago

@harryg

Yep that's how I've got my course relationship set up. Okay that's pretty straight forward now I think about it, I think I'm still too wrapped up in my old DB structure to think outside the box! Ideally the latest report method would be return a relationship because I need to use it with the ->has and ->doesntHave eloquent methods (which I think only work with relationships?) so I'm guessing I can do something like:

public function latestReport()
{
    return $this->reports()
        ->where('course_id', $this->course_id)
        ->latest('date_to');
}

@pmall

That's quite a different approach to what I'm currently doing with the student - course relationship (which is currently one to many). I do need a way to keep track of the student's current course, so I'm assuming I'd keep the student's current course on the student model but then add an entry into the student/course table when creating a report to link it all up?

To both harryg and pmall - Thanks so much for your input on my question I really do appreciate your responses! I don't think I'll be able to implement all the suggestions you have made just yet due to time constraints on the project, but I definitely hope to come back to it very soon and implement your suggestions then hopefully post back here to benefit others and let you know what solution worked for me.

5th January, 2016

haakym left a reply on Dynamic Eloquent Relationship • 1 year ago

@harryg

Thanks again for your response, however I don't think it addresses how to retrieve the last report for the student's current course or even a specified course, unless I'm missing something.

Just to reiterate, I don't want the relationship to ONLY get the latest report, I want it to get the latest report which would be the report that is related to their course. So for example, if the student's current course is master I want to retrieve the latest MasterReport linked to that student.

Thanks

haakym left a reply on Dynamic Eloquent Relationship • 1 year ago

@pmall and @harryg - Many thanks for your replies and taking the time to explain the correct way to go about this.

I think I was failing to understand that each "subreport" (e.g. PhdReport) would have/be linked to a parent Report instance earlier.

However, I'm still failing to understand how I would implement the relation to retrieve the latest report for the student's current course using the approach you guys have suggested.

Just to make things clear, let's say we have a student whose current course is master and this student has two reports an EslReport and a MasterReport, how is the latestReportrelation implemented to retrieve the report for his current course (the master report)???

haakym left a reply on Dynamic Eloquent Relationship • 1 year ago

@pmall Thanks a lot for your reply.

By Document I assume you mean Report?

I'm not entirely sure how a polymorphic relationship solves the issue, but I'm most probably missing something!

Currently I have a abstract Report model which is the parent model of PhdReport, MasterReport, BachelorReport, FoundationReport and EslReport with each of the 5 aforementioned reports being different in their attributes. I can't see how I can work a ReportType model into this current set up as wouldn't this require me to scrap the 5 report models in favour of one Report model therefore assuming all the attributes for each report be the same?

I'll also add that a student could begin by being on the ESL course and therefore have an EslReport then later change to Master and have a MasterReport. What I was trying to do with the relation in the first post is get the latest report for the student's current course.

haakym left a reply on Dynamic Eloquent Relationship • 1 year ago

Current solution is dynamically changing the relationship called, e.g.

$courseName = 'Master';

$students = Student::with('latest' . $courseName . 'Report')->get();

This does require a method for each report type in the student model which I'm guessing isn't the best solution but for now it works!

haakym started a new conversation Dynamic Eloquent Relationship • 1 year ago

I'm using eloquent and trying to set up what I would best describe as a dynamic relationship.

I have a Student model that can be on a Course: PhD, Master, Bachelor, Foundation or ESL and a student can have a report specific to each course, therefore I have the following eloquent models: PhdReport, MasterReport, BachelorReport, FoundationReport or EslReport.

One such relationship I require is to get the latest report for the student's current course. So if the student is on the bachelor course I want to grab the BachelorReport model where the date_to attribute is the most recent. This is my implementation on the Student model for the relationship:

public function latestReport()
{
    $courseReport = ucfirst(strtolower($this->course->name)) . 'Report'; 

    return $this->hasOne('\App\Models\\' . $courseReport)->latest('date_to');
}

This relationship works fine when I run the following code in artisan tinker:

// get a student
$student = App\Models\Student::first();

// student returned
=> <App\Models\Student #000000003dd8f51b00000000d869fe64> {
       course_id: 2, /* which is the master course */
       // other attributes ...
}

// get the latest report for the student's current course
$s->latestReport

// we get a MasterReport as expected
=> <App\Models\MasterReport #000000003dd8f51900000000d869fe64> {
    // attributes
}

However, when I run the following code:

$students = $this->student
    ->where('course', 2)
    ->where('is_active', '1')
    ->with('latestReport', /* other relationships */)
    ->get();

It always appears to run the code for PhdReport, this is shown when I check the Laravel debugbar

select * from `phd_reports` 
  where `phd_reports`.`student_id` in (/* list of ids */) 
  order by `date_to` desc

My current idea for a workaround is to conditionally apply a relation specific to the course/report:


$students = $this->student
    ->where('course', 2) /* for masters */
    ->where('is_active', '1');

if ($course == 'master') {
    $students = $students->with('latestMasterReport');
}

Any advice would be much appreciated. Thank you!

7th December, 2015

haakym left a reply on Best Practice For Date Conversion For View Data/data From Ajax • 1 year ago

A question I asked on Stackoverflow got a working answer for me, code:

Route::get('/', function () {

    $student = App\Models\Student::first();

    $response = new League\Fractal\Resource\Item($student, new App\Transformers\Models\StudentTransformer);

    $manager = new \League\Fractal\Manager();
    $manager->setSerializer(new \League\Fractal\Serializer\ArraySerializer());

    return response()->json($manager->createData($response)->toArray());

});

Link: http://stackoverflow.com/questions/34017140/transform-eloquent-model-using-fractal

haakym left a reply on Assign A Query To Variable To Then Perform Two Separate Queries? • 1 year ago

@screenager Again, I don't see how your code with altered syntax addresses the question. Thanks for your comment anyway though, it's always good to get a different perspective.

Yes, you're right I think I can use filters as one approach, thanks a lot.

As for the question I asked: can I start an eloquent query, assign it to a variable then continue using the variable for two separate queries without them conflicting with one another, the feedback I got from stackoverflow was no I can't, so use query scopes or I could use filters as you suggested.

http://stackoverflow.com/questions/34131581/assign-a-query-to-variable-to-then-perform-two-separate-queries#34131892

haakym left a reply on Assign A Query To Variable To Then Perform Two Separate Queries? • 1 year ago

@screenager I don't see how that answers the question? All you've done is modify the syntax of the code snippet I put in my question. Please clarify further if you can.

Edit Your Profile
Update

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