FabLPA

FabLPA

Member Since 2 Years Ago

Experience Points
730
Total
Experience

4,270 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
3
Lessons
Completed
Best Reply Awards
0
Best Reply
Awards
  • start-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-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-token Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer-token Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • lara-evanghelist 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 1
730 XP
Feb
18
5 days ago
Activity icon

Replied to Eloquent Resource Collection With Relations

Damn f*£%#$ language barrier...

So, it was not the solution I need to achieve my goal, but you lead me to the solution ;)

Doing hundreds call to the BookServices' Search method take the same time than only one... So I could refine the search and get what I need.

    /**
     * Search Books
     *
     * @param BookServices $bookServices
     * @param BookSearch   $request
     *
     * @return mixed
     */
    public function search(BookServices $bookServices, BookSearch $request)
    {
        $response = $bookServices->search($request, false);

        // Get Categories figuring in the Search results
        $forCategories = $categories = [];
        $i = 0;
        foreach(Category::whereHas('frontendBooks')->get() as $category){
            $forCategories[$i] = $bookServices->search($request, false);
            if($forCategories[$i]->where('category_id', $category->id)->count() > 0) {
                $categories[$category->id] = $category;
                $i++;
            }
        }
        $categories = CategoryResource::collection($categories);

        // Get Catalogs figuring in the Search results
        $forCatalogs = $catalogs = [];
        $i = 0;
        foreach(Catalog::get() as $catalog){
            $forCatalogs[$i] = $bookServices->search($request, false);
            $id = $catalog->id;
            if($forCatalogs[$i]->whereHas('catalogs', function ($query) use($id) {
                    return $query->where('catalogs.id', $id);
                })->count() > 0) {
                $catalogs[$id] = $catalog;
                $i++;
            }
        }
        $catalogs = CatalogResource::collection($catalogs);

        // Get stats for authors / titles / resume figuring in the Search results
        $authors = $titles = $resumes = null;
        if(isset($request->term)) {
            $authors = 0;
            $foo = [];
            foreach($bookServices->search($request, false)->select('author_id')->getResultsInAuthors($request->term)->distinct()->get() as $authorBook){
                if(!in_array($authorBook->author, $foo)){
                    $foo[] = $authorBook->author;
                    $authors++;
                }
            }
            $resumes = $bookServices->search($request, false)->select('resume')->getResultsInResumes($request->term)->distinct()->count();
            $titles = $bookServices->search($request, false)->select('title')->getResultsInTitles($request->term)->distinct()->count();
        }

        $meta = [
            'meta' => [
                'catalogs' => $catalogs,
                'categories' => $categories,
                'authors' => $authors,
                'titles' => $titles,
                'resumes' => $resumes,
            ]
        ];

        return (BookForListResource::collection($response->paginate($request->perPage ? $request->perPage : 12)))->additional($meta);
    }

I don't think it's the proper way or even a clean way to do, but it works... and after days on this, it's time to let it like this

Activity icon

Replied to Eloquent Resource Collection With Relations

As said yesterday, I'll copy/paste the necessary parts of my code here for a better comprehension of my problem.

My mean issue is how to get the same stuff as the left column of the website I gave as example (https://bibliotheque.braille.be/fr/catalogue).

In my Eloquent Book Model, I have those relationships :

    public function catalogs()
    {
        return $this->belongsToMany(Catalog::class)
            ->using(CatalogFrontendBook::class)
            ->withPivot('frontend_book_id', 'catalog_id', 'nbr_of_copies', 'new', 'newed_at', 'length')
            ->withTimestamps();
    }

    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function author()
    {
        return $this->belongsTo(Author::class);
    }

    public function serie()
    {
        return $this->belongsTo(Serie::class);
    }

The search Method in my BookController :

    /**
     * Search Books
     *
     * @param BookServices $bookServices
     * @param BookSearch   $request
     *
     * @return mixed
     */
    public function search(BookServices $bookServices, BookSearch $request)
    {
        $response = $bookServices->search($request, false);
        
        // How to get those relations based on the whole results, not on the 12 results returned by the pagination,
        // without running a foreach on $response->get() to crawl all results 
    // perhaps have I to do a raw query to get all joined tables ?
        $catalogs = []; 
        $categories = [];
        $authors = [];
        $series = [];

        $meta = [
            'meta' => [
                'catalogs' => $catalogs,
                'categories' => $categories,
                'authors' => $authors,
                'series' => $series,
            ]
        ];

        return (BookForListResource::collection($response->paginate($request->perPage ? $request->perPage : 12)))->additional($meta);
    }

The Search method in the Book service :


    /**
     * Run Search for a book
     * 
     * @param      $request
     * @param bool $auth
     *
     * @return mixed
     */
    public function search($request, $auth = false)
    {
        $catalog = $request->catalog;
        $category = $request->category;
        $field = $request->field;
        $term = $request->term;

        // termSearch - catalogSearch - categorySearch are scopes in Book models
    // here is the eager load of all required relations
        $books = FrontendBook::with('author', 'serie', 'catalogs', 'category', 'subcategory')
                             ->termSearch($term, $field)
                             ->catalogSearch($catalog)
                             ->categorySearch($category);

        return $books;
    }

And the Resource "BookForListResource" (Json\JsonResource) :

    public function toArray($request)
    {
        $defaultCover = Storage::disk('s3')->url('covers/default.jpg');

        $inFavoris = $inLoans = $inWishlist = $hasCommented = false;
        if(auth('api')->check()){
            $inLoans = $this->loans()->where('member_id', auth('api')->id())->count() > 0 ? $this->loans()->where('member_id', auth('api')->id())->first() : false;
        }

        return [
            'id' => $this->id,
            'title' => $this->title,
            'author' => $this->author ? $this->author->complete_name : false,
            'resume' => $this->resume,
            'cover' => $this->cover == '' ? $defaultCover : $this->cover,
            'length' => $this->whenPivotLoaded('catalogs', function () {
                return $this->pivot->length;
            }),
            'href' => $this->unique_key,
            $this->mergeWhen(auth('api')->check(), [
                'in_loans' => $inLoans ? true : false,
            ]),
            'categories' => $this->categories
        ];
    }

Is quite hard to explain it in English... Hope it'll be easier to understand what I want to achieve and where I'm stuck. @sinnbeck

Feb
17
6 days ago
Activity icon

Replied to Eloquent Resource Collection With Relations

@sinnbeck it’s just a part of my code, I’ve leaved the office, I’ll copy/paste the whole code tomorrow morning. Perhaps you’ll have a better view of where I’m stuck.

This said, have you take a look to the link I gave? How would you do to have the same kind of results (left and right column) through an API with API Resources ?

Thanks for your help ;)

Activity icon

Replied to Eloquent Resource Collection With Relations

@sinnbeck like this, I'll have only the authors for the paginate() results (here 12), not for the whole results (let say that the result will return thousands of books).

All needed relationship are already eager loaded and used through Book Resource when needed (to display book name / author on search result's pages).

But through this, I can't have all authors of the whole search result, just get the 12 authors for the 12 books of the search result's page (pagination). Am I wrong ? Have i missed something with API Resources ?

Activity icon

Started a new Conversation Eloquent Resource Collection With Relations

Hi All,

So... I'm stuck on how to achieve the same system as here : https://bibliotheque.braille.be/fr/catalogue

What to achieve :

I'm building an API to retrieve books.

As on the example, I have to do a "search" engine which return a paginated book resource. The search engine is already done and work well but I'm stuck on how to do for the left column.

How, on this basis

$books = Book::where('title', 'rings'); // the search is into a service provider and...is a little bit more hard

return BookCollection($books->paginate(12));

could I get, a list of authors and the count of this author's book into the search result.

With the paginate() I can't have the whole authors for the whole book's search results...

I try to add something like :

$books = Book::where('title', 'rings');

$authors = [];
foreach($books->get() as $book){
    $author = $book->author //=> the relationship exists
    $authors[] = new AuthorCollection($author);
}

$meta = [
    'meta' => [
        'authors' => $authors
    ]
];

return (BookCollection($books->paginate(12)))->additional($meta);

but it takes so many times to achieve the request that I get a timeout... and it's only for the authors...I have to do that for "catalogs" / "categories" / "series" etc.

Any clue or suggestion will be welcome !

Feb
14
1 week ago
Activity icon

Replied to Lazy Loading Vue Components And Laravel-mix Issue

Hi @georgie817 , Have you found a solution to this problem? I have been focusing on this since this morning and I have not yet found solutions.

Jan
30
3 weeks ago
Activity icon

Started a new Conversation Advice (or A Big Hug) About L5.8 Passport (7.5) And Password Grant Type

Hello peeps',

First, sorry for my English ! Hope you'll understand the purpose of my question.

So...

I tear the little hair I have left on user authentication via an API and the persistence of this authentication ...

In summary :

I have a front-end (and a CMS but at this point we don't care). In this one I have a classic login form: email / pass.

When submitting the form, a POST request is sent to my route: api/login which is on the same domain as the front-end.

This route points to an "AuthMemberController" controller. In the Login method, I make a call via Guzzle in POST to oauth/token with correct credentials (of the passport client and the user). I have received a Token: https://share.getcloudapp.com/9ZuN1xgd

It is from there that I get more ...

Via Postman:

I make a request in GET to api/me which is supposed to return me the data of the connected user (Resource). Except that I get an "Unauthenticated".

Via the front-end:

The form is in VueJS. The request is sent to api/login via Axios. If successful (so recovering a token), I reload the page. For my test, I shifted the reload to 2 seconds, and there I see via the debugbar that the user is well connected to the "web" guard: https://share.getcloudapp.com/yAuLNDdO

At the reload, the user is no longer connected.

It's probably a bullshit, but by dint of testing everything I saw / read I probably fucked up the souk ... And even if I read the doc, I don't see where I shit.

Config of the project NGINX server Laravel 5.8 Passport 7.5 a bunch of other packages (mainly Spatie stuff)

**And for the files: ** config/auth.php

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'members',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'members',
        ],
        'api' => [
            'driver' => 'passport',
            'provider' => 'members',
        ],
    ],
        'providers' => [
        'members' => [
            'driver' => 'eloquent',
            'model' => App\Member::class,
        ],
    ],

app/Providers/AuthServiceProvider.php

    public function boot()
    {
        $this->registerPolicies();
        Passport::routes();
    }

app/Http/Controllers/Api/AuthMemberController.php

    public function login(MemberAuthLogin $request)
    {
        $http = new GuzzleHttp\Client;
        try {
            $response = $http->post(route('passport.token'), [
                'form_params' => [
                    'grant_type' => 'password',
                    'client_id' => config('api.member.client_id'),
                    'client_secret' => config('api.member.client_secret'),
                    'username' => $request->email,
                    'password' => $request->password,
                    'scope' => '*',
                ],
            ]);
        } catch (GuzzleHttp\Exception\ClientException $ex) {
            return response()->json(['error' => 'Unauthorized', 'code' => $ex->getCode(), 'msg' => $ex->getMessage()], 401);
        }
        if ($this->attemptLogin($request)) {
            $member = Auth::user();
        } else {
            return response()->json(['error' => 'Auth failed'], 401);
        }
        return response()
            ->json(json_decode((string)$response->getBody(), true), 200);
    }

app/Http/Controllers/Api/MemberAccountController.php

    public function me()
    {
        if(Auth::user()) {
            return new MemberResource(Auth::user());
        }else{
            return response()->json(['error' => 'Unauthorized'], 401);
        }
    }

I also tried to add parameters to Passport via AuthServiceProvider like:

        Passport::cookie('MonApp');
        Passport::enableImplicitGrant();

But not better ...

Do I forget a Middleware somewhere? Or to declare something somewhere? Does it shit because the 3 entities of the app (Api / Consumer App / CMS) work in the same Laravel project? When I return from the login, do I have to do something more than just return the token? Do I have to make a call to a "web" route to continue the authentication (I doubt ...)?

Note that I have a 3rd guard for admins who must connect to the CMS (and who will have access to the API via a MachineToMachine Client access).

Any help will be appreciable and appreciated at its fair value: D

Nov
06
3 months ago
Activity icon

Started a new Conversation Search Results With Pagination But Also Containing Information On All Data Without Regard To Pagination

Hi People,

For a customer, I'm developing an API for an online book catalog and I'm drying out on a feature, or more specifically on some part of this feature.

An example of what I try to obtain: https://bibliotheque.braille.be/fr/catalogue?filters%5Bsearch%5D=King

On the left is a column of sub-filters that is based on all the results of the search.

And on the right, the list of books with pagination.

Do you have any idea of how I can build my query to have pagination AND "filters" based on the entire search result?

It's probably stupid as cabbage, but probably too much head on the handlebars to find the solution ...

What I use for the moment:

  • a Controller which receives in POST the fields of the search form
  • a Service that performs the search in the db
  • a Resource that is returned to the front-end by the Controller

If I do that in my controller:

$response = $ bookServices-> search ($ request);
$bookGlobal = BookResource :: collection ($ response-> get ());
$bookPaginate = BookResource :: collection ($ response-> paginate ($ request-> perPage));

return response () -> json (['books' => $ bookPaginate, 'filters' => $ bookGlobal], 201);

It returns to me my paginated books (books) and books without pagination (filters) that will allow me in front of "build" the left column, but it's a little devil ... I lose the pagination info for " books ", and the loading time is not great.

By doing that :

$ response = $ bookServices-> search ($ request, false);

return BookResource :: collection ($ response-> paginate ($ request-> perPage));

The answer contains the pagination info, but I have nothing complete to build the left column.

An idea ?

Laravel version: 5.8

And sorry for my poor English...

Sep
18
5 months ago
Activity icon

Started a new Conversation Forms Shared By Back & Front End : How To Properly Deal With It

Hi all,

Until now, I've always separate the back & the front end of my apps. But... it's quite boring to create a special form for the back (CRUD ops mainly), and praticaly the same for the front with only few differences. And of course, 2 controllers for the same Model, one for the back, one for the front. Not easy to maintain...

How to you deal with this ?

Do you use an API inside your app ? If so, how do you deal the auth ? It'll be different between the back & the front, with perhaps multiple roles for the back-end