Our Black Friday sale is now live! All individual subscriptions are 50% OFF. This week only!

RomainB

Full stack developper at Toulon, France

Member Since 1 Year Ago

Toulon

Experience Points
56,100
Total
Experience

3,900 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
488
Lessons
Completed
Best Reply Awards
4
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 12
56,100 XP
Nov
05
2 weeks ago
Activity icon

Replied to API Resource: Using Count() With WhenLoaded()

Searching to do the same thing: get the count only if it exists.

And Actually the way @sinnbeck says and marked as the answer does the exact same thing that @jbloomstrom and has been judged as "unappropriate":

'playedUpCount'=> $this->whenLoaded('playedUps', function() { // If the playedUps relation has ben loaded from the controller
    return $this->playedUps->count() // Then it count the collection's items
}),

That's definitively not a COUNT() from the database and does the exact same thing that @jbloomstrom has said: it loads the entire relation's collection, and then does just a count on the collection's elements

To do the same, I have done like this:

class ShopResource extends \Illuminate\Http\Resources\Json\Resource
{
    public function toArray($request)
    {
        $resource = [
            'id' => $this->id,
            'name' => $this->name,
            'description' => $this->description,
            'lat' => $this->price,
            'lng' => $this->quantity,
            'photos' => $this->whenLoaded('photos'),
            'products' => ProductResource::collection($this->whenLoaded('products'))
        ];

        if ($this->products_count) {
            $resource['products_count'] = $this->products_count;
        }

        return $resource;
    }
}

And then from the controller:

// Get the count directly from the relationship query
$shops = Shop::withCount('products');
return new JsonResponse(
    ShopResource::collection($shops->get())
);
Nov
02
3 weeks ago
Activity icon

Replied to ->performDeleteOnModel() On Model When ->decrement() <= 0 Does Not Fire Deleting/deleted Event

@rodrigo.pedra Oooh myyy gash!

The problem was not the EventServiceProvider because I'm using the event discovery feature

You know what? The problem was on this part:

<?php

use App\Models\Building;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    $building = Building::query()->with('resources')->first();

    $resource = $building->resources->first();

    $resource->pivot->decrement('quantity', 1);

    return 'ok';
});

The problem was the fact that I was using tinker to run my debug test and waiting into Telescope for my event to appear. But I just discovered that tinker doesn't send any event before it exits well (using return false in the thread, not tested).

Using your route made it work magically...

Two big lesson learned today:

  • There is still people who likes to help other people they never met
  • Always debug in a real environment: the browser. Instead of using alternative debug tool where unknown behaviour may appear.

P.S: about the updating/updated event. Yes, it definitely a question of choice where my use case made me choose the first one for two reasons:

  • Like you've done, my database field was unsigned so I didn't want to save negative a value before deleting it because it will crash my script
  • I said to myself: why would to save something, if the final goal is to delete it? perform only one query: delete it directly

But I may choose the other hand in the future for other use case ;)

Activity icon

Replied to ->performDeleteOnModel() On Model When ->decrement() <= 0 Does Not Fire Deleting/deleted Event

Hi @rodrigo.pedra , thanks for you time.

Here is my relation:

// Trait HasResource, used by Building, Character and more to come
public function resources(): \Illuminate\Database\Eloquent\Relations\morphToMany
{
    return $this->morphToMany(
                    ResourceDefinition::class,
                    'owner',
                    'resources',
                    'owner_id'
                )
                ->using(Resource::class)
                ->withPivot('id', 'quantity');
}

// Class Resource
class Resource extends MorphPivot
{

    // This is just to be able to retrieve the definition directly from the resource
    public function definition(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(
            ResourceDefinition::class,
            'resource_definition_id'
        );
    }

    // I also use a "HasOwner" in this pivot model defining this
    // This is only to be able to retrieve the owner from the pivot model
    public function owner(): \Illuminate\Database\Eloquent\Relations\MorphTo
    {
        return $this->morphTo();
    }
}

// Class ResourceDefinition
class ResourceDefinition extends Model
{
    // Nothing about the relation here, should it do?
    // I'll never need to retrieve anything from the resource definition
}

Can't look further at the doc for now, will give it a look in 3 hours and edit the message if I found something interesting there.

Nov
01
3 weeks ago
Activity icon

Started a new Conversation ->performDeleteOnModel() On Model When ->decrement() <= 0 Does Not Fire Deleting/deleted Event

Hi everyone.

I'm working with a Resource pivot model between Owners and ResourceDefinition models.

When trades are made, I'm using decrement on the additional pivot "quantity" field:

DB::transaction(function () use ($givenItem, $target, $quantity) {
    $target->receive($givenItem, $quantity);

    $givenItem->pivot->decrement('quantity', $quantity);
});

I've registered a callable function into the updating event to perform the deletion of the model (and relation):

protected static function booted(): void
{
    /**
     * Because Resource is just a pivot between its owner and ResourceDefinition
     * We need to delete it when it decrease to 0
     */
    static::updating(static function (self $model) {
        if ($model->quantity <= 0) {
            Log::debug('from model');

            $model->performDeleteOnModel(); // I've also tried ->delete(), but my model is not deleted....
        }
    });
}

but for some kind of owner (it's a polymorphical relationship), I need to delete the owner when the quantity hit the ground, so I've created an event which should be fired when deleting the model:

// In my resource model class
protected $dispatchesEvents = [
    'deleting' => Deleting::class
];

// My event:
class Deleting
{
    public ResourceModel $resource;

    public function __construct(ResourceModel $resource)
    {
        Log::debug('from event');

        $this->resource = $resource;
    }
}

// My listener
class DestroyAndRespawnCollectableBuilding
{
    public function handle(Deleting $event)
    {
        Log::debug('from listener');
    }
}

Listener discovering is activated so I don't need to register the event (all others work fine)

I've used log to not blow your mind with my code-logic, but the result is here, I'm trying to fire the event twice, but no log from the event or listener is registered:

[2020-11-01 21:24:14] local.DEBUG: from model
[2020-11-01 21:23:18] local.DEBUG: from model

Does someone know why this is happening?

Oct
31
3 weeks ago
Activity icon

Replied to SetBindings On UpdateExistingPivot()

You should post your own thread so your problem would be more visible.

Anyway, yes you can update "only the additional pivot table field" using updateExistingPivot. It should be something like:

$user->clients()->updateExistingPivot($clientId, ['data' => 'new data stuff']);

https://laravel.com/docs/8.x/eloquent-relationships#updating-a-record-on-a-pivot-table

@michaloravec thanks to you, I've already this these post yesterday but I was missed something in my relationship declaration, I'm using a pivot model and was binding it instead of the final related model.

You made me search more deeply in my code to found the problem. Now I can use:

    $resource->pivot->increment('quantity', $quantity);

Thanks!

Oct
30
3 weeks ago
Activity icon

Started a new Conversation SetBindings On UpdateExistingPivot()

Hi everyone,

I have a ManyToMany polymorphic relation, and I would like to increment a pivot field.

The query should be like:

UPDATE `pivotTable` set field = field + 6;

The problem is I've don't succeed into using addBindings, setBindings or mergeBindings methods.

The way I've done for now is "ok" for numeric value, but it would create a security breach for a text field:

$this->resources()->updateExistingPivot(
    $item->id, [
        // TODO: Find a way to use bindings instead of type casting
        'quantity' => DB::raw('quantity + '. (int) $quantity)
    ]
);

All my tries ended up with an incorrect number of bindings.

Does anyone know how to do that?

Aug
23
3 months ago
Activity icon

Replied to Automatically Apply A Scope On All Queries

Ok, I've just found my way, overriding the newQuery parent method:

    public function newQuery()
    {
        $query = parent::newQuery();
        /** Avoid to only query the x and y columns */
        if (blank($query->getQuery()->columns)) {
            $query->addSelect('*');
        }

        return $query->addSelect([
            'x' => DB::raw('ST_X(position) as x'),
            'y' => DB::raw('ST_Y(position) as y')
        ]);
    }
Activity icon

Started a new Conversation Automatically Apply A Scope On All Queries

Hi, I'm working with PostGIS and I would to return x and y integer from the point(position) column with all my model request.

I've created a scope:

    public function scopeWithXY(Builder $query)
    {
        return $query
            ->selectRaw('ST_X(position) as x, ST_Y(position) as y');
    }

but is it possible to apply it on all queries automatically without the need to call MyModel::withXY()?

Jun
28
4 months ago
Activity icon

Replied to Use ->with() With Additionnal Parameters

The problem of the whereHas solution is the fact I'll need to duplicate the complex SQL query. I didn't found any example where I could use just the child scope? Am I missing something?

[EDIT] I've just tried and it seems to work well with a scope:

public static function scopeAround($query, string $postal_code, int $distance = 10)
{
    return $query->whereHas('land', fn ($q) => $q->around($postal_code, $distance));
}

Seems like you are a life saver :)

Activity icon

Started a new Conversation Use ->with() With Additionnal Parameters

Hi, working for a house builder I have two models: Land and Offer (related to a Land and a HouseModel).

I need to geolocate lands and offers around a specific land/offer to display the ones next to the one currently displayed. I created a scope in my Land model using a relatively complex SQL geolocation which is working well:

// Land.php
public function scopeAround($query, string $postal_code, int $distance = 10)
{
    return $query->join(DB::raw(
         // Complex geolocation query, useless for this thread
    ), 'geoloc.name', '=', 'romainmazb_realestate_lands.town')
    ->addBinding($postal_code)
    ->where('distance_in_km', '<=', $distance);
}

Querying Land::around(<aPostalCode>) is working well. What I need to achieve now is to geolocate offers around a specific offer, where I've been for now is:

// Offer.php
public static function scopeAround($query, string $postal_code, int $distance = 10)
{
    return $query->with([
        'land' => fn ($q) => $q->around($postal_code, $distance),
        'house_model'
    ]);
}

The problem is: when I'm using Offer::around(<aPostalCode>), it returns me all the 5k offers! Looked at the SQL generated( using Offer::around(<aPostalCode>)->toSql(), the eager loading is definitely not applied:

select * from `romainmazb_realestate_offers` where `romainmazb_realestate_offers`.`deleted_at` is null