tylernathanreed

tylernathanreed

Member Since 4 Years Ago

Dallas

Experience Points
53,610
Total
Experience

1,390 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed
648
Lessons
Completed
Best Reply Awards
13
Best Reply
Awards
  • start-engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-session Created with Sketch.

    School In Session

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

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

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

  • subscriber-token Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer-token Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • lara-evanghelist Created with Sketch.

    Laracasts Evangelist

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

  • chatty-cathy Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

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

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

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

Level 11
53,610 XP
Sep
22
3 weeks ago
Activity icon

Replied to Make A Job Wait On Several Other Jobs

@bobbybouwmann

I'm not certain your first solution would work. Let's say the "A-finished" job gets dispatched, and then "B", "B", and "B-finished" are dispatched concurrently. If I had three queue listeners, then all three jobs would get picked up. This would cause "B-finished" to run early.

For you alternative solution, what would trigger the cronjob? My goal here is to essentially have both multi-threading (by running jobs in parallel) and process-dependency (by using chaining or some other approach).

My application currently has 7 processes that need to be chained, and each process currently runs actions in a loop over a series of models. However, each model-specific action is isolated to that model, so I'd like to run that part concurrently.

Here's the sort of workflow I'm expecting:

  1. Dispatch the first process ("A")
  2. "A" dispatches 5+ "A-record" processes
  3. Something ("A", "A-record", or other) dispatches the second process ("B") when all "A-record" processes are complete
  4. "B" dispatches 300+ "B-record" processes
  5. Something dispatches the third process ("C"), similar to #3
  6. "C" dispatches 8000+ "C-record" processes
  7. etc.

Since my plan here is to use Laravel Vapor in the long run, when something like #6 happens, I'm expecting 8000+ queue listeners to spin up, handle the job, and spin down. I'm currently just operating in a basic Laravel environment, so I'll likely only have 1 to 4 listeners always running until I get this process ironed out. If I were to chain the 8000 job instances together, then they'd run sequentially, rather than in parallel.

I think my biggest problem here is knowing when to dispatch the next process that has a dependency (i.e. #3 and #5). I can envision various ways of tackling this problem, but they all of pros and cons that make me worry that I'm not thinking about the solution in the correct manner (hence why I'm coming here for insight).

Sep
19
1 month ago
Activity icon

Started a new Conversation Make A Job Wait On Several Other Jobs

Is there a "best practice" for having a job in Laravel wait on several other jobs? I'm aware of the "job chaining" functionality in Laravel, but it doesn't do quite what I want.

For example, I have a job ("A") that dispatches multiple jobs ("B"), and another job ("C") chained to the first job ("A"). If I had to put this in a topological order, it would look like this:

"A" > "B", "B", "B", "B" > "C"

Where the first job "A" runs, dispatches all of the "B" jobs (which can run in parallel), but "C" can't run until all instances of "B" are cleared from the queue.

What is the best way to achieve this functionality?

I hoping to move my current application into Laravel Vapor once I have my queuing process ironed out, so I'd like the solution for this to work in an auto-scaling environment.

Jul
25
2 months ago
Activity icon

Replied to Custom LoginController For Nova

@mrwilde @martinfolkerts

I know this is old, but I just found a solution that works better for me.

In the Nova Service Provider, you can alias Nova's Login Controller for your own, meaning when the routing layer creates the Login Controller, it's using yours instead of Nova's.

Example:

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        $this->app->alias(
            \App\Http\Controllers\Nova\LoginController::class,
            \Laravel\Nova\Http\Controllers\LoginController::class
        );
    }
May
17
5 months ago
Activity icon

Replied to Renaming A Column In SQLite On A Table Referenced By A Foreign Key Fails

This is still a problem for me. Does anyone have any ideas?

Apr
21
5 months ago
Activity icon

Replied to Renaming A Column In SQLite On A Table Referenced By A Foreign Key Fails

@nomguy

I tried that first, and it didn't work. I figured I'd try Laravel's equivalent, just in case that did something else, but that didn't work either.

:/

Apr
19
6 months ago
Activity icon

Replied to Renaming A Column In SQLite On A Table Referenced By A Foreign Key Fails

I also just tried changing my migration code to this:

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        DB::transaction(function() {

            Schema::disableForeignKeyConstraints();

            Schema::table('users', function (Blueprint $table) {
                $table->renameColumn('name', 'display_name');
            });

            Schema::enableForeignKeyConstraints();

        });
    }

And I'm getting the same exception. How am I supposed to rename columns in SQLite?

Activity icon

Replied to Renaming A Column In SQLite On A Table Referenced By A Foreign Key Fails

@nomguy That would have the same issue. Seeing as I can't even get this migration to go through, due to this exception, I'm not even at a point where I can run the down code.

Activity icon

Started a new Conversation Renaming A Column In SQLite On A Table Referenced By A Foreign Key Fails

I'm trying to add a username column to my users table (which currently just has the standard columns provided in a new Laravel project on it). To avoid confusion with the name column, I wanted to first rename the name column to display_name.

I attempted to do so using the following migration:

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->renameColumn('name', 'display_name');
        });
    }

Which results in the following exception:

SQLSTATE[23000]: Integrity constraint violation: 19 FOREIGN KEY constraint failed (SQL: DROP TABLE users)

I was immediately concerned that I coded something wrong, but upon further inspection, this appears to be the standard for SQLite. Here's the SQL the migration is trying to run:

CREATE TEMPORARY TABLE __temp__users AS
    SELECT
        id,
        name,
        email,
        email_verified_at,
        remember_token,
        created_at
        updated_at,
        password
    FROM users

DROP TABLE users

CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    email VARCHAR(255) NOT NULL COLLATE BINARY,
    email_verified_at DATETIME DEFAULT NULL,
    remember_token VARCHAR(255) DEFAULT NULL COLLATE BINARY,
    created_at DATETIME DEFAULT NULL,
    updated_at DATETIME DEFAULT NULL,
    password VARCHAR(60) DEFAULT NULL COLLATE BINARY,
    display_name VARCHAR(255) NOT NULL
)

INSERT INTO users (
    id,
    display_name,
    email,
    email_verified_at,
    remember_token,
    created_at,
    updated_at,
    password
)
    SELECT
        id,
        name,
        email,
        email_verified_at,
        remember_token,
        created_at,
        updated_at,
        password
    FROM __temp__users

DROP TABLE __temp__users

This is basically creating a temp table with the new column, dropping the original table, then recreating the table, and filling in the data. While this would technically get the job done, this also ignores all issues regarding foreign keys.

I understand that there's probably ways around this (such as just creating a new column and dropping the original, or disabling foreign key constraints for migration), but I haven't seen any mentioning of this requirement on the Laravel documentation, and I'm currently under the impression that what I'm doing is supposed to work without any gimmicks.

Am I doing something incorrectly here, or is this a bug?

Dec
28
9 months ago
Activity icon

Replied to Unable To View Action Events On User Detail Page

Bump.

Is there any additional information I can provide here to help you guys answer my question?

Dec
21
9 months ago
Activity icon

Started a new Conversation Unable To View Action Events On User Detail Page

As the title suggests, I am unable to view the Action Events log. It just shows up with a blank listing and the "No action matched the given criteria." message.

I only have the one user in my system, as I'm still tinkering around with things, but I've definitely performed several actions (as my actions log in my database shows many records).

After looking at the API call to display the listing of actions, I am indeed getting zero results back:

Request:

~/nova-api/action-events?
    search=
    &filters=
    &orderBy=
    &orderByDirection=desc
    &perPage=25
    &trashed=
    &page=1
    &viaResource=users
    &viaResourceId=1
    &viaRelationship=actions
    &relationshipType=hasMany

Response:

{
    "label": "Actions",
    "resources": [],
    "prev_page_url": null,
    "next_page_url": null,
    "softDeletes": false
}

However, I went into the ResourceIndexController in the Nova source code, and dumped out the query to see what it was trying to do, and I think I've discovered the problem:

"select *
from "action_events"
where "action_events"."actionable_id" = 1
    and "action_events"."actionable_id" is not null
    and "action_events"."actionable_type" = 'App\Models\User'
order by "action_events"."id" desc"

I'll be honest, I'm not quite sure I understand the difference the "actionable", "target", and "model" morph on the "action_events" table, but all three morphs seem to be storing the same information (being the model that was acted upon).

However, I would think that this query would be looking at either "user_id", since that contains the foreign key to my user. If the "actionable_id" is supposed to be my user id, then Nova isn't storing action events correct.

Just to be certain, I updated my Nova instance to 1.2.1, and I'm still seeing this issue.

Any thoughts here?

Sep
17
1 year ago
Activity icon

Replied to How To Convert Laravel Query To Db::raw

@pordonez

No, because the bindings escapes SQL to prevent it from changing the code. You're also trying to concatenate an array to a string.

You're better off doing this:

DB::table('leads')->whereIn('lead_agent', $array)->orderBy('created_at', 'desc');
Activity icon

Replied to Counting Days Between Two Dates Per Data-row

@wilco You can do this in eloquent, but not easily.

Also, I might have misplaced some parenthesis. I typed it up on my phone.

Sep
16
1 year ago
Activity icon

Started a new Conversation Add Prompt For "New Discussion" Button

When the current page has a form that has been filled out, pressing the "New Discussion" button should prompt with a "Are you sure you want to do this?" style message.

If someone hits the "New Discussion" button instead on the submit button (presumably on accident), they are redirected away from the current form, and all of their work will be lost.

This has tripped me up on mobile a couple of times. I know it's user-error, but having a handy feature to prevent that from happening would be great.

Activity icon

Replied to Wanna Get All Articles A User Has Favourited

Your point of failure is the $favorite->article call is returning null.

Could you post how you've set up the article relation on your Favorite model?

Sep
15
1 year ago
Activity icon

Started a new Conversation Automatic Form Model Binding

I've created a component for a generic <form>:

<template>
    <form>
        <slot></slot>
    </form>
</template>

And I'm using it as a simple form wrapper:

<v-form method="POST" action="{{ route('register') }}">
    @csrf

    <div class="form-group row">
        <label for="name">Name</label>
        <input id="name" type="text" name="name" value="{{ old('name') }}" required autofocus>
    </div>

    <!---->
</v-form>

I would like my Vue component to read the slot contents and automatically bind to form inputs (such as the name field) without having to hard code data: function() { return {'name': null}; } or tack on the v-model="name" attribute on the input element.

Since I know that my component is isolated to a form, it wouldn't think it difficult to programmatically find all of the input HTML elements and automatically bind to them.

Note: I'm assuming that the input's name property is the key to use as both v-model and as the data property on the Vue component.

Is this possible with Vue? Normally I'd whip out jQuery and have this problem solved quickly, but I'm trying to learn the Vue equivalents to things.

Sep
14
1 year ago
Activity icon

Replied to Counting Days Between Two Dates Per Data-row

I'll be honest here: this isn't easy. However, it's not impossible.

Your main problem here is allowing for overlap. Here's what a traditional overlap means:

Definition A: If another Services record exists for the same user_id, where its date_from or date_to values range between the date_from or date_to of the Service record in question, then the Service record in question is overlapped by the other Service.

Since overlap is allowed, if we were to just aggregate the date difference between date_from and date_to, our count would potentially be too high, as we would have counted certain date ranges more than once, explicitly where overlap has occurred.

But what if we could count overlap, but ensure that we only count it once?

If we redefine what "overlap" means in a special way, we can solve our problem:

Definition B: If another Services record exists for the same user_id, where its date_from or date_to values range between the date_from or date_to of the Service record in question, and the id of the other Service is higher than the Service in question, then the Service record in question is overlapped by the other Service.

To get a total count, per service, we can execute the following database query:

select
    services.id,
    services.date_from,
    services.date_to,
    case
        when datediff(day, coalesce(max(start_overlaps.date_from), services.date_from), coalesce(min(end_overlaps.date_to), services.date_to)) + 1 > 0
            then datediff(day, coalesce(max(start_overlaps.date_from), services.date_from), coalesce(min(end_overlaps.date_to), services.date_to)) + 1
        else 0
    end as [non_overlapping_days]
from services
    left join services as start_overlaps
        on start_overlaps.user_id = services.user_id
            and start_overlaps.id > services.id
            and start_overlaps.date_from between services.date_from and services.date_to
    left join services as end_overlaps
        on end_overlaps.user_id = services.user_id
            and end_overlaps.id > services.id
            and end_overlaps.date_from between services.date_from and services.date_to
group by
    services.id,
    services.date_from,
    services.date_to

And if we want this per user, per service type, we can use the following database query:

select
    days_per_service.user_id,
    days_per_service.service_type,
    sum(days_per_service.non_overlapping_days) as days
from services
    inner join (
        select
            services.id,
            services.user_id,
            services.service_type,
            services.date_from,
            services.date_to,
            case
                when datediff(day, coalesce(max(start_overlaps.date_from), services.date_from), coalesce(min(end_overlaps.date_to), services.date_to)) + 1 > 0
                    then datediff(day, coalesce(max(start_overlaps.date_from), services.date_from), coalesce(min(end_overlaps.date_to), services.date_to)) + 1
                else 0
            end as non_overlapping_days
        from services
            left join services as start_overlaps
                on start_overlaps.user_id = services.user_id
                    and start_overlaps.id > services.id
                    and start_overlaps.date_from between services.date_from and services.date_to
            left join services as end_overlaps
                on end_overlaps.user_id = services.user_id
                    and end_overlaps.id > services.id
                    and end_overlaps.date_from between services.date_from and services.date_to
        group by
            services.id,
            services.user_id,
            services.service_type,
            services.date_from,
            services.date_to
    ) as days_per_service
        on days_per_service.user_id = users.id
group by
    days_per_service.user_id,
    days_per_service.service_type

See if that works for you.

Activity icon

Replied to How To Convert Laravel Query To Db::raw

The second parameter to DB::select(...) is your bindings. This means that you can do this:

DB::select('select * from leads where lead_agent in ?', [$array]);
Activity icon

Replied to Coalesce Not Working In Laravel

The Illuminate\Database\Query\Expression class is used whenever you have a DB::raw(...) statement. Given that you're trying to convert this to an integer in a jQuery datatable, odds are that your passing something to your front-end incorrectly.

Activity icon

Replied to Admin Panel

@shez1983 Have you considered using Laravel Nova?

https://nova.laravel.com/

Aug
24
1 year ago
Activity icon

Replied to List All Database Column Names And Types Laravel 5.6

Use this:

DB::getDoctrineSchemaManager()->listTableColumns($table)
Jan
30
1 year ago
Activity icon

Replied to Require('js') Returns Empty Object

Yes, of course.

I'm on the latest LTS for Node.js and npm. I've also been running npm run watch without issues (other than the fs issue I've described here).

Jan
29
1 year ago
Activity icon

Started a new Conversation Require('js') Returns Empty Object

I'm working with some of the node.js functionalities within Laravel, namely using laravel-mix, and I'm encountering a problem with my source code.

For whatever reason, require('fs') is returning an empty object, essentially preventing me from using the module.

I've already tried adding fs: 'empty' to my webpack configuration:

let mix = require('laravel-mix');

mix.webpackConfig({
    node: {
        fs: 'empty'
    }
});

mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css')
   .sourceMaps();

Which didn't solve the problem.

I'm using Windows 10 right now, and I tried running it on Windows 7 this morning. Neither of which worked.

Is there something I'm doing wrong?

Jun
21
2 years ago
Activity icon

Replied to Polymorphism: Why Should I Violate Database Design?

@jimmck If the morphable_type column is stored on a separate table, then how would the application know what table morphable_id references? I've never heard of this being done. Are you perhaps thinking of Class Table Inheritance or Single Table Inheritance?

If there's an alternative implementation that Polymorphism that solves some or all of my issues with it, then I'd love to learn more.

Jun
20
2 years ago
Activity icon

Replied to Polymorphism: Why Should I Violate Database Design?

@martinbean My views towards Laravel's implementation of polymorphic relations is that it actually does it very well. The real issue I have is with polymorphism in itself.

I eventually just used to argument of "Eloquent is my database abstraction layer, so as long as I use that to enforce my relationships, I'll be fine", as my original issue with Polymorphism was that I couldn't enforce/create Foreign Keys. However, I also eventually learned that every now and then you do have to go down to the database layer, and run raw queries on it (This is outside of the code, and typically run for one-off cleanups or reporting). I could argue that this is in fact bad practice when using Polymorphism, because you create the possibility of leaving orphaned records. However, it can be difficult to get away from it when the pointy-haired boss is telling you to do it.

@jimmck morphable_type and morphable_id are stored in the same table as per Laravel's implementation of polymorphism. Without the morphable_type column, you don't know what table you're joining to. If you're always going to join to the same table, then you don't need polymorphism. In this case, a simple Foreign Key would suffice.

That is effectively the alternative to Polymorphism: Create a bunch of Foreign Keys, and loose the "morphable" concept all together. However, once you start making heavy use of this practice, you'll discover that you have tons of pivot tables and tons of joins. Joins are a necessary means, but they should be minimized for the sake of performance. In the world of Acadamia, performance doesn't matter all that much, so this approach is typically taken.

This is what put this thought in my mind in the first place. Polymorphism is essentially loosing the ability to use Foreign Keys for the added benefit of simplifying your relationships and minimizing the number of tables and joins you have. The major drawback to Polymorphism is the loss of Foreign Keys. If you're not careful, you can leave a bunch of orphaned records.

Jun
16
2 years ago
Activity icon

Replied to Polymorphism: Why Should I Violate Database Design?

@martinbean This topic has always sat in the back of my mind. No worries.

At my workplace, we're using Laravel, and we're making use of polymorphism quite a bit. We've really only had one big issue with them: There are no foreign keys. Sometimes we forget about certain tables when deleting records (We have a 289 tables right now, so it can be difficult to keep stuff straight). This leaves records that shouldn't exist in our database, and it can break certain code pieces on the polymorphic table that assumed its polymorphic relation existed.

The only other potential issue we've had is our vendor integration. Sometimes we have to give third-party businesses read access to our application. Showing them the <morphable>_type data gives some clue into how our code-base is structured. This issue isn't big enough to deter me from polymorphism, but it is big enough to point out.

After a year of trying out both design patterns, I can definitely say that polymorphism is very useful, but comes with some problems that I mentioned in the OP. I know that in the workforce, the mentality is basically "Screw the problems, we'll find ways around it", which is fine, but that gut feeling of "I told you so" comes back to bite me every time we have issues related to polymorphism.

Nov
17
2 years ago
Activity icon

Replied to Eloquent - Where Date Range Overlaps, Either Before And/or After, Another Date Range

As far as logic goes, you want this:

  • The Start Date of the Event happened before To
    • i.e. The Start Date needs to be in the past from the perspective of To
  • AND The End Date of the Event happened after From
    • i.e. The End Date needs to be in the future from the perspective of From

In this example, your query would be:

$user = User::where('id', Auth::user()->id)
  ->with([ 'events' => function($query) use ($from, $to) {
    $query->where('start', '<=', $to)->where('end', '>=', $from)
  }])
  ->first();

To clean things up a bit, I like to add "Time" Macros to all of my Queries:

AppServiceProvider:

use Carbon\Carbon;
use Illuminate\Database\Query\Builder;

public function boot()
{
    Builder::macro('past', function($column, $when = 'now', $strict = true) {

        $when = Carbon::parse($when);
        $operator = $strict ? '<' : '<=';

        return $this->where($column, $operator, $when);
    }

    Builder::macro('future', function($column, $when = 'now', $strict = true) {

        $when = Carbon::parse($when);
        $operator = $strict ? '>' : '>=';

        return $this->where($column, $operator, $when);
    }
}

This would allow you to make queries like this:

$user = User::where('id', Auth::user()->id)
  ->with([ 'events' => function($query) use ($from, $to) {
    $query->past('start', $to)->future('end', $from)
  }])
  ->first();

To take things a step further, I'd add this as a scope to your Event Model:

public function scopeOverlapping($query, $from, $to)
{
    return $query->past('start', $to)->future('end', $from);
}

Which further clarifies your original query to:

$user = User::where('id', Auth::user()->id)
  ->with([ 'events' => function($query) use ($from, $to) {
    $query->overlapping($from, $to);
  }])
  ->first();

Now then, a few optimizations:

Judging the context of this query, you're wanting to load the overlapping events onto the Authenticated User. Seeing as you already have the Model, it might make more sense to do this:

$events = Auth::user()->events()->overlapping($from, $to)->get();

If you really need the Authenticated User to be passed along with an $events variable, you can always do this:

$user = Auth::user()->setRelation('events', $events);

This could be inlined as:

$user = Auth::user()->setRelation('events', 
    Auth::user()->events()->overlapping($from, $to)->get()
);

This effectively does exactly the same thing, but I consider it to be more readable than a ->with construct using an array and a closure.

To clean things up even further, you could add the following function to your User Model:

public function loadOverlappingEvents($from, $to)
{
    return $this->setRelation('events', 
        $this->events()->overlapping($from, $to)->get()
    );
}

Seeing as the setRelation function returns the calling Model, you could now do this:

$user = Auth::user()->loadOverlappingEvents($from, $to);

$events = $user->events;

I know that I probably said more than what you needed, I just wanted to point out some design tips. Hopefully somewhere along writing all of this, I managed to answer your question.

Activity icon

Replied to Cannot Use App\Product As Product Because The Name Is Already In Use

Oddly, this can happen when your Namespaces and Includes don't match. My guess is that you incorrectly defined the Namespace for your Product Model.

Are you certain that your model is under the App Namespace? I know that some developers put it under the App\Models Namespace.

Activity icon

Replied to Laravel 5.1 Multiple Login

@fikri1510 That's because you're still using the 5.1 RedirectIfAuthenticated Middleware. You need to be using the one from 5.2.

Nov
03
2 years ago
Activity icon

Replied to Many To Many - Pivot Tables

So, is this your table structure?

pilots
    id

subunits
    id

tasks
    id
    subunit_id

pilots_subunits
    pilot_id
    subunit_id

pilot_tasks
    pilot_id
    task_id

Clearly, if you want the Tasks of a Pilot, you do this:

$pivot->tasks

And if you want the Tasks of a Subunit, you do this:

$subunit->tasks

But if you want the Tasks of all Subunits of a Pilot, then you are correct in that it is complex. However, I'd do this:

$pivot->subunits()->with('tasks')->get()->pluck('tasks')->collapse();

That is to say, "Get all of the Subunits of this Pilot, with it's Tasks, then grab only those Tasks, then collapse the collection (Because you have a collection of collections until you do that)."

Also, because this was grabbed through a BelongsToMany relation, each Task with have a Pivot Entry containing the associated Subunit ID.

Hope that helps.

Activity icon

Replied to Eloquent Relationship Returns Null When Using Query Scope

@ianmcqueen Yes. Any method call that the relationship doesn't have calls the underlying query instead.

Example:

return $user->roles()->toSql();
"select * from [roles] inner join [role_user] on [roles].[id] = [role_user].[role_id] where [role_user].[user_id] = ?"

As for storing Events, I've done this in the past, but with a single model, called EventLog, which looked like this:

event_log
 - id (big increments)
 - event (string 255) [This contains the Class Path of the Event, i.e. "App\Events\MarkedLessonComplete"]
 - data (text / json) [Contains JSON of all parameters passed to Event Constructor]
 - fired_at (datetime)

I'm not sure if anything about what I did then applies to your current application through.

However, when I'm naming my classes, the last "studly word" ("Event" in this case) typically denotes what type of object it is.

Here's a few examples:

  • MySqlConnection
  • SqliteConnection
  • UserPresenter
  • RolePresenter
  • ArticlesTableSeeder
  • CommentsTableSeeder
  • PagesController
  • AuthController
  • CountryPolicy
  • StatePolicy

All of these are children of their suffix (Connection, Presenter, Seeder, Controller, Policy). So if I see "MarkedLessonCompleteEvent", my brain immediately tells me "This object must extend App\Events\Event or some similar class." When this ends up not being the case, it leads to confusion.

This is why I called my model "EventLog" instead of "Event". It also allows the natural flow of things to look like this:

public function(EventLog $entry)
{
    /* ... */
}

You're free to call things whatever you like, but you might be confused in the future when you make the same assumption I did, and turn out to be wrong.

Activity icon

Replied to How Transform This Collection

@divanoli Makes sense. If that's the case, then you want your collection to look like this:

{
    "Windows & Doors" => {},
    "Kitchen Items" => {},
    "Wrought Iron" => {
        5 => "Staircase",
    },
    "Stainless Steel" => {
        6 => "Staircase"
    }
}

To get a Select Box like this:

  • Window & Doors
  • Kitchen Items
  • Wrought Iron
    • Staircase
  • Stainless Steel
    • Staircase

If your input is an array, then you want this:

$collection = collect($array);

$select = $collection->keyBy('title')->map(function($item) { return collect($item['child'])->lists('title', 'id'); });

However, if these "items" are Models, and "child" is a nested relation, then you don't need the collects:

$select = $collection->keyBy('title')->map(function($item) { return $item->child->lists('title', 'id'); });

Seeing as child is an array, I would personally use children instead. Either way, you'll end up with this:

Form::select('item', $select->toArray())

To get the following HTML:

<select name="name">
    <optgroup label="Windows & Doors"></optgroup>
    <optgroup label="Kitchen Items"></optgroup>
    <optgroup label="Wrought Iron">
        <option value="5">Staircase</option>
    </optgroup>
    <optgroup label="Stainless Steel">
        <option value="6">Staircase</option>
    </optgroup>
</select>

Personally, I'd exclude groups that have no selectable options. If you're using the second option, you can do this:

$select = $collection->keyBy('title')->map(function($item) { return $item->child->lists('title', 'id'); })->reject(function($item) { return $item->isEmpty(); });

And when fully broken down...

$select = $collection->keyBy('title') // Key by Title for Groups
                     ->map(function($item) { return $item->child->lists('title', 'id'); }) // Get listing of Children for Group Options
                     ->reject(function($item) { return $item->isEmpty(); }); // Remove Empty Groups

To instead get this:

<select name="name">
    <optgroup label="Wrought Iron">
        <option value="5">Staircase</option>
    </optgroup>
    <optgroup label="Stainless Steel">
        <option value="6">Staircase</option>
    </optgroup>
</select>

Hope that helps.

Oct
25
2 years ago
Activity icon

Replied to How Transform This Collection

You're mixing ordered arrays with associative arrays, and then ignoring the case of something in your nested relations, which uses a third style of formatting.

Are you absolutely certain that it needs to be in this format? Why not this:

[
    1 => {
        "title": "Windows & Doors",
        "child": []
    },
    2 => {
        "title": "Kitchen Items",
        "child": []
    },
    3 => {
        "title": "Wrought Iron",
        "child": [
            5 => {
                "title": "Staircase",
            }
        ]
    }
    4 => {
        "title": "Stainless Steel",
        "child": [
            6 => {
                "title": "Staircase",
            }
        ]
    }
]

This format is much more intuitive and consistent.

If you really wanted to trim things down, you could do this:

{
    "Windows & Doors" => {},
    "Kitchen Items" => {},
    "Wrought Iron" => {
        "Staircase" => 5,
    },
    "Stainless Steel" => {
        "Staircase" => 6
    }
}

This format is closer to your original desire, but remains consistent, as items without children are still keyed as if they have children.

Activity icon

Replied to Eloquent Relationship Returns Null When Using Query Scope

I'd double check your join. Make sure that there's a subscription tied to that User.

Also, what does the SQL say? Maybe there's clues in that.

Side Note:

Are MarkedLessonCompleteEvent and MarkedSegmentCompleteEvent Models? Their class names indicate that they're Events. The names themselves shouldn't be causing any issues, it's just a bit misleading to me.

Activity icon

Replied to Make Blade @push And @stack Dynamic

No, but you can do this:

@push('layout.0')
    ...
@endpush

@push('layout.1')
    ...
@endpush

@push('layout.2')
    ...
@endpush

@for($i = 0; $i <= 2; $i++)
    @stack("layout.{$i}")
@endfor

If your naming convention isn't that clean, you could do this instead:

@push('foo')
    ...
@endpush

@push('bar')
    ...
@endpush

@push('baz')
    ...
@endpush

@foreach(['foo', 'bar', 'baz'] as $stack)
    @stack($stack)
@endforeach
Activity icon

Replied to Multi-Auth In Laravel 5.1

I ended up creating my own package for this. I've been using it for awhile now, and I've been making tweaks as I go.

This is more or less 5.2 Multi-Auth ported into 5.1. There's also some 5.3 features that I'm integrating as well.

Check it out here: https://github.com/tylernathanreed/laravel-auth

Jul
31
3 years ago
Activity icon

Replied to Eloquent Multiple Joins

Fun fact: You can Eager Load using closures:

Area::select([
    'id',
    'province_id',
    '<column> AS <alias>',
    /* ... */
])->with([
    'province' => function($query) {
        return $query->select([
            'id',
            'country_id',
            '<column> AS <alias>',
            /* ... */
        ]);
    },
    'province.country' => function($query) {
        return $query->select([
            'id',
            '<column> AS <alias>',
            /* ... */
        ]);
    }
])->get();

Result:

Illuminate\Support\Collection: {
    #items: [
        0 => App\Models\Area {
            'id' => 1,
            'province_id' => 1
            '<alias>' => /* ... */
            'province' => App\Models\Province {
                'id' => 1
                'country_id' => 1,
                '<alias>' => /* ... */
                'country' => App\Models\Country {
                    'id' => 1
                    '<alias>' => /* ... */
                }
            }
        }
        /* ... */
    ]
}

Get be sure to pull in any Foreign Keys / Primary Keys that are used in the joins for the Eager Loading, or else the relationship will return an empty set.

Jul
30
3 years ago
Activity icon

Started a new Conversation Never Execute A Duplicate Query Again

I bet you have Barryvdh's Debug Bar or some equivalent enabled, and you're seeing tons of duplicate queries, and you simply don't have the time to track them all down.

Boy do I have the solution for you!

Have you considered caching every single query per request? Check this out:

Every SELECT query in Laravel, whether it's using Eloquent, or the DB Facade, all runs through a single function. We're going to override that function:

~/app/Support/Database/Builder.php

<?php

namespace App\Support\Database;

use Cache;
use Illuminate\Database\Query\Builder as QueryBuilder;

class Builder extends QueryBuilder
{
    /**
     * Run the query as a "select" statement against the connection.
     *
     * @return array
     */
    protected function runSelect()
    {
        return Cache::store('request')->remember($this->getCacheKey(), 1, function() {
            return parent::runSelect();
        });
    }

    /**
     * Returns a Unique String that can identify this Query.
     *
     * @return string
     */
    protected function getCacheKey()
    {
        return json_encode([
            $this->toSql() => $this->getBindings()
        ]);
    }
}

So, we're caching every query by it's SQL and it's Bindings. Neat, right? But what's this all about?

Cache::store('request')->...

That's right, we need to set up a custom Cache Driver. We're doing this so that we don't mess with any existing Cache logic you might already be using. Here's how I've defined this:

~/config/cache.php

'stores' => [
    'request' => [
        'driver' => 'array'
    ]
]

In case you're wondering, the array driver is an in-memory Cache store that just stores everything inside an array. This is typically wiped at the end of each request, as once the application gives a response, this is naturally freed from memory. This is actually exactly what we want, as we only care about queries being run within the same request.

Just in case you decide to set things up differently, you can flush the Cache at the end of every request by adding this:

~/public/index.php

try
{
    // Flush the Request Cache
    $app->make('cache')->store('request')->flush();
}
catch(ReflectionException $ex)
{
    // Do nothing
}

After the $kernel->terminate($request, $response) statement.

Now, don't go trying this yet, as it's not going to work. Remember how we "created" a custom Query Builder? Well, we have to tell our Models how to use it. This can be done with the following trait:

~/app/Support/Database/CacheQueryBuilder.php

<?php

namespace App\Support\Database;

trait CacheQueryBuilder
{
    /**
     * Get a new query builder instance for the connection.
     *
     * @return \Illuminate\Database\Query\Builder
     */
    protected function newBaseQueryBuilder()
    {
        $conn = $this->getConnection();

        $grammar = $conn->getQueryGrammar();

        return new Builder($conn, $grammar, $conn->getPostProcessor());
    }
}

You'll want to slap this on any Model that you want to use this new feature:

~/.../SomeModel.php

<?php

namespace App;

use App\Support\Database\CacheQueryBuilder;
use Illuminate\Database\Eloquent\Model;

class SomeModel extends BaseModel
{
    /**
     * For Caching all Queries.
     */
    use CacheQueryBuilder;
}

And viola! Give it a try! See what happens!

Jul
29
3 years ago
Activity icon

Replied to Laravel 5.1 Multiple Login

@eijinaal Here's a package that I'm working on: https://github.com/tylernathanreed/laravel-auth

It's literally just Multi-Auth from Laravel 5.2 refactored and dropped into 5.1.

I've actually gotten this to work in an existing 5.1 project, so I know that it does the basics. If you have any troubles setting it up, let me know. This package is still early in its development, so any feedback would be appreciated. I'm in the same boat as you, I needed Multi-Auth in 5.1, hence why I created the package in the first place.

I'm actively making any changes to this if any issues arise, so I'll definitely help with any problems you might have.

Jul
21
3 years ago
Activity icon

Replied to How Does Composer Know The Patch Version Of My Package?

@willvincent All of the Tags that I've created for my repository are automatically made as Releases on GitHub. Is this because my tags are using the vX.Y.Z notation?

Jul
20
3 years ago
Activity icon

Replied to How Does Composer Know The Patch Version Of My Package?

@willvincent Then can I have a Tag that doesn't refer to a Release?

Activity icon

Replied to How Does Composer Know The Patch Version Of My Package?

@ricardovigatti Even Composer itself recommends against specifying a Version Number, as humans are prone to errors.

@willvincent How unusual. That's quite an odd feature to duplicate.

Jul
19
3 years ago
Activity icon

Replied to How Does Composer Know The Patch Version Of My Package?

@ricardovigatti Tags might just be the solution I was looking for. I thought that this was done with Tags, but I couldn't find it on the Laravel Framework Repository.

Turns out that was because GitHub doesn't show that option on mobile, and that was where I started doing my research.

Let me assert an answer, and tell me if I'm understanding this correct:

To inform Composer of a Patch Version, I apply a Tag to specific Commit that should represent that Patch. The name of the Tag should match the Composer Versioning pattern, meaning a Tag of v5.1.22 maps to laravel/framework: "5.1.22". And using laravel/framework: 5.1.* grabs the latest Patch based on the version.

That said, what's the difference between a Release and a Tag in terms of GitHub?

Activity icon

Replied to How Does Composer Know The Patch Version Of My Package?

@wolle404 Then why doesn't Laravel have 5.1.1, 5.1.2, 5.1.3, ... , and 5.1.40 branches? It only has a 5.1 branch.

@ricardovigatti Yes, I know this, and that's not what I asked.

I'm wanting to create a package. I know how to use packages, and I know how versions are specified on the composer.json file for pulling in other packages.

If I want to have patch versions on my custom built composer package, how do I specify these without a branch for each patch (Minor versions will have their own branches)?

Jul
18
3 years ago
Activity icon

Replied to How Does Composer Know The Patch Version Of My Package?

But where? And what goes in it?

I know that there's a composer.lock file, but that serves a different purpose.

Jul
17
3 years ago
Activity icon

Replied to One-To-Many Polymorphic Relationship

@IvanBernatovic This relationship seems n:n to me.

n:n always looks like 1:n from the perspective of the calling Model. If this happens on both sides, you have an n:n relationship.

Consider these functions within these Models:

Customer.php

public function tags()
{
    // Plural, ?:n
    // return $this->belongsToMany(Tag::class);
    return $this->morphToMany(Tag::class, 'taggable');
}

Tag.php

public function customers()
{
    // Plural ?:n
    // return $this->belongsToMany(Customer::class);
    return $this->morphedByMany(Customer::class, 'taggable');
}

This is n:n. A 1:n would look like this:

Customer.php

public function tag()
{
    // Singular ?:1
    // return $this->belongsTo(Tag::class);
    return $this->morphTo();
}

Tag.php

public function customers()
{
    // Plural ?:n
    // return $this->hasMany(Customer::class)
    return $this->morphMany(Customer::class, 'taggable');
}

OR

Customer.php

public function tags()
{
    // Plural, ?:n
    // return $this->hasMany(Tag::class)
    return $this->morphMany(Tag::class, 'customerable')
}

Tag.php

public function customer()
{
    // Singular ?:1
    // return $this->belongsTo(Customer::class);
    return $this->morphTo();
}

The first example shows a 1:n between Customers and Tags (or n:1 between Tags and Customers).

The second example shows an n:1 between Customers and Tags (or 1:n between Tags and Customers), which honestly doesn't make much sense, but I added it for example purposes.

The same logic applies to Timelogs. You have an n:n relationship there too.

Activity icon

Started a new Conversation How Does Composer Know The Patch Version Of My Package?

I've always been confused by this.

Let's take the laravel/framework repository as an example. Obviously, each branch denotes the Major and Minor versions (X.Y i.e. 5.1, 5.2, etc.), but how are the Patch versions determined (X.Y.Z i.e. 5.1.40, 5.2.14, etc.)?

I'm curious about this because I'm already working on creating my own package, and I'd like to specify my Patch versions.

Jul
12
3 years ago
Activity icon

Replied to Multi-Auth In Laravel 5.1

@jlrdw Sorry, but no. This just looks like Laravel Socialite.

Jul
08
3 years ago
Activity icon

Replied to Sharing One Database For 2 Laravel Apps?

Personally, I'd move all of the common logic between the two applications into a separate Git Repository, so that I'm not duplicating my Models and what-not on both applications. I do this with private software all the time:

composer.json (In both Projects)

repositories: [
    {
        type: "vcs",
        url: "../packages/<package-name>"
    }
]

Where the projects are stored like this:

~/www*

project-1
project-2
packages
    <package-name>

Then, make sure that all of the Models that come from the package share a database connection. Maybe something like this:

~/config/database.php (In both Projects)

'core' => [
    'driver'    => 'mysql',
    'host'      => env('DB_CORE_HOST', 'localhost'),
    'database'  => env('DB_CORE_DATABASE', 'forge'),
    'username'  => env('DB_CORE_USERNAME', 'forge'),
    'password'  => env('DB_CORE_PASSWORD', ''),
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => 'core_',
    'strict'    => false,
],

This means that all core Models are on the same database, and because these Models are from a single package, you've basically got yourself a pseudo-project that two projects share.

The remaining implementation is a pure design choice. Here's the choice, and the results:

Is there a Model is one of the projects, that needs to have relationships with a Core Model?

Yes

Then either make that Model a Core Model, and the other project doesn't have to use it.

OR

Give the project a connection on the same database as core, but with a different prefix (This was hinted at by @phpMick ).

No

Then the project can have it's own database connection, and do whatever it pleases.

OR

Still give the project a connection on the same database as core, but with a different prefix.

Notice that in both cases, there's an option to give the project a connection on the same database as core, but with a different prefix. By choosing this route, you then do not care if project-specific Models share information with Core Models, because in either case, they can communicate.

I've done this before, where I have an internal application for a customer service rep to use, and an external application for a customer to use (Like checking your Bank Statements online, versus a Bank Employee managing your account internally). We ended up with schema looking similar to this:

internal_user
    id
    username
    password
    ...

internal_customer
    id
    name
    ssn
    credit_card
    ...

external_user
    id
    customer_id (FK on internal_customer)
    username
    password
    ...

This happened to be a great use-case for Multi-Auth, but it allowed us to separate internal and external logic. They may have shared the same database, but from Laravel's point of view, they were completely different.

Also, our Models looked like this:

~project-1/app/Models/Customer.php

public function user()
{
    return DB::connection('project-2')->table('users')->where('customer_id', $this->id)->first();
}

~project-2/app/Models/User.php

public function customer()
{
    return DB::conection('project-1')->table('customers')->where('id', $this->customer_id)->first();
}

Pretty much every other non-core Model that needed access to the other project was done through the Customer/User bridge. So if we had an Email Model on the Internal side, and an Article Model on the External side, and we wanted to display that Email on an Article, the Eloquent Query would look like this:

$article->user->customer->email

And with 'Magic Accessors' in Laravel, we could just have a getEmailAttribute on the User Model that differs to the Customer Model:

~/external-project/app/Models/User.php

public function getEmailAttribute()
{
    return $this->customer->email;
}

~/external-project/resources/views/articles/index.blade.php

{{ $article->user->email }}
Activity icon

Replied to Business Logic In Frontend Using Backend As API

One of the projects I've worked on used two applications, one for server-side logic, and the other for the public-facing portion of the site.

Both projects used Laravel, one being a typical MVC app, but the other was 90% Views, 10% Controllers. The Controllers just made API Calls and handed the information over to the Views.

Also, we did the API calls using Curl Requests, rather than Ajax requests, but the same logic applies.

Activity icon

Replied to Multi-Auth In Laravel 5.1

I need to authenticate over two different tables, one for Users (standard auth), and one for Api Users (token auth).

I'm not using Capcha or "I am not a robot". Those are really for validation, not authentication.