oliverbusk

oliverbusk

Member Since 6 Months Ago

Experience Points 6,260
Experience Level 2

3,740 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 53
Lessons
Completed
Best Reply Awards 0
Best Reply
Awards
  • Start Your Engines Achievement

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • First Thousand Achievement

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • One Year Member Achievement

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • Two Year Member Achievement

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • Three Year Member Achievement

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • Four Year Member Achievement

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • Five Year Member Achievement

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • School In Session Achievement

    School In Session

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

  • Welcome To The Community Achievement

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • Full Time Learner Achievement

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • Pay It Forward Achievement

    Pay It Forward

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

  • Subscriber Achievement

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • Lifer Achievement

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • Laracasts Evangelist Achievement

    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 Achievement

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • Laracasts Veteran Achievement

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • Ten Thousand Strong Achievement

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • Laracasts Master Achievement

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • Laracasts Tutor Achievement

    Laracasts Tutor

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

  • Laracasts Sensei Achievement

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • Top 50 Achievement

    Top 50

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

19 Mar
18 hours ago

oliverbusk left a reply on PHP - Designing A Rule Based Parsing Engine

@BOBBYBOUWMANN - @bobbybouwmann Above makes perfect sense. Especially the catch where you set $content = $this.. as this will ultimately return the string after all rules have been applied.

I have tried to apply it in my code and it works beautifully!

Thanks a lot for your help and reassurance! I am still quite new to Laravel and only programming as a hobby.

I have two follow up questions:

  1. Would it make sense to save the final $content in the database? Maybe on the documents table, in a column called parsed_content. This way, when the user navigates away from the page and back (or comes back later), the final string will be saved and the server will not need to parse it again. I could then maybe compare parsing_rules.updated_at with documents.updated_at to see if any changes was made to the parsing rules (if there were, all documents associated with the Stream will have to be parsed again.). Which leads me to the other question:

  2. Would it make sense to add the actual parsing of the document - parse() - to a job queue? This way I won't flood my server with parsing requests.

oliverbusk started a new conversation PHP - Designing A Rule Based Parsing Engine

Dynamically apply methods/"rules" to documents

I hope someone here can help me/guide me in the right direction. I am currently creating a web application, where users can import a text file, and then programmaticaly apply different methods on the text.

Example

Imagine that an user have imported a text document, that looks like below.

Raw string

Now as explained, I wish to allow my users to perform/apply a range of different methods to above text. They should be able to apply all rules, in any given order. Consider below example where I have perfomed 4 rules to the original text document:

Rules

As you can see, the text is transformed during each rule, as the method should be applied to the text and output the new text string.

Now the users should be able to save these rules, so the next time the user uploads a document to this specific stream. The thought is, that the next time the user uploads a document, these rules should automatically be applied for the document.

My question is, what would be the best approach to allowing my users to do this dynamically?

I will define the methods/rules that a user can perform on the text document - but what's the best approach:

  1. Save the rules to the database
  2. Programmatically apply the rules to each incoming document (parse each document, based on the rules)

My progress so far

So I am a bit lost on where to begin here, but I was thinking something like below.

Streams: A stream is kind of like a "stack" for all documents. I can upload multiple different documents to a stream. I can create multiple streams, which holds multiple rules.

streams table

id | name
  1. Name: the name of the stream. For example "Documents from Acme Inc"

documents table:

id | stream_id | path | content
  1. Stream Id: A Stream will be can have many documents. So each document uploaded to a specific stream, will be parsed by the rules defined on the stream.
  2. Path: the server path to the document
  3. Content: The text content of the document

parsing_rules table

id | stream_id | method | arguments
  1. Stream Id: Parsing rules will belong to a stream. So all documents imported into the stream, will be parsed by the rules associated with the specific stream.
  2. Rule: the name of the rule applied by the user. This will also refer to the method name in my PHP code.
  3. Arguments: Optional. The arguments that will be applied to each rule/method.

An example of the rules from the 2nd screenshot above, would then look like in the parsing_rules table:

1 | 5 | remove_empty_lines | null
2 | 5 | text_replace | "a:2:{s:6:"Search";s:9:"Laracasts";s:7:"Replace";s:6:"Google";}"
3 | 5 | regex_text_replace | "a:2:{s:7:"Pattern";s:9:"/Google/i";s:11:"Replacement";s:6:"Amazon";}"
4 | 5 | start_position_no_lines | a:1:{s:4:"Line";s:1:"2";}"

So here, method accepts the name of the actual method that should be called, and arguments is the arguments the specific method accepts/requires - but serialized.

#How to apply these rules?

I was thinking that each time a new document is uploaded/imported into a stream, I will apply the rules associated with the stream. Something like:

$content = $document->content;
$parsing_rules = $stream->parsingRules()->get();
foreach($parsing_rules as $rule)
{
    $arguments = unserialize($rule->argments);
    
    return $this->{$rule->method}($arguments, $content);
    
}

Now above is no where near perfect, and it will return the $content already after the first iteration.

Any feedback is highly appreciated. Above is only my thoughts on how to do this project, but I am not sure if there is a better approach to solve this.

oliverbusk left a reply on Validate Incoming E-mail Attachment By Filetype

OK so I fixed this by just checking the File::extension directly on the filename like this:

if (in_array($this->getFileExtension($attachment), ['jpeg', 'jpg', 'bmp', 'png', 'gif'])) {
      $attachments[] = $stream->addDocuments($this->attach($stream, $attachment));
} 

And the method for checking the file extension:

public function getFileExtension($attachment)
{
    return File::extension($attachment->getFileName());
}

oliverbusk started a new conversation Validate Incoming E-mail Attachment By Filetype

I am currently trying to validate incoming emails into my application and save the emails attachments to my database. However, I want to control which attachment types are allowed.

I use Mail-Mime-Parser for PHP, and the Laravel Inbound Mailbox package.

This is my code:

$attachments = collect($email->attachments())->map(function ($attachment) {
    return [
      'file' => $attachment-> getContentType()
    ];
})->validate(['file' => 'mimes:jpeg,jpg,bmp,png,gif,pdf']);

Above returns false, even though the incoming attachment is indeed a pdf file. This is the methods I have tried:

$attachment->getContentType(), whih returns:

Collection {#521
  #items: array:1 [
    0 => array:1 [
      "file" => "application/pdf"
    ]
  ]
}

I have also tried to return the actual content of the PDF file to file, but the validation still fails.

I have also tried to:

[...]->validate(['file' => 'mimetypes:application/pdf']); 

But it still returns false.

What am I doing wrong? How can I successfully validate the attachments mime filetype on the fly?

I am using Spaties Collection Macro for the validate() method.

For reference: This is the actual header content of the attachment, when I dd($email->attachments()):

  -headers: array:5 [
    0 => array:2 [
      0 => "Content-Type"
      1 => "application/pdf; name="Eksamenscase___BIGfinal.pdf""
    ]
    1 => array:2 [
      0 => "Content-Description"
      1 => "Eksamenscase___BIGfinal.pdf"
    ]
    2 => array:2 [
      0 => "Content-Disposition"
      1 => """
        attachment; filename="Eksamenscase___BIGfinal.pdf";\r\n
        \tsize=522462; creation-date="Sun, 03 Mar 2019 14:47:23 GMT";\r\n
        \tmodification-date="Sun, 03 Mar 2019 14:47:23 GMT"
        """
    ]
    3 => array:2 [
      0 => "Content-ID"
      1 => "<[email protected]>"
    ]
    4 => array:2 [
      0 => "Content-Transfer-Encoding"
      1 => "base64"
    ]
  ]
17 Mar
2 days ago

oliverbusk left a reply on Blade - Map Database Values And Show In View

@SNAPEY - @snapey I can't seem to find in the docs, where I can use accessors to achieve my goal? Do you mind providing a short example of what you mean?

oliverbusk left a reply on Blade - Map Database Values And Show In View

@nikos Thanks!

I have added a new file in my langfolder: en/emailrules.php:

    //Fields
    'fromName' => 'From Name',
    'from' => 'From E-mail',
    'toName' => 'To Name',
    'to' => 'To Receiver',
    'cc' => 'CC Receiver',
    'subject' => 'Subject',
    'text' => 'Body',

And I use it like this:

 {{ __('emailrules.'.$rule->field.'') }}

oliverbusk left a reply on Blade - Map Database Values And Show In View

@nikos I wasn’t sure if Translation Strings should be used like this or if there was another way, since the data comes from the database. But will give it a look!

oliverbusk started a new conversation Blade - Map Database Values And Show In View

Hi all.

So imagine I have a database table, that has two columns: fields and operators. The fields can have below values:

fromName from toName

and the operators column can have:

= !=

Now, I would like to show the above in my Blade view, but I wish to rewrite the actual values to something more readable.

I can do:

@forelse ($stream->rules as $rule)
  @if ($rule->field === 'fromName')
      From Name
  @endif


   @if ($rule->field === 'toName')
      To Name
   @endif

   @if ($rule->operator === '=')
      Equals
   @endif

   @if ($rule->field === '!=')
      Does Not Equals
   @endif

@empty

    <div>No rules defined!</div>

@endforelse

And so on - however this feel rather chunky and messy.

Is there a way to "map" the names more elegant?

oliverbusk left a reply on Saving Array To DB - Grammar::parameterize() Error

Just what I needed! Thanks a lot Pawel!

oliverbusk left a reply on Saving Array To DB - Grammar::parameterize() Error

@PAWELMYSIOR - Ah! But how would I go about creating the array so the key => value pairs corresponds to my database table?

Since I already use Laravels built in validation, and bind the names to the array:

        //Validate the request.
        $attributes = request()->validate([
            'field' => 'required|array|min:1',
            'field.*' => [
                'required', 'string',
                Rule::in(['fromName', 'from', 'subject', 'text', 'to', 'cc']),
            ],
            'operator' => 'required|array|min:1',
            'operator.*' => [
                'required', 'string',
                Rule::in(['=', '!=', 'matches']),
            ],
            'value' => 'required|array|min:1',
            'value.*' => 'required|string|min:3|max:255',
        ]);

oliverbusk started a new conversation Saving Array To DB - Grammar::parameterize() Error

I have an array, which looks like this:

array:3 [▼
  "field" => array:2 [▼
    0 => "fromName"
    1 => "from"
  ]
  "operator" => array:2 [▼
    0 => "="
    1 => "="
  ]
  "value" => array:2 [▼
    0 => "Oliver"
    1 => "[email protected]"
  ]
]

I am trying to save the above array, into my database table called email_rules:

My database table

Below is my code.

StreamEmailRulesController.php:

public function store(Stream $stream)
{
    //Validate the request.
    //Validate the request.
    $attributes = request()->validate([
        'field' => 'required|array|min:1',
        'field.*' => [
            'required', 'string',
            Rule::in(['fromName', 'from']),
        ],
        'operator' => 'required|array|min:1',
        'operator.*' => [
            'required', 'string',
            Rule::in(['=', '!=', 'matches']),
        ],
        'value' => 'required|array|min:1',
        'value.*' => 'required|string|min:3|max:255',
    ]);
   
    //Add the document to the database.
    $stream->addRules($attributes);

    //Return back.
    return redirect()->back();
}

Now the $stream->addRules() function is responsible for saving the data to the database.

Stream.php:

/**
* A stream can have many rules.
*/
public function rules()
{
    return $this->hasMany(EmailRule::class);
}


/**
 * Add Email Rules(s) to the stream
 *
 * @return Illuminate\Database\Eloquent\Model
 */
public function addRules(array $attributes)
{
    return $this->rules()->create($attributes);
}

Now, above does not work. I get below error:

Argument 1 passed to Illuminate\Database\Grammar::parameterize() must be of the type array, int given, 

What am I doing wrong?

07 Mar
1 week ago

oliverbusk started a new conversation Rule Engine - Bind To Specific Model

I am currently trying to create a web application, that saves inbound emails. I have figured out how to save the incoming emails into my database, and I have all the email information available (headers, body etc.)

I want to be able to allow my users to set custom conditions for each of the email inboxes they have. So image user A have three inboxes. User A decides that for Inbox 1, below rule should apply:

Mockup

Meaning that the script, in this case, should:

  1. Check that the subject contains the word "Welcome!"
  2. Check that the From message does not contain the word "@hotmail.com"

Now I know I can just write a "simple" ifstatement, but this will not solve my problem, as I need it to be:

  1. Dynamic
  2. Specific for the given inbox

I am not sure how to go around this. I have found this project hoaproject/Ruler which seems to be suiting my needs in regards to writing "complex, dynamic" rules.

However, how would I go about implementing this dynamically?

As said, I want my users to be able to set rules that are specific for their own mailboxes.

Should these rules be saved in a database?

05 Mar
2 weeks ago

oliverbusk left a reply on Laravel Queues - Class Dispatch Does Not Exist

OK the answer was actually quite simple, yet very frustrating.

I am using valet with Laravel, and was accessing my site at: mywebsite.test. I tried to load it through:

php artisan serve, and then tried the exact same thing, just from the IP (127.0.0.1) - and then it worked!

So I just restarted valet, and then it worked there as well.

valet restart

And bam it worked..

04 Mar
2 weeks ago

oliverbusk started a new conversation Laravel Queues - Class Dispatch Does Not Exist

I am trying to use queues in Laravel, and have installed Redis and Horizon for this purpose.

My users can upload images through a frontend. When this happens, it calls a store method:

public function store(Stream $stream)
{
    //Validate the request.
    $validate = request()->validate([
        'file' => 'mimes:jpeg,jpg,bmp,png,gif,pdf',
    ]);

    ImportDocuments::dispatch($stream);
}

In my Jobs/ImportDocuments.php class, I have this code:

class ImportDocuments implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $stream;

    /**
     * Create a new job instance.
     *
     * @param  Document  $document
     * @return void
     */
    public function __construct(Stream $stream)
    {
        $this->stream = $stream;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle(Request $request)
    {
        //Store the actual document. returns the path.
        $store = $request->file('file')->store($this->stream->token);

        //Set the attributes to save to DB.
        $attributes['name'] = $request->file->getClientOriginalName();
        $attributes['path'] = $store;

        //Add the document to the database.
        $this->stream->addDocuments($attributes);
    }
}

For your reference, the addDocuments() method look like this:

Stream.php:

public function addDocuments(array $attributes)
{
    return $this->documents()->create($attributes);
}

Whenever I try to upload an image, I get below error:

Class dispatch does not exist {"userId":1,"email":"[email protected]","exception":"[object] (ReflectionException(code: -1): Class dispatch does not exist at /Users/MyUsername/Sites/playground/vendor/laravel/framework/src/Illuminate/Container/Container.php:779)
  • Redis is running
  • predis/predis is installed
  • Horizon is running
  • Horizon status says 'Active'

What am I doing wrong here?

03 Mar
2 weeks ago

oliverbusk left a reply on Code Review Needed - Saving Inbound Emails And Attachments To Server

Ah I see - thanks a lot @jordandalton!

Last question I think.. Would it make sense to please this NewEmail class anywhere else than the app\ folder? My general idea was that only the Models would be placed here.

oliverbusk left a reply on Code Review Needed - Saving Inbound Emails And Attachments To Server

@jordandalton sorry, but I am a bit confused right now. Where do we use the NewEmail class? And what is the difference by splitting them up into two separate models?

Example in the Email class now, you are still calling:

$this->storeAttachments($stream, $email->saveStream($stream));

But saveStream() is placed in the NewEmail class now?

oliverbusk left a reply on Code Review Needed - Saving Inbound Emails And Attachments To Server

This is the Email model:

<?php

namespace App;

use BeyondCode\Mailbox\InboundEmail;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;

class Email extends InboundEmail
{
    protected $table = 'emails';

    protected $fillable = [
        'message', 'stream_id'
    ];

    /**
     * Handle the incoming email.
     */
    public function __invoke(Email $email, $token)
    {
        //Get the correct stream.
        $stream = Stream::where('token', $token)->firstOrFail();

        //If any attachments, persist them to the database.
        $this->storeAttachments($stream, $email->saveStream($stream));
        
    }

    /**
     * Save the stream_id to the Email object.
     */
    public function saveStream(Stream $stream)
    {
        return tap($this)->update(['stream_id' => $stream->id]);
    }

    /**
     * Stores the attachments on the server.
     * @return array
     */
    public function storeAttachments(Stream $stream, Email $email)
    {
        $attachments = [];

        foreach ($email->attachments() as $attachment) {
            $attachments[] = $stream->addDocuments($this->attach($stream, $attachment));
        }

        return $attachments;
    }

    /**
     * Stores the attachments on the server
     * @return array ['name', 'path']
     */
    public function attach(Stream $stream, $attachment)
    {
        $filename = $this->getFileName($attachment);

        $this->storeFileOnServer($stream, $filename, $attachment);

        return [
            'name' => $filename,
            'path' => $stream->token . '/' . $filename
        ];
    }

    /**
     * Generates a filename for our attachment.
     * @return string (filename.ext)
     */
    public function getFileName($attachment)
    {
        return uniqid() . '.' . File::extension($attachment->getFilename());
    }

    /**
     * Stores the actual file: streamtoken/filename.ext
     * @return boolean
     */
    public function storeFileOnServer(Stream $stream, $filename, $attachment)
    {
        return Storage::put($stream->token . '/' . $filename, $attachment->getContent());
    }

    /**
     * An email belongs to a Stream.
     */
    public function stream()
    {
        return $this->belongsTo(Stream::class);
    }
}

oliverbusk left a reply on Code Review Needed - Saving Inbound Emails And Attachments To Server

@jordandalton Wow, that is really neat! WIll definitely come in handy!

I have tried the above code and almost everything works great.. However the email itself is not being stored in the database.

I get below error:

SQLSTATE[HY000]: General error: 1364 Field 'stream_id' doesn't have a default value (SQL: Insert into emails ...)

I think it's because I removed this from the __invoke() method:

 //Persist the token to the database. {token}@in.myapp.com
 $email->stream_id = $stream->id;

Because now, the $email object, doesn't have a stream_id defined.

It seems like the saveStream(Stream $stream){} method set's the correct stream_id for the documents SQL insert.

Should I just add the:

 //Persist the token to the database. {token}@in.myapp.com
 $email->stream_id = $stream->id;

line again, before the

$this->storeAttachments($stream, $email->saveStream($stream));

line in the __invoke() method?

oliverbusk left a reply on Code Review Needed - Saving Inbound Emails And Attachments To Server

@jordandalton First of all, thank you very much for taking the time to assist me with the above. After updating my code, I can see the benefits of breaking up the code for storing attachments into different methods!

One thing I don't get though is below:

public function saveStream(Stream $stream)
{
    return tap($this)->update(['stream_id' => $stream->id]);
}

What exactly is happening here? Every time an email is being received, and the __invoke function is being called:

    $this->storeAttachments($stream, $email->saveStream($stream));

Will this then:

  1. Store the actual file/attachment on the server (addDocuments())
  2. Save the name and path to the database, while adding the correct stream_idas well?

I am not familiar with the tap() method.

Again, thank you!

oliverbusk started a new conversation Code Review Needed - Saving Inbound Emails And Attachments To Server

I have below code, which is basically handling inbound emails in my application, save the actual email content (text + attachments) to my database, and further save the actual attachment file on my server.

In my Email.php model, I have below function that handles the incoming email. The $token is the first string of the email. For example, my To: email can look like this: [email protected] where avdksokiell is my token.

So as you can see, I fire off the Email model as below:

Mailbox::to('{token}@myapp.com', Email::class);

When above condition is met, below will be run:

public function __invoke(InboundEmail $email, $token)
{
    //Get the correct stream.
    $stream = Stream::where('token', $token)->firstOrFail();

    //Persist the token to the database. {token}@in.myapp.com
    $email->stream_id = $stream->id;

    //Save the email.
    $email->save();

    //If any attachments, persist them to the database.
    $this->storeAttachments($stream, $email);

}

Above works, because I have a relationship set up between Stream and Email:

Stream.php:

/**
 * A stream can have many e-mails
 */
public function emails()
{
    return $this->hasMany(Email::class);
}

Email.php:

/**
 * An email belongs to a Stream.
 */
public function stream()
{
    return $this->belongsTo(Stream::class);
}

Furthermore, in order to save the actual attachment from the mail, I have created a method called storeAttachments(Stream $stream, InboundEmail $email) function in Email that looks like below:

/**
 * A method to store incoming attachments from email.
 *
 */
public function storeAttachments(Stream $stream, InboundEmail $email)
{
    $attributes = [];
    foreach ($email->attachments() as $attachment) {
        //Set an unique filename
        $filename = uniqid() . '.' . File::extension($attachment->getFilename());
        //Store the file on the server
        $store = Storage::put($stream->token . '/' . $filename, $attachment->getContent());
        //Add file information, so we can persist it to the database.
        $attributes['name'] = $attachment->getFilename();
        $attributes['path'] = $stream->token . '/' . $filename;

        //Persist it to the database.
        $stream->addDocuments($attributes);
    }
}

Because my users can choose to:

  1. Upload files from a web frontend
  2. Send files by email into my app

I also have a Document model, that stores all the files:

I also have a relationship set up here:

Stream.php:

/**
 * A stream can have many documents
 */
public function documents()
{
    return $this->hasMany(Document::class);
}

Document.php:

//A document belongs to a Stream.
public function stream()
{
    return $this->belongsTo(Stream::class);
}

Now, for handling the saving files to the database, I have below method in my Stream model:

/**
 * Add document(s) to the stream
 *
 * @return Illuminate\Database\Eloquent\Model
 */
public function addDocuments(array $attributes)
{
    return $this->documents()->create($attributes);
}

I am a bit unsure if above design/methodology is correct and seen as "best practice".

One thing I notice is, that whenever I handle an incoming mail in the __invoke function, I run a query to get the stream_id by looking up the token because the relationships are using stream_id.

Hope someone can help me shed some light if above is OK or if anything can be improved.

I'll be happy to share more code if needed.

28 Feb
2 weeks ago

oliverbusk left a reply on Extending Package Model To Your Own

@SMNHUNT - I tried to include it in my Email class:

    protected static function boot()
    {
        parent::boot();
    }

But still the same error:

Undefined property: App\Email::$message {"exception":"[object] (ErrorException(code: 0): Undefined property: App\Email::$message at /Users/Username/Sites/playground/vendor/beyondcode/laravel-mailbox/src/InboundEmail.php:130)

oliverbusk started a new conversation Extending Package Model To Your Own

Hi there

I am currently trying to setup a simple web-app, using Laravel Mailbox. I can see that I can define a custom model to use in the config file:

    /*
     * The model class to use when converting an incoming email to a message.
     * It must extend the default model class
     */
    'model' => \BeyondCode\Mailbox\InboundEmail::class,

I have changed it to:

    /*
     * The model class to use when converting an incoming email to a message.
     * It must extend the default model class
     */
    'model' => Email::class,

Above is the default model it uses.

Now, I wish to use my own model, because I want to store the e-mails on another table. For this, I have created my own model:

App/Email.php:

namespace App;

use BeyondCode\Mailbox\InboundEmail as InboundEmail;

class Email extends InboundEmail
{
    protected $table = 'emails';
}

However, above gives me below error:

Undefined property: App\Email::$message {"exception":"[object] (ErrorException(code: 0): Undefined property: App\Email::$message at /Users/Username/Sites/playground/vendor/beyondcode/laravel-mailbox/src/InboundEmail.php:130)

I suspect it is because I don't have the original methods in my own model App/Email.php, that are present in the package model.

Isn't there a way that I can use my own model, by extending the package model, but without copying the content of the package model into my own?

20 Feb
3 weeks ago

oliverbusk left a reply on Using Multiple Models In One Shared Blade Template

@ty Like this:

app\Stream.php:

  /**
    * A stream can have many documents
    */
  public function documents()
  {
      return $this->hasMany(Document::class, 'stream_id');
  }

and this is my document model:

app\Document.php:

 /**
   * Documents belongs to a Stream
   */
  public function stream()
  {
      return $this->belongsTo(Stream::class);
  }

I don't understand why I cannot use the $stream variable inside a shared navigation blade template when I have the relationships defined.

oliverbusk started a new conversation Using Multiple Models In One Shared Blade Template

Hi there

OK, so consider below navigation, which is stored in a blade template:

menu.blade.php:

<ul class="nav flex-column leftbar">
    <li class="nav-item">
        <a class="nav-link" href="{{ $stream->path() }}">Overview</a>
    </li>
</ul>

So, as you can see, above references the $stream variable.

The $path function is inside my app\Stream model:

 public function path()
 {
      return '/streams/' . $this->token;
 }

Now I can use the menu/navigation whenever I view a specific resource - for example in my StreamsController:

public function show(Stream $stream)
{
      return view('streams.show', compact('stream'));
}

Now the problem arises when I have a new model. This is called app\Documents.php. The relationships are like this:

A stream has many documents. A document belongs to a stream.

If I go to a page, that uses the DocumentsController, I get this error:

Undefined variable: stream (View: /Users/user/Sites/playground/resources/views/streams/nav/menu.blade.php) 

What am I doing wrong?

oliverbusk left a reply on Extending AuthorizeResource To Custom Method

@MICHAPIETSCH - Very valid point! Thanks a lot for your help! :)

19 Feb
1 month ago

oliverbusk left a reply on Extending AuthorizeResource To Custom Method

@MICHAPIETSCH - Hi Micha

You make quite an interesting point with separating it into another controller StreamDocumentsController. Just real quick:

I will allow my users to upload multiple documents to their "streams" (for example .PDF files, .xlsx files etc.). So I guess that separating this logic makes sense.

18 Feb
1 month ago

oliverbusk started a new conversation Extending AuthorizeResource To Custom Method

Hi all

I have a resource controller called StreamController.php, that utilizes a policy called StreamPolicy.php.

In my controller, I have this:

//StreamController.php
    /**
     * Construct method.
     */
    public function __construct()
    {
        $this->middleware('auth');
        $this->authorizeResource(Stream::class, 'stream');
    }

With above, all the RESTful endpoints is successfully "protected" using the policy.

However, I have added a new method to my controller, called documents(), like so:

//web.php
Route::get('streams/{stream}/documents', '[email protected]');
//StreamController.php
 /**
     * Display the imported documents of the resource
     *
     * @return \Illuminate\Http\Response
     */
    public function documents(Stream $stream)
    {
        return view('streams.documents', compact('stream'));
    }

Now the problem is, if I visit the url:

example.com/streams/1 and I am not the owner of the stream, I get a 403 page - but if I go to: example.com/streams/1/documents and I am not the owner of the stream, I can still access the page.

What am I doing wrong? How can I make so my policy also covers the documents() methods in my controller?

16 Feb
1 month ago

oliverbusk left a reply on Spark - Eloquent Relationships For Teams

Let's say I am part of a team, that have 10 other members. I (my user) have created a lot of projects, but some day, I am kicked out of the team. In this case, I do not want the projects to be associated with my user, but rather the team.

Hope it makes sense!

15 Feb
1 month ago

oliverbusk started a new conversation Spark - Eloquent Relationships For Teams

Hi all

I am currently trying to create a simple SaaS application, where teams can create projects. I am currently stuck at the migration, because I am unsure if the user or the team should "own" the project?

For example, I would normally do this:

User.php:

public function projects()
{
     return $this->hasMany('App\Projects');
}

Project.php:

public function user()
{
     return $this->belongsTo('App\User');
}

So in above case, the user can have many projects and a project belongs to an user.

How should I do this in Laravel Spark with teams?

28 Aug
6 months ago

oliverbusk left a reply on PHP Laravel Passport - /oauth/tokens 401 Unauthorized

Request header:

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: da-DK,da;q=0.9,en-US;q=0.8,en;q=0.7,nb;q=0.6
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImY5OGNiZjBhYmNjZGIyNzk1ZDRhOTllODEwZTQxMzFhMjMwNzhhNzVjYWMzYmM0Y2I2Yzg3NjM3ZDFlMzdkNmI3YzU4YWIzNWM4YmU5MDIxIn0.eyJhdWQiOiIyIiwianRpIjoiZjk4Y2JmMGFiY2NkYjI3OTVkNGE5OWU4MTBlNDEzMWEyMzA3OGE3NWNhYzNiYzRjYjZjODc2MzdkMWUzN2Q2YjdjNThhYjM1YzhiZTkwMjEiLCJpYXQiOjE1MzU0NDU2MzgsIm5iZiI6MTUzNTQ0NTYzOCwiZXhwIjoxNTY2OTgxNjM3LCJzdWIiOiIyIiwic2NvcGVzIjpbXX0.KUSlBt4IQkqYec2TzOTY3QGFxOfuS-SdYpWc26sLDqXpKdRLAqW4XtDOYwzrMtaO51iAuUR1WIGpShaIOZJUhJ_Ya082LVJvuA8tZziAHvjgjReKG_ou6gGhxIWsD8-g88sd0eSyDMfsJBtTs2jrHTJsHQLjFtgwm1RLlSRSkYjO4Tn3fU0dWNUHvcMWVxbuKN_bqC0lpCakjxSQKZe_ep6XpdyFfO84ncsfigVVrfJE3wpJliUfwwv16CpLU0KeNvGhNmKguASCYh9-lWOHPBCMW2S5rF85QgzpTwqYSr5QrIQmqrRKSv6Go545IKN_Hy-xigFV17im-wlVXGOVYgv9C0DJOwCCLOOHB9eMTFO2TGTI5-CLzC8Z9hxHSfMArGGGsTrw6wH45cszvgXH975dk2l1-2rWnVwOMd6-Z2_45Ut0TbomUAfA70OrfSyluxuKKfzNzJ9uobfXB6bGZrIkQMBOPw19N05IkaADAIkip9N99iJ-bF2dCk3GUREmtZPVHo_Yzp0-Ovj0W42eGG5uI_HEhgiuyKdLDWxb92dH_91XhTawhcREx9C1xXQNOUWtT_K2IWaywldfaWy41ZApmd2ZQzhyFxHp28ll1IHKEJRsr88mv4Hjv2hLt5-HeTuL1PW5gaqPZZE5NttpTyK4a2gV7CTtAgm3E_h_Q_Q
Connection: keep-alive
Content-Length: 39
Content-Type: application/json;charset=UTF-8
Cookie: access_token=Bearer%20eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImY5OGNiZjBhYmNjZGIyNzk1ZDRhOTllODEwZTQxMzFhMjMwNzhhNzVjYWMzYmM0Y2I2Yzg3NjM3ZDFlMzdkNmI3YzU4YWIzNWM4YmU5MDIxIn0.eyJhdWQiOiIyIiwianRpIjoiZjk4Y2JmMGFiY2NkYjI3OTVkNGE5OWU4MTBlNDEzMWEyMzA3OGE3NWNhYzNiYzRjYjZjODc2MzdkMWUzN2Q2YjdjNThhYjM1YzhiZTkwMjEiLCJpYXQiOjE1MzU0NDU2MzgsIm5iZiI6MTUzNTQ0NTYzOCwiZXhwIjoxNTY2OTgxNjM3LCJzdWIiOiIyIiwic2NvcGVzIjpbXX0.KUSlBt4IQkqYec2TzOTY3QGFxOfuS-SdYpWc26sLDqXpKdRLAqW4XtDOYwzrMtaO51iAuUR1WIGpShaIOZJUhJ_Ya082LVJvuA8tZziAHvjgjReKG_ou6gGhxIWsD8-g88sd0eSyDMfsJBtTs2jrHTJsHQLjFtgwm1RLlSRSkYjO4Tn3fU0dWNUHvcMWVxbuKN_bqC0lpCakjxSQKZe_ep6XpdyFfO84ncsfigVVrfJE3wpJliUfwwv16CpLU0KeNvGhNmKguASCYh9-lWOHPBCMW2S5rF85QgzpTwqYSr5QrIQmqrRKSv6Go545IKN_Hy-xigFV17im-wlVXGOVYgv9C0DJOwCCLOOHB9eMTFO2TGTI5-CLzC8Z9hxHSfMArGGGsTrw6wH45cszvgXH975dk2l1-2rWnVwOMd6-Z2_45Ut0TbomUAfA70OrfSyluxuKKfzNzJ9uobfXB6bGZrIkQMBOPw19N05IkaADAIkip9N99iJ-bF2dCk3GUREmtZPVHo_Yzp0-Ovj0W42eGG5uI_HEhgiuyKdLDWxb92dH_91XhTawhcREx9C1xXQNOUWtT_K2IWaywldfaWy41ZApmd2ZQzhyFxHp28ll1IHKEJRsr88mv4Hjv2hLt5-HeTuL1PW5gaqPZZE5NttpTyK4a2gV7CTtAgm3E_h_Q_Q; laravel_token=eyJpdiI6IitjQitXXC9iZHd1REtLOWNlZk5qa1d3PT0iLCJ2YWx1ZSI6Im9odjA4SmlqOEY0WndLalpwT29LUGh3R3krXC95eG9sSmtLSHlwYWZlNWFcL1lHbHE2WnRNYWk4UUViVzhUSEpRRzVlWThrdmF4czIrMysrYUZ6UlFzdHVMMDFLMER2VDdUazZDQXBWXC9LMVVZRzdHY2F2RXpFMlRnNmdpaXVXXC9GNFhBK3ZGUm5VdWxKamxsV1RLMDIrTUY1K0JaazBsc2hcL1dHUlBoVXNcL1owalwva3NoVlVzeGc2VElybFwvMFhkN1I0S3g2ZHIralJ4dzIrU3l2aUc2cFwvV1pvQjFRWTRGVXdCdDhwb3UxVXhJeGhpcjNtKzFocjByd25ZQnpzUzVEYUo3dzB0TExqTUVkVCt6ZVFjQ0t4S2dRPT0iLCJtYWMiOiI3NWI0ZjU3OGNhZWQwMTQzYjE1MDBhYzEwNDc4MjBkYzMxZjU5NzI4OGJiMjJmYjQ5NjBhZmMxZTU5ZGZiNmMxIn0%3D; XSRF-TOKEN=eyJpdiI6IkhrQnB1SCs5dWV4OU8zck10djZRbEE9PSIsInZhbHVlIjoieFwvZTJCUFVRZ0haQWNZVjBvUkJ2Q1FTSGtGTHM5SjBXTndOeXBFc2o2Q3pjclRRbjFqeHVpclJOQ3FPTUdKQ2t4M0g4bE5VUXRcL0twdXFNR25IT1NBdz09IiwibWFjIjoiYjI5MzRkNTEwMWZhNWUzNTI5ZTY2OTg5YTYxODQ3MDBkMTU2ZjJjZTE3YzdhZDc2ODMwNjI0NzlmMmQyZTY1NyJ9; laravel_session=eyJpdiI6InY1V3RmeVhvaUd2S2lsRE8wT0tTcHc9PSIsInZhbHVlIjoiQUppMThcL1hka3RXT0NIRWxKNHNUNm5xNjBuaGZSMHpGTXN5czdlWXBqN3dtR2E0UzdQNGFJbk5pS3ZLN1FxZVdnSlVXaE1BaFhVR1lpZnVoek9TMlBBPT0iLCJtYWMiOiIzYmZhYjM5Y2EzYzgwYjdmYTA0OTdjYmYwZGQ2ZThlMDk4YWQ4N2ZiNzRiMjJlZTVkMjM1MjZkYjAyNTZkMTdkIn0%3D
Host: spa.test
Origin: http://spa.test
Referer: http://spa.test/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
X-CSRF-TOKEN: v9z5uFoGWPGprc3kJaCMhLpHGbvgQ7usXLwZu11e
X-Requested-With: XMLHttpRequest
X-XSRF-TOKEN: eyJpdiI6IkhrQnB1SCs5dWV4OU8zck10djZRbEE9PSIsInZhbHVlIjoieFwvZTJCUFVRZ0haQWNZVjBvUkJ2Q1FTSGtGTHM5SjBXTndOeXBFc2o2Q3pjclRRbjFqeHVpclJOQ3FPTUdKQ2t4M0g4bE5VUXRcL0twdXFNR25IT1NBdz09IiwibWFjIjoiYjI5MzRkNTEwMWZhNWUzNTI5ZTY2OTg5YTYxODQ3MDBkMTU2ZjJjZTE3YzdhZDc2ODMwNjI0NzlmMmQyZTY1NyJ9
26 Aug
6 months ago

oliverbusk left a reply on PHP Laravel Passport - /oauth/tokens 401 Unauthorized

Unfortunately, this does not work. I even tried adding all the available routes from RouteRegistrar.php. Still the same result - 401 Unauthorized.

This is a SPA, which uses Passport for logging in - no idea if that can be the reason why it doesn't work?

25 Aug
6 months ago

oliverbusk started a new conversation Vue / Laravel - Handle Logout Correctly

Hi there I am currently trying to create a simple SPA using Vue and Laravel. I've got the basics to work - users can register and login.

I just can't figure out how to create a logout function.

This is what I currently have:

AuthController.php:

`public function logout() { $accessToken = auth()->user()->token();

    $refreshToken = DB::table('oauth_refresh_tokens')
    ->where('access_token_id', $accessToken->id)
    ->update([
        'revoked' => true
    ]);

    $accessToken->revoke();

    return response()->json(['status' => 200]);
}`

routes/api.php:

Route::middleware('auth:api')->group(function () { Route::post('/logout', 'API\[email protected]'); Route::get('/get-user', 'API\[email protected]'); });

Right now, this is what I have tried to do:

Layout.vue:

`methods: { logout() { axios.post('/api/logout').then(response => { this.$router.push("/login")

            }).catch(error => {
                location.reload();
            });
        }

}`

Which calls my logout function in Auth.js: logout() { localStorage.removeItem('token') localStorage.removeItem('expiration') }

However, when users click on the logout function, they are not logged out immediately (redirected to the login page) - they can still browse "user only pages".

I have to refresh the page before I am properly logged out.

Can anyone assist me with this? Is this even the right approach to a "secure" logout function?

oliverbusk started a new conversation PHP Laravel Passport - /oauth/tokens 401 Unauthorized

I am currently trying to create a SPA application that uses Laravel. However with this application, I also need to be able for other applications to interact with it.

This is my boilerplate, and I have just made a fresh install.

After installing this, I can successfully login my SPA. I then want to be able to administer tokens, to issue to 3rd party applications. To do this, I follow the official documentation for Laravel Passport.

I've registered the Vue components as mentioned in the documentation, and they also do show up in my app. However, for some reason they contain a lot of "empty" clients and tokens:

Empty Clients

Empty Tokens

Checking my console, I see that I can't even access the /oauth/*:

Errors

This is my AuthServiceProvider.php:

public function boot()
{
    $this->registerPolicies();

    Passport::routes(function ($router) {
        $router->forAccessTokens();
    });
}

This is my routes/api.php:

Route::middleware('auth:api')->group(function () {
    Route::get('/user', function (Request $request) {
        return $request->user();
    });
});

Please note, I can successfully log in / out of the "main" application. I just can't create new clients/tokens, so I can access my API from other applications.