andersb

andersb

Member Since 2 Years Ago

Experience Points
9,770
Total
Experience

230 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
83
Lessons
Completed
Best Reply Awards
1
Best Reply
Awards
  • start your engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-in-session Created with Sketch.

    School In Session

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

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

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

  • subscriber Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • evangelist Created with Sketch.

    Laracasts Evangelist

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

  • chatty-cathy Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

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

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

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

Level 2
9,770 XP
Aug
08
1 month ago
Activity icon

Replied to Can You Write Dd(); In The View ?

For anyone else arriving at this old post due to Google searches: @dump($var) was added in Laravel 5.6 so the syntax now is a simple:

@dump($var)
Aug
05
1 month ago
Activity icon

Replied to Nova Resource Route Redirect

@bobbybouwmann I could not get your solution to work. Trying to do so causes an InvalidArgumentException: Action Laravel\Nova\Http\Controllers\[email protected] not defined. thrown on line 459 in vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php which is simply because the nova.index route is not defined (dd'ed $this->routes).

This seems to correspond to the response in this issue, and I can confirm that it does not work in Laravel Nova v3.8.2: https://github.com/laravel/nova-issues/issues/2724

Workaround solution

Implementing an invokable controller like so:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class NovaResourceRedirectController extends Controller
{
    /**
     * Redirect to a Laravel Nova Resource.
     *
     * @param  Request  $request
     * @param  string  $resource
     * @param  int|null  $id
     * @return \Illuminate\Http\RedirectResponse
     */
    public function __invoke(Request $request, string $resource, ?int $id = null)
    {
        // Nova does not have a named route (uses Vue router) so instead redirect to the router
        // @see https://laracasts.com/discuss/channels/nova/nova-resource-route-redirect?page=1
        // @see https://github.com/laravel/nova-issues/issues/2724
        return redirect()->to(config('nova.path')."/resources/{$resource}/{$id}");
    }
}

and setting up a route for this in routes/web.php

Route::get('/nova-redirect/resources/{resource}/{id?}', 'NovaResourceRedirectController')->name('nova.resource');

Make is possible to link to a Nova resource using:
```php
return redirect()->route('nova.resource', ['resource' => 'users', 'id' => 1]);
Aug
04
1 month ago
Activity icon

Awarded Best Reply on Passing Attributes From Blade Component To Subcomponents

Now we are talking @marianomoreyra ! :)

That works - with side effects - since setting :attributes="$attributes" overrides any other attributes set normally (meaning properties not defined as props).

So here we are passing properties and also setting the attributes manually:

<x-input :attributes="$attributes" placeholder="{{ $placeholder }}" name="{{ $name }}" autocomplete="off"/>
// Renders: <input class="rounded-md text-gray-800" value="example"/>

which does not work, but instead setting attributes manually and merging other attributes works:

<x-input :attributes="$attributes->merge(['placeholder' => $placeholder, 'name' => $name, 'autocomplete' => 'off'])"/>
// Renders: <input class="rounded-md text-gray-800" placeholder="Search ..." name="search" autocomplete="off" value="example"/>

It seem there is not a simple "pass attributes down" kind of approach, but the proposed solution from @marianomoreyra with assigning the variable :attributes works when also merging any extra attributes to :attributes="$attributes->merge(....)"

Activity icon

Replied to Passing Attributes From Blade Component To Subcomponents

Now we are talking @marianomoreyra ! :)

That works - with side effects - since setting :attributes="$attributes" overrides any other attributes set normally (meaning properties not defined as props).

So here we are passing properties and also setting the attributes manually:

<x-input :attributes="$attributes" placeholder="{{ $placeholder }}" name="{{ $name }}" autocomplete="off"/>
// Renders: <input class="rounded-md text-gray-800" value="example"/>

which does not work, but instead setting attributes manually and merging other attributes works:

<x-input :attributes="$attributes->merge(['placeholder' => $placeholder, 'name' => $name, 'autocomplete' => 'off'])"/>
// Renders: <input class="rounded-md text-gray-800" placeholder="Search ..." name="search" autocomplete="off" value="example"/>

It seem there is not a simple "pass attributes down" kind of approach, but the proposed solution from @marianomoreyra with assigning the variable :attributes works when also merging any extra attributes to :attributes="$attributes->merge(....)"

Activity icon

Replied to Passing Attributes From Blade Component To Subcomponents

@marianomoreyra this is just a simplified example. The point is that my input component is very generic and should be able to accept any attributes but I don't know which ones. So I should not define any props on that component.

Now the point is that there an attributes class defined when we consume the search component (again this could be any attributes) and that should be passed along to the general input component, but I have no idea how.

I have tries adding {{ $attributes }} but that does not work either - but note that the value is being passed correctly, but the default class (rounded-md) is overriden.

// resources/views/components/search.blade.php

@props(['placeholder' => 'Search ...', 'name' => 'search'])

<x-input placeholder="{{ $placeholder }}" name="{{ $name }}" autocomplete="off" {{ $attributes }}/>

Activity icon

Started a new Conversation Passing Attributes From Blade Component To Subcomponents

Does anyone know how to pass attributes from one blade component to another component used in the first component?

Simplified example

Usage:

<x-search
    class="text-gray-800"
    value="example"
/>
// Should render:
<input class="rounded-md text-gray-800" placeholder="Search ..." name="search" autocomplete="off" value="example"/>
// Renders:
<input class="rounded-md" placeholder="Search ..." name="search" autocomplete="off"/>

Search blade component:

// resources/views/components/search.blade.php

@props(['placeholder' => 'Search ...', 'name' => 'search'])

<x-input :placeholder="$placeholder" :name="$name" autocomplete="off"/>

Generic input component

// resources/views/components/input.blade.php

<input {{ $attributes->merge(['class' => 'rounded-md']) }}/>
Jul
08
2 months ago
Activity icon

Started a new Conversation Require Packages Like AlpineJS And MapBox GL JS As Dependency Or CDN?

We are using quite a lot of 3rd party packages like AlpineJS and MapBox GL JS and are facing an issue how to properly import these so they are available from scripts in blade files.

Let us say that we need to show a MapBox on a page using blades. We could do this like so:

// /resources/views/map.blade.php
@extends('layouts.app')

@section('content')
    <div id='map' style='width: 400px; height: 300px;'></div>
    <script>
        mapboxgl.accessToken = '<your access token here>';
        var map = new mapboxgl.Map({
            container: 'map',
            style: 'mapbox://styles/mapbox/streets-v11',
            center: [-74.5, 40],
            zoom: 9
        });
    </script>
@endsection

Now the code above needs access to mapboxgl and this is the reson for this post. How do we make that available? As I see it we have the following options:

NPM dependency

Install MapBox as a npm dependency and make it available in resources/js/app.js like so:

//resources/js/app.js

window.mapboxgl = require('mapbox-gl');

where we make sure to include public/app.js in the header of the page (not the bottom since the script will run before the library is made available causing an error Uncaught ReferenceError: mapboxgl is not defined):

<!-- /resources/layouts/app -->
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

    <head>
        <meta charset="utf-8">
        ...
        <script src="{{ mix('js/app.js') }}"></script><!-- Important this is in the head section -->
    </head>
    <body>
        @yield('content')
    </body>
</html>

but won't that affect all page loads forcing the browser to load a potential large app.js file before processing the HTML?

CDN in head-section

Use a CDN in the <head> of our /resources/layouts/app file like so:

<!-- /resources/layouts/app -->
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

    <head>
        <meta charset="utf-8">
        ...
        <script src='https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.js'></script>
    </head>
    <body>
        @yield('content')
    </body>
</html>

This script will still have to load on each pageview but loads through a potentially fast CDN and can be cached by the browser across sites. But now we do not get any information from NPM when an update is available and our site needs to fetch a lot of javascript files this way.

Conditional CDN

Use a CDN like above but only conditionally add it to the <head> section using the @push('scripts') syntax (require a @stack('scripts') part in the <head> section like described in the Laravel Docs)

<!-- /resources/layouts/app -->
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

    <head>
        <meta charset="utf-8">
        ...
        @stack('scripts') <!-- This will output any scripts pushed to the 'scripts' stach -->
    </head>
    <body>
        @yield('content')
    </body>
</html>

Where we push the CDN on the pages where the map is needed:

// /resources/views/map.blade.php
@extends('layouts.app')

@push('scripts')
    <script src='https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.js'></script>
@endpush

@section('content')
    <div id='map' style='width: 400px; height: 300px;'></div>
    <script>
        mapboxgl.accessToken = '<your access token here>';
        var map = new mapboxgl.Map({
            container: 'map',
            style: 'mapbox://styles/mapbox/streets-v11',
            center: [-74.5, 40],
            zoom: 9
        });
    </script>
@endsection

NPM dependency and wait for DOMContentLoaded

Install MapBox as a npm deendency (see above) but implemented the /public/app.js script in the bottom of the page and wait for the event DOMContentLoaded before initializing the mapbox:

// /resources/views/map.blade.php
@extends('layouts.app')

@section('content')
    <div id='map' style='width: 400px; height: 300px;'></div>
    <script>
        var map;

        document.addEventListener("DOMContentLoaded", function(event) {

            mapboxgl.accessToken = '<your access token here>';
            var map = new mapboxgl.Map({
                container: 'map',
                style: 'mapbox://styles/mapbox/streets-v11',
                center: [-74.5, 40],
                zoom: 9
            });
        });
    </script>
@endsection

Conclusion

Maybe I am missing something, but it does not seem to me like there is an optimal solution that encapsulates all scenarios? :/

Jul
02
2 months ago
Activity icon

Replied to Optional Properties In Blade Component

Just a note for others checking this issue. When using anonymous components (components without an associated PHP Class) simply set the variables including any default values in the @props part of the blade file as described in the docs:

<!-- /resources/views/components/alert.blade.php -->

@props(['type' => 'info', 'message'])

<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>
    {{ $message }}
</div>
May
29
3 months ago
Activity icon

Awarded Best Reply on Github Actions + Dusk

@brainbox I just confirmed the issue, and maybe this would be a good opportunity to add this to the Laravel documentation, but the problem is simply that Github uses 127.0.0.1:8000 as host, so it is important that your .env file has set APP_URL=http://127.0.0.1:8000.

You can force this by setting the variable in your workflow like so:

...
- name: Run Dusk Tests
  run: php artisan dusk
  env:
    APP_URL="http://127.0.0.1:8000"

Does this solve your issue?

May
22
3 months ago
Activity icon

Replied to Github Actions + Dusk

Nice to hear that it worked for you @brainbox , and yes now the documentation includes this. Happy to help. Please mark this as solved.

May
20
4 months ago
Activity icon

Replied to Github Actions + Dusk

@brainbox I just confirmed the issue, and maybe this would be a good opportunity to add this to the Laravel documentation, but the problem is simply that Github uses 127.0.0.1:8000 as host, so it is important that your .env file has set APP_URL=http://127.0.0.1:8000.

You can force this by setting the variable in your workflow like so:

...
- name: Run Dusk Tests
  run: php artisan dusk
  env:
    APP_URL="http://127.0.0.1:8000"

Does this solve your issue?

May
11
4 months ago
Activity icon

Replied to Github Actions + Dusk

Can you start by posting the errors from Github Actions?

I suggest that you then have a look at your environment variables and perhaps dump these during debugging to ensure that you are using the correct ones during testing.

You are defining the DB_CONNECTION=sqlite and DB_DATABASE=:memory: in your phpunit.xml file: https://github.com/brokerbridge/github-actions/blob/master/phpunit.xml#L30 but you also create a MySQL database with a root user during setup. Note that you have not set a DB_PASSWORD in .env.example (which is copied to .env during setup) nor in .env.testing.

Note that you can pass certain variables directly to dusk using like done for phpunit here

Activity icon

Replied to Logging With Laravel HTTP Client

@bugsysha after having looked more deeply into the middleware then I agree with your proposal of using a dedicated class for this as it complicates things adding the middleware globally.

May
02
4 months ago
Activity icon

Started a new Conversation Logging With Laravel HTTP Client

Due to the simplicity of the Laravel HTTP Client then I am trying to implement this client for making external API request from our application.

However we have a requirement of logging requests and responses in certain situations but I have not found a nice way of doing this. There are a few available Guzzle logging middleware packages out there and it should be possible to always push this to the Guzzle stack using the AppServiceContainer as described here.

Now the problem is that I don't know how to pass any extra information to the middleware which could be used to determine whether or not the request/response should be logged but also this information would be nice to log as well.

Example:

Say we were to make an external API request to update the title of an external Post using the following API request:

$response = Http::patch('http://test.com/posts/'.$postId, [
    'title' => 'New title',
]);

Now it would be nice if I could pass a few parameters like $type='posts.update' and $postId=123 to the handler for example. This info could be use when logging the response (could be used for the filename or for a column in a DB record for the logged request/response for example).

Proposed solution

It looks like I can pass Guzzle Request Options like so (described in Laravel Docs here):

$postId = 123;
Http::fake();

$response = Http::withOptions([
    \GuzzleHttp\RequestOptions::DELAY => 444, // This shuld be an allowed option
  'x_type' => 'posts.update', // Custom option
  'x_id' => $postId, // Custom option
])->patch('http://test.com/posts/'.$postId, [
    'title' => 'New title',
]);

Http::assertSent(function ($request) {
  dd($request);
});

Problem

But as can be seen then none of the options are passed to the request - not even the allowed delay option. I am not sure what is wrong here :/ But I am not even sure if it is possible to use custom options, cause if that is not an option, then the only solution I can see is to use custom headers, but that could potentially lead to problems since these are actually sent to the client.

Does anyone know how to pass any data to the Guzzle middlewares?

Mar
23
5 months ago
Activity icon

Replied to Laravel Airlock, Api In The Same Domain (not Even Subdomain)

@luddinus bacially you have three relevant configurations here: APP_URL, AIRLOCK_STATEFUL_DOMAINS and SESSION_DOMAIN.

You can read details about this configuration in Mohammed Said's blog post here.

If you have everything on the same domain, then you should actually just put that domain in all three configurations. This is an example where we are running the application via Valet on http://example.test

APP_URL=http://example.test
AIRLOCK_STATEFUL_DOMAINS=example.test
SESSION_DOMAIN=example.test

While you cannot have your app and API on two completely different domains, then you can have them on different subdomains. This is from the blog post mentioned above:

That's why you can't have the API hosted in domain.com while the SPA is on another-domain.com. They both need to be on the same domain so they get the same session ID.

Say for example your app is on https://app.example.com and your SPA on https://example.com then you would use:

APP_URL=https://app.example.com
AIRLOCK_STATEFUL_DOMAINS=example.com,app.example.com
SESSION_DOMAIN=.example.com

Note the dot in the SESSION_DOMAIN which enables any subdomain.

For man people then you have both app and SPA in the same domain, but you are working both locally and on your production server. In this case, remember to set the appropriate values for all the three variables.