DavidSprauel

DavidSprauel

Web developer at Freelance

Member Since 5 Years Ago

Strasbourg

Experience Points
30,405
Total
Experience

4,595 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
314
Lessons
Completed
Best Reply Awards
0
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 7
30,405 XP
Sep
09
1 month ago
Activity icon

Replied to Calling Envoy From A Controller

@christopher Did you find any solution ?

Activity icon

Started a new Conversation Valet Requires Homebrew To Be Installed On Your Mac

I'm working on a project which use nextcloud as a document manager and when i'm upload a file, I want to launch nextcloud files sync so I use envoy to manage my command.

My command works when i type it in the CLI, it works when i'm running a test of my store new document. But when I use it the normal way through the interface and add a document, the buffer logs me : Valet requires Homebrew to be installed on your Mac.

Of course I have homebrew on my Mac and i'm running anything related to valet in my task.

@servers(['localhost' => '127.0.0.1'])

@task('synchronize', ['on' => 'localhost'])
    cd {{ $path }}
    docker-compose exec -T --user www-data app php occ files:scan {{ $user }}
@endtask

As I said, it work manually and through a unit test but not when i'm using it from my interface... Any Idea ?

EDIT: Here are my logs

[2020-09-09 07:41:33] local.DEBUG: Nextcloud Syncronized
[2020-09-09 07:41:33] local.DEBUG: ["Valet requires Homebrew to be installed on your Mac."]
[2020-09-09 07:47:06] testing.DEBUG: Nextcloud Syncronized
[2020-09-09 07:47:06] testing.DEBUG: ["Starting scan for user 1 out of 1 (admin)\n","+---------+-------+--------------+\n| Folders | Files | Elapsed time |\n+---------+-------+--------------+\n","| 28      | 13    | 00:00:01     |\n+---------+-------+--------------+\n"]

testing env is my unit test and local is my normal env for dev. nothing changes between the 2 except DB credentials

Sep
08
1 month ago
Activity icon

Started a new Conversation Symfony Process: No Such File Or Directory

Hi fellow developers,

I experienced Envoy and Laravel this afternoon and everything work fine until i'm trying to exec the command from the code.

 $command = ["~/.composer/vendor/bin/envoy run synchronize", " --path={$path} --user={$user}"];

        $process = new Process($command);
        $process->run(
            function ($type, $buffer) use ($result) {
                dd($buffer);
                $buffer = str_replace('[127.0.0.1]: ', '', $buffer);
                $result[] = $buffer;
            }
        );

Here is the code i'm trying to run. the dd I got in $buffer returns me this :

sh: /Users/David/.composer/vendor/bin/envoy run synchronize: No such file or directory\n
sh: line 0: exec: /Users/David/.composer/vendor/bin/envoy run synchronize: cannot execute: No such file or directory

I've tried to execute ~/.composer/vendor/bin/envoy run synchronize --path=myPath --user=myUser manually and it works just fine. But no way to get it working from my function.

The function is in a class i'm just calling from a unit test :

 /** @test */
    public function files_are_scanned() {
        dd((new NextCloud())->synchronize(true));
    }

EDIT: the problem is that Process escape my arguments and add a ' on my command so it doesn't work. I don't know how to avoid that. This function is modifying my command:

 private function escapeArgument(?string $argument): string
    {
        if ('' === $argument || null === $argument) {
            return '""';
        }

        if ('\' !== \DIRECTORY_SEPARATOR) {
            return $argument;
            return "'".str_replace("'", "'\''", $argument)."'";
        }
        if (false !== strpos($argument, "LARACASTS_SNIPPET_PLACEHOLDER")) {
            $argument = str_replace("LARACASTS_SNIPPET_PLACEHOLDER", '?', $argument);
        }
        if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) {
            return $argument;
        }

        $argument = preg_replace('/(\\+)$/', '', $argument);

        return '"'.str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument).'"';
    }

I've tried to return the argument without modifying it and it works.

Jul
22
3 months ago
Activity icon

Started a new Conversation Notification Not Sent

Hi everyone,

I'm building an app in TDD and i'm facing a weird error i've been searching a solution on it since yesterday.

In the app, you have the possibility to invite a user in the platform via email. I have an endpoint where you can create a user and send him an email with a temp password.

Everything in the script works well and the test as well but there is only one problem when I wanna send the notification, the test always return not sent.

Here is my create user script:

public function invite(InviteUser $request)
    {
        $tempPassword = Str::random(8);

        $data = [
            'company_id'       => $request->input('data.relationships.company.data.id'),
            'user_category_id' => UserModel::CATEGORY_EMPLOYED,
            'firstname'        => $request->input('data.attributes.firstname'),
            'lastname'         => $request->input('data.attributes.lastname'),
            'email'            => $request->input('data.attributes.email'),
            'is_admin'         => $request->input('data.attributes.isAdmin'),
            'password'         => Hash::make($tempPassword),
            'key'              => Str::random(16)
        ];

        $user = $this->write->store($data);
        $user->notify(new UserInvited($tempPassword));

        return Transformer::transformResponse((new UserTransformer())->transform($user));
    }

here is my test:

/** @test */
    public function an_admin_can_invite_another_admin_or_editor()
    {

	Notification::fake();

        $admin = factory(User::class)->create([
            'user_category_id' => User::CATEGORY_ENTREPRENEUR,
            'is_admin'         => 1
        ]);

        $this->signIn($admin);

        $attributes = [
            'data' => [
                'attributes'    => [
                    'firstname' => 'David',
                    'lastname'  => 'Sprauel',
                    'email'     => '[email protected]',
                    'isAdmin'   => rand(0, 1)
                ],
                'relationships' => [
                    'company' => [
                        'data' => ['id' => auth()->user()->company_id]
                    ]
                ]
            ]
        ];

        $this->json('post', '/users/invite', $attributes)
            ->assertStatus(200)
            ->assertJsonStructure(['meta', 'links', 'data']);

        unset($attributes['data']['attributes']['isAdmin']);

        $this->assertDatabaseHas('users', array_merge($attributes['data']['attributes'], [
            'company_id' => auth()->user()->company_id
        ]));

        Notification::assertSentTo(User::latest()->first(), UserInvited::class);
    }

And here is my notification:

class UserInvited extends Notification
{

    public string $password;

    public function __construct(string $password)
    {
        $this->password = $password;
    }

    public function via($notifiable)
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        Log::debug('I was here');

        return (new MailMessage)
            ->greeting('Bienvenu ' . $notifiable->firstname)
            ->line('Vous avez été invité à rejoindre la plateforme test.com')
            ->line('Vous pourrez vous connecter en suivant le lien ci dessous et en utilisant le mot de pase suivant: ' . $this->password)
            ->action('Me connecter', env('ENTREPRENEUR_URL'))
            ->line('Si vous rencontrez des difficultés, n\'hésitez pas à nous contacter');
    }

    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

I tried several log into the notification and it seems go through constructor and method via but never goes into the toMailmethod.

This is not a configuration problem as I got another test for reset password that send an email as well and the test is passing without any issue. Does someone has an idea ?

EDIT: tried to run the test 50 times in a row, and it pass once out of 50.

Jul
20
3 months ago
Activity icon

Replied to Model Factory Loop

@mvd

Alright, I wasn't aware of that, thanks. I kinda found a solution:

factory(Company::class)->create([
            'contact_id' => factory(Contact::class)->create([
                'user_category_id' => 6
            ])->id
        ])

that work with no issues.

Activity icon

Replied to Model Factory Loop

Thanks fo your answer.

Just for me to know, there is a difference between doing

 'contact_id'      => function() {
            return factory(Contact::class)->create()->id;
        },

and

'contact_id' => factory(Contact::class)

?

The problem is, I can't set the contact_id to 0 as it has a foreign key and SQL will return an error

Activity icon

Started a new Conversation Model Factory Loop

Hey,

I'm facing a problem I struggle to resolve while trying to setting up some test for my application. When i'm generating a factory i fall in a loop which leads to an allocated memory error.

The database schema were already there and i have (unfortunetly) to deal with it.

Here is my 3 main factories:

$factory->define(Contact::class, function (Faker $faker) {
    return [
        'company_id'       => factory(Company::class),
        'user_category_id' => rand(1, 3),
        'entry_date'       => now(),
        'key'              => Str::random(16),
        'email'            => $faker->safeEmail
    ];
});
$factory->define(Company::class, function (Faker $faker) {
    return [
        'name'            => $faker->company,
        'contact_id'      => factory(Contact::class),
        'location_id'     => factory(Location::class),
        'company_type_id' => rand(1, 3),
    ];
});
$factory->define(User::class, function (Faker $faker) {
    return [
        'contact_id'     => factory(Contact::class),
        'firstname'      => $faker->firstName,
        'lastname'       => $faker->lastName,
        'email'          => $faker->unique()->safeEmail,
        'password'       => 'yIXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password,
        'key'            => Str::random(16),
        'remember_token' => Str::random(10),
    ];
});

The problem is, when i wanna create a user, it creates a contact, which create a company, which create another contact, and that should stop there but for an unknown reason it seems to loop and create another, then another contact which needs another company etc...

So i'm trying to create the company first and already here it seems to loop when creating a contact although it shouldn't. When I create a company, that 'contact_id' => factory(Contact::class), line should create a contact with a direct relationship with the company, so in theory, the contact factory shouldn't create another company right ?

Is there something i'm missing ?

Jul
19
3 months ago
Activity icon

Replied to Model Events Not Firing

Alright, guess with transaction, it wasn't working, and as I always sent the same data, it wasn't updating anymore ^^

Jul
17
3 months ago
Activity icon

Replied to Model Events Not Firing

Sure

<?php

namespace App\Models\Entities\Eloquent;

use App\Library\RecordsLog;

class Message extends BaseModel
{
    use RecordsLog;

    protected $casts = [
        'data' => 'object'
    ];

   protected static $recordableEvents = ['updated', 'created'];

    const QUESTION_TYPE_SINGLE = 1;
    const QUESTION_TYPE_MULTI = 2;

    /*-----------------------------------------------------------------------*/
    /*-------------------------- RELATIONSHIPS ------------------------------*/
    /*-----------------------------------------------------------------------*/

    public function company()
    {
        return $this->belongsTo(Company::class);
    }

    public function sender()
    {
        return $this->belongsTo(User::class, 'sender_id');
    }

    public function recipient()
    {
        return $this->belongsTo(User::class, 'recipient_id');
    }
}

and before you ask, here is my baseModel

abstract class BaseModel extends Model
{

    protected $guarded = [];
    protected $casts = [
        'id' => 'integer'
    ];

    const EXCLUDE_AUTO_WITH = [];

    public function scopeFilter($query, $filters)
    {
        return $filters->apply($query);
    }

    protected function serializeDate(DateTimeInterface $date)
    {
        return $date->format('Y-m-d H:i:s');
    }
}
Activity icon

Replied to Model Events Not Firing

Just tried it protected static $recordableEvents = ['updated'] and it doesn't even go into the event updated, only saved

Activity icon

Replied to Model Events Not Firing

oldAttribute is a variable on top of my trait. The problem is that it doesn't even get into the the static::$event where $event = updated.

It boots the trait but the event is saving instead of updated

Activity icon

Started a new Conversation Model Events Not Firing

Hello,

I'm working on a project which need to records all models action that are done in the app. I've followed the whole Birdboard tutorial of Jeffrey and love the way he was handling this kind of things.

So I used more or less what he coded and I'm facing a weird problem. Model event updated and updating are not fired but it works when I listen the event saved or 'saving`

Here is my trait I use

trait RecordsLog
{
     public $oldAttributes = [];

    /**
     * Boot the trait.
     */
    public static function bootRecordsLog()
    {
        foreach (self::recordableEvents() as $event) {

            static::$event(function ($model) use ($event) {              
                // records log
            });

            if ($event === 'updated') {
                static::updating(function ($model) {
                    $model->oldAttributes = $model->getOriginal();
                });
            }
        }
    }

protected static function recordableEvents()
    {
        if (isset(static::$recordableEvents)) {
            return static::$recordableEvents;
        }

        return ['created', 'updated'];
    }

and here is tha way i'm saving the updated data

 $data = [
            'data' => $request->input('data.attributes.data'),
        ];

        $message->update($data);

        //TODO add audit trail
//        $this->write->update($message, $data);

Basically, my $this->write->update is $message->update($data) but it is just in an abstraction layer. I tried to do it directly in the code and have the same issue.

To be honest, i'm running out of solution and I really don't get why because in the tutorial everything is just working fine.

Jun
29
4 months ago
Activity icon

Started a new Conversation State Variables Undefined

First, I rather new to VueJs and VueX, this is my first project with it.

I've setup a store for my auth which manage current user. Here is my inital state:

const initialState = user
    ? {status: {loggedIn: true}, user}
    : {status: {loggedIn: false}, user: null};

When i sign in the user everything works fine and got no problem but as soon as my state got reset by a logout or anything else, I got millions errors on my console telling me that for example currentUser.avatar is not defined.

In some of my component I compute some values of my state like that :

 computed: {
            currentUser() {
                return this.$store.state.auth.user;
            }
        },

and use it like that :

<h2 class="text-display3 font-weight-500 m-t-0">{{ currentUser.attributes.firstname}}</h2>

The odd thing is that, i'm on my login page and got all of these console errors, but sure, my state is not yet updated by the login and these pages are not accessibles without being authenticated.

The app basically send me error of component that are not rendered yet.

Is that normal ? or am I missing something ?

Jun
04
4 months ago
Activity icon

Started a new Conversation Integrating Next Cloud With Laravel

I have a project that'll come in the next few weeks where the client wants to have a NextCloud integration for his document management.

I had a look on the next cloud doc and have to admit I was a bit lost. It seems to use WebDav protocol, which I googled and I am now okay with that.

But neither the doc nor google is really crystal clear on how it works. I may be searching at the wrong place or with wrong keywords. I'm used to work with RESTful API so webdav looks a bit ... old. It seems everything has to be manager through XML.

If someone knows good resources or if someone already use nextcloud with Laravel, i'll be down for hearing your experience with it and any advice is welcome.

May
25
5 months ago
Activity icon

Awarded Best Reply on Step By Step Form

Found a solution, don't know if this is the best one but it works.

<template>
    <div class="flex h-screen items-center">
        <div class="m-auto border card text-center">
            <div class="pt-20 my-auto">
                <slot name="content" v-bind:step="step"></slot>

                <div @click="next">
                    <slot name="trigger" v-bind:step="step"></slot>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {

        data() {
            return {
                step: 0
            }
        },

        methods: {
            next() {
                this.step++;
            },

            prev() {
                this.step--;
            }
        }

    }
</script>

 <quiz-preview>
        <template v-slot:content="slotProps">
            <div v-show="slotProps.step === 0">
                <h1 class="text-center text-2xl font-normal mb-20">{{ $quiz->name }}</h1>

                {{ $quiz->description }}
            </div>

            <div v-show="slotProps.step === 1">
                <h1 class="text-center text-2xl font-normal mb-20">Step 2</h1>

               Lorem ipsum
            </div>
        </template>

        <template v-slot:trigger="slotProps">
            <div v-show="slotProps.step === 0">4
                <button class="block button w-full mt-10">Begin Quiz</button>
            </div>

            <div v-show="slotProps.step === 1">
                <button class="block button w-full mt-10">Next</button>
            </div>
        </template>
    </quiz-preview>
Activity icon

Replied to Step By Step Form

Found a solution, don't know if this is the best one but it works.

<template>
    <div class="flex h-screen items-center">
        <div class="m-auto border card text-center">
            <div class="pt-20 my-auto">
                <slot name="content" v-bind:step="step"></slot>

                <div @click="next">
                    <slot name="trigger" v-bind:step="step"></slot>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {

        data() {
            return {
                step: 0
            }
        },

        methods: {
            next() {
                this.step++;
            },

            prev() {
                this.step--;
            }
        }

    }
</script>

 <quiz-preview>
        <template v-slot:content="slotProps">
            <div v-show="slotProps.step === 0">
                <h1 class="text-center text-2xl font-normal mb-20">{{ $quiz->name }}</h1>

                {{ $quiz->description }}
            </div>

            <div v-show="slotProps.step === 1">
                <h1 class="text-center text-2xl font-normal mb-20">Step 2</h1>

               Lorem ipsum
            </div>
        </template>

        <template v-slot:trigger="slotProps">
            <div v-show="slotProps.step === 0">4
                <button class="block button w-full mt-10">Begin Quiz</button>
            </div>

            <div v-show="slotProps.step === 1">
                <button class="block button w-full mt-10">Next</button>
            </div>
        </template>
    </quiz-preview>
Activity icon

Started a new Conversation Step By Step Form

I'm rather new to VueJS and I'm trying to make a multi step form using vue but it seems i can't use my component data in my slots:

Here is my component:

<template>
    <div class="flex h-screen items-center">
        <div class="m-auto border card text-center">
            <div class="pt-20 my-auto">
                <slot name="content" :step="step"></slot>

                <div @click="next">
                    <slot name="trigger" :step="step"></slot>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {

        data() {
            return {
                step: 0
            }
        },

        methods: {
            next() {
                this.step++;
            },

            prev() {
                this.step--;
            }
        }

    }
</script>

and here my view:

@extends('layouts.quiz')

@section('content')

    <quiz-preview>
        <template v-slot:content>
            <div v-show="step === 0">
                <h1 class="text-center text-2xl font-normal mb-20">{{ $quiz->name }}</h1>

                {{ $quiz->description }}
            </div>

            <div v-show="step === 1">
                <h1 class="text-center text-2xl font-normal mb-20">{{ $quiz->name }}</h1>

                {{ $quiz->description }}
            </div>
        </template>

        <template v-slot:trigger>
            <div v-show="step === 0">4
                <button class="block button w-full mt-10">Begin Quiz</button>
            </div>

            <div v-show="step === 1">
                <button class="block button w-full mt-10">Begin Quiz</button>
            </div>
        </template>
    </quiz-preview>
@endsection

So far vue tells me that step is not a props nor a method but I have it in my component. What am doing wrong ?

EDIT: i've tried to put the v-if or v-show at several place to test but none seems to works

May
22
5 months ago
Activity icon

Replied to Laravel Validation Odd Behavior

Yes I did, in php.ini, this is on 8MB and in nginx config, 128M.

I receive a 422 and a laravel generic error message.

Activity icon

Replied to Laravel Validation Odd Behavior

I run several website on this server and got no problem with others :/

Activity icon

Replied to Laravel Validation Odd Behavior

Sure, I know about that but I don't get a proper error message, I get just a generic one : The given data is invalid instead of The file is too big!

Activity icon

Started a new Conversation Laravel Validation Odd Behavior

I'm working on a file upload and it upload well until I try to get a file I'm not supposed to be able to upload.

My rules are:

 public function rules()
    {
        return [
            'media' => ['required', 'image', 'max:2000']
        ];
    }

public function messages()
    {
        return [
            'media.required' => 'You must give a file to upload!',
            'media.image'    => 'The file is not an image!',
            'media.max'      => 'The file is too big!',
        ];
    }

and when I try to upload a file which is 2,3Mo I got a 422 but the message is always The given data is invalid without telling me which one is invalid.

Then in my controller, this is how I use it:

public function uploadMedia(AddMediaRequest $request, MyEntity $entity)
    {
        $filename = $entity->addMedia($request->validated());

        return response()->json(['filename' => $filename], 200);
    }

Am I missing a simple point ? (I use Vue for the front end with axios)