web-head's avatar

web-head liked a comment+100 XP

2mos ago

The 'feature filters' described here are an implementation of the Interface Segregation Principle, or to put it simply, keeping interfaces focused on one specific task:

interface HasAuthor()
{
    public string $author { get; set; }
}

interface HasContent()
{
    public string $content { get; set; }    
}

interface CanBeLiked()
{
    public function like(): void;
    public function isLiked(): bool;
}

class Post implements HasAuthor, HasContent, CanBeLiked
{
    public string $author = '...';
    public string $content = '...';
    public function like(): void { ... }
    public function isLiked(): bool { ... }
}

This principle is more achievable in PHP now that we have Intersection Types. For example:

class Thread
{
    /** @var HasAuthor&HasContent&CanBeLiked[] */
    private array $replies = [];

    public function __construct(private HasAuthor&HasContent $subject)
    {
    }

    public function display()
    {
        echo $this->subject->content . '<br>';
        echo 'Author: ' . $this->subject->author . '<br><br>';
        foreach ($this->replies as $reply) {
            echo $reply->content . '<br>';
            echo 'Author: ' . $reply->author . '<br><br>';
            if ($reply->isLiked()) {
                echo '(Someone has liked this reply!)<br><br>';
            }
        }
    }
}

The Thread class doesn't know anything about a Post class; it just knows that its $subject property must implement both HasAuthor and HasContent interfaces and that $replies must be an array of elements implementing (via static analysis), HasAuthor, HasContent, and CanBeLiked. These could be instances of Post, Comment, Letter, Car, Dog... anything really. Thread doesn't care.

It's easy to go overboard with this approach, creating dozens of tiny interfaces with massive intersectional types. As with much in coding, try to strike a balance between readability and loose coupling!

web-head's avatar

web-head liked a comment+100 XP

2mos ago

This is what made it click for me:

So $this->gateway->charge($amount); in the invoice class could be interpreted as - in case of a PaypalGateway object - as PaypalGateway ->charge(amount)?

Yes, that's correct! The line $this->gateway->charge($amount); in the Invoice class is a call to the charge method of the object that was injected into the Invoice class via its constructor.

Let's break it down step by step:

  1. Dependency Injection:

    • When you create an instance of the Invoice class, you pass an object that implements the BillingGateway interface to its constructor. For example:
      $paypalGateway = new PaypalGateway();
      $invoice = new Invoice($paypalGateway);
      
    • In this case, $paypalGateway is an instance of the PaypalGateway class, which implements the BillingGateway interface.
  2. Constructor Assignment:

    • Inside the Invoice class constructor, the passed BillingGateway object is assigned to the $gateway property:
      public function __construct(BillingGateway $gateway)
      {
          $this->gateway = $gateway;
      }
      
    • So, $this->gateway now refers to the $paypalGateway object.
  3. Method Call:

    • When you call $this->gateway->charge($amount); in the pay method of the Invoice class, it is equivalent to calling $paypalGateway->charge($amount); because $this->gateway is the $paypalGateway object.
    • The charge method of the PaypalGateway class will be executed with the $amount parameter.

Example Walkthrough:

Output:

Charging 100 using PayPal.

Explanation:

  • The PaypalGateway instance is created and passed to the Invoice constructor.
  • The Invoice class stores this instance in its $gateway property.
  • When the pay method of the Invoice class is called with an amount, it calls the charge method on the PaypalGateway instance stored in $this->gateway.
  • The charge method of the PaypalGateway class is executed, printing the message "Charging 100 using PayPal."

This demonstrates how dependency injection allows the Invoice class to use any implementation of the BillingGateway interface without being tightly coupled to a specific implementation.

web-head's avatar

web-head wrote a reply+100 XP

3mos ago

All right, I'll try watching them offline. Thanks.

web-head's avatar

web-head wrote a reply+100 XP

3mos ago

Steps 1, 2, 3, 4, 5 did not help me. Tried all of them.

These are the console errors.

  1. Partitioned cookie or storage access was provided to “https://player.vimeo.com/video/758852697/config/request?atid=2360365769.1768476732&expires=3600&referrer=https%3A%2F%2Flaracasts.com%2F&session=c00d12b0b8cf6ed3c5868ab0de956b2d26597b031768476732&signature=715cdc4592a30fcc28f56ada14e871ee&time=1768476732&v=1” because it is loaded in the third-party context and dynamic state partitioning is enabled.

  2. Media resource blob:https://player.vimeo.com/8521b86b-3b1f-473f-9fef-24b32ff66103 could not be decoded.

  3. This error message will be blank when privacy.resistFingerprinting = true. If it is really necessary, please add it to the whitelist in MediaError::GetMessage: virtual MediaResult mozilla::MP4ContainerParser::IsInitSegmentPresent(const MediaSpan &): Invalid Top-Level Box:����

  4. Cookie “__cf_bm” will soon be rejected because it is foreign and does not have the “Partitioned“ attribute. request

  5. Cookie “player” will soon be rejected because it is foreign and does not have the “Partitioned“ attribute. 758852697

web-head's avatar

web-head started a new conversation+100 XP

3mos ago

Hi, Laracasts team!

I'm watching from Kazakhstan, have a forever account. Since yesterday, there are player errors constantly appearing. Cannot play videos normally. Quality decreasing and stopping.

Error message: Player Error The player is having trouble. We’ll have it back up and running as soon as possible.

What can be done?

Usage OS: Linuxmint 22.2 Cinnamon Browser: Firefox & Brave (latest versions) Interned speed: ~150-200 mbps

P.S. Why there's no way to include a screenshot?

web-head's avatar

web-head wrote a comment+100 XP

4mos ago

@jdworks if you try adding ./public in front of the path to the file, it might fix your problem.

So the whole path to the font would be ./public/fonts/pixl/DepartureMono-Regular.woff2