achatzi

Senior Web Developer at LALIZAS SA

Experience

3,910

0 Best Reply Awards

  • Member Since 1 Year Ago
  • 34 Lessons Completed
  • 0 Favorites

31st July, 2018

achatzi started a new conversation Failed Job Logging • 2 weeks ago

Hello.

I have a Job that has a failed function, logging the Exception that caused the failure in a specific channel.

Every time the job fails, I have 2 entries in my log, one the in the appropriate channel and one in the default channel, where all the events of the app get logged.

I thought that the failed function of the job handles the exception, could you please help me find the reason why it gets logged twice;

I should also mention that I am using a custom mysql logger.

This is the job

namespace App\Jobs\B2B;

use App\Contracts\HasJobEvents;
use App\Traits\LogsRemotely;
use App\Traits\Notifies;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Log;

class GenericUpdate implements ShouldQueue, HasJobEvents
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Notifies, LogsRemotely;

    
    /**
     * @var int
     */
    public $timeout = 300;

    /**
     * @var int
     */
    public $tries = 3;  

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle() {
        //do stuff
    }
    
    public function failed(\Throwable $exception = null)
    {
        Log::channel('b2b')->error('Job Failed', ['exception' => $exception]);
    }
}

Thank you.

achatzi left a reply on Deadlock Issues • 2 weeks ago

I encountered this issue recently and from what I understand, the problem lays with multiple workers on the same queue.

I had 10 workers running the same queue and I always got a deadlock with the jobs table because some worker was trying to delete a finished job while another one was trying to update some other job.

I changed the driver to redis in order to solve it completely (and because I had timeout issues as well).

11th July, 2018

achatzi left a reply on Queues And Model Events Logging (with Auth) • 1 month ago

@lostdreamer_nl Your suggestion works perfectly, thank you!

10th July, 2018

achatzi left a reply on Queues And Model Events Logging (with Auth) • 1 month ago

@lostdreamer_nl Thanks for the reply.

Actually, this is the direction I was going as well, but I could not find a way to distinguish when the login was from the web or the console. I think what you wrote might do the trick.

Quick question though, do I really need a new listener? Right now my listeners are like this

class LogSuccessfulLogin
{
    /**
     * Create the event listener.
     *
     * @param  Request  $request
     */
    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Handle the event.
     *
     * @param  Login  $event
     * @return void
     */
    public function handle(Login $event)
    {
        
            //$user = $event->user;
            
            $login = new AccountLogin();
            $login->account_id = $event->user->id;
            $login->account_ip = $this->request->ip();
            $login->login_date = Carbon::now()->toDateTimeString();
            $login->save();

            $event->user->current_login_id = $login->id;
            $event->user->save();
       
    }
}

if I add an if condition in the handle method, wouldn't be enough?

public function handle(Login $event)
{
    if (!\App::runningInConsole()) {
        //$user = $event->user;
        
        $login = new AccountLogin();
        $login->account_id = $event->user->id;
        $login->account_ip = $this->request->ip();
        $login->login_date = Carbon::now()->toDateTimeString();
        $login->save();

        $event->user->current_login_id = $login->id;
        $event->user->save();
    }
}

9th July, 2018

achatzi started a new conversation Queues And Model Events Logging (with Auth) • 1 month ago

Hello to everyone.

I have used a package (https://docs.spatie.be/laravel-activitylog/v2/introduction) to log the changes in my models. By default it uses the auth user as the causer of the change. So if I change an order from Pending to Approved, a record would be created in my activity log, saying that the user achatzi modified the order #123456.

This has worked fine until the need presented to have queued jobs updating the models (for example, I have a job that connects to our ERP Webservice, collects data and updates the app). That meant that the queue worker does not have access to the logged in user and all my changes are logged with null as the causer.

So I am trying to find a way for the queue worker to have access to the logged in user (which is the user that initiated the job). I tried using

auth()->loginUsingId($this->account_id);

in my jobs as a workaround, but this has created other issues, For example, I have an event handler for the login event that creates a record in a logins table and updates the current_login_id of the user, so when I use the workaround it gets fired and I have multiple logins for the same user.

14th June, 2018

achatzi left a reply on Extra Data In Failed Jobs Table • 2 months ago

Ok, I managed to find a solution and I am posting it in case someone finds it useful.

I found a package in GitHub to store failed jobs in files (https://github.com/pmatseykanets/file-queue-failer) and I used that for inspiration.

I created a ServiceProvider that overwrites the queue.failer with a class that extends DatabaseFailedJobProvider. In that class I overloaded the log function and everything seems to work.

namespace App\Providers;

    use Illuminate\Support\ServiceProvider;
    
    class ExtendedQueueServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap services.
         *
         * @return void
         */
        public function boot()
        {
            // Get a default implementation to trigger a deferred binding
            $_ = $this->app['queue.failer'];
        
            // Swap the implementation
            $this->app->singleton('queue.failer', function ($app) {
                $config = $this->app['config']['queue.failed'];
                
                return new ExtendedDatabaseFailedJobProvider($this->app['db'], $config['database'], $config['table']);
            });
        }
    }

achatzi started a new conversation Extra Data In Failed Jobs Table • 2 months ago

Hello everyone.

I have an api that accepts orders and adds them to a queue in order to be transferred to our ERP system (it uses COM objects and it takes a long time, so queues was the best way to go).

When the job fails, it gets transferred to the failed jobs table. My question is if there is a way to add extra data in the failed jobs table, ex the order id. I would like to have a json column in the failed jobs table and add data there.

Is that possible?

31st January, 2018

achatzi left a reply on Create Tree Structure From Flat Array In Blade • 6 months ago

Sorry for the late reply. Yes everything is ok, thanks!

26th January, 2018

achatzi left a reply on Create Tree Structure From Flat Array In Blade • 6 months ago

The requirements of the app was that a user can have many parents and children. The solution (which I did not create by the way, I found it like this) was to create 3 tables.

The first is the users table, the second is a table called users_hiers which has id, parent_id (referencing the id of the same table) and user_id, the third is a table called users_hiers_tree which has parent_id (referencing id in users_hiers), child_id (referencing id in users_hiers) and depth. It is sort of a closure table.

Various triggers handle the updates and inserts in the users_hiers_tree table. So we have multiple trees of users_hierarchies in the same table.

When you fetch the hierarchies of a user, the result is what I posted and I am trying to show this in a html list.

Anyway, today I wrote a php function to solve my problem and I will convert it to a macro for blade usage.

Thank you.

achatzi left a reply on Checkboxes & Relationships • 6 months ago

Sorry, small typo there! Thanks for pointing out. I edited my reply.

24th January, 2018

achatzi started a new conversation Create Tree Structure From Flat Array In Blade • 6 months ago

Hello everybody.

I have this scenario:

User has multiple parents and multiple children modeled like this:

Relationship 1 Parent 1 Parent 2 User Child 1 Child 2 Child 3 Relationship 2 Parent 1 User Child 1

You get the idea...

Now, when I query the relationships I get an array like this:

Array [
    [ //first relationship
        'parents' => [
            ['name' => 'parent 1', 'depth' => 2],
            ['name' => 'parent 2', 'depth' => 1],
            ['name' => 'user', 'depth' => 0]
        ],
        'children' => [
            ['name' => 'user', 'depth' => 0],
            ['name' => 'child 1', 'depth' => 1],
            ['name' => 'child 2', 'depth' => 2],
            ['name' => 'child 3', 'depth' => 2]
        ]
    ],
    [//second relationship
        'parents' => [
            ['name' => 'parent 1', 'depth' => 1],
            ['name' => 'user', 'depth' => 0]
        ],
        'children' => [
            ['name' => 'user', 'depth' => 0],
            ['name' => 'child 1', 'depth' => 1]
        ]
    ]
]

My goal is to create a ul list in a blade view based on the depth. So my final list should be:

<ul>
    <li>Relationship 1
        <ul>
            <li>Parent 1
                <ul>
                    <li>Parent 2
                        <ul>
                            <li>User
                                <ul>
                                    <li>Child 1
                                        <ul>
                                            <li>Child 2</li>
                                            <li>Child 3</li>
                                        </ul>
                                    </li>
                                </ul>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>

    <li>Relationship 2
        <ul>
            <li>Parent 1
                <ul>
                    <li>User
                        <ul>
                            <li>Child 1</li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

Any ideas?

achatzi left a reply on Checkboxes & Relationships • 6 months ago

@Snapey old habit I guess :simple_smile:

The solution was quite simple actually and I do not know why it gave me some trouble.

At the checkbox code I replaced false with $companies->languages

{!! Form::checkbox('languages[]', $language->id, $companies->languages, ['id' => 'languages_' . $language->id, 'class' => 'md-check']) !!}

19th January, 2018

achatzi started a new conversation Checkboxes & Relationships • 6 months ago

Good morning.

I have 2 models (companies & languages) with many-to-many relationship, using a pivot table (companies_languages).

For the model Company I have a partial view (form.blade.php) which contain a form bind with the model and 2 views (create & edit) that include that partial.

I have an issue using checkboxes for the relationship with the Language model. My goal is at the create view the form will show the languages list and nothing is checked (obviously) and at the edit view the form will show the list but have the company's languages checked. Also, the session flash data should work.

My models

class Company extends Model
{ 
        public function languages() {
            return $this->belongsToMany('App\Models\Language', 'companies_languages');
        }
}

My Controller

public function create()
{
            $html = [
                'languages_list' => Language::all(),
            ];
    
            return view('companies.create', $html);
}

public function edit(Company $company)
{
 
            $html = [
                'languages_list' => Language::all(),
                'company' => $t
            ];
    
            return view('companies.edit', $html);
}

My Form View

@if (isset($company))
    {!! Form::model($company, ['route' => ['companies.update', $company->id], 'method' => 'patch', 'class' => 'form']) !!}
@else
    {!! Form::open(['route' => 'companies.store', 'method' => 'post', 'class' => 'form']) !!}
@endif
<div class="form-body">

        <div class="col-sm-6">
            <div class="form-group form-md-checkboxes">
                <label>Languages</label>
                <div class="md-checkbox-list">
                    @foreach($languages_list as $language)
                        <div class="md-checkbox">
                            {!! Form::checkbox('languages[]', $language->id, false, ['id' => 'languages_' . $language->id, 'class' => 'md-check']) !!}
                            <label for="languages_{{ $language->id }}"><span></span><span class="check"></span><span class="box"></span> {{ $language->title }}</label>
                        </div>
                    @endforeach
                </div>
            </div>
        </div>
    </div>

</div>
{!! Form::close() !!}

Shouldn't checkbox('languages[]') be enough to bind the checkbox list with the model's languages attribute? From what I read here https://github.com/LaravelCollective/html/issues/23 & https://github.com/LaravelCollective/html/pull/45 that should be the case so there must be something I am missing, right?

Any help would be greatly appreciated.

8th August, 2017

achatzi left a reply on Many To Many Through Many To Many • 1 year ago

Ok, I figured it out, after I read a little bit more about querying relationships.

So now the scopeFilter function looks like this:

/**
 * @param Builder $query
 * @param array $filters
 * @return Builder
 */
public function scopeFilter(Builder $query, array $filters)
{
    if (isset($filters['created_range'])) {
        $query->whereBetween('listings.created_at', explode(' - ', $filters['created_range']));
    }
    
    if (isset($filters['title'])) {
        $query->where('listings.title', 'like', '%' . $filters['title'] . '%');
    }
    
    if (isset($filters['user'])) {
        $query->where('listings.user_id', '=', $filters['user']);
    }
    
    if (isset($filters['product'])) {
        $query->whereHas('products', function ($q) use ($filters) {
            $q->where('product_id', $filters['product']);
        });
    }
    
    if (isset($filters['category'])) {
        $categories = Category::find($filters['category'])->getDescendantsAndSelf()->pluck('id');
        
        $query->whereHas('products', function ($q) use ($categories) {
            return $q->whereHas('category', function ($q2) use ($categories) {
                $q2->whereIn('products.category_id', $categories);
            });
        });
    }
    
    if (isset($filters['active'])) {
        $query->where('listings.is_active', $filters['active']);
    }
    
    if (isset($filters['order']) && $filters['order'] == 'desc') {
        $order = 'desc';
    }
    else {
        $order = 'asc';
    }
    
    if (isset($filters['sort'])) {
        $query->orderBy('listings.' . $filters['sort'], $order);
    }
    
    return $query;
}

Thanks for the help!

achatzi left a reply on Many To Many Through Many To Many • 1 year ago

Thank you for the reply @Parasoul, much appreciated.

I made a few changes in my code, not the Category model is like this

class Category extends Node
{
    public function products()
    {
        return $this->hasMany('\App\Models\Product');
    }
    
    public function listings()
    {
        return $this->hasManyThrough('\App\Models\Listing', '\App\Models\Product');
    }
}

and in my Listing model I modified the scopeFilter function like this

public function scopeFilter(Builder $query, array $filters)
{
    if (isset($filters['category'])) {
        $categories = Category::find($filters['category'])->getDescendantsAndSelf()->pluck('id');
        
        $query->whereIn('products.category_id', $categories);
    }

    if (isset($filters['active'])) {
        $query->where('listings.is_active', $filters['active']);
    }

    return $query;
}

Finally, in my Listings controller I have this

$listings = Listing::with(['user', 'products.category'])->filter(request()->all())->paginate(10);

Unfortunatelly I get this error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'products.category_id' in 'where clause' (SQL: select count(*) as aggregate from `listings` where `products`.`category_id` in (2, 3, 9, 10, 8))

when I try to filter for a category.

Any ideas why it does not include the relations in the count function?

7th August, 2017

achatzi started a new conversation Many To Many Through Many To Many • 1 year ago

Hello.

I have 3 models and their respective tables, along with a pivot table:

| Categories | | ------------- | | id | | title |

| Products | | ------------- | | id | | title | | category_id |

| Listings | | ------------- | | id | | title |

| Listings_Products | | ------------- | | listing_id | | product_id | | price | | is_sold |

My models are like this:

class Listing extends Model
{
    public function products()
    {
        return $this->belongsToMany('App\Models\Product', 'listings_products');
    }

    /**
     * @param Builder $query
     * @param array $filters
     * @return Builder
     */
    public function scopeFilter(Builder $query, array $filters)
    {
        $query->with(['user', 'products.category']);

        if (isset($filters['product'])) {
            $query->where('listings_products.product_id', '=', $filters['product']);
        }
    
        return $query;
    }
}

class Product extends Model
{
    public function category()
    {
        return $this->belongsTo('\App\Models\Category');
    }
    
    public function listings() {
        return $this->belongsToMany('App\Models\Listing', 'listings_products');
    }
}
    
class Category extends Node
{
    protected $table = 'categories';
    
    public function products() {
        return $this->hasMany('\App\Models\Product');
    }   
}

I am trying to filter the list of the listings per category in the scopeFilter function of the model. For example if I select the category 5 I want all the listings that contain products that belong to that category or its descendants. I can get the descendants by using this

$categories = Category::find($filters['category'])->getDescendantsAndSelf()->pluck('id');

Any help would be much appreciated.

Thanks

25th July, 2017

achatzi left a reply on Database & Model Structure Assistance • 1 year ago

Excellent answers from both.

I think I will try @mushood answer because, as he already guessed, I am trying to create a multilinual website.

Thank you both...

achatzi started a new conversation Database & Model Structure Assistance • 1 year ago

Hello.

I am new in Laravel but so far it has been an excellent experience.

Right now, I have a test project I use in order to get used to Laravel and I want to ask for your advice.

Consider this schema:

languages (id, is_active) categories (id, is_active) categories_translations (category_id, language_id, title)

I already have Category & Language models.

Should I use a ManyToMany relationship with the two models and treat the categories_translations table as pivot table?

Then I would use something like

class Category extends Model {

public function translations() {
    return $this->belongsToMany('App\Language');
}

}

$translations = App\Category::find(1)->translations(); or for a specific translation (providing the language id) if necessary.

Am I on the right track or should I consider other options to implement this? Feel free to propose other methods for something like that.

Thanks

Edit Your Profile
Update

Want to change your profile photo? We pull from gravatar.com.