Bounoable

Bounoable

Member Since 3 Years Ago

Experience Points 38,500
Experience Level 8

1,500 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 426
Lessons
Completed
Best Reply Awards 2
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.

06 Feb
2 years ago

Bounoable left a reply on Namespaceing Convention

That's the thing. I also have a Style and a Location class for the villa class and the Location class also depends on another class.

So is this the best approach?

App\Property\Villa::class
App\Property\Villa\Type::class
App\Property\Villa\Style::class
App\Property\Villa\Location::class
App\Property\Villa\Location\Distance::class

Or this:

App\Property\Villa::class
App\Property\Type::class
App\Property\Style::class
App\Property\Location::class
App\Property\LocationDistance::class

I'm questioning if it's a good approach to put classes that "belong to" another class into a sub-namespace with the name of that class (Villa and Location in this example).

Bounoable started a new conversation Namespaceing Convetion

Given I have a villa class:

´´´ App\Property\Villa::class ´´´

And I want to create a class for the type of the villa - which namespace would you take for the Type class?

´´´ App\Property\Villa\Type::class ´´´

or

´´´ App\Property\VillaType::class ´´´

or

´´´ App\Property\Type::class ´´´

I know it's just personal preferences, but I'd like to know how you would deal with this.

01 Feb
2 years ago

Bounoable left a reply on Laravel 5.3 Session Is Not Presistant

Make sure that the route to the AuthController has the "web" middleware group applied, otherwise the session will not start.

Bounoable left a reply on Laravel 5.3 Session Is Not Presistant

This can also happen when you don't "return" from your controller, but instead "die" or "exit" out of a controller

Bounoable left a reply on PHP Artisan Fails, Php Cli Version Issue

That's because composer will try to run the scripts (php artisan optimize) via the default PHP which points to php version that doesn't support the PHP-code from artisan and when you run the script manually, the correct php version is used (/opt/plesk/php/7.1/bin/php)

31 Jan
2 years ago

Bounoable left a reply on Append Html Code From Database Into The Page

Yes, either with default XMLHttpRequest (which is painful if you don't use a library like axios) or with native JS fetch:

fetch('/api/websites/WEBSITE_NAME').then(...);

But to use "fetch" in all browsers you would need do polyfill that (https://github.com/github/fetch) and then axios would be the better solution in my opinion.

Bounoable left a reply on Laravel And Fractal

I had this problem, too. The solution to this is to create your own Serializer implementation for Fractal.

I've changed Fractals DataArraySerializer to remove the data-keys completely:


namespace App\Database\Serializer;

use League\Fractal\Pagination\CursorInterface;
use League\Fractal\Serializer\SerializerAbstract;
use League\Fractal\Resource\ResourceInterface;
use League\Fractal\Pagination\PaginatorInterface;

class ArraySerializer extends SerializerAbstract
{
    public function collection($resourceKey, array $data)
    {
        return $data;
    }

    public function item($resourceKey, array $data)
    {
        return $data;
    }

    public function null()
    {
        return [];
    }

    public function includedData(ResourceInterface $resource, array $data)
    {
        return $data;
    }

    public function meta(array $meta)
    {
        if (empty($meta)) {
            return [];
        }

        return ['meta' => $meta];
    }

    public function paginator(PaginatorInterface $paginator)
    {
        $currentPage = (int) $paginator->getCurrentPage();
        $lastPage = (int) $paginator->getLastPage();

        $pagination = [
            'total' => (int) $paginator->getTotal(),
            'count' => (int) $paginator->getCount(),
            'per_page' => (int) $paginator->getPerPage(),
            'current_page' => $currentPage,
            'total_pages' => $lastPage,
        ];

        $pagination['links'] = [];

        if ($currentPage > 1) {
            $pagination['links']['previous'] = $paginator->getUrl($currentPage - 1);
        }

        if ($currentPage < $lastPage) {
            $pagination['links']['next'] = $paginator->getUrl($currentPage + 1);
        }

        return ['pagination' => $pagination];
    }

    public function cursor(CursorInterface $cursor)
    {
        $cursor = [
            'current' => $cursor->getCurrent(),
            'prev' => $cursor->getPrev(),
            'next' => $cursor->getNext(),
            'count' => (int) $cursor->getCount(),
        ];

        return ['cursor' => $cursor];
    }
}

I also created a QueryBuilder-wrapper for API-requests to reduce the boilerplate for those. It also automates the pagination and sorting by retrieving the "page"/"offset", "sortBy" and "order" values from the request and applying these on the query.

Aaaand it automatically eager loads all related models which are requested by the "include" property on the request object.

For example you can fetch all users and their orders and invoices from "http://laravel.dev/api/users?include=orders,invoices" and Fractal will include those while Laravel eager loads them.

namespace App\Database;

use Illuminate\Http\Request;
use League\Fractal\Manager;
use League\Fractal\Resource\Item;
use Illuminate\Database\Query\Builder;
use League\Fractal\Resource\Collection;
use App\Database\Serializer\ArraySerializer;
use League\Fractal\TransformerAbstract as Transformer;

class QueryBuilder
{
    const QUERY_LIMIT_DEFAULT = 100;
    const QUERY_LIMIT_MAX = 1000;

    protected $request;
    protected $query;
    protected $fractal;

    public static function make(Request $request, $query = null)
    {
        return new static($request, $query);
    }

    public function __construct(Request $request, $query = null)
    {
        $this->request = $request;

        $this->initFractal();
        $this->setQuery($query ?: app(Builder::class));
    }

    public function setQuery($query)
    {
        $this->query = $query;
    }

    public function query()
    {
        return $this->query;
    }

    public function get(Transformer $transformer = null)
    {
        $this->setupQuery();

        $data = $transformer ? $this->getTransformed($transformer) : $this->query->get()->all();

        return $this->returnResult($data);
    }

    public function first(Transformer $transformer = null)
    {
        $this->setupQuery();

        $data = $transformer ? $this->firstTransformed($transformer) : $this->query->first();

        return $this->returnResult($data);
    }

    public function getTransformed(Transformer $transformer)
    {
        return $this->fractal->createData(
            new Collection($this->query->get(), $transformer)
        )->toArray();
    }

    public function firstTransformed(Transformer $transformer)
    {
        return ($result = $this->query->first()) ? $this->fractal->createData(
            new Item($this->query->first(), $transformer)
        )->toArray() : $result;
    }

    public function parseIncludes(array $includes = [])
    {
        $this->fractal->parseIncludes(
            is_array($includes) ? $includes : func_get_args()
        );

        return $this;
    }

    protected function initFractal()
    {
        $this->fractal = (new Manager)->setSerializer(new ArraySerializer);

        $this->fractal->parseIncludes($this->extractIncludesFromRequest());
    }

    protected function extractIncludesFromRequest()
    {
        return array_filter(explode(',', $this->request->include), function ($include) {
            return strlen($include);
        });
    }

    protected function setupQuery()
    {
        $this->setPagination()
             ->setSorting()
             ->setIncludes();
    }

    protected function setPagination()
    {
        $limit = $this->capLimit(
            abs($this->request->input('limit', static::QUERY_LIMIT_DEFAULT))
        );

        $offset = $this->normalizeOffset(
            $this->request->input('offset', null),
            $this->request->input('page', null),
            $limit
        );

        $this->query->offset($offset);
        $this->query->limit($limit);

        return $this;
    }

    protected function capLimit($limit)
    {
        return $limit <= static::QUERY_LIMIT_MAX ? $limit : static::QUERY_LIMIT_MAX;
    }

    protected function normalizeOffset($offset = null, $page = null, $limit = 0)
    {
        if ($offset) {
            return abs((int) $offset);
        } elseif ($page) {
            return (abs((int) $page) - 1) * $limit;
        }

        return 0;
    }

    protected function setSorting()
    {
        $sortBy = $this->request->input('sortBy', null);
        $order = $this->request->input('order', 'asc');

        if ($sortBy)
            $this->query->orderBy($sortBy, $order);

        return $this;
    }

    protected function setIncludes()
    {
        $this->query->with($this->extractIncludesFromRequest());

        return $this;
    }

    protected function returnResult($data = [], array $merge = [])
    {
        return array_merge(['data' => $data], $merge);
    }
}

So in my Api-Controller I just do something like this:

public function index(Request $request)
{
    return QueryBuilder::make($request, Product::query())->get(new ProductTransformer);
}

And if you don't want to use a Transformer, you can just omit it and get the default results from Laravels QueryBuilder.

Bounoable left a reply on IE 11 Vuex Polyfill

I'm using this polyfill for Promises: https://github.com/stefanpenner/es6-promise

Via node:

npm install es6-promise
var Promise = require('es6-promise').Promise;

Or you could just pull it in via the script tag:

<script src="http://abc.xyz/path/to/promise/polyfill.js">

Bounoable left a reply on Append Html Code From Database Into The Page

Assuming you are using a library like axios you could fetch the website from your server with an api request like that:

axios.get('/api/websites/WEBSITE_NAME').then(
    html => document.querySelector('html').innerHTML = html
);

And in your routes file something like:

Route::get('/api/websites/{name}', '[email protected]);

WebsitesController:

...
public function show($name)
{
    return Website::where('name', $name)->first()->html;
}
...
04 Jan
2 years ago

Bounoable left a reply on Gulp Does Not Automatically Refresh Browser Css / Js Files

I'm using the CacheKiller Chrome extension to force the cache to be deleted at every reload.

25 Aug
2 years ago

Bounoable left a reply on Laravel5.3 - Controller Auth Problems

Same problem here.. Can anyone tell me how I am supposed to share my user variable in my Controllers if I can't do this in the constructor? I did that in nearly every Controller I made, so I have to ensure that all of the Controllers have access to the user in the same way they've had it until now but I'm not having a clue how to do it right.